From 8cc71aa30c9a3465e7e3251382ebeaf4d5722dfc Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Sun, 19 Oct 2025 13:57:39 +0200 Subject: [PATCH 01/62] Submit html css exercices --- courses/foundation/git/Blog | 1 + courses/foundation/git/exercice 0/index.html | 56 ++++++++++++++++++++ courses/foundation/git/exercice 0/style.css | 27 ++++++++++ courses/foundation/git/exercice-1/index.html | 44 +++++++++++++++ courses/foundation/git/exercice-1/styles.css | 33 ++++++++++++ courses/foundation/git/exercice-2/index.html | 39 ++++++++++++++ courses/foundation/git/exercice-2/styles.css | 46 ++++++++++++++++ 7 files changed, 246 insertions(+) create mode 160000 courses/foundation/git/Blog create mode 100644 courses/foundation/git/exercice 0/index.html create mode 100644 courses/foundation/git/exercice 0/style.css create mode 100644 courses/foundation/git/exercice-1/index.html create mode 100644 courses/foundation/git/exercice-1/styles.css create mode 100644 courses/foundation/git/exercice-2/index.html create mode 100644 courses/foundation/git/exercice-2/styles.css diff --git a/courses/foundation/git/Blog b/courses/foundation/git/Blog new file mode 160000 index 000000000..07c5b5379 --- /dev/null +++ b/courses/foundation/git/Blog @@ -0,0 +1 @@ +Subproject commit 07c5b537992d7c51750acd612280ebec448b0ee4 diff --git a/courses/foundation/git/exercice 0/index.html b/courses/foundation/git/exercice 0/index.html new file mode 100644 index 000000000..a14c3b21e --- /dev/null +++ b/courses/foundation/git/exercice 0/index.html @@ -0,0 +1,56 @@ + + + + + + Present Yourself + + + + +
+

Oumaima

+

Web developer

+
+ +
+
+

+ about me +

+

+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere culpa + eum cumque similique consequuntur inventore unde error incidunt dolorum + obcaecati autem est maxime deserunt, + laudantium et doloribus tempora totam quibusdam nisi distinctio + adipisci aut quasi cum? Error officia accusamus ipsa nostrum odit + voluptas soluta laudantium, nisi minus magni magnam mollitia! +

+
+
+

Films that i watched recently

+
    +
  • Harry Potter
  • +
  • Shutter Island
  • +
  • Lord of the rings
  • +
+
+
+

+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Assumenda enim + cupiditate possimus. Fuga maiores amet labore sed repellat facere quo + quia similique, eligendi, officia animi. +

+
+
+

Three books I read

+
    +
  1. Atomic habits
  2. +
  3. The housemaid
  4. +
  5. Nobody's girls
  6. +
+
+ cat image +
+ + diff --git a/courses/foundation/git/exercice 0/style.css b/courses/foundation/git/exercice 0/style.css new file mode 100644 index 000000000..7078e1407 --- /dev/null +++ b/courses/foundation/git/exercice 0/style.css @@ -0,0 +1,27 @@ + +body{ + background-color: bisque; + font-family: Arial, Helvetica, sans-serif; + padding: 1rem; +} + +h1{ + text-align: center; + color: brown; +} + +.centerText{ + text-align: center; +} + +img{ + position: relative; + left: 40%; + border-radius: 10px; + +} + +h3{ + font-weight: 300; + color: red; +} \ No newline at end of file diff --git a/courses/foundation/git/exercice-1/index.html b/courses/foundation/git/exercice-1/index.html new file mode 100644 index 000000000..7b885e8cd --- /dev/null +++ b/courses/foundation/git/exercice-1/index.html @@ -0,0 +1,44 @@ + + + + + + + + Table + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Available products +
Product NamePriceIn Stock
Table1000yes
Bed5000Yes
cup50No
+ + diff --git a/courses/foundation/git/exercice-1/styles.css b/courses/foundation/git/exercice-1/styles.css new file mode 100644 index 000000000..978509d48 --- /dev/null +++ b/courses/foundation/git/exercice-1/styles.css @@ -0,0 +1,33 @@ + +body{ + display: flex; + align-items: center; + justify-content: center; + font-family: Arial, Helvetica, sans-serif; +} + +.table{ + margin-top: 10rem; + width: 30rem; + gap: 10rem; +} + + +th, td ,caption{ + padding: 10px; + text-align: center; +} + + +th,td,table{ + border: 1px solid green; +} + +th{ + background-color: rgb(106, 123, 106); +} + +caption{ + font-weight: bold; + background-color: rgb(219, 223, 219); +} \ No newline at end of file diff --git a/courses/foundation/git/exercice-2/index.html b/courses/foundation/git/exercice-2/index.html new file mode 100644 index 000000000..20b917da3 --- /dev/null +++ b/courses/foundation/git/exercice-2/index.html @@ -0,0 +1,39 @@ + + + + + + + Form + + +
+

Contact Form

+ + + + + + + + + + + +
+ + diff --git a/courses/foundation/git/exercice-2/styles.css b/courses/foundation/git/exercice-2/styles.css new file mode 100644 index 000000000..48621ecd5 --- /dev/null +++ b/courses/foundation/git/exercice-2/styles.css @@ -0,0 +1,46 @@ +body { + display: flex; + flex-direction: column; + font-family: Arial, Helvetica, sans-serif; + align-items: center; + justify-content: center; +} + +.form { + display: flex; + flex-direction: column; + width: 30rem; + gap: 2rem; +} + +.form input, +.form select { + height: 2rem; + border: solid rgb(199, 198, 198); +} + +.form textarea { + height: 6rem; +} + +label { + margin-bottom: 0.4rem; + font-weight: bold; + color: #555; +} + + +button { + width: 10rem; + height: 2rem; + margin-left: 10rem; + font-weight: bold; + border-radius: 5px; + border: none; +} + +button:hover{ + scale:1.05; + background-color: rgb(140, 142, 143); +} + From 3d888872f036fe466dd1ecc09e8b3cb4329d7bd6 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Sun, 19 Oct 2025 14:53:57 +0200 Subject: [PATCH 02/62] Add week-1 exercices --- courses/foundation/git/{ => HTML-CSS/Week-1}/Blog | 0 .../foundation/git/{ => HTML-CSS/Week-1}/exercice 0/index.html | 0 courses/foundation/git/{ => HTML-CSS/Week-1}/exercice 0/style.css | 0 .../foundation/git/{ => HTML-CSS/Week-1}/exercice-1/index.html | 0 .../foundation/git/{ => HTML-CSS/Week-1}/exercice-1/styles.css | 0 .../foundation/git/{ => HTML-CSS/Week-1}/exercice-2/index.html | 0 .../foundation/git/{ => HTML-CSS/Week-1}/exercice-2/styles.css | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename courses/foundation/git/{ => HTML-CSS/Week-1}/Blog (100%) rename courses/foundation/git/{ => HTML-CSS/Week-1}/exercice 0/index.html (100%) rename courses/foundation/git/{ => HTML-CSS/Week-1}/exercice 0/style.css (100%) rename courses/foundation/git/{ => HTML-CSS/Week-1}/exercice-1/index.html (100%) rename courses/foundation/git/{ => HTML-CSS/Week-1}/exercice-1/styles.css (100%) rename courses/foundation/git/{ => HTML-CSS/Week-1}/exercice-2/index.html (100%) rename courses/foundation/git/{ => HTML-CSS/Week-1}/exercice-2/styles.css (100%) diff --git a/courses/foundation/git/Blog b/courses/foundation/git/HTML-CSS/Week-1/Blog similarity index 100% rename from courses/foundation/git/Blog rename to courses/foundation/git/HTML-CSS/Week-1/Blog diff --git a/courses/foundation/git/exercice 0/index.html b/courses/foundation/git/HTML-CSS/Week-1/exercice 0/index.html similarity index 100% rename from courses/foundation/git/exercice 0/index.html rename to courses/foundation/git/HTML-CSS/Week-1/exercice 0/index.html diff --git a/courses/foundation/git/exercice 0/style.css b/courses/foundation/git/HTML-CSS/Week-1/exercice 0/style.css similarity index 100% rename from courses/foundation/git/exercice 0/style.css rename to courses/foundation/git/HTML-CSS/Week-1/exercice 0/style.css diff --git a/courses/foundation/git/exercice-1/index.html b/courses/foundation/git/HTML-CSS/Week-1/exercice-1/index.html similarity index 100% rename from courses/foundation/git/exercice-1/index.html rename to courses/foundation/git/HTML-CSS/Week-1/exercice-1/index.html diff --git a/courses/foundation/git/exercice-1/styles.css b/courses/foundation/git/HTML-CSS/Week-1/exercice-1/styles.css similarity index 100% rename from courses/foundation/git/exercice-1/styles.css rename to courses/foundation/git/HTML-CSS/Week-1/exercice-1/styles.css diff --git a/courses/foundation/git/exercice-2/index.html b/courses/foundation/git/HTML-CSS/Week-1/exercice-2/index.html similarity index 100% rename from courses/foundation/git/exercice-2/index.html rename to courses/foundation/git/HTML-CSS/Week-1/exercice-2/index.html diff --git a/courses/foundation/git/exercice-2/styles.css b/courses/foundation/git/HTML-CSS/Week-1/exercice-2/styles.css similarity index 100% rename from courses/foundation/git/exercice-2/styles.css rename to courses/foundation/git/HTML-CSS/Week-1/exercice-2/styles.css From 57a5f18791759c62b57d4aa2d17080889f75bd8b Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Sun, 19 Oct 2025 15:37:11 +0200 Subject: [PATCH 03/62] Create new git branch --- courses/foundation/git/HTML-CSS/Week-1/Blog | 1 - 1 file changed, 1 deletion(-) delete mode 160000 courses/foundation/git/HTML-CSS/Week-1/Blog diff --git a/courses/foundation/git/HTML-CSS/Week-1/Blog b/courses/foundation/git/HTML-CSS/Week-1/Blog deleted file mode 160000 index 07c5b5379..000000000 --- a/courses/foundation/git/HTML-CSS/Week-1/Blog +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 07c5b537992d7c51750acd612280ebec448b0ee4 From 628d7692ca3c741bf97adef19e61c25ffa0cba55 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Sun, 19 Oct 2025 15:45:45 +0200 Subject: [PATCH 04/62] Add apple-file --- .../foundation/git/Week-1/session-playground/apples-file.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 courses/foundation/git/Week-1/session-playground/apples-file.txt diff --git a/courses/foundation/git/Week-1/session-playground/apples-file.txt b/courses/foundation/git/Week-1/session-playground/apples-file.txt new file mode 100644 index 000000000..aa45de0db --- /dev/null +++ b/courses/foundation/git/Week-1/session-playground/apples-file.txt @@ -0,0 +1,2 @@ +dfhsdjkfsdøfljksdamdfaskldkdspåflæsdkvgbmfdoåhlgæhkmfdlf.flsdfæølh.ghøjh +H \ No newline at end of file From d4f46db9e75c1cf7b97a93daf290b8a9cff9dc43 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Mon, 20 Oct 2025 14:27:56 +0200 Subject: [PATCH 05/62] Add Blog exercice --- .../git/HTML-CSS/Week-1/Blog/README.md | Bin 0 -> 1642 bytes .../git/HTML-CSS/Week-1/Blog/index.html | 136 +++++++++++ .../git/HTML-CSS/Week-1/Blog/styles.css | 226 ++++++++++++++++++ 3 files changed, 362 insertions(+) create mode 100644 courses/foundation/git/HTML-CSS/Week-1/Blog/README.md create mode 100644 courses/foundation/git/HTML-CSS/Week-1/Blog/index.html create mode 100644 courses/foundation/git/HTML-CSS/Week-1/Blog/styles.css diff --git a/courses/foundation/git/HTML-CSS/Week-1/Blog/README.md b/courses/foundation/git/HTML-CSS/Week-1/Blog/README.md new file mode 100644 index 0000000000000000000000000000000000000000..5bca7bbda3f8cf415192befd6465b48499e0bacb GIT binary patch literal 1642 zcmaKs-EPxB5QXO&iFa73Hy{yi5HA2#)C+n6lm~E}#If3VBReU9hX=kh>y2I4MNty( z?EIWLbH;!FytY?%Wx+n#gGD}jp1)XaTifuo7@ayh+Aq9hPu`U&I%QCfYwkKLttI|| zcTK*=@8`4Ecn2%^wjOzK|Bkpvukz627*}37&Wf0y_^ilKQ%RV%M3;8LvavO1)ecyq z{RVd+PI+srmA&J<_vbZnC+>pnK(g{|o!=LDD$mBzwB%Uhp-k%UNK`>wXYaAx5iJZ; zOsZDmbs|>W1V>k1xRFJ;TmF@y(F&c)s}1tqj)R%$}hlq#D47WGX5?oy@PK}I#L zpK(1!E3W}nu5*Jm%~t9h=0E0D8&}X>!YJiQyMqpLuDpA?&srGgsZn+T`$=yZrFP^@ z_MAnX&naiB&~avMP-FM79efJf4dqmC4K=kzLZr=43h6HOmfXCg!vEEr@8&s@1J$J^ z-3&Xhg2CvBwMCf=%}Cs8>(o()o@!2Fe|Tp}A4|?>yfqE&XVL3?(5h^mzZJxQCST3w z5st*vm{FlP5Un>#MFnkv5J_{IRGQXvJ>Pi;J3J#DM`CL%n#&J + + + + + Life Style Blog + + + + + + + + +
+

🌸 Bloom Life

+

+ Little rituals, cozy spaces, and mindful living ✨ +

+
+ +
+ +
+

Why Lifestyle Habits Matter

+

+ The way we live day to day shapes the way we feel. Our spaces, our + routines, the little things we do without thinking they all add up. + Every morning cup of tea, every quiet corner we create, every small + habit we choose becomes part of the rhythm of our lives. When we pause + to look at these details with intention, we begin to see how much + power they hold. By slowing down, adjusting our environment, and + choosing rituals that bring comfort and joy, we can design days that + nourish us from the inside out. It’s not about perfection or following + a strict routine, it’s about creating a gentle structure that supports + the life we want to live. Through mindful choices, we can build lives + that feel soft, meaningful, and truly ours. +

+
+ +
+ +
+

How I Create Calm Mornings ☀️

+

+ Mornings set the tone for my entire day. A cup of warm tea, soft + sunlight, and a few quiet minutes to breathe that’s where my peace + begins. In this post, I’ll share the simple habits that help me + start each morning with calm energy and a clear mind. +

+
+ Morning Coffee +
+ + + +
+

My favorites

+ +
+ +
+

Morning Playlist

+ + Music + +
+
+

Book List

+ book image +
+
+

Decor Inspiration

+ sofa image + +
+
+
+
+ +
+

© 2025 Bloom Life. All rights reserved.

+

Made with ☕ and soft lighting.

+
+ + diff --git a/courses/foundation/git/HTML-CSS/Week-1/Blog/styles.css b/courses/foundation/git/HTML-CSS/Week-1/Blog/styles.css new file mode 100644 index 000000000..ffc0ad83b --- /dev/null +++ b/courses/foundation/git/HTML-CSS/Week-1/Blog/styles.css @@ -0,0 +1,226 @@ + +* { + box-sizing: border-box; +} + +body { + font-family: "Rouge Script", cursive; + font-weight: 400; + font-style: normal; + font-size: larger; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 1rem; + width: 100%; + margin: 0; +} + + +.header { + display: flex; + flex-direction: column; + width: 100%; + position: fixed; + background-color: white; + top: 0; + left: 0; + z-index: 1000; + padding: 1rem 0; +} + +h1 { + color: #a0c3d2; + text-align: center; + font-size: xx-large; + margin: 0; +} + +.centerText { + text-align: center; +} + +.boldText { + font-weight: bolder; +} + + +main { + padding-top: 6rem; + width: 100%; + display: flex; + flex-direction: column; + align-items: center; +} + + +.heroSection { + width: 100%; + min-height: 30rem; + padding: 2rem; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; + background-image: url(https://images.unsplash.com/photo-1566501248434-6d513596c485?ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&q=80&w=1171); + background-repeat: no-repeat; + background-size: cover; + background-position: center; + color: black; +} + + +.card { + display: flex; + flex-direction: column; + background-color: #f7f5eb; + width: 80%; + max-width: 60rem; + min-height: 2rem; + align-items: center; + justify-content: center; + box-shadow: 2px 2px 2px 2px rgb(233, 230, 230); + margin: 3rem auto; + border-radius: 5px; + padding: 1rem; +} + +.card img { + width: 100%; + max-width: 20rem; + height: 8rem; + object-fit: cover; + margin-top: 1rem; + +} + +.card:hover { + background-color: #eae0da; +} + +.favoriteCard a { + display: flex; + justify-content: center; + width: 100%; +} + + +a { + text-decoration: none; + color: black; +} + +ul { + list-style: none; + color: black; + padding-left: 0; +} + +ul li:hover { + font-weight: bold; +} + + +.posts { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + max-width: 60rem; + margin: 3rem auto; +} + +.posts img { + width: 100%; + height: auto; + margin-top: 2rem; +} + + +.favoriteCardsContainer { + display: flex; + gap: 2rem; + justify-content: center; + align-items: flex-start; + flex-wrap: wrap; + padding-top: 2rem; + padding-left: 2rem; +} + +.favoriteCard { + display: flex; + flex-direction: column; + background-color: #f7f5eb; + box-shadow: 2px 2px 2px 2px rgb(233, 230, 230); + width: 10rem; + min-height: 15rem; + border-radius: 5px; + align-items: center; + justify-content: center; + padding: 0.5rem; +} + +.favoriteCard:hover { + transform: scale(1.05); +} + +.favoriteCard img { + width: 60%; + height: 4rem; + object-fit: cover; +} + + +footer { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 3rem 1rem; + font-size: small; + color: gray; +} + + +@media (max-width: 600px) { + body { + font-size: medium; + } + + .heroSection { + padding: 3rem; + min-height: 19rem; + } + + .heroSection p { + font-size: 0.9rem; + } + + .card { + width: 90%; + margin: 2rem auto; + } + + .card img { + max-width: 100%; + height: auto; + } + + .posts { + width: 100%; + } + + .favoriteCardsContainer { + flex-direction: column; + gap: 1.5rem; + align-items: center; + } + + footer { + padding: 2rem 1rem; + text-align: center; + } +} From 6a6c032eb5bb80ba2d1f01ff8160618ffd461678 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Mon, 20 Oct 2025 14:56:48 +0200 Subject: [PATCH 06/62] add the file my-favourite-food.txt --- courses/foundation/git/week1/Oumaima/my-favourite-food.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 courses/foundation/git/week1/Oumaima/my-favourite-food.txt diff --git a/courses/foundation/git/week1/Oumaima/my-favourite-food.txt b/courses/foundation/git/week1/Oumaima/my-favourite-food.txt new file mode 100644 index 000000000..4448f1f64 --- /dev/null +++ b/courses/foundation/git/week1/Oumaima/my-favourite-food.txt @@ -0,0 +1,7 @@ +Homemade Pasta Recipe Ingredients +You only need 4 ingredients to make delicious fresh pasta at home, and there’s a good chance you have all of them on hand already: + +All-purpose flour – In the past, I thought you needed 00 flour or semolina flour to make great fresh pasta, but this homemade pasta recipe proved me wrong. In it, regular all-purpose flour yields chewy, bouncy noodles every time. +Eggs – The key ingredient for adding richness and moisture to the dough! +Olive oil – Along with the eggs, a splash of olive oil moistens the dough and helps it come together. +Salt – Add it to the dough and the pasta water for the best flavor. \ No newline at end of file From cd833183f886902e78266c1264d0549e1907941a Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Mon, 20 Oct 2025 14:58:19 +0200 Subject: [PATCH 07/62] add my-second-favourite-food.txt file --- .../git/week1/Oumaima/my-second-favourite-food.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 courses/foundation/git/week1/Oumaima/my-second-favourite-food.txt diff --git a/courses/foundation/git/week1/Oumaima/my-second-favourite-food.txt b/courses/foundation/git/week1/Oumaima/my-second-favourite-food.txt new file mode 100644 index 000000000..70cb6d5fb --- /dev/null +++ b/courses/foundation/git/week1/Oumaima/my-second-favourite-food.txt @@ -0,0 +1,7 @@ +giHow to Make Lasagna +While homemade lasagna may have a few steps, each step is easy – and I assure you it’s worth the time; the perfect Italian meal! + +Boil pasta: In a large pot of salted water boil lasagna noodles per the recipe below. +Prepare meat sauce: Cook sausage and beef with onion and garlic. Drain well, add the pasta sauce (I love this brand) & simmer it for a few minutes to thicken. +Combine cheese mixture: Stir the cheese mixture together in a bowl. +Layer & bake: Layer the meat sauce and cheese mixture with lasagna noodles and bake until the top of the lasagna is golden brown. \ No newline at end of file From 84056c0220361552dfc3737475c711994315b7d4 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Mon, 20 Oct 2025 14:59:17 +0200 Subject: [PATCH 08/62] add countries.txt file --- courses/foundation/git/week1/Oumaima/countries.txt | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 courses/foundation/git/week1/Oumaima/countries.txt diff --git a/courses/foundation/git/week1/Oumaima/countries.txt b/courses/foundation/git/week1/Oumaima/countries.txt new file mode 100644 index 000000000..423742a4c --- /dev/null +++ b/courses/foundation/git/week1/Oumaima/countries.txt @@ -0,0 +1,9 @@ +Morocco + +Finland + +Argentina + +South Korea + +New Zealand \ No newline at end of file From 09f92127f80e43843bae38eadc714522f9548ad8 Mon Sep 17 00:00:00 2001 From: ousakka Date: Mon, 20 Oct 2025 16:00:50 +0200 Subject: [PATCH 09/62] Delete courses/foundation/git/Week-1/session-playground/apples-file.txt --- .../foundation/git/Week-1/session-playground/apples-file.txt | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 courses/foundation/git/Week-1/session-playground/apples-file.txt diff --git a/courses/foundation/git/Week-1/session-playground/apples-file.txt b/courses/foundation/git/Week-1/session-playground/apples-file.txt deleted file mode 100644 index aa45de0db..000000000 --- a/courses/foundation/git/Week-1/session-playground/apples-file.txt +++ /dev/null @@ -1,2 +0,0 @@ -dfhsdjkfsdøfljksdamdfaskldkdspåflæsdkvgbmfdoåhlgæhkmfdlf.flsdfæølh.ghøjh -H \ No newline at end of file From b6d03246c3097eb980dae51c1b31e9b83d836978 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Mon, 20 Oct 2025 16:18:04 +0200 Subject: [PATCH 10/62] Add apples file --- courses/foundation/git/week1/session-playground/apples-file.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 courses/foundation/git/week1/session-playground/apples-file.txt diff --git a/courses/foundation/git/week1/session-playground/apples-file.txt b/courses/foundation/git/week1/session-playground/apples-file.txt new file mode 100644 index 000000000..517d672cf --- /dev/null +++ b/courses/foundation/git/week1/session-playground/apples-file.txt @@ -0,0 +1 @@ +This is apples file \ No newline at end of file From c04c2a0834ac0b73f48bdb046c3f722e768d4ac3 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Mon, 20 Oct 2025 16:19:37 +0200 Subject: [PATCH 11/62] add bananas file --- courses/foundation/git/week1/session-playground/bananas-file.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 courses/foundation/git/week1/session-playground/bananas-file.txt diff --git a/courses/foundation/git/week1/session-playground/bananas-file.txt b/courses/foundation/git/week1/session-playground/bananas-file.txt new file mode 100644 index 000000000..1d6e303d3 --- /dev/null +++ b/courses/foundation/git/week1/session-playground/bananas-file.txt @@ -0,0 +1 @@ +This is bananas file \ No newline at end of file From 30b2458f9bde14b7ba413fa52345071717bdf3a3 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Mon, 20 Oct 2025 16:20:02 +0200 Subject: [PATCH 12/62] Add oranges file --- courses/foundation/git/week1/session-playground/oranges-file.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 courses/foundation/git/week1/session-playground/oranges-file.txt diff --git a/courses/foundation/git/week1/session-playground/oranges-file.txt b/courses/foundation/git/week1/session-playground/oranges-file.txt new file mode 100644 index 000000000..a67c39aec --- /dev/null +++ b/courses/foundation/git/week1/session-playground/oranges-file.txt @@ -0,0 +1 @@ +This oranges file \ No newline at end of file From 694dd3f9b1422c6423d4b7d9939f8d7f739d5a3b Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Mon, 20 Oct 2025 16:21:03 +0200 Subject: [PATCH 13/62] Add changes to the apples file --- .../foundation/git/week1/session-playground/apples-file.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/courses/foundation/git/week1/session-playground/apples-file.txt b/courses/foundation/git/week1/session-playground/apples-file.txt index 517d672cf..b920f2960 100644 --- a/courses/foundation/git/week1/session-playground/apples-file.txt +++ b/courses/foundation/git/week1/session-playground/apples-file.txt @@ -1 +1,2 @@ -This is apples file \ No newline at end of file +This is apples file +Add some text to the apples file \ No newline at end of file From a4735b4d731d69eb111150fc59de9edb4da296c9 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Tue, 21 Oct 2025 11:09:26 +0200 Subject: [PATCH 14/62] Add the assignment file --- courses/foundation/git/week1/session-playground/assignment.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 courses/foundation/git/week1/session-playground/assignment.txt diff --git a/courses/foundation/git/week1/session-playground/assignment.txt b/courses/foundation/git/week1/session-playground/assignment.txt new file mode 100644 index 000000000..32b1b6d84 --- /dev/null +++ b/courses/foundation/git/week1/session-playground/assignment.txt @@ -0,0 +1 @@ +The clock hummed softly as the rain whispered against the window. A half-eaten apple sat beside an open notebook filled with sketches of impossible machines. Somewhere in the distance, a train sounded its horn — three long notes that felt like a memory trying to find its way home. \ No newline at end of file From 9ce4eb0bdaf20be80ad7298292612f1e87be7a08 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Tue, 21 Oct 2025 11:10:52 +0200 Subject: [PATCH 15/62] Add more text to assignment file --- .../foundation/git/week1/session-playground/assignment.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/courses/foundation/git/week1/session-playground/assignment.txt b/courses/foundation/git/week1/session-playground/assignment.txt index 32b1b6d84..aab39c3db 100644 --- a/courses/foundation/git/week1/session-playground/assignment.txt +++ b/courses/foundation/git/week1/session-playground/assignment.txt @@ -1 +1,3 @@ -The clock hummed softly as the rain whispered against the window. A half-eaten apple sat beside an open notebook filled with sketches of impossible machines. Somewhere in the distance, a train sounded its horn — three long notes that felt like a memory trying to find its way home. \ No newline at end of file +The clock hummed softly as the rain whispered against the window. A half-eaten apple sat beside an open notebook filled with sketches of impossible machines. Somewhere in the distance, a train sounded its horn — three long notes that felt like a memory trying to find its way home. + +A blue umbrella drifted down the empty street like it had somewhere important to be. The pigeons held a silent council on the power line above, judging everyone below. Someone left a note on a park bench that just said, “Remember the sound of leaves in September.” Nobody knew what it meant, but somehow, everyone felt it was meant for them. \ No newline at end of file From 4b4bedb903458ae8dcffdeea190abea7044a87d4 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Tue, 21 Oct 2025 11:15:05 +0200 Subject: [PATCH 16/62] Add more text to assignment file after creating a pull request --- .../foundation/git/week1/session-playground/assignment.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/courses/foundation/git/week1/session-playground/assignment.txt b/courses/foundation/git/week1/session-playground/assignment.txt index aab39c3db..d5ca49c03 100644 --- a/courses/foundation/git/week1/session-playground/assignment.txt +++ b/courses/foundation/git/week1/session-playground/assignment.txt @@ -1,3 +1,5 @@ The clock hummed softly as the rain whispered against the window. A half-eaten apple sat beside an open notebook filled with sketches of impossible machines. Somewhere in the distance, a train sounded its horn — three long notes that felt like a memory trying to find its way home. -A blue umbrella drifted down the empty street like it had somewhere important to be. The pigeons held a silent council on the power line above, judging everyone below. Someone left a note on a park bench that just said, “Remember the sound of leaves in September.” Nobody knew what it meant, but somehow, everyone felt it was meant for them. \ No newline at end of file +A blue umbrella drifted down the empty street like it had somewhere important to be. The pigeons held a silent council on the power line above, judging everyone below. Someone left a note on a park bench that just said, “Remember the sound of leaves in September.” Nobody knew what it meant, but somehow, everyone felt it was meant for them. + +The toaster refused to cooperate this morning, claiming artistic differences with the bread. Meanwhile, a cat wearing philosophical expressions sat by the window, contemplating the metaphysics of pigeons. Somewhere in a drawer, an old key dreamed of unlocking something important, but couldn’t remember what. The air smelled faintly of possibility and forgotten cinnamon. \ No newline at end of file From 1386f89322b6940fbaa076ef76061448cf8b0d0a Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 11:15:10 +0100 Subject: [PATCH 17/62] Add html file --- .../Intro to IA Assignment/index.html | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html new file mode 100644 index 000000000..97c641c93 --- /dev/null +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html @@ -0,0 +1,11 @@ + + + + + + My Portfolio + + + + + From 6c4f67cb1a2f5a14b02fb29c7d68e361dc0e585e Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 11:20:20 +0100 Subject: [PATCH 18/62] Add the header to html file --- .../intro-to-using-ai/Intro to IA Assignment/index.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html index 97c641c93..e0465327f 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html @@ -5,7 +5,12 @@ My Portfolio + +
+

Oumaima Sakka

+
+ From 4f413cc85817f60b8832685d060f5e06ab49bc40 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 11:37:01 +0100 Subject: [PATCH 19/62] Add about me section --- .../Intro to IA Assignment/index.html | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html index e0465327f..7f9a1dd6c 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html @@ -10,7 +10,16 @@

Oumaima Sakka

- +
+

About Me

+

Hi, my name is Oumaima. I'm passionate about web development and currently learning to build modern, responsive websites. + I’m always curious and motivated to discover new technologies, tools, and ideas that help me grow as a developer and a lifelong learner. + I believe that every project is an opportunity to improve, create, and make something meaningful.

+ + + + +
From 949f0988d5e530cd8f4e4767291249993a992f48 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 11:39:10 +0100 Subject: [PATCH 20/62] Add interests section --- .../Intro to IA Assignment/index.html | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html index 7f9a1dd6c..9c32f7f90 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html @@ -1,25 +1,32 @@ - - - + + + My Portfolio - + -
+

Oumaima Sakka

-
- -
-

About Me

-

Hi, my name is Oumaima. I'm passionate about web development and currently learning to build modern, responsive websites. - I’m always curious and motivated to discover new technologies, tools, and ideas that help me grow as a developer and a lifelong learner. - I believe that every project is an opportunity to improve, create, and make something meaningful.

- - +
+ +
+

About Me

+

+ Hi, my name is Oumaima. I'm passionate about web development and + currently learning to build modern, responsive websites. I’m always + curious and motivated to discover new technologies, tools, and ideas + that help me grow as a developer and a lifelong learner. I believe that + every project is an opportunity to improve, create, and make something + meaningful. +

- -
- - +

My Interests & Skills

+
    +
  • Frontend Web Development
  • +
  • Learning New Technologies
  • +
  • Sharing Knowledge and Helping Others Learn
  • +
+ + From 65f321e0afd5a679689fefd2bfdd14c256441ed0 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 11:44:54 +0100 Subject: [PATCH 21/62] Add change background button --- .../intro-to-using-ai/Intro to IA Assignment/index.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html index 9c32f7f90..e8b178efd 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html @@ -10,7 +10,7 @@

Oumaima Sakka

-
+

About Me

Hi, my name is Oumaima. I'm passionate about web development and @@ -27,6 +27,8 @@

My Interests & Skills

  • Learning New Technologies
  • Sharing Knowledge and Helping Others Learn
  • -
    + + + From c55d8e6d67a4ae17941a34ca639ed5ef8101a825 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 12:11:06 +0100 Subject: [PATCH 22/62] Add syles.css file --- .../intro-to-using-ai/Intro to IA Assignment/styles.css | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css new file mode 100644 index 000000000..e69de29bb From 15edfac01b746dd18af35ae3519169ba182e6c59 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 12:13:18 +0100 Subject: [PATCH 23/62] Add body styling --- .../intro-to-using-ai/Intro to IA Assignment/styles.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css index e69de29bb..b9449986a 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css @@ -0,0 +1,9 @@ +body { + font-family: 'Poppins', sans-serif; + margin: 0; + padding: 0; + background-color: #f0f4f8; + color: #333; + margin: 1rem; + +} \ No newline at end of file From f55f57130711b69a7387e7e085fb050ea6b6b434 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 12:17:01 +0100 Subject: [PATCH 24/62] Add styling to the header --- .../intro-to-using-ai/Intro to IA Assignment/styles.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css index b9449986a..4c03ac61c 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css @@ -6,4 +6,12 @@ body { color: #333; margin: 1rem; +} + + +header{ + display: flex; + align-items: center; + justify-content: center; + color: #333; } \ No newline at end of file From f0e756822d6ef96efbd3a3ca77d5e727db6a9323 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 12:29:12 +0100 Subject: [PATCH 25/62] Add styling to about me container --- .../Intro to IA Assignment/styles.css | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css index 4c03ac61c..ed04a6770 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css @@ -8,10 +8,19 @@ body { } - header{ display: flex; align-items: center; justify-content: center; color: #333; +} + +.container { + max-width: 37.5rem; + margin: 3.125rem auto; + padding: 3.125rem; + text-align: center; + background: white; + border-radius: 16px; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); } \ No newline at end of file From e193a670a62e7d8ab6025c817fffbd99d36ee328 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 12:33:11 +0100 Subject: [PATCH 26/62] Add styling to h1,h2 and h3 --- .../Intro to IA Assignment/styles.css | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css index ed04a6770..c709562d2 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css @@ -23,4 +23,13 @@ header{ background: white; border-radius: 16px; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); -} \ No newline at end of file +} + +h1 { + color: #555; + font-size: 2rem; +} + +h2,h3 { + color: #4e00cc; +} From 137b4bd77191009afa6e68d3ef1967c066d9549f Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 12:34:59 +0100 Subject: [PATCH 27/62] Add styling to the list and to the paragraph --- .../Intro to IA Assignment/styles.css | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css index c709562d2..5bdecd9b6 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css @@ -33,3 +33,13 @@ h1 { h2,h3 { color: #4e00cc; } + +ul { + list-style-type: none; + padding: 0; +} + +li,p { + padding: 8px 0; + font-size: 1.1em; +} \ No newline at end of file From 740fb2045702d49af9d74e7abb00930e9a5967e7 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 12:38:46 +0100 Subject: [PATCH 28/62] Add styling to the button --- .../Intro to IA Assignment/styles.css | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css index 5bdecd9b6..32266c458 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css @@ -42,4 +42,16 @@ ul { li,p { padding: 8px 0; font-size: 1.1em; +} + +button { + margin-top: 1.5rem; + padding: 0.6rem 1.5rem; + font-size: 1rem; + background-color: #4e00cc; + color: white; + border: none; + border-radius: 8px; + cursor: pointer; + transition: background-color 0.3s ease; } \ No newline at end of file From c46d6c28dbde6e17e951a1a29770af95039172d7 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 12:40:49 +0100 Subject: [PATCH 29/62] Add hover to the button --- .../intro-to-using-ai/Intro to IA Assignment/styles.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css index 32266c458..a74f29f6b 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css @@ -54,4 +54,8 @@ button { border-radius: 8px; cursor: pointer; transition: background-color 0.3s ease; +} + +button:hover { + background-color: rgb(75, 58, 82); } \ No newline at end of file From f2c16216246e43bdf08e2176e947f8d69134d79c Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 12:45:37 +0100 Subject: [PATCH 30/62] Add media query --- .../Intro to IA Assignment/styles.css | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css index a74f29f6b..fe29ac142 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css @@ -31,6 +31,7 @@ h1 { } h2,h3 { + font-size: 1.5rem; color: #4e00cc; } @@ -41,7 +42,7 @@ ul { li,p { padding: 8px 0; - font-size: 1.1em; + font-size: 1rem; } button { @@ -58,4 +59,24 @@ button { button:hover { background-color: rgb(75, 58, 82); +} + +@media (max-width: 600px) { + .container { + margin: 1.5rem; + padding: 1rem; + } + + h1 { + font-size: 1.5rem; + } + + h2,h3 { + font-size: 1rem; +} + +li,p { + font-size: 0.7rem; +} + } \ No newline at end of file From 2dbd288ba70ea64fc4eea678ef88a5f0a6093cee Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 12:47:19 +0100 Subject: [PATCH 31/62] Add js file --- .../foundation/intro-to-using-ai/Intro to IA Assignment/script.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 courses/foundation/intro-to-using-ai/Intro to IA Assignment/script.js diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/script.js b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/script.js new file mode 100644 index 000000000..e69de29bb From 9478959da3cf4fdfea3999144c5515e759dd2727 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 12:51:13 +0100 Subject: [PATCH 32/62] Create getRandomColor function --- .../intro-to-using-ai/Intro to IA Assignment/script.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/script.js b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/script.js index e69de29bb..850ff68b4 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/script.js +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/script.js @@ -0,0 +1,8 @@ +function getRandomColor() { + const letters = '0123456789ABCDEF'; + let color = '#'; + for (let i = 0; i < 6; i++) { + color += letters[Math.floor(Math.random() * 16)]; + } + return color; +} \ No newline at end of file From 0379fe522562609c6ff7c26c2eded39c3bb2db99 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 12:57:09 +0100 Subject: [PATCH 33/62] Add event listner --- .../intro-to-using-ai/Intro to IA Assignment/script.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/script.js b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/script.js index 850ff68b4..ae70353ae 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/script.js +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/script.js @@ -5,4 +5,8 @@ function getRandomColor() { color += letters[Math.floor(Math.random() * 16)]; } return color; -} \ No newline at end of file +} + +document.getElementById('backgroundColorButton').addEventListener('click', () => { + document.body.style.backgroundColor = getRandomColor(); +}); \ No newline at end of file From 369df6b30b3c2890048628785ef2857b99c7b4da Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 29 Oct 2025 16:46:22 +0100 Subject: [PATCH 34/62] Create Reflection.md file --- .../Intro to IA Assignment/Reflection.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 courses/foundation/intro-to-using-ai/Intro to IA Assignment/Reflection.md diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/Reflection.md b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/Reflection.md new file mode 100644 index 000000000..b0189acbc --- /dev/null +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/Reflection.md @@ -0,0 +1,15 @@ +## 1. Three new things I learned from AI +1. How to use event listeners in JavaScript to create dynamic and interactive behavior on a webpage. +2. How to generate random numbers in JavaScript +3. How to write Markdown (.md) files + +## 2. Tweaks I made to Copilot's suggestions +The CSS styling suggested by Copilot was not exactly how I wanted, so I made changes to adjust the layout, centering, and overall visual appearance. I also used Copilot to explain the JavaScript code step by step, including the theory behind each function, which helped me understand how and why the code works. + +## 3. Copilot: Generator vs Learning Partner +Using Copilot is really helpful because it makes the coding process easier and can inspire creative ideas. However, relying on it to generate code automatically doesn’t help you learn or be creative, as it can make you more passive. When you use Copilot as a learning partner, it becomes a powerful tool to quickly find information and generate examples that help you understand new concepts. It feels like having a teacher beside you at home, guiding you while you learn. + +## 4. Risks of relying too much on AI +1. Becoming passive and losing the ability to brainstorm or solve coding problems independently. +2. Failing to develop real developer skills due to a lack of hands-on coding practice. +3. Relying completely on AI tools instead of building confidence and independence as a programmer. From 7dc5f5863dbfafbce44ad5026461d065644519cb Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Thu, 30 Oct 2025 09:44:07 +0100 Subject: [PATCH 35/62] Link css and js file with the html file --- .../Intro to IA Assignment/index.html | 2 + .../Intro to IA Assignment/styles.css | 38 ++++++++++--------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html index e8b178efd..d37112ba4 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/index.html @@ -4,6 +4,7 @@ My Portfolio +
    @@ -30,5 +31,6 @@

    My Interests & Skills

    + diff --git a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css index fe29ac142..201e12aa1 100644 --- a/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css +++ b/courses/foundation/intro-to-using-ai/Intro to IA Assignment/styles.css @@ -1,18 +1,17 @@ body { - font-family: 'Poppins', sans-serif; + font-family: "Poppins", sans-serif; margin: 0; padding: 0; background-color: #f0f4f8; color: #333; margin: 1rem; - } -header{ - display: flex; - align-items: center; - justify-content: center; - color: #333; +header { + display: flex; + align-items: center; + justify-content: center; + color: #333; } .container { @@ -26,12 +25,13 @@ header{ } h1 { - color: #555; - font-size: 2rem; + color:black; + font-size: 2rem; } -h2,h3 { - font-size: 1.5rem; +h2, +h3 { + font-size: 1.5rem; color: #4e00cc; } @@ -40,7 +40,8 @@ ul { padding: 0; } -li,p { +li, +p { padding: 8px 0; font-size: 1rem; } @@ -71,12 +72,13 @@ button:hover { font-size: 1.5rem; } - h2,h3 { + h2, + h3 { font-size: 1rem; -} + } -li,p { - font-size: 0.7rem; + li, + p { + font-size: 0.7rem; + } } - -} \ No newline at end of file From a634b10f90fe6f24b794eecfe8577d0843dc90e2 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Tue, 4 Nov 2025 12:01:08 +0100 Subject: [PATCH 36/62] Add intro to js assignment --- .../intro-to-javascript/Assignment/index.html | 11 ++++ .../intro-to-javascript/Assignment/script.js | 55 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 courses/foundation/intro-to-javascript/Assignment/index.html create mode 100644 courses/foundation/intro-to-javascript/Assignment/script.js diff --git a/courses/foundation/intro-to-javascript/Assignment/index.html b/courses/foundation/intro-to-javascript/Assignment/index.html new file mode 100644 index 000000000..a9f675b55 --- /dev/null +++ b/courses/foundation/intro-to-javascript/Assignment/index.html @@ -0,0 +1,11 @@ + + + + + + Document + + + + + \ No newline at end of file diff --git a/courses/foundation/intro-to-javascript/Assignment/script.js b/courses/foundation/intro-to-javascript/Assignment/script.js new file mode 100644 index 000000000..bcc46e4f0 --- /dev/null +++ b/courses/foundation/intro-to-javascript/Assignment/script.js @@ -0,0 +1,55 @@ +/* Age-ify (A future age calculator) */ +let yearOfBirth=1999; +let yearFuture=2045; +let age=yearFuture-yearOfBirth; +console.log("You will be " + age + " years old in " + yearFuture); + +/* Goodboy-Oldboy (A dog age calculator) */ +const dogYearOfBirth = 2017; +const dogYearFuture = 2027; +const shouldShowResultInDogYears = true; + +let dogYear = dogYearFuture - dogYearOfBirth; + +if (shouldShowResultInDogYears) { + dogYear = dogYear * 7; + console.log("Your dog will be " + dogYear + " dog years old in " + dogYearFuture); +} else { + console.log("Your dog will be " + dogYear + " human years old in " + dogYearFuture); +} + +/* Housey pricey (A house price estimator) */ +let houseHeightPeter = 10; +let houseWidthPeter = 8; +let houseDepthPeter = 10; +let houseVolumePeter = houseHeightPeter * houseWidthPeter * houseDepthPeter; +let gardenSizeInM2Peter = 100; + +let housePricePeter = houseVolumePeter * 2.5 * 1000 + gardenSizeInM2Peter * 300; +if (housePricePeter <= 2500000) { + console.log("Peter is paying too much"); +} else { + console.log("Peter is paying too little"); +} + +let houseHeightJulia = 8; +let houseWidthJulia = 5; +let houseDepthJulia = 11; +let houseVolumeJulia = houseHeightJulia * houseWidthJulia * houseDepthJulia; +let gardenSizeInM2Julia = 70; +let housePriceJulia = houseVolumeJulia * 2.5 * 1000 + gardenSizeInM2Julia * 300; +if (housePriceJulia <= 1000000) { + console.log("Julia is paying too much"); +} else { + console.log("Julia is paying too little"); +} + +/* Ez Namey (Startup name generator) */ + +let firstWords=["Easy","Smart","NextGen","Quick","Green","Tech","Bright","Future","Innovative","Dynamic"]; +let secondWords=["Solutions","Systems","Technologies","Concepts","Designs","Ideas","Ventures","Labs","Works","Studios"]; + +let startupName; +let randomIndex=Math.floor(Math.random()*10); +startupName=firstWords[randomIndex]+" "+secondWords[randomIndex]; +console.log("The starup name is "+startupName); \ No newline at end of file From d07bf68885e29899baa4edf0bfd7ed85855e4b30 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Tue, 4 Nov 2025 12:14:04 +0100 Subject: [PATCH 37/62] Add pizza exercise --- .../pizza-exercise/index.html | 13 ++++++++++ .../pizza-exercise/pizza.js | 26 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 courses/foundation/intro-to-javascript/pizza-exercise/index.html create mode 100644 courses/foundation/intro-to-javascript/pizza-exercise/pizza.js diff --git a/courses/foundation/intro-to-javascript/pizza-exercise/index.html b/courses/foundation/intro-to-javascript/pizza-exercise/index.html new file mode 100644 index 000000000..4f1e396eb --- /dev/null +++ b/courses/foundation/intro-to-javascript/pizza-exercise/index.html @@ -0,0 +1,13 @@ + + + + + + Document + + + + + + + \ No newline at end of file diff --git a/courses/foundation/intro-to-javascript/pizza-exercise/pizza.js b/courses/foundation/intro-to-javascript/pizza-exercise/pizza.js new file mode 100644 index 000000000..cb12c203a --- /dev/null +++ b/courses/foundation/intro-to-javascript/pizza-exercise/pizza.js @@ -0,0 +1,26 @@ +console.log("I love pizza"); + +let pizzaName = "Margherita"; +let pizzaPrice = 100; +let pizzasAmount = 5; +let takeaway = true; +let totalPrice = pizzaPrice * pizzasAmount; +let orderType; + +if (takeaway) { + orderType = "Yes"; +} else { + let orderType = "No"; +} + +console.log( + "Takeaway: " + + orderType + + " : " + + pizzasAmount + + " " + + pizzaName + + ". Total cost for the order is " + + totalPrice + + " kr." +); From 31c6d199d009c31507ed7dfd802cb1cc585d60e9 Mon Sep 17 00:00:00 2001 From: ousakka Date: Tue, 4 Nov 2025 12:27:01 +0100 Subject: [PATCH 38/62] Delete courses/foundation/intro-to-javascript/Assignment directory --- .../intro-to-javascript/Assignment/index.html | 11 ---- .../intro-to-javascript/Assignment/script.js | 55 ------------------- 2 files changed, 66 deletions(-) delete mode 100644 courses/foundation/intro-to-javascript/Assignment/index.html delete mode 100644 courses/foundation/intro-to-javascript/Assignment/script.js diff --git a/courses/foundation/intro-to-javascript/Assignment/index.html b/courses/foundation/intro-to-javascript/Assignment/index.html deleted file mode 100644 index a9f675b55..000000000 --- a/courses/foundation/intro-to-javascript/Assignment/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - Document - - - - - \ No newline at end of file diff --git a/courses/foundation/intro-to-javascript/Assignment/script.js b/courses/foundation/intro-to-javascript/Assignment/script.js deleted file mode 100644 index bcc46e4f0..000000000 --- a/courses/foundation/intro-to-javascript/Assignment/script.js +++ /dev/null @@ -1,55 +0,0 @@ -/* Age-ify (A future age calculator) */ -let yearOfBirth=1999; -let yearFuture=2045; -let age=yearFuture-yearOfBirth; -console.log("You will be " + age + " years old in " + yearFuture); - -/* Goodboy-Oldboy (A dog age calculator) */ -const dogYearOfBirth = 2017; -const dogYearFuture = 2027; -const shouldShowResultInDogYears = true; - -let dogYear = dogYearFuture - dogYearOfBirth; - -if (shouldShowResultInDogYears) { - dogYear = dogYear * 7; - console.log("Your dog will be " + dogYear + " dog years old in " + dogYearFuture); -} else { - console.log("Your dog will be " + dogYear + " human years old in " + dogYearFuture); -} - -/* Housey pricey (A house price estimator) */ -let houseHeightPeter = 10; -let houseWidthPeter = 8; -let houseDepthPeter = 10; -let houseVolumePeter = houseHeightPeter * houseWidthPeter * houseDepthPeter; -let gardenSizeInM2Peter = 100; - -let housePricePeter = houseVolumePeter * 2.5 * 1000 + gardenSizeInM2Peter * 300; -if (housePricePeter <= 2500000) { - console.log("Peter is paying too much"); -} else { - console.log("Peter is paying too little"); -} - -let houseHeightJulia = 8; -let houseWidthJulia = 5; -let houseDepthJulia = 11; -let houseVolumeJulia = houseHeightJulia * houseWidthJulia * houseDepthJulia; -let gardenSizeInM2Julia = 70; -let housePriceJulia = houseVolumeJulia * 2.5 * 1000 + gardenSizeInM2Julia * 300; -if (housePriceJulia <= 1000000) { - console.log("Julia is paying too much"); -} else { - console.log("Julia is paying too little"); -} - -/* Ez Namey (Startup name generator) */ - -let firstWords=["Easy","Smart","NextGen","Quick","Green","Tech","Bright","Future","Innovative","Dynamic"]; -let secondWords=["Solutions","Systems","Technologies","Concepts","Designs","Ideas","Ventures","Labs","Works","Studios"]; - -let startupName; -let randomIndex=Math.floor(Math.random()*10); -startupName=firstWords[randomIndex]+" "+secondWords[randomIndex]; -console.log("The starup name is "+startupName); \ No newline at end of file From 75b86530d01010af9222a8a32452731e1797dfd8 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 12 Nov 2025 11:33:53 +0100 Subject: [PATCH 39/62] Add js week2 assignment --- .../intro-to-javascript/week-2/script.js | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 courses/foundation/intro-to-javascript/week-2/script.js diff --git a/courses/foundation/intro-to-javascript/week-2/script.js b/courses/foundation/intro-to-javascript/week-2/script.js new file mode 100644 index 000000000..04dfc7851 --- /dev/null +++ b/courses/foundation/intro-to-javascript/week-2/script.js @@ -0,0 +1,147 @@ +/* Flight booking fullname function */ + +/* const firstName="chantal"; +const surName="Duval"; + +function getFullName(firstName,surName) +{ + return firstName+" "+surName; +} + +console.log(getFullName(firstName,surName)); */ + +/* Formal fullname */ + +const firstName = "Benjamin"; +const surName = "Hughes"; +const gender = "male"; +const useFormalName = true; + +function getFullName(firstName, surName, useFormalName) { + if (firstName === " " || surName === " ") { + console.log("First name or last name is empty"); + } else if (useFormalName === true && gender === "male") { + return "Lord " + firstName + " " + surName; + } else if (useFormalName === true && gender === "female") { + return "Lady " + firstName + " " + surName; + } else { + return firstName + " " + surName; + } +} + +console.log(getFullName(firstName, surName, useFormalName, gender)); + +/* Event application */ +const weekdays = [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", +]; +function getEventWeekday(daysFromToday) { + const today = new Date(); + const todayIndex = today.getDay(); + + const eventIndex = (todayIndex + daysFromToday) % 7; + + return weekdays[eventIndex]; +} + +console.log(getEventWeekday(9)); + +/* Weather wear */ + const todayTemperature = 0; +function whatToWear(todayTemperature) { + if (todayTemperature <= 0) { + return "a heavy coat, gloves, and a scarf"; + } else if (todayTemperature > 0 && todayTemperature <= 10) { + return "a jacket and warm pants"; + } else if (todayTemperature > 10 && todayTemperature <= 15) { + return "a sweater or long-sleeve shirt"; + } else { + return "shorts and a t-shirt"; + } +} + +console.log(whatToWear(todayTemperature)); + +/* Student manager */ +const class07Students = []; +function addStudentToClass(studentName) { + const length = class07Students.length; + + if (studentName === " ") { + console.log("The student name is invalid"); + } else if (studentName === "Queen") { + class07Students.push(studentName); + console.log("Welcome Queen"); + } else if (length >= 6) { + console.log("Cannot add more students to class 07"); + } else if (class07Students.includes(studentName)) { + console.log("Student" + studentName + "is already in the class"); + return; + } else { + class07Students.push(studentName); + console.log(studentName + " has been added to class 07"); + } +} + +function getNumberOfStudents() { + return "The number of students in class 07 is" + class07Students.length; +} + +addStudentToClass("Benjamin"); +addStudentToClass("Sarah"); +addStudentToClass("Thomas"); +addStudentToClass("Anna"); +addStudentToClass("Peter"); +addStudentToClass("Maria"); +addStudentToClass("Queen"); + +/* Candy helper */ + +let boughtCandyPrice = []; + +function addCandy(candyType, weight) { + if (candyType === "sweet") { + pricePerGram = 0.5; + } else if (candyType === "chocolate") { + pricePerGram = 0.7; + } else if (candyType === "toffee") { + pricePerGram = 1.1; + } else if (candyType === "chewing-gum") { + pricePerGram = 0.03; + } else { + console.log("Unknown candy type!"); + } + + const price = pricePerGram * weight; + boughtCandyPrice.push(price); +} + +addCandy("sweet", 20); +addCandy("chocolate", 10); +addCandy("toffee", 5); + +console.log(boughtCandyPrice); + +let amountToSpend = Math.random() * 100; +let totalPrice = 0; +function canBuyMore() { + for (let i = 0; i < boughtCandyPrice.length; i++) { + totalPrice += boughtCandyPrices[i]; + } + + console.log("Total spent: ", totalPrice); + + if (totalPrice < amountToSpend) { + console.log("You can buy more, so please do!"); + return true; + } else { + console.log("Enough candy for you"); + return false; + } +} From 3bb90bd9479aa23b9040065d7cdb59c6e11b31ef Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 19 Nov 2025 12:06:39 +0100 Subject: [PATCH 40/62] Add code correction after feedback --- .../intro-to-javascript/week-2/script.js | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/courses/foundation/intro-to-javascript/week-2/script.js b/courses/foundation/intro-to-javascript/week-2/script.js index 04dfc7851..bf59997b1 100644 --- a/courses/foundation/intro-to-javascript/week-2/script.js +++ b/courses/foundation/intro-to-javascript/week-2/script.js @@ -5,6 +5,12 @@ const surName="Duval"; function getFullName(firstName,surName) { + if (!firstName || firstName.trim() === " ") { + return "You did not provide first name" +} + if (!surName|| surName.trim() === " ") { + return "You did not provide surname" +} return firstName+" "+surName; } @@ -18,8 +24,10 @@ const gender = "male"; const useFormalName = true; function getFullName(firstName, surName, useFormalName) { - if (firstName === " " || surName === " ") { - console.log("First name or last name is empty"); + if (!firstName || firstName.trim() === " ") { + return "You did not provide first name"; + } else if (!surName || surName.trim() === " ") { + return "You did not provide surname"; } else if (useFormalName === true && gender === "male") { return "Lord " + firstName + " " + surName; } else if (useFormalName === true && gender === "female") { @@ -29,7 +37,7 @@ function getFullName(firstName, surName, useFormalName) { } } -console.log(getFullName(firstName, surName, useFormalName, gender)); +console.log(getFullName(firstName, surName, useFormalName, gender)); /* Event application */ const weekdays = [ @@ -50,10 +58,10 @@ function getEventWeekday(daysFromToday) { return weekdays[eventIndex]; } -console.log(getEventWeekday(9)); +console.log(getEventWeekday(9)); /* Weather wear */ - const todayTemperature = 0; +const todayTemperature = 0; function whatToWear(todayTemperature) { if (todayTemperature <= 0) { return "a heavy coat, gloves, and a scarf"; @@ -66,7 +74,7 @@ function whatToWear(todayTemperature) { } } -console.log(whatToWear(todayTemperature)); +console.log(whatToWear(todayTemperature)); /* Student manager */ const class07Students = []; From ae108d2938618d40642d8fea6a85ff79ce9ed8a0 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 19 Nov 2025 12:09:23 +0100 Subject: [PATCH 41/62] Add js week3 assignment --- .../js-week-3/CactusIO-interactive.js | 57 +++++++++++++++++++ .../js-week-3/Item-Array-Removal.js | 19 +++++++ .../js-week-3/Series-Duration-Of-My-Life.js | 32 +++++++++++ .../js-week-3/Smart-ease.js | 38 +++++++++++++ .../js-week-3/When-Will-Be-There.js | 15 +++++ 5 files changed, 161 insertions(+) create mode 100644 courses/foundation/intro-to-javascript/js-week-3/CactusIO-interactive.js create mode 100644 courses/foundation/intro-to-javascript/js-week-3/Item-Array-Removal.js create mode 100644 courses/foundation/intro-to-javascript/js-week-3/Series-Duration-Of-My-Life.js create mode 100644 courses/foundation/intro-to-javascript/js-week-3/Smart-ease.js create mode 100644 courses/foundation/intro-to-javascript/js-week-3/When-Will-Be-There.js diff --git a/courses/foundation/intro-to-javascript/js-week-3/CactusIO-interactive.js b/courses/foundation/intro-to-javascript/js-week-3/CactusIO-interactive.js new file mode 100644 index 000000000..7188c1306 --- /dev/null +++ b/courses/foundation/intro-to-javascript/js-week-3/CactusIO-interactive.js @@ -0,0 +1,57 @@ +let activities = []; +const limitTime = 60; +const options = { + weekday: "long", + year: "numeric", + month: "long", + day: "numeric", +}; +const today = new Date(); + +function addActivity(date, activity, duration) { + activities.push({ date, activity, duration }); +} + +addActivity("11/19/2025", "Youtube", 30); +addActivity("11/19/2025", "Instagram", 60); +addActivity("11/18/2025", "Instagram", 60); +console.log(activities); + +function showStatus(activities, limitTime) { + let usageTime = 0; + let activitiesNumber = 0; + for (i = 0; i < activities.length; i++) { + if (activities[i].date === today.toLocaleDateString("en-US")) { + usageTime += activities[i].duration; + activitiesNumber += 1; + } + } + + console.log( + "You have added " + + activitiesNumber + + " activities. They amount to " + + usageTime + + " min of usage" + ); + + if (usageTime > limitTime) { + console.log("You have reached your limit, no more smartphoning for you!"); + } +} + +showStatus(activities, limitTime); + +function mostUsedActivity() { + let longestDuration = 0; + let mostUsedActivity; + for (i = 0; i < activities.length; i++) { + if (longestDuration < activities[i].duration) { + longestDuration = activities[i].duration; + mostUsedActivity = activities[i].activity; + } + } + console.log("You spend so much time on " + mostUsedActivity); +} + +mostUsedActivity(); diff --git a/courses/foundation/intro-to-javascript/js-week-3/Item-Array-Removal.js b/courses/foundation/intro-to-javascript/js-week-3/Item-Array-Removal.js new file mode 100644 index 000000000..9555296a9 --- /dev/null +++ b/courses/foundation/intro-to-javascript/js-week-3/Item-Array-Removal.js @@ -0,0 +1,19 @@ +const names = [ + "Peter", + "Ahmad", + "Yana", + "kristina", + "Rasmus", + "Samuel", + "Katrine", + "Tala", +]; +const nameToRemove = "Ahmad"; + +const index = names.indexOf(nameToRemove); +if (index !== -1) { + names.splice(index, 1); +} +// Code done + +console.log(names); // ['Peter', 'Yana', 'kristina', 'Rasmus', 'Samuel', 'Katrine', 'Tala'] diff --git a/courses/foundation/intro-to-javascript/js-week-3/Series-Duration-Of-My-Life.js b/courses/foundation/intro-to-javascript/js-week-3/Series-Duration-Of-My-Life.js new file mode 100644 index 000000000..900dc1b9c --- /dev/null +++ b/courses/foundation/intro-to-javascript/js-week-3/Series-Duration-Of-My-Life.js @@ -0,0 +1,32 @@ +const seriesDurations = [ + { + title: "Game of thrones", + days: 3, + hours: 1, + minutes: 0, + }, + { + title: "Sopranos", + days: 3, + hours: 14, + minutes: 0, + }, + { + title: "The Wire", + days: 2, + hours: 12, + minutes: 0, + }, +]; + +function seriesDurationPercentage(days,hours,minutes){ + const myLifeDurationPerMinutes=80*8760*60; + const serieDurationPerMinutes=days*24+hours+minutes; + return serieDurationPerMinutes/myLifeDurationPerMinutes*100; +} + +for(i=0;i Date: Wed, 19 Nov 2025 12:10:50 +0100 Subject: [PATCH 42/62] Delete courses/foundation/intro-to-javascript/pizza-exercise directory --- .../pizza-exercise/index.html | 13 ---------- .../pizza-exercise/pizza.js | 26 ------------------- 2 files changed, 39 deletions(-) delete mode 100644 courses/foundation/intro-to-javascript/pizza-exercise/index.html delete mode 100644 courses/foundation/intro-to-javascript/pizza-exercise/pizza.js diff --git a/courses/foundation/intro-to-javascript/pizza-exercise/index.html b/courses/foundation/intro-to-javascript/pizza-exercise/index.html deleted file mode 100644 index 4f1e396eb..000000000 --- a/courses/foundation/intro-to-javascript/pizza-exercise/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - Document - - - - - - - \ No newline at end of file diff --git a/courses/foundation/intro-to-javascript/pizza-exercise/pizza.js b/courses/foundation/intro-to-javascript/pizza-exercise/pizza.js deleted file mode 100644 index cb12c203a..000000000 --- a/courses/foundation/intro-to-javascript/pizza-exercise/pizza.js +++ /dev/null @@ -1,26 +0,0 @@ -console.log("I love pizza"); - -let pizzaName = "Margherita"; -let pizzaPrice = 100; -let pizzasAmount = 5; -let takeaway = true; -let totalPrice = pizzaPrice * pizzasAmount; -let orderType; - -if (takeaway) { - orderType = "Yes"; -} else { - let orderType = "No"; -} - -console.log( - "Takeaway: " + - orderType + - " : " + - pizzasAmount + - " " + - pizzaName + - ". Total cost for the order is " + - totalPrice + - " kr." -); From 7b0059537d112983bbfe1622fad8a4599c3fc708 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Thu, 20 Nov 2025 13:03:10 +0100 Subject: [PATCH 43/62] Modify the code after feedback --- .../js-week-3/CactusIO-interactive.js | 16 ++++-------- .../js-week-3/Series-Duration-Of-My-Life.js | 25 ++++++++++++------- .../js-week-3/Smart-ease.js | 2 +- .../js-week-3/When-Will-Be-There.js | 4 +-- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/courses/foundation/intro-to-javascript/js-week-3/CactusIO-interactive.js b/courses/foundation/intro-to-javascript/js-week-3/CactusIO-interactive.js index 7188c1306..8cd01db4e 100644 --- a/courses/foundation/intro-to-javascript/js-week-3/CactusIO-interactive.js +++ b/courses/foundation/intro-to-javascript/js-week-3/CactusIO-interactive.js @@ -1,15 +1,9 @@ -let activities = []; +const activities = []; const limitTime = 60; -const options = { - weekday: "long", - year: "numeric", - month: "long", - day: "numeric", -}; -const today = new Date(); - -function addActivity(date, activity, duration) { - activities.push({ date, activity, duration }); +const today = new Date().toLocaleDateString("en-US"); + +function addActivity(today, activity, duration) { + activities.push({ today, activity, duration }); } addActivity("11/19/2025", "Youtube", 30); diff --git a/courses/foundation/intro-to-javascript/js-week-3/Series-Duration-Of-My-Life.js b/courses/foundation/intro-to-javascript/js-week-3/Series-Duration-Of-My-Life.js index 900dc1b9c..bd05ab3e3 100644 --- a/courses/foundation/intro-to-javascript/js-week-3/Series-Duration-Of-My-Life.js +++ b/courses/foundation/intro-to-javascript/js-week-3/Series-Duration-Of-My-Life.js @@ -19,14 +19,21 @@ const seriesDurations = [ }, ]; -function seriesDurationPercentage(days,hours,minutes){ - const myLifeDurationPerMinutes=80*8760*60; - const serieDurationPerMinutes=days*24+hours+minutes; - return serieDurationPerMinutes/myLifeDurationPerMinutes*100; +function seriesDurationPercentage(days, hours, minutes) { + const myLifeDurationPerMinutes = 80 * 8760 * 60; + const serieDurationPerMinutes = days * 24 + hours + minutes; + return (serieDurationPerMinutes / myLifeDurationPerMinutes) * 100; } -for(i=0;i Date: Wed, 26 Nov 2025 11:46:01 +0100 Subject: [PATCH 44/62] Add js week4 assigment --- .../intro-to-javascript/js-week-4/codeWars.js | 60 +++++++++++++++++ .../js-week-4/voiceAssistant.js | 67 +++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 courses/foundation/intro-to-javascript/js-week-4/codeWars.js create mode 100644 courses/foundation/intro-to-javascript/js-week-4/voiceAssistant.js diff --git a/courses/foundation/intro-to-javascript/js-week-4/codeWars.js b/courses/foundation/intro-to-javascript/js-week-4/codeWars.js new file mode 100644 index 000000000..d314afe75 --- /dev/null +++ b/courses/foundation/intro-to-javascript/js-week-4/codeWars.js @@ -0,0 +1,60 @@ +/* Vowel count */ +const phrase = "Oumaima Sakka"; + +function vowelCount() { + count = 0; + for (let i = 0; i < phrase.length; i++) { + if ( + phrase[i].toUpperCase() === "A" || + phrase[i].toUpperCase() === "E" || + phrase[i].toUpperCase() === "I" || + phrase[i].toUpperCase() === "O" || + phrase[i].toUpperCase() === "U" + ) { + count++; + } + } + + console.log("the number of vowels in this phrase is: " + count); +} + +vowelCount(); + +/* Square every digit */ + +const num = 765; + +function squareEveryDigit(num) { + let stringSquareString = ""; + let numToString = num.toString(); + + for (let i = 0; i < numToString.length; i++) { + stringSquareString += ( + Number(numToString[i]) * Number(numToString[i]) + ).toString(); + } + + return Number(stringSquareString); +} + +console.log(squareEveryDigit(num)); + +/* Highest and Lowest */ + +const number = "1 2 3 4 5"; + +function highAndLow(numbers) { + const arr = numbers.split(" ").map(Number); + + let highest = arr[0]; + let lowest = arr[0]; + + for (let i = 1; i < arr.length; i++) { + if (arr[i] > highest) highest = arr[i]; + if (arr[i] < lowest) lowest = arr[i]; + } + + return highest+" "+lowest; +} + console.log(highAndLow(number)); + diff --git a/courses/foundation/intro-to-javascript/js-week-4/voiceAssistant.js b/courses/foundation/intro-to-javascript/js-week-4/voiceAssistant.js new file mode 100644 index 000000000..52f20c946 --- /dev/null +++ b/courses/foundation/intro-to-javascript/js-week-4/voiceAssistant.js @@ -0,0 +1,67 @@ +const command = "Hello my name is Oumaima"; +let savedName = ""; +const toDo = []; + +function getReply(command) { + command = command.trim(); + if (command.startsWith("Hello my name is")) { + savedName = command.slice(17).trim(); + return "Nice to meet you " + savedName; + } else if ((command === "What is my name?")) { + if (savedName === "") { + return "Sorry, I don't know your name yet"; + } else return "Hello, Your name is " + savedName; + } else if ((command = "Add fishing to my todo")) { + toDo.push("fishing"); + return "fishing added to your todo list"; + } else if (command === "Add singing in the shower to my todo") { + toDo.push("singing in the shower"); + return "Singing in the shower is added to your todo list"; + } else if (command === "Remove fishing from my todo") { + toDo.pop(); + console.log("Fishing is removed from your todo list"); + } else if (command === "What is on my todo?") { + return "You have " + toDo.length + " todos"; + let toDoList = ""; + for (let i = 0; i < toDo.length; i++) { + toDoList = toDoList + " and " + toDo[i]; + } + } else if (command === "What day is it today?") { + const today = new Date(); + + const day = today.getDate(); + const year = today.getFullYear(); + + const months = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + ]; + + const monthName = months[today.getMonth()]; + return day+". of "+monthName+" "+year; + } + + else if(command.startsWith("Set a timer for")) + { + let minutes = parseInt(command.split(" ")[4]); + let ms = minutes * 60 * 1000; + + setTimeout(function () { + console.log("Timer done"); + }, ms); + } + + else return "Sorry, I don't understand the command"; +} + +console.log(getReply(command)); \ No newline at end of file From 78d20008be5c8b3f3ebf95d8b8faf3ffa8c48a21 Mon Sep 17 00:00:00 2001 From: ousakka Date: Wed, 26 Nov 2025 11:47:34 +0100 Subject: [PATCH 45/62] Delete courses/foundation/intro-to-javascript/js-week-3 directory --- .../js-week-3/CactusIO-interactive.js | 51 ------------------- .../js-week-3/Item-Array-Removal.js | 19 ------- .../js-week-3/Series-Duration-Of-My-Life.js | 39 -------------- .../js-week-3/Smart-ease.js | 38 -------------- .../js-week-3/When-Will-Be-There.js | 13 ----- 5 files changed, 160 deletions(-) delete mode 100644 courses/foundation/intro-to-javascript/js-week-3/CactusIO-interactive.js delete mode 100644 courses/foundation/intro-to-javascript/js-week-3/Item-Array-Removal.js delete mode 100644 courses/foundation/intro-to-javascript/js-week-3/Series-Duration-Of-My-Life.js delete mode 100644 courses/foundation/intro-to-javascript/js-week-3/Smart-ease.js delete mode 100644 courses/foundation/intro-to-javascript/js-week-3/When-Will-Be-There.js diff --git a/courses/foundation/intro-to-javascript/js-week-3/CactusIO-interactive.js b/courses/foundation/intro-to-javascript/js-week-3/CactusIO-interactive.js deleted file mode 100644 index 8cd01db4e..000000000 --- a/courses/foundation/intro-to-javascript/js-week-3/CactusIO-interactive.js +++ /dev/null @@ -1,51 +0,0 @@ -const activities = []; -const limitTime = 60; -const today = new Date().toLocaleDateString("en-US"); - -function addActivity(today, activity, duration) { - activities.push({ today, activity, duration }); -} - -addActivity("11/19/2025", "Youtube", 30); -addActivity("11/19/2025", "Instagram", 60); -addActivity("11/18/2025", "Instagram", 60); -console.log(activities); - -function showStatus(activities, limitTime) { - let usageTime = 0; - let activitiesNumber = 0; - for (i = 0; i < activities.length; i++) { - if (activities[i].date === today.toLocaleDateString("en-US")) { - usageTime += activities[i].duration; - activitiesNumber += 1; - } - } - - console.log( - "You have added " + - activitiesNumber + - " activities. They amount to " + - usageTime + - " min of usage" - ); - - if (usageTime > limitTime) { - console.log("You have reached your limit, no more smartphoning for you!"); - } -} - -showStatus(activities, limitTime); - -function mostUsedActivity() { - let longestDuration = 0; - let mostUsedActivity; - for (i = 0; i < activities.length; i++) { - if (longestDuration < activities[i].duration) { - longestDuration = activities[i].duration; - mostUsedActivity = activities[i].activity; - } - } - console.log("You spend so much time on " + mostUsedActivity); -} - -mostUsedActivity(); diff --git a/courses/foundation/intro-to-javascript/js-week-3/Item-Array-Removal.js b/courses/foundation/intro-to-javascript/js-week-3/Item-Array-Removal.js deleted file mode 100644 index 9555296a9..000000000 --- a/courses/foundation/intro-to-javascript/js-week-3/Item-Array-Removal.js +++ /dev/null @@ -1,19 +0,0 @@ -const names = [ - "Peter", - "Ahmad", - "Yana", - "kristina", - "Rasmus", - "Samuel", - "Katrine", - "Tala", -]; -const nameToRemove = "Ahmad"; - -const index = names.indexOf(nameToRemove); -if (index !== -1) { - names.splice(index, 1); -} -// Code done - -console.log(names); // ['Peter', 'Yana', 'kristina', 'Rasmus', 'Samuel', 'Katrine', 'Tala'] diff --git a/courses/foundation/intro-to-javascript/js-week-3/Series-Duration-Of-My-Life.js b/courses/foundation/intro-to-javascript/js-week-3/Series-Duration-Of-My-Life.js deleted file mode 100644 index bd05ab3e3..000000000 --- a/courses/foundation/intro-to-javascript/js-week-3/Series-Duration-Of-My-Life.js +++ /dev/null @@ -1,39 +0,0 @@ -const seriesDurations = [ - { - title: "Game of thrones", - days: 3, - hours: 1, - minutes: 0, - }, - { - title: "Sopranos", - days: 3, - hours: 14, - minutes: 0, - }, - { - title: "The Wire", - days: 2, - hours: 12, - minutes: 0, - }, -]; - -function seriesDurationPercentage(days, hours, minutes) { - const myLifeDurationPerMinutes = 80 * 8760 * 60; - const serieDurationPerMinutes = days * 24 + hours + minutes; - return (serieDurationPerMinutes / myLifeDurationPerMinutes) * 100; -} - -function showAllSeriesPercentage() { - for (i = 0; i < seriesDurations.length; i++) { - const seriePercentage = seriesDurationPercentage( - seriesDurations[i].days, - seriesDurations[i].hours, - seriesDurations[i].minutes - ); - console.log( - seriesDurations[i].title + " took " + seriePercentage + " of my life" - ); - } -} diff --git a/courses/foundation/intro-to-javascript/js-week-3/Smart-ease.js b/courses/foundation/intro-to-javascript/js-week-3/Smart-ease.js deleted file mode 100644 index 22c4fa59d..000000000 --- a/courses/foundation/intro-to-javascript/js-week-3/Smart-ease.js +++ /dev/null @@ -1,38 +0,0 @@ -const notes=[]; - -function saveNote(content,id) -{ - notes.push({content,id}); -} - -saveNote("Pick up groceries", 1); -saveNote("Do laundry", 2); -saveNote("Pick up groceries", 1); -saveNote("Do laundry", 2); - - -console.log(notes); - -function getNote(id) -{ - for(i=0;i Date: Wed, 26 Nov 2025 11:47:46 +0100 Subject: [PATCH 46/62] Delete courses/foundation/intro-to-javascript/week-2 directory --- .../intro-to-javascript/week-2/script.js | 155 ------------------ 1 file changed, 155 deletions(-) delete mode 100644 courses/foundation/intro-to-javascript/week-2/script.js diff --git a/courses/foundation/intro-to-javascript/week-2/script.js b/courses/foundation/intro-to-javascript/week-2/script.js deleted file mode 100644 index bf59997b1..000000000 --- a/courses/foundation/intro-to-javascript/week-2/script.js +++ /dev/null @@ -1,155 +0,0 @@ -/* Flight booking fullname function */ - -/* const firstName="chantal"; -const surName="Duval"; - -function getFullName(firstName,surName) -{ - if (!firstName || firstName.trim() === " ") { - return "You did not provide first name" -} - if (!surName|| surName.trim() === " ") { - return "You did not provide surname" -} - return firstName+" "+surName; -} - -console.log(getFullName(firstName,surName)); */ - -/* Formal fullname */ - -const firstName = "Benjamin"; -const surName = "Hughes"; -const gender = "male"; -const useFormalName = true; - -function getFullName(firstName, surName, useFormalName) { - if (!firstName || firstName.trim() === " ") { - return "You did not provide first name"; - } else if (!surName || surName.trim() === " ") { - return "You did not provide surname"; - } else if (useFormalName === true && gender === "male") { - return "Lord " + firstName + " " + surName; - } else if (useFormalName === true && gender === "female") { - return "Lady " + firstName + " " + surName; - } else { - return firstName + " " + surName; - } -} - -console.log(getFullName(firstName, surName, useFormalName, gender)); - -/* Event application */ -const weekdays = [ - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", -]; -function getEventWeekday(daysFromToday) { - const today = new Date(); - const todayIndex = today.getDay(); - - const eventIndex = (todayIndex + daysFromToday) % 7; - - return weekdays[eventIndex]; -} - -console.log(getEventWeekday(9)); - -/* Weather wear */ -const todayTemperature = 0; -function whatToWear(todayTemperature) { - if (todayTemperature <= 0) { - return "a heavy coat, gloves, and a scarf"; - } else if (todayTemperature > 0 && todayTemperature <= 10) { - return "a jacket and warm pants"; - } else if (todayTemperature > 10 && todayTemperature <= 15) { - return "a sweater or long-sleeve shirt"; - } else { - return "shorts and a t-shirt"; - } -} - -console.log(whatToWear(todayTemperature)); - -/* Student manager */ -const class07Students = []; -function addStudentToClass(studentName) { - const length = class07Students.length; - - if (studentName === " ") { - console.log("The student name is invalid"); - } else if (studentName === "Queen") { - class07Students.push(studentName); - console.log("Welcome Queen"); - } else if (length >= 6) { - console.log("Cannot add more students to class 07"); - } else if (class07Students.includes(studentName)) { - console.log("Student" + studentName + "is already in the class"); - return; - } else { - class07Students.push(studentName); - console.log(studentName + " has been added to class 07"); - } -} - -function getNumberOfStudents() { - return "The number of students in class 07 is" + class07Students.length; -} - -addStudentToClass("Benjamin"); -addStudentToClass("Sarah"); -addStudentToClass("Thomas"); -addStudentToClass("Anna"); -addStudentToClass("Peter"); -addStudentToClass("Maria"); -addStudentToClass("Queen"); - -/* Candy helper */ - -let boughtCandyPrice = []; - -function addCandy(candyType, weight) { - if (candyType === "sweet") { - pricePerGram = 0.5; - } else if (candyType === "chocolate") { - pricePerGram = 0.7; - } else if (candyType === "toffee") { - pricePerGram = 1.1; - } else if (candyType === "chewing-gum") { - pricePerGram = 0.03; - } else { - console.log("Unknown candy type!"); - } - - const price = pricePerGram * weight; - boughtCandyPrice.push(price); -} - -addCandy("sweet", 20); -addCandy("chocolate", 10); -addCandy("toffee", 5); - -console.log(boughtCandyPrice); - -let amountToSpend = Math.random() * 100; -let totalPrice = 0; -function canBuyMore() { - for (let i = 0; i < boughtCandyPrice.length; i++) { - totalPrice += boughtCandyPrices[i]; - } - - console.log("Total spent: ", totalPrice); - - if (totalPrice < amountToSpend) { - console.log("You can buy more, so please do!"); - return true; - } else { - console.log("Enough candy for you"); - return false; - } -} From 93763e595e8e33dada2a73245433161c57e6c652 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 3 Dec 2025 14:08:38 +0100 Subject: [PATCH 47/62] Add web architecture 101 assignment --- .../Web architecture 101 assignment.pdf | Bin 0 -> 261359 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 courses/foundation/web-architecture-101/Web architecture 101 assignment.pdf diff --git a/courses/foundation/web-architecture-101/Web architecture 101 assignment.pdf b/courses/foundation/web-architecture-101/Web architecture 101 assignment.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f15bebc4f4adef00b0a9685b5f84c01b1310c50b GIT binary patch literal 261359 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 gzsV|zxXdJQdf4;O}A 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 Date: Fri, 5 Dec 2025 10:46:59 +0100 Subject: [PATCH 48/62] Change the assignment from pdf to png form --- .../Adding a new recipe.png | Bin 0 -> 101604 bytes .../Editing an existing recipe.png | Bin 0 -> 104938 bytes .../Viewing a specific recipe.png | Bin 0 -> 103468 bytes .../Web architecture 101 assignment.pdf | Bin 261359 -> 0 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 courses/foundation/web-architecture-101/Adding a new recipe.png create mode 100644 courses/foundation/web-architecture-101/Editing an existing recipe.png create mode 100644 courses/foundation/web-architecture-101/Viewing a specific recipe.png delete mode 100644 courses/foundation/web-architecture-101/Web architecture 101 assignment.pdf diff --git a/courses/foundation/web-architecture-101/Adding a new recipe.png b/courses/foundation/web-architecture-101/Adding a new recipe.png new file mode 100644 index 0000000000000000000000000000000000000000..3380d4ba5d10999db1d25f01fdbcd8aa634eca52 GIT binary patch literal 101604 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 literal 0 HcmV?d00001 diff --git a/courses/foundation/web-architecture-101/Editing an existing recipe.png b/courses/foundation/web-architecture-101/Editing an existing recipe.png new file mode 100644 index 0000000000000000000000000000000000000000..5007b08373c93587d47d7d41b3d952dceba82eff GIT binary patch literal 104938 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�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

    9R*3-p4S+ikM+yZS z{MW0m%mClXxOFD!CNAJNOs612CJH({I4l88fn|rD1~dU^hzFrcIJ9Uc@UjsJgFpt* zLn7fj!T``2f(UznTaW`6g>k`QOtYS$!3pd)Ox$pOqoNwKT;b{Eg%VFt$ARWJeEgUt zGbg~e9#H@ED)i>~L;(2aE3+HdJ~8ibfpFj=7MEfLHJ>lWdPb@lb=J5hm0 zTnEzGKraG_1Tsh=_8CcrKpG45VqzuFKt~4=93XJuGF}ADKXieVEyW+eF-H#+D;gx< zDXT;D2`QXf;J67t(d3^D3QjeC)3+ygYnOfaAzV=q`Z zL8YQmXr=%n-BcKykiQnVRrvIr4)>gqtO|{&6%`d59Qs4R*o}c<3&HA%^5{wh)NMlU zC>SC-&Cz~_Z7m3U5*Q#9DxwEBK3@Tn6rgw@n_dyiAuHgC9AtS}K<)iLnwb!b52FAQ z4XJO=U}FI3H0g7^&j{2v9+-IU3z685RE7YwhhnqfBycAH2jYpvknlXDSH-ZkJ2UHn zhTJpo)(ot6$o~(4@eYlxT^8j?rhtGX)Q+XNuRw%^2(M8&IqKK^tjYysGL( z281Wz{h&En+o+@?1A!%+w6I)(9f`OUV!;U>brcZ@M|%X1QB4*ykwQ_)d1=bzj~+UT z4}ziXEyUWuu=-+2(P9Exc@$^_xHY`lv}W)hhQj(W2ZkPCb^H_=!=!&7`Kw2$GXW>5i@t7D0N~A>Yj;~*CvhtwJ(a_rqU?D-q5{N*$ZF^ry zyRR0c5;q~dB*_y_RR}#jIUfNeV4i37H-RdN34OC_VFnW_K0V=(iy?f{7fr_m|NB>5 z$S#m@iVOetu+Np5yP*ppZn)S@-^u^!RHT>^q+x(F<>WizbJJc;He_Z-$36sT_$Bvmfyze(r9|N0Ia=VS0A3k!6~&XN zmVkfV=82M|g=XFrELd$^|MQKakUUmbPc^0!&x=r_k}ry)0TT@=^2&U|`0v>aj|`s4 zNt6fXrD!hHgmj(L23!_;mlhd$0p|Z2asJ%bz>^WbF7yeoQM7k~GesmVih4pvDx!s# z+=+k}hh8u2)DR3gCnR1WBm)3+t0X2{Qqf#T+Kq4!l$^0{{^Q4w&)*6`<|!;~Ena`W1%`O#K}^GA0|jI;_5wU5v_g8=U)Y6el*AQ}sSEQc_k7&g#s z@t~>=79j+N{=?pI;pPegi9Z2iP(t7iXj<-gpdDGyf*2A87NpODB)GI@bR;4_Hq?KV zKGGG-IK$)~IqZd_pQ?d;$shtVSy9z~wk@Z;^zMNnac3;V>ik<*RmL6XAfulG0$8Ds z{{%-p>ikB@RM2_>E8hRHuue>DClNm1uwZ6?WyX3HkyRflQZ!kLy*G1mka*^ek@Qg8S)?T zPySW-A?TtTBc~$ME&kVgRRK=*#9;;&fH-^Rn0P=dU>>?&{wkOuHZzk0j(ea`EN(D~ z+g=3$FMMsJAffolmjw=bK__4L5KVsa_5c6z|38rb%VMw-5h^er3UZsBZ0UQ=r!2&3 za=3ENZ8m9J(7KzCnzg0hgJXQsRi^1(mEO<0`k^Ds&R_c$X=1990}Ks^i*czQpFaM5 zx2|hsIkmoT(T(9D$Bi#Kg%3JT4@t8{v24%rF9;?NS#fyux_Pb`3mmv86Jh+kE^s|% zTf*e`4Edx?#|`5Y0_n6D+qE9_imBh!FZmToDVje?+5Tzz`<~SAW~t^-$?cB74PDuY za`m8`oc(mW_%6=z>9B{($KmI@n(A&Pn^djoesVQEz+F!5b$Ido?s=)^*1e1C zx0ga=juK{9-DEKZx>0}qpPuAEdQr~muP!?! zA?4Qk)f#Wbol%`~lj?A~n~CSo%HQWRKqU&I!MTa9QX1l1bZJ-m$zf9j3E;&f*#x zILVonGBj8%vo2AVqXxC$7eruQ0Re@sNAh}}l z(7#ft_aH1z=aaj7`jdB=askgN)im@C>!ZKDW{w!gRa>X|jlPjF~<2HKo#D!s+UAt!)HSA-B`iLu=b+H>R@ZZhn0wMd-4z zf}OlxDML#!cT?O?s_opyig4)}&i7K;b7pm~q^w;wp7t}YzllxWw@QC$en|euTwu~B zkW@snt)W#gU2rWnu^@iQ;*5HMadiA_-huR<^S)zgs&M@JK2 z8x@MjHLc}n)%4V#C8yBLhg&5NSa32kL$_+4AjXLM!lj=SjX?`f%8H!1v~x#& z{d(;*(%zBk>C5^jsMJU9){GT+NN(69hREK#*{uGf$87trym)+$?*-)*&@_-MX`mVK1(ArRw35 zf{c8W!M={kbmVJCg4|%z)0yqhJxP5ItIr%y?J-^YdOFk>F3{Ew6uJIr+(#^*=0$%PV>WCgunf=Y?3$A>Foj*prb9v3t4f1F~m7@UAHJxU?Qg(rnf&M2cdnP%qInCd!shBzj%+jd2~8 z&2M}{+Po(#^`~5P=(2COkGz2DywX;^dm9xH}>Z8wKM#NjcpeH-tyJ95%S`RD!Mw8imiX`!} z9);y_nB*wVP$WU~cfY?YUrk$Sgt2`X$}ofQMKs!tEN6Cc3EOIXEe@#LYPZ$--#L3q76?=GA*Pv+WM}Fq{!OuMoD!)`HY9W95BhQAW#aA<6ysPKphSZ$lnc0 zzml!HR-UAB=MT%)eShLT-NN$Q3Z_=(0-oFfA?~J3b-h=aY=_Q=76v^E_sOUzmwSxw zOe)H4rOEv+A?r@d^*)~8b;sR$6Y^KtFOiIfsMt7Y<|^JFHx$y0STm$qWGz6 zK6iO5@~D_C3$3kOw>__1(bL`-is#uV%u&b;b*XC_xvqtu!%-*a8Q@o^SSCit6H13q z#uYYrMso5?fW}Cbv9Nk@{~~rkt{mGCR!&Gk;4ZQOeHfCc-tp~EdMoDXY#suPAy5*0n{>tIyiVMBV))*`yePq5VhgTJBG_0&u z^qFK!CSG2*>LSU+`~~y`#{24-XT7I2J>&^KWK)*p&V=fET^%-^7clldW*ax3<;TkY zO`4iP7Z4%Gb})LE9p6Vkw9iV4$WkHx=auoi5~}IMOT-y>mL}3y_Tx1of_L&_G(2?3 zL{uchVruUwJipG?`M@>u)$Coow%veq>z!L*mla3p6+>J2t<|Mf^< zsVB(Bq4Qwzg@5UQ^3Lg?(1#2qa;B3^w2?zRx0bvMma=s_xwORlv-}@@AO`anytsT~ zn`52Ek7+bJ>f4ulD0BDM=I`H$o~O$u797)P@``eu3F%MsdYh|}H6(9Rd{OiBn;;EX zTs4cAOnI|s4Cl8$=!9DK2#VIUDMwJV(RvKv1>^>C>f{D;&fe#ds)H0Fn|Qn>pRaw2 zD#JDHqU(JR+QR~t<0-cA;~fdJxNUUK65DeJI1>Ej?IG8ix@XkEKCRAkGwK|fjkAd0 zM%LDn*cm2&r8CF6J6S5Bkq>UQwNCnU<2F92oY&T0V#qKendzyWsA<1?Yqdt<*65jN zuA8m)0$6qwa?_NY*#X_;(^9|XQn#q=GU-VI8ov&?uNvPwDJ;*fSIx9ZFwVqvaJBu=)9LDECEcZx<(Sery^DFtKf=L4aMSUj_vzFK%CmzWXU`8dnSG!3?Wiih zQnaoSLdw?^EbVkUsr2Iwv;Is9{{b1*aH;ovU4pmqM|IwZ)+_IhMthj%xpn_g%sQ`1 zOcjCog{zAHn(Y$lg}9pzVHqFvQ@e+AJ?~(NR;Mlgu4le1`-s`y)MMPvoQGEZ3-9B5 zv$^6kr+=2;h?T!)V4!I=C8$Z97Tg+3CNHd$v9c#FRWttEh~n(P6TCYilxD5T;?XH# zyiWJ~Gt+zrjQt~|*o#~x&A9_Kf;Pw{V>aciCmM2nA8E!N4cK}OyKj~-4 zjaXWIgFy+iDZ$BTVh)Z=WO*tAt4=#!zQ$EIEo_&VvEpt{EM|O=d+qbEv6Dn3ASvR7 zwG6x56eCuZ(q$o|%3HU%Y_H)4A8tP&Zj_v4x;u&gQkyS6D{1>8Ck{8n{grh1Oe_BUaJzi(Y$ z2px0w0C&Lg1L4L_t!N*Hb2lmNRJc!*AJbpSA-5svdKC0cfWK5;F8Rsq-9KrKM7f3m z5eC?T7QKrHhef3g1MTtt`ggQFKeNmxM;;81zH`iGs@|PXPf#_XG^ znzzQMw@E7+@x**h3nT%V_g?K3`RextMUZdjJ`B}dC@gtAocSyCBN>YVU$OqBBzL_j zn_@ZFn#rU`TH#suIczHv!vsmr?9S??Fh{ETD8y+Eg#N_bU-#qvoVPhK7eDdRBfQP_ zQBiY4aAJv^-kgXaPmK`q-n&Dy$G2Tg{cv%~wsStWNp4Ay9A4uYx0z(8CFp0fpS|lp z(KFDV7NgJh-TU*ksh4^w%0E(;y2v{ljQO~U!g*u1Sy%V>jpZm-iu>MJ&TN`0dTG3A z{$j88W0<9c2ln{AH+~-{yu*sBB_-s3LkTu+YYq3i{?o4?GoU1q$O(7}ZcB!Vc`K93{ZUv@ zw+l%3dL+1>XpEOiM#UjYY*R5~)+16yT+U&54HYiW2c+)-FHlJ8W%L5Vs6OB1oeLm59p zxv9{_VJ!cyzx0Je;$<3+VigmvbyJhKe8?Owb19f?(=+!jR8lloV(5F=zRb$g4ja2U zKJlqAKZW_Izfy5QoL=CP9NuuFa$0Jx{%>k;u`#~4HEc7*F2vbmM-xwH?5$MU{%(*@ z+GoD+f9#~d;s2A4(ob$tVYAnm;_BSPwB98{CVykY*WGe`lEoyl!(C^YiYB)Dlg!%o zSSGfHwSj|M*2M8*ahZ}CD`OX+TwI7_E*Nx)hU5Lqph77|hNHXHlUk(!ZMyT?Mp@mp zX}5Q#>qrvfd>Up%Bpd$j>>sBMEe^{+?NY9Mv^{0B6(U2SC1>Ojx6?fJ^l!uTeYJq9 zuDg#1v^-DQjTA!a_O)!h;__r_pK9xzOcLBZ+_T+>Sbrwg^gnWVeq3I?*js$laDUoP z^VVPHIoEj}~iST`#?08%nbW-qAVh?8rf4>~=LQ&POy%MDk|X!7p9aCvh&E z%eP%w1?)K%;+~}qZo!*YT=;8boVAb`^0!l=!|$eH;%}wCftMs#a=62uMF)(UjORqHw9?c1Wn#)|u1_ zPE-lzXzK(1e&`G{Sl2%r#N3m982EX=cT zXZ=pw%JNZ-DqZ^Yvgfxk=b>bX+GV0|pEvYtGL5+c`bGE`!Rs8y@56pP9rrkr0-czOOilpUGU-YR_5_cHcQ~O< z+5DkSCHIHSo6MmiMpRd<|>zr}sWMc`h-Qk6e z^$IqY&T5o==h+)~iccrTb&c)Rvi!V2U*Sp@SfX;HXsZ-11lrZ+BeoTfG^&U-QIdUn zc#NlYe}ptcE$`I%Q*k_2Yn~}du`IT!SM4J)-qyalP4%|>Zu4>yExInd>3FUY&FadQOt=T)+|T*9e4n}vMKPx}+AlqFEINJZ%VlDs*QM9rX0I~IJeUa2 zN|C(q&VqQZvgb_w%z~nEn~U|GHmVYgOIA0>eYKNI(skA6keQ$6 zuGl^7V)qBIWWotz=D+5k)DTJE{5ET! z+nDP<_Lb8q+eP zit}vx$Lk*Y_Vxll1_?flYozUOA~3ORQtkhy&0Y<8yH`B!a5KzeG72u1uc@tEC$jEH zxfVA<**(|8rOTK$HiO zKSSljU*bsfBdDe)Y_*_yM|R-N$Mspq#xXzI;vcW1nyn2!%hr-^J7gPag*ib95r$5)Zmj$n z3MS3Zc;g&ag}5o>eC}+%SdH=FKesIHzhS=b#9Kj-Sd1Ti$^k#Cdu~GD943al#l2~a z5*g0BxwP37hxzU-m0K;dJMZqBjE{0^X?#$XUA)@8>7$v|tuZS0i0GBrXT0Dvk?d^l zydW)&d=z&(NbolVTaCDI?W4pMR{Q5n<)mtw~XNeY?lQxF?ye|@o+Gq(fnSYio&qHzho;d;Vc` zQhHEbElFgIfJS-Q*Ote>SPB;ky}!*5G~wRK!L7TA*;jVwO7QWa1R2I#xo+=yCzI|| zp2P34HmFJ`UYw~~y;-%EwYDTB)q4LFImqMR_de`QVSkv~iGRh;qr*%dU(%!RsMiz& zBY@9#5tjDHb)v7&V+kV)0{kZH`41-`u<7sR$4_JZuzpTq?Wsusk#*b!8lb@zsvTST_on0{>wjk=*Bn? z300`dUjBEZ^Gm;Ie!fOEZ%uv1}(@;j_k{$mRM-xQbBV zGxtCVPs*s^&!mRdk;wv`W6~zuitwqT!7|T>L`V94L~WH6yJ9%+?yljz;i-vWIx9NS z(00mDc28`E$c-jhtjFw6mgC>NZOh4VLUl=O(#eVCFF83;5sh|!giHLhz$A|Tk4HiqMC3RMv@DJS(*8dl4BtDeehzR+gtx$vL$_~PIFsqDnPY1H>-s9ek6G;XJ8wAL4VBxI9eF@kNvKk}L7IL3sJ1*{-?6@!OJ9sz zLcQfoo4$zekM)jphc65YjEH=tboFd1-v< zy*ZVl=;L42Loph)i#Hv=i^;+8MM~xJM261mdNy-hZv*d)71uv$t2Lu87Y<2eM&Nkw z>$VQQNJSrM*B`vYj4S8!*Xps2F=M{EjGkw+p2hgj_qk=aryOpT90eG)Y-J5rl9(7! zMa+w{2nf;nB;Ld5tl9ipL61AJ9mKm3G43PslRt?P}AU#)IWqJXfwZ`bKLDuUp@PVe)!~eFj6J zkznaL(Mh^Dt^4_-6TvtU4{G`Ch_oG4FMiOu?fS8)#O?eku`C^nd6tXY+b{oi=06c` zZx-fCxi^&~uD$~sQd*Vgx&WT#D@wNy2lNX=-Z(CVcbjg+{Jp%yr=NQ6oOy@oTl<_D zM-eqqKf(ivjrte0vm$KZaW>(Mf-=G#o~jQQN=)Xi$2D)%|AF}E)sld;Iq2CMa#G~JiXGd1PRJfy1e z9Hf6#np`)X^TN?$kv07AP$;fjKh^R%si-&o&*dK`)?1Mc9(UWC-p3wKbhYHZ9L>e9 zPO8BS>XIJQX|+wo{d_&vg>QUy`P@P{p?vI%?{a6pmfSphX)Cz-!|f2xU+?L&M-L4L zRq*)J<+hSjF1mDU8kT#W!_`r5e6d*FxMy+2!jgI3RPlfuv@Tj#JQi8c8HYFJUb6BJ zi1*tXy}M$!{iV-+PAJbNFexVNW@%g(MUGtPUw^f0nAJMOc8>GJ(dzUs@Myjo-H{X;`fBN@z` zJ)f{q^U#*c2h?@n@2@TkjHc}m<%&D+a`V&cg(;i+G+SDV6xq;hP)}=q$Eju{xK>jx zVSAWIVf=Sh`d&L-kc094fa<|pOys-!QUvSmvKaZLKlgJ?rfg|_iEw!9kJeu}y3aCi z9N6MV4u~}9r1WyV`Cwl6ba1?CW$9~1-*$&=U#Ts|$lND_RZH1xHR@QH=Vc%N*=F+< z@eo|A%D?FGOZmX#FKbEra^Shq_U6EAe^)p;7Xr&fsMn4pcO1K9{=Ohz&1xPPdN8%h z`NKuNCJH;c>=Vbx;xW%wa#i>`?(x@x?edAz*CTFKqrGM7ntUVDn<|1eTTGFKmu(MZ zB@ti?UHSGF{Cy zJ31~-XVKGoZ(g1|{pyMIXps45^%eX6^SX!4SF>LG_-|t^Cvd<%(?$Ib%n#xhZUJ_Pk1Mn3gw%e|e;^ZM*Qt3O+h zq-UONJQxXIUse5{Nwdq{P9~GbYTk9H@f+<_&4kj204 zNF40)C=P^_tdpsh%zoU{b>sAEd@+CaMQ&@=M$n)BZ|Z&A7uFc>-NGxjQd{l!y?uK5 z3a@VC&%E4=hh@BlX?{5xd#;qP845y8o7$_He_v(72ypcFc%{UrTicnp=xMsNu~lYTkL6H? zRxF2VWd-Qu3N%azEA&LSRk0rZ=~vq6pYfr@NY(HNO-$h<&cqjru1U*DvM%l0QS8UP zv3u?DN)d@DTMhAi#NBvK?(Sol_}Tc5O;ige`NI&kWAj5fsF zL-gyR#5ix80V~ z*v+gU`D9QGU_UOE>cgC}_p#Nu`gn`+j-8*MIn+9F?HK0kPlPpEh3C8;xy=w}6tF*1 z&hkJ3cRYK8Dk+TI#cPN`FvFZhv%TIpYf)OEkcK4zx1Ix4Ud|ZI;l_}(XZlPFqx#xY4$ICRh1H|Z>!;=+bF9v2XtiC6 zCE+nX8CxjB_2rA5PD>=FybRkv)}?#h1vga+TQ4^ebgi~fS{s?pb0m6}DjHT)_!eI7{rs51o+VdYurg3%&@H(1 z1x4k(k9d#PtZ)8jJ54Wj4xmw#sZ|1Z`yjzA(skw)TiR{ikh;lt1r#Hu^o>Kzggy1Y z!`=h*xh>hW{STy(WV{FLMiQ_aY?d=l6hxXYp7V0~mo3v#FbhwOw>M7ia7dhy=)Le8 zF9)Y4D4En-7RSO++ShM3#^gM8U{m*v5i9>c-V7oRIPZ+41I?*!o9Mh3rPbQv_YPPX z8Wi`LxRm#vdW=$w-Z^{k)yE|dospz4@gwz1F^}``vPlAMW-KQ{1T99swy;={^#!O1|(BQ1o#KxU>)I-EtRp+wzC|p@pX@v47 zzSTZb`a~$NJ2}U>!+AmMoKC@7KZElUtSOa5ACUGjVG0+vAPE7gc|q)b-XR zRGcH~#5~$f+$XQ^S_pT@J{>CiCBCLk@QEHFEWtlgQ>N2rN;?dK$Uj+MhoY*7j zkEp(|$&qLaW3+cAVP051$Ioz#+o>#3hSPmTS41|py8`oqM_XoA;f$U9;j)pkie{9@ zM?U9>m)|2K{n9hd{kn88F)&`WE6ZQidOlAVoNd}QKg~1*_+J7|bDt+Xami<7FK&%% z6!Oo-Kl1ptOVlX1-Z$Gcz7g$19J?6&m3C7j_obiJ(&oWRYs)`MY-qmcH%l=O(QRDW z6}p%E1`kPGXE<**Pt{#6;I3QxMdYSMwCT~h_NTW}Z+4OQod@3n7vqyQ>fc zCk@h0KfmERLsyN5XeiE4gL3y9v5dw&daZ|l z%;h}`2zg||c))hWI&mZIF?I3k|+rJwthTCts~!(QR$$>l=#g z|M!3XKmXA)BK}TGec_kki%u!B)i1?x7OR%4WMfL4395~W18@#symeriTCU-tAgadG z%IaEu;O6i$O8NuQ2w67wj?D;l(XJ~_^&4;E%L>29MK$^>>M{)pi`=$vSKj$`_Iui2 z_FDx{v~+kS(s_p76+F9Tc^21-C@ybLNakowP0P9CI3n;}jo{w#LXxX4xz1qIa{sVi z`K7DT7@?4;f~)xs)FRn+KhqJ-O zBj`TikagLDi(UHgLc7VcBPnl&eL>O7L=AOZ9kOz2!`FtW4p-|p@jL}97_q+F`cq1{ z5et6MxaR)m_zADf$W-{VvzcSNHjfke@1Idr8^9UW~{Z%+H5C!42;wJHGJKp zXH-NMY<|lRk8yO)N4)5)n=}nhV}3Wc!Blj3y|zl+v-23&Flq>^{-0+;#%OZ|Y&q z?;~m^e^N{~XhE=Nb08Z zRAlDU3+)#Lf(^H@tLc7`joaav58uTx-}RU+bohl*k7=B&>{rA`6M87XY@)?!+rI%?jNHpg{@;4KiSL%Vsls4wnHqN3rPQv zW{$UL3ry~(#m;?pv>9Z#jjX|lupGCMOL4{@6tz=42*7p5IqP;-SyI&e*U{OZQn%FZ zJ8_wkiP}j9s8&r^Gk^T^w%nXq`C3EnJNmxL`?CC6pMPzL-5iTjd;Q!|`N5ZYndcL~ zY#KuUeXN!7{`9ZKOppDt{KjdI!u$QzR_}ky4~;9Laxz(0JaAvhpHS=BtN0jR^Sn}) z_H*-woZC8wpx~B7_QQd>tD!d;{n~n7!S6Um6uT6D_ z29bv*j=Op7;DuAm5crKQhTPnwOT~zOvBsjP9&$BunuztS{R+Xzc|k06HE1wN{m;)C zVTFQObCdn43WL{8`gq#LS7f_YHohIqJ50s-(9ry}f{QpFahDD7(tFL^-KnUH{VpZN zI`@`asp~nu>93n<7knfY-44}78rGtxDts8S3t&q=k6L7@`;udx! zk-Q4!;qcO-c+3G+yWKIJQNZC&wu5Y|ticDa4webn4nDNUfm>Tw<~2eJE!5SYOfaqI zU+F1qy>@+iAHS)R;?#5!cAs;>#DmoD1H%{ZwHvl3ZDUjN-wjF%(n<9(%2;h*TcQ`& zUS(2AwOQq_-u323j$QC!n_A$C;bFYB4HbJ&WtS4xpDt0`zt)UlqIA7(z*5&^j5(&q zE0V-7a6I;lq$5|2qtB9_ZIUbvBf(r0X8jS-Xx<^2m`X&_nv>;d)Q;zd2?6bz;Ju^7 z@Hg{kbSrH6Nb}AM@KWc|e@)EzQNY(dmA`<2-`-@_-xc#v@u8E;yr=4s3Gp5gb>Q*7 z3*S+Z)CVTA=AO2ucb$HMCSw=FUzgBT@Q?5e={=3>i{F`Ckk)Xe@zCaNOx$^pv7AW$ z?t;rSqqs-ZPooh(iW|Kbj`TITus_|jYj8cL33;}B?rXvE>t|UFYx!|h?;6ae8Lgb6 zBn(GBW8LU&NZ)b9D0<;y+Bv03eQ8WO{K%7L>&TLAEat$7@`=)}7o`k?5Qd-3OJBAM zfmF`$#wqw){V#Uhb}npq%o-8U?BC@beig{vL1F&w>i3@0I}7!-e`HOl*;_}R-tNzk z()AsuJQ^w>zmbqv`|JT5&TR5<=x(g+*SAO57Z;AJ8wX?^Uhe*U?u0j=kbCu@*rTlI z0SSAJEZ!lmS8#{VP!vzXQcI0*)eqU`m$iNuEe=!<5#fHlLrPqbF%gfL~>d~jt-T}}2{%epSthvN^l$)+vpys1%v>W=-O;Bmj`OR*ZP zHxWjG84t)zY`x=u$sfg6=^pJ;6EIvlHEDGeI_1%0bN5-t4?716>%3r<=2U-NW84p3 zgV64Bm=9Ln^uHMZ9@ zcTeFubn7l%y8fb7U@%xqM(|}%=uF;{8b@tl2VeR9FJbQzI5Pb;wA?=Z57yo>x{|kB z_f9&t?T&5RHaoW2v5k(=v2EMViq)~zvF)7ofA-$b-tQRi8RvXB^>M8=YE{jecg-8W z`?|JE_$IO??lrkvGc!P_I5PW0wg33~1A71?zOc2R@APpC202qT*2u^>?^fUCqkxr* z;2k^}1Okv_?j8Afh5uKPTxg|hh{&1lNr%LrQIZq&1OS$6+kkr+Y#hqpSdSm-lBch8cEV|xlgLEEewwPwi#S6UeBEs`- zj!$Bd`4QDCt=)5CsPgKBeqKyP5x%RHE^8eO0XhxO5{&6YO3bkpt)4EG*JssmQ`^kI=Le{>gGk#d?B~| z#5&nq&LWxeJuX5At`m)6V7U(WrXF6+9}r;!gpwl>L`07%c;8|`;Pa@Zz5S$Y4KAqE0st;3SZGpYbZ*B;BZ(obB8|F*VK@ztgWHf6Kt8mXC2lImlI zj@epI=*%}RW$LoyO=pOx%xLt^D&@afsWX3~yy|nRh13ydf{X@MH z*F@1)P z$Ffk@r}noV$q#Gi(I5MZU$<=;y!*o{Ac^Kz-ivI$dtaHhxT`8Db+PqvqD!Y|Sw>CFHvWe>D)_1=n5- z;1~GF0Pc#FFQ2jS{YEXY2h()7^NYr3@Bu zP;XQxvnJ$?&Dy6@heV&h>21+nu2@37S)-j6EeQ6akE~V8?FXFR#<7!6T_;yr(gb9n z9<|ctt2HDs5m)lchAm2o4(R!%tv&tbqVAQ-RzEY<3LVH_*KtP_@YNQe{~o8&j%=G_ zt=aquN{Y3VK6C$+ToNk=SM zb60~AGTtwmCA^+&&k{7t?6CvSNlbl4K42V3NOje#R$XD;lfe@c9N6 za{xFlssFO&vBq;q;fn6<+7&Ivo>W9@HnT2cTcVt$q55&we!{24g*Ts-K5?{(fxa$h z(hys8$=7?P5e$38k%gRU&)4z@%L#8SrmP+}*m{&~t&_4H#pLi$Bl5LtU|aIltUA)3 z`T5$fBOz}&<2)Bds8+Uqm#LO*+F7MCoK?#EMbNpZG}}G}K7xY>-K@#ss6?7j;WgOK zKl2K%4H1agKiGbgI9JCjY0g>@n|PWB!>0vfkXdLlu4z}U5&m;N!FYz%Nt<#>siV>1 zx9d#O6L+9Fhh~?pqVNa0Kb7@4rj!k5ocnreMz4%&JB&+c#w_7(DgA=l(#iCy}CyiyGk!$c_#;? z16LxG;xbd_nf!E#)swS@&JthLb=Ze@zOKt&q&>~H{xqpVTo-=4ED)xT9u|xS1S-qX zBl=^;IsBNppsc~GHCG+96ZI`~@kkcbNs>azu){wsEE=p7#L|bDKFUGDQ&O)`C}Mcf zacfea_cn}PbyHC=o-&~^b7?pj{56BwG-?$9F2ydthE#F+YLUQ*>B(|8mj z0au)q++Ta)vDD$;sd9=^PDYa%Qjug1r@2x<;j5&W({HekE*jz*$ z0K^-M=anDDEHHViffYc*M>B<@L9h8pdIr`^qxqBu7nv-WWtt$mtT}raS6V*F!K8+mn5Pc!?NY`vjxhFC+r$zada}J z_I{B@o@GC#<~CT@}7zdw1=Oy}@N0ks_VHrm;AdyhhPa`u_O;s&4XXe`VXB?d(Ke{?bGZbTXV~bRm8JI$+M4J9V;J z6l#J&5VxG8d>5bOE(!irVNtpKOY$-afxQuovNn2ehRR{Nn$Nxgo+Pg_D)`I9q6xU! zGc?dnZW;$S7V8KGCekM=0MX)*e~`!N&dwkx>fSvF)+V_1-2P;ih7E3)iA zq6Fw+N;*lw)IPJ$r{8>7i}*KSi%VtG!rXhKC0i;4zU!YwYY!(*0>(@%fb8Eu1@Kn( zup_Urj&{-%;$+9DOQ6CXK3>ghN$Z_lLJ;m}tw0ZQB<3N&_=0u%x9{~RPcbbw$LF3W zzkHRH<|1=3f{Mr-)0upox2% z@YK#y;DPGqfi^ls02kmdHSXsWo$VkKWF$FJTk>6!4&7Pa z7KQ>iYpqctH-CuC`R<7M^frRffA1hE)A-A8AmFvpSqciFv$Fcb!7~~7jx|}Ywf*ey zr*TTH8o$=c&qOn-j-;%}!txaS zKqxCwqK!QFy07(*p3y&oBq9T#=P^nyPBcL=Sfw*?0wZi0Bhgfl?Vu0{kWj#%VnLS3+4No)H4v8j6?j4<;m z3=PZj!6w;x=}@qpNw5pY4-0!AP|bf%@1+#l$eJ~NrVhvK?c4du@beC&*}^x<88Y9q z^U|YnJM;J$PG}L{g!2l}VRf~e4(UY(U;s2d8Hjs)lpJ$kd0=26%n7N2K)WFppMr;i z;h#eYnLKJZN<$Yw&snFiEE#0*C)?v~_N&jRy)8A?5p(`Mj0a9?sVd!V8pf2+TkQDoB{?(1?mN3oq&We7b<( zy899g3Z@6w2KE*4tpP$o4N(`s9u#XA&n%b!Z zP(?2Bx@ip5{A}yZvJl$p_EEA6mkA%rhqTs$1x$mw1v%}x^}4FC<3&xqEgP+Q&*TLP z;M7l)?tW+vD)(9`PV(w|&ZI^$U>waiA?uzE^gh#LV5(JY^2OTqHoVBfhFEE8%C%>V zh92q@-Ukt!)AN!RqfJ&AQ0Hb6D?2|CK@A4i1~2qn1S$*HcoBOgCX@?QS!+rhI*IJ! zM_6q6;5l?ZP;7ZzsCQkPa=q)(Nf;qsI=U-?FcE+3k*6sx{&eKue73jjUtP3SbS3R* z@Babv?&T9x43q?I|7$Vk;o@8`UaegtwB)MWs^z4T>WTJ)0t`|ZnHV}i-=Tx89Mt{t zAVrq|b92X>kGejCmzsWSoRpT z$n-7g5$sWi#-9iFN<=S^q~`dvx(_-bnVGEM&-s95S=nW?m!EVv+f(;De+wLML&CwF z?z}pNPZuCYC%bY}d!>cLhkjh`-)(xi%j$S??V!bUN!_Nm6`)8V z`2({W_4W65-9t2CO?Hm3cco@*W$UKYl2x-x@;f>9I?+9ogP*%2<+9B1#9|0#79amk zUuIj5JxN87+;6pBSb@~C_P4m;z5Zok>+Q$UvdI4&%xE8O2d=jM{ zH{653b8|I%eeYRMMiL3ID>P5(tTq;q4E&r`43xUw6cVfl5;1n^p?X_bnrZMJ=dX zdoSYZH3s+U;U}z|K90xuApFLMXR?5}zlq^}h3rCfYar)YDDWE?HYdQdj&MFz=`y`Y zfG4welhrmVN2@!@>l1vVwCv-f<-3z!U;xK1g$_M3y3&SZIQ`T%#X5aHWVrEHUyN}u z!f3>506(`I^w|RLY}U{(bb@o9dq7(0$F7>k=1BY}R147`P{?j(M2>z-ygl&EgzD$b zdsoRWKR|?H>K^kQ>7;}fPSqNh zU5;mJ`yz52Ox`P4DRgN2S`c_b*GVj9AcuadA&*9j%XN)Gq_M=8fXT9Pd47lB=|nsh zJhXaF<%0LO6@(;!rvNjRMNlW==(j`JD;i9w?#1f)9ElJxqlR>|ioxnppnDjnm9~?w zP^@g1PdOCurJSo7C$2_VBW|;U&T^5gdw4pdcoB~KT?{r?`~dgd0jy+w8(4xm12kFlE%jd!7 zdt%a~(LG7cds2p-EOrq z6x4727eDB}46zSK2t}>6VG-?~VO2GYMQ|1n6kn-9p&ebC!t=T#hMrBcdVhA_d*^`) zIffK=gIo-Y4N>L-lGneTcJpKU`Z^e2jOIKa12(ymy>M@O<-}@9Xs=rVaM*A9vJ-{q zq+C1$`m=k+#(ar02K{!Gl=Lxd{yLxIS$N7s1y=`D_2|j}eH3 zHlaaX)!SNa1WIanqkk`u4M{3WenlYFynS6=CW2X{{1io`vJAt8b0=ulq5TQvZ4&9y0L|R`W1{%D%_J|QzAS9A9C=~m z^KbAMcc7T>ULfwe-E@d5h_DV_0xd+R+qzM^jB)*OopHO*Te(a<%TzG#9OS2Y=+C&~|GY`=fE5lpE*~?|;wHL5O1Jd}JwbsJGn#+X$HV&NTdL}4 z3^0!NIl{wlv5Ery5Rv6KpsTKyzPD;_k*3|Ky&_vv$0=$Ne$w0m1O)I6$$22`e}CF_ z8HYL7;zPaiamMDbgUT}~hg69mAy6*#GJYTD=koJG`VQz0>Q7i!zRIrm_@n8R>sk>Q zkL+(b!vKI9JpBHsMKiC0Xf&v)T2G_?E6-k0`*&&(sODpBA5ao6Cbzxu`Y+`bNr9QS zPhB&J(N`;Wt}FGKLuaxjr%HT4Hsi1YIUGtq zybBWbjib+TpVMdUNd5lBhxZaQ_f1&!U&C&2I!%nE7s@+DPoyUBai17<&yBxh7=x>G z>#>mqKuu;5rP=9HR>{xbY9rRYPrb0M@z06rsJ*wvvp^H|jbdR1x;JH^Az} z%I)TNYK@3gDXk0w8b}l8hQHd&zgTjWRh)A4{jD**F;T=w?;P)bXObwaA%E0A&1C(s`}Z%P}*2Y!x+1r@jI!O8W4-kev<3kuKDdmc<$ z?x=3kiI!D^=aAhb+0Wk8a%mDUM` z>zwA3rL>kzb>JBf2%`hM0gsmXr@PZ}OFCrURTD%7kA6|3(*cYLH$X)kN{ zU-L%AzQCdP?b1VWWdr7$1H*h1aK=>$ft&G4jx0PR-C9(>7O}AXvw*o@2MA2rPWh4Y zHfR{(L(Bz}fTi4qq&9)Spjvdfy|x%_ z1bg;$QNgJtqZPL9q^6yY6J0MIdN;$k;FfrFkgzZ_%EEZGoi(BG$6kxKo=|Tqw*3AC zj`d_C{Zzn0vw%!B;$J_P4CgaW1q#^yk0StBq7po# z>#XkKU!SgmIrPow2+4qU5Ws&x&Drf{&iit_6xK?*ldd zN@xNo|M=gBlu*w9vroP0&wNEAc|Y_Y(Emv3BxHEnyB@ab zX0jHCy-#_Qn=2x*U&c8G0r4uT@*(Pel^bpe|63W&efmtA7!7@&+4?2m83c&S@}QS)1YG^*D0ofG{-rYN_1H6c=uNTq# zQ&ybCB-F~)r>CjG8G^;yD9KRJ9{~S;3$V^Y*F2&wKE9pJJo1iiZcy3%T8!3U07B#Y zTkQ!gQBQ33%}R9UC77Nzn}AmfbxzqytoCR3_1`R{3g&Hf!Kb~RKAUa{Bk{jrpI3On zqiVFkY5VOE0l3l@yMe=JxY>Wg1+-Civ)u~$z+z+4y7Wo=H(K!HkytY|!b-7aU}Bqc zfXj4=^lX8{b`3uc4r#(D4xOHX+;*VEt~CBfNm5n5=w1`$-09z|1TC&*kJs3@qFvt#--Lx^csF9; zbX_|Dnt17e|LRK0aV0No?#A(tuyS^CU~l3Rsn;X+J*-14CFRJTS9?9FJ^4l7q5PXu z{2D)EOVKj{N|02v%>^#CRoH0u29SQR(E=S^p))^2yUmkn4_7_f^?* z%=u-zigl7FveJ}9HM$*(qK^1;@$B~ag>zxoj~OVmYUJUn3lGclg~h8tG1x=4s@&o#0=Kiq%{SsdAg}07L2M|t$hKG{{G@P*3 zc}%(CPt-|vm$>d0urTH%p+@Bb<=*!&1dXO%t5@7LDqgG(g{*mow{yKto3Z_)8L-mkzO%AE+;G$G=m1|i0>Xk{37 z-)0;dFQb>@a!0B`08<9!Go9eFI8u2bJenBv^bFM=MA&%LPSi6F2l01u2r73P(U6-t2;Fr9gSQp?Cl}wGR%<{9KJ;i}eQ$(+0xuWe`G{d4vYDAH ztwj8y55!{)HeeSLvDP4FC8`D5@))#UiLsN_rojGFfAY->GDYm7uil0CnX?+sBI=Q5 zc$xed$hhEEZGLi|XR?V+4Vd8AlmC+d_{+bCkY`Eh8BouVY<36?gIVz+ZCyqnZ0c*B z@z&w)qKmZ9jhYcSgtOPz>kVIo+r*+p0G+*tOVKY88+B-u_B?&PeJ-_yzpfc*K_d|NVbr0OQDf`%c|AXn6*#H_jVsl z^J#-$$8AY%e-}XHeQbVDs|&4O)Fk%QW|_-*?6i|YQP&FsFJ@Tl<_~Vwb_Y@^%fdBG zRd~Uru#Zaub53z2A;FF#xLnQ_k9_@X#Tm>hnTeh3jJqo}DG{3H2h zz#1ipD?Qqr?*U@v!4<%wHU{AKaHfUH3pV4ejo;UTIFM@-X`?J#&%ppia@8FTk~w}d z91je}UuS0bIoPTg?g%zJJ8(#kfhDo)&t9~9Xe=#RbE1GnO^9<04J?|hZ2bK!Pg5j;kJES-qQrC?s;m} z`yox^V;UsZ~87nm4593f@J@ zX2ds#pl}c?Ju5HmkGAphF)_r`Bnygax2w9`nB2u5-a7%Uay=W5BBK^CK6*0F41fJ6 z=rSM2ZNA=^+AV~q4(8Ve(5id~+sCHzs*{bIzDFiF#+VKHtg(iL)ojUb%KR}bxG^zy zu~~+^;PQZET-S@YSVIDDL#Bdpjq-G)T7cNlMmA6~aUg1uEcDhVtm`kXXpQ6~!kTbu@9e2=P=u90sOMGJ7%l}>3&L^Z zUaYM&+k8QG$$(hG23(FlY7U+GqpY4vy2m!G)2Q)K5G9g#p?c?0EEW3#_2Mrt-f{n) z-a2VZNBSu4DIr2PS+@qsE+Jp3c8_Ew?midlHzm5V0r({&EPj(-=NRZ}TjvCxV`-$a z$`X2HZ=Zf_s-wZv1RYVj4{l(<=;^%&VK4E71nNJkLBn>qyrhV4Dkd=ChJ?+^yA-(_ zqAfY2P*drx`rQg(x>{hI1r>eL6hd(n#SEn6#E4)MqK<02eZyd|<6a~~*>t$9llZ)R z`e9I9^fj7oW*xt9d+-}M5*DckBU_ca`yf|;NdLi>y3BgE^am~E3zsVS3ajJn>p+XI zKW<%yKf6R{(S7pMh3J$*?5*bfVKI@_5}Y~XJ{$)P$Fn2SU1c}Y?}A(w7v0c~jMz*m z{#pqnQ&Bt!JAOQ7GQN<&=JS6zC%04KlsS3a^0FBc&!=Pjp5w}ryq_fwO3*sbohs;J zUV?A*NEkdkUwvGV72PjtSJU@RPWg&|QfyTKIk3Qovz5?Q#AqEy@q$MK8M{95f%#&8 zbu59-AB6oLLTUrWR+wu;8oTDXUS?A}?Ni^3cfp4X^j~~+L4&C9+1hE{zR#--ragmb zHUtAw0tFNXS}ysC8RLgrV;3hS$YpL17D{!3n+rAYFg9Y!7=3Y(-xxqE?RH3_g-t(y zjG`U;qlE_3Qdu*(xWLyQOR;2zoAUwIWbj(jT!y&PM%VjyUDeSuWA|Dz#W(9yQvE%H z1!NNXb1770Rop*$-753*oHJpfWjQIJE|L-O7o>_RwjAweSg)X6D3Xqtb!xEO?s-b+ zqw^{&C^{8ZhiyW+DLBa!9oUhr@K}CHHc_@#MRdzySLjo{;QRsCHsErC&ge=YD70mcE$>$os{k)X*%Q^MrQF z;17(p;wm*E>=uz~C-Ri|ET&kyQc)7L>v+6(%4IG6V*h=4j%TL7Y<$miXp199R1D@_ zHCduj$vWpoFTndj9FsqP`(A)`lCRYG!C5Y`eLCO9G>}}8p~r2u+$`dM^j{2<$^v9n ze6KqjUO9MVAZhzYO3q~O2rUl8ys;v|jQ?^BJNmROD@p9gVZq;Igy0n^wfe2=i^)cw zKn;{2u;6fq19B54Pg6JWGpa@S49EDF-=}Bu$BffPnmWK|NJwAR7^VXyD6CwbH*n!v z!_Gl;n)o@vR1ayOo1)Mi8na}~$cm}$PN6Qz z62}|1Tr6WduDouKsrbDq)qfXHKqj(3mql48tlLcK1%@rXd(UhQ&RXDM&~-vDR4Z4g zGS9U7sN^n>nOe!&oFUg;Q^}S!X3T8GvY7$Z*S|Nz6T6-CzbPVFKd7-t0% zRKOy~Y)$iqY{93QDU*pA>Kb1Hr#G%?TdBe7GLM33Q7~k6t|lt|)T2BCql58N((3-* zTS2n|!n>!f%R|NjV`{1YUITZ%+_d|6`mWQSz0A>m5XR{w)OR1l9(y68pn@>mVW!g` zL2IH{j+b|rY7ur^Q&c?G z&T&6gWD|@5CvuCH<%`MF?%tA|1v1DuTt9hZHjgpPkLB;tZU_`N*w_4xKAl~Z17M#h zx#|1U-X1hH?+_fw7YR!4e8}Ic_;0Co%95-8_;SREit@8Q`HsXgz!oH;SytK!8DAz_ z*G>u&d4BtFC^)_pD@1As+$XkPvVGw(s9-#!?B7XS|M9d2c-ag5w)cA?^~N!%Q=WHt zcC#+qe{tYds=hrM<@#fj=cTXzL>(Tj)90K1x)-}M#<=v;m{*e~Ta?SqX6_)ph#~!- zz`%bZ#buZw@YhayXSj*~svdm|D{Nn8o7vPJfW{;D4Yw~WsoS@riG=^!Yg#4d_y3ZF zS4!p#q$pn<$rq5}>3VhEU3@C2JVoGMJ1<(*y@>=%?ip;;Qw26>iN6%HGOuwfMs85T z?w5Eit;+Sg;oi~iJeiT`gS|Ue&XhNWAnIc~!ik7dD*pzRjuMMv#|)Z_wc!u_CkaG8 zl0ALarm>+^CP>jTRnft?m}r`ZwyO3w8vJ+_bs1Sz7HsikfQ{CGJ*Uog+x$OKCDyeH z+0RJ3#qYsis%%ztV*a6bIW4T6cZR>5zEvCV-@uULCgOT;dit#k%O`(HWpJiW=sukw z$LiF@rN8{c@_eCe7!k_({n-ku2qXHb*rR5klW%FbWCh813+g+-g% zZ75p2?P#LYZ0>-wF$2!S_$uE)E!OhFvieh#q!{Y=lJg`z!>_vhd3UPTn|DUGz2u;a>MGXmWs`iU3-PH$f*+HM;m9$ly^H17@Qw7#^4X(hZ$^U3u zi)s64a&c;9M8$%V7c{FivM-T#;t<`C@7AajatvP6VHFZ4ZHxvLxy?Wfm|C1U%ODLZ z>rD_guc86X(#B3m<)7Acf|%}4bK86K{%n*2C z>1fLqUI;o#<8xzr?U@CY2a_Z&0b#<17K-{KeUzsOMMAf*bYKYke4iBwu?;W$wrAn$ zDwX!g&=WlqR^bP(f2Lb`@KXGq#N{Rd_ff2ly+VPWpD&*4*u`~(?eZ!srO>YV(`Ea$ z%;6O|DTWl^4y0QF4rG)+I|L3=5xn)5)B8|nvw&TjTibhH`5P?J^IK*%I^sVpQ!t-~ zKS4$GPROi6^;FKB+G|*0GN%*u33|LYt~3_>HM~89zcXdND=i@LNSOSj5BG)3^BlhE zRaT3=F6Nh@2+HRkKK`E*Cu(kp09c?8Q7~fcQC*WFvGrSM!CT+2XFm&2Z7~;7CHh9n zEVBITn{dxEd_#D3!svXSFjj4ThHBgh4hpx>u-*u6fXl3bOqg_8RbGJmW(WDqoODe0 zBU|G1Nj@TMu&48l@Ju<}^;G;LlV{T=IH*E?_Usy88nnY-1bvx-@+!VxJuN}=L?|6NpifB{<4@fSk5-{jIlLgr7OH$NKe5`fe+>kkBr&@=8g$L(Q-6~j z$^(H+`%rTfi)yJh+{z9mUP+RYl}W6EQ@=j*C=Di^roRa8Tl0gy5I{!j-ToDXiE@mo z26t*bMor(6kYnO{xZ7v|j_n!zHCk8v#iKUl5J`=JGhZ9^$=~lU5f9akS zOc{?!GyOza;o;GulOqKh%_4q-i_dici4X106^scO(YtxQR%F^Q<;rT;L9^TTf)O76 z)gRF1{gSta_=r){X&4}Z6X722CK|KP%53fR{Wi+&@tnYU#fLE1jQY z!o@-3a>*s>Gaysle8&*HE9*L@V#R1#_>-K{638TxOPSx4H(kr{i<&RjLD{Xf+!Wj# z>(Byx5a2VsNB_XpHMX{LHKHn*DGZ+f@@L0?$b1~?+E2a`2UiYxP{R2r>dlPeE8G3CJy4T(Xu13$fA8H$ zDkowF0czbWFKzrA*IShE@-Lb-?;8tdC=FgXF8d@DC&)SeIWaL&2H!~!Lkuh^ieh2@ zA+g(KXVm1Tx8r<0eTRz|YPRTau5N!K`;FCKb~g}~Hyd}?^{2}X z@9FiQ;(OizCAMJ{@aF-E>FkN!&7JI1bh2=4HP`8SP*Ey(16diE>n{+8K?H`Z@0$rD zsWeuFId-R~;F7#I(hS=yDYqMUN%t4cz!|6bj3>aUR{Li-wahalhY-TX@Jl1s#1EtO zfT{y@-NmS~F(ZlOw#zsO!z^ZL8__`!L-wKUXE4np1taJ38HH)!Yd zCvwN%N$Y9A()~HO)6>b(v_OPFYYaMJcs%kn5FlKBHC}%nb>?63LHHMK4P4x-kzKAu zh@0^Ci!!-s1)yGDP9xvif8URNdHaCJDNTs?0Bw!j4yP)Z8e-RCa~Gg+SKS}wBxTyy z%7-Yx+sK0GtA*;(@4%l()$vRDhXzY3Ob!30kVELWBd@F2>Vab-Ou<65uzpe5jJSjX z4jKe<{1AFo1ObBWc%)F1+&@TQy4B=?mcPqWvq^l;*PZuYT$a~Or&|m<@t+~-c^5+j z6npz=jv5q^l)3B2pE1FFVC4XA=l zyy*N_T-oZCW}h(+H5xS)lUkSX&c=YQOdKW$21wH^1);rA9n5;FU4=vWs3#d*$B#9H z*=aO=b~~ECHnI!!->;htFdv66MyB<``(_o6cMf7|vNMF9jtFgmnqxVgQ`fd)A1qKt zaS$D1lU`rW=S%J*zXesC&fIuZfG_s_g8E}q^vYy6m8oOZ>-8np*-p0s)(d%u7e0Hn z8sCiD9p`YwUyWOUqt1t8zQ0ICTOBd?3u5PMZO|sXo_Y6*&hhD1TbcPgz{rr{^I5Aa zV8zDFnGA@$``tU3>heTyV@40E+Naj}=@d*3A>z)|85KX<Tcg^z`bD0ei~4t z%N4{Hd4mI7p@Veg_02U&LHobyr(=jaWW%E!5aCr2QFGrQ#K_=h>jm2^I*>d>(KjVY zbTTm`*NPKY5B}*|?7$p{I6wufSqy`W$$AOez{Srx3sHEviipV-?4i_4GkWAaB`w5R zGNmcky0C#QAl(UiqFIx+QQa035-e>V3_kklRQ36z9uLKR0@Fxu4Yb8>mU;t` z+na-UWJ5aQ7h`(7?4LlC{z)h6kY=P%6X9$Z43jKHw$)la=Mz^wX;1KA4;q}Kw2$l%*Vv=Q!TZS7Bc7 z@*V~-SFRlY296rr+?ZkSpR-M>77J=+$SciYKK54w(X}najdP91TW#l^^oRAeG*7FL z?37O5#i2S8KbQ}#{JAiu9}!Oc4Lg;qhA)b|F6c#q|GO05%&d!DY7A{@GN=#}F_IR*DQl)A$ z)-f9ChXk4v!#tiAVR%IlbSe57MeVQ<&T>V;a(P@S=-$>FSuYwyjGz4r#ei_gZsKEh z=YAmJneUP?=lG6ftDN!!HAUW0Cxq+7(e&(!Ns&{QxlY!m>)I7H=t>jJL+nM<2nmW8 zH0++X&G>eG9R@1F^d%G6cP~DLDt6Hw?#M{QhsPveF$DGFcZ90ZH$&Q@SN7NW=dXas;pu+_BJ`2`?3g8=AAPX*_eYzkL>Ya>4qJlNSbPeCymM@cBt>A0pB$?BHCp^Dz~?+? z0S@eNi1@}97S#mH&@vaPZf6;+ZT}P^59rPMp3mQjPXwPCwPI2(CCeRxU?4wSp++9m z!T-ZJ8X~BW^c;eofntR8ynuNy*t^Zsz{X3GRW}_CPQ_G5mZe!}Lbbd^8z;e@PSc7dV{Bjrw8W7xeU9yWj&# zM;ZCiU+euxs`ZDg;p&EiUPWFyu#bN`OPt4`_T*;tx!}r`l^9v{Y$<31dATfw1Guri9o76dPb`TmbrpW>C_D-F= z4*W3|V(;5xU*ULfg-}SVOR#_w$%yX*EoxFyox?+^hlvmTW%4O_Whv6{irjgg9t5@G znvw-*;fP*Li&XyrBWDvQI(7u=aE_hI^2+!Mc#&4h4?2HksbOD*vw&9SmRd&p8iHRr zL?02Gr7BK5pICC|?BKMYk9}|^+oH1690DRmRx+Sh%YXudk4!DzceCghC(c-c?Wo+5 zrva)c-sdozGv@rKN{^39e)DyDPcl29!`#rn6~-)IhW}bclbXpv3FUg>)Jr~P5y?H(BdmuLf-Y6*5f!1Ii|xshHya6h`zHEEI;ZH&Z-Fck2Or0itT zh;7+`t%lL^&y~N;XthbDFQ3yxeGZ?~?wV0b3m8~)5N)`H_aNxX$kFf9?BtO?(c)o2}i*Bfn z>6sttYJG~9mPV1}Cbd@0p!DqbnWPnT&t^wXq-@ z${|Y!uqKFNA1WU^2L!D}5lGY?iQDbM0yH#sF?F8yM`Ot^)bF8p1BxjpHPVs~&KgEv zLwz^U)fW6xGoz5ak|qp(7UWe;?DEQ~Sy>e}ucQ_`+tgEqn&C|{EHokHvO9!K>MW<$ zjBB6wa>o_roahLe^Qvw~He+)b5-uxV$mysP127_+e|MWp(&tyHw?(mm1q9_4t&IhL zlFa<7z$K-{#t z4m7LPkA`=>0-K8=hi=@pfYKXiq^mI8t{|Pd^Qr4rQI?|On*Seorc2hqT}P`=s;nGZ z!tagz-k~4aiy>2Yx;~W$rDg@(GgC?4ENvxY?IcPUC_`8PhNC&UKYw#+^HaN6qw!JA zF~Rdi| zc2?RH+vxe_%I=TER^E*~oM0FE8Zf}s-g?j}tB~^2V^4~4&rRm}M3#yGZzQjp?GbW) z(H+r%^TicRbau%=(%H zE}S1YcK0@BertANyp&bHwBs^2cJPWKuXH?1>@~$x&by#ZAQx;3GsE+MHbGAJ$NW}Z zt3r0C2#61E8ibLWc9JmEqB`Z)(cj|Ox%?}J&*MsIgRGPY8ICBd~skASD}}u*H}fH|o2Hl5}Dt$8$p%M83SDySPFR z!!II;lvF9f?IF3C>vF?sg_tPNK2yRSykNuUPK>6@?66!cVdkT&QNtvQmUIMM?QlLZ zzHdD-#NzY8$xl&0TkV2L-W7m=3|>TWd9gvPx*?!oUdE}g#8-iV{hUW65uir1-bQY6 z(C>6yocy*S^@#?Uu@KQ5MCvCIzHZnL1kI& zfwtPlPexK_`A5zvy#x0e4pBIseUK)2Va29qcPM}V`7DRuCwLG=O+yb3l}VtDwC64} zs@Lx-s#6kiud0M1Bcv%HuGvuL-t|FMF#j(ilsm&r8z{>GOGhg%01)pigH zfRzrxT#pe3CSw6)DLGyvd~6|7V?Nz|Slhz$5}xX{k>zkJ14A^qhv^60`scQ{{!84i zL$A0(G@Wx;5pmZT5X_ylEBt}A#`-Kb*p6fJ$p~kL=@7rm5M3wA{aj`_>ts6+6Rf!` z-qEo$1dz0EkWtUPNky4OQ1AZf%6O}hQH7tcbQ(VX^w&m&|L&*p=Q02B333Id{(ol= z#mYO$4Y?|t>sQZWHZTcNE?CmxS9qY;#|-+rZ7Cbv1_Xt4r`na*iw5)n+NbxQ$A~(* zj_p8X)b~8nF9sIW9Z`(}m%F&uEgaU++Bak#t*4GBC@u9DUzXf!J{$1M=$=i`A|`0@ ziOVtdE}y$>%!4<}+D-x|vg~4}rY+(zZe5SuK|!Nhm^*jzG*G&>-9oE3@U*4Bh+Iuv z2jT8};f6%8uo-N0kr!yPPvTS404GapO{f|+o^wy+5YX`XN^4;Wfb(WlA!U=k`6mm+ z>rYL?4g^XdEgP3lZ?iLvB(GxjxHqv(?Fbho48h z?6tUoiCjx}AVt%Eh*e#oV$5L8+I}F$z_~;Jn>j689x3MMzZubx#3Y3ErkHg?)!Bfx zET|+@fYmZ0em&3bXKz$urX>B)X(|Bq6#`1GOw|$Zy?vZo7?VPz*dD-lw~r$0a&iy8;OWv6J6xFx|Iqdk_rw z6YlZDQ-y*4{tzEU0;d`_=LzE8gE9nd@9ii=!= z&-I-nmhO%z)$Y5W-D)ZN-5UE-Dy42y(P)<;n|m9h&T8pbT7Fr|ZbWpd9prrt(7*I$ z1+hIuS?#tUUKUHgeo3eUxvsEYLNZ&5cMz8v4pQJBUq{)tKe?kMhL7UHoN3hGFVhYT zaH`@8zr{pFJ?ikTLTt}lifC%4URGOTK0#9aF2M9Q)qt+=1u(3RB-#-VJSEH8RhG+D zZ=Vz?WEu6b>QLfBLIh4m(l4ln*!FcrrWI+bFTJVs+s`h%Xmb8D`Vd05|90K z(EfQ@@=D~=xL;WEqyR!uFVV3I=y6%3<2Zx;De9J-5Ljv9TPoE+{~e+>00@V@FV#Tp z%1aaEdvgqZ=x0_>@**4>=YBq691df6m%Z^aSoYavJwWo-(>qjU_JBYuUko?EyepWm zq0yvzdyW175p^Z_@2KmZSHe(x6?&B2p04MP>xmS&JBVGS<(PHDY!i<^*S5mmdKPR_ zKSJvPB$YN=P(h-HXwz?h8D6c1MCC`s1&UD`N`QvzZogNx#TndFy&6~JK8@dh3DWyk zQ}3k^7&9QN(nyEd>>2xF|4J>9&5Jl|TY4*A0rcBtsa#$;5YCuYa@Z`X`BswLc~)tN zZe_***A*jRH5Pc7TZB+~9$Fs*@^k#C$Vytg^YttGWM-<@I=vlU{AfgXTD`;Z zO97gg-1=AcUUb@U4;X^Gyk`^}D@8oD6!h%~g>aMi&SK^FE^|>C-kBxm6MqXPukeQD649;81 z=?%nC9KT2eq&zh^bGV$PA*DBqovKKs8yyiW?#YD8ybdLjVADaK@bO>zoH`9H5|exe{|@ zeq09ut2j~hRDp&&pLN$Go)G~7R+wgBS5lDR?q9V|Ec6d<6#OLm?v)0%=kSg$ ziSL-TPW0r{p(}0d%l~0zW4BntijW9SE+`%Gn=6JoT3HJRABOKD)<g*iIw|{q;>5`h9fMVc=u!U>9M-HA z-|hP^VC5w_2cue6`vphaJ2|4X3|x0dIMZ+&qi%zD_pu7$T^2P6mMd>bY%8j{rk5?u zUg-;RI&DNhHg#-6gCVZ++hI^bf4jGl*J;PlZFAJw0t)O1F3aThR#^sO>pL@N@>6G{ zBvRLINM*d*1~cZL%zuCM_s;!46BLr}NN&pt#u-*vLvM=>Y$ut4VAJFgtA8NF?K)=y5OB5UiPWIZq0yj$d#exJ+msoL z!IsJu(NneMbCewYLV`Vjcn6xHHt&!pUd6K6zHluGZ~e6V)Bge?YacD?+E<> zqA+w%H+cm_+JcBI+{~oUT00D64nx>=GLMo@&W;3 zt|~jzMsK+g(v&lIay&}}{qEp|Z?ZE4SnB1l2(7@za#*anI@q$&%^ptYMoB@IZJLGb z7xjx4`3G+L8Xxcj`jm?<+}q5Wd$yU8%Tn`Tx`sGqrZS&jcCy)tD1?Yaj6?pLC2ZlN zpi@-wnia1GUrvY)LbrMV-NY~eGvrI4S+8PEQ%sckyVCk~k3)sn{8y;a2$MP1 z$X4_xY!I>+GBxY(Uzm_yHG}_<%CVz;GUN&moyOSyEkDVVgSsk&{=@{YXNN~h0gl@0 zR<WCRl8tssg<5v^ zWH>Vt?Zyd}JaEnZZdrh;C>aIT5P;-{4Z6hL3Nw`1gA$1yP0iWpB12LrhL<2OL{nqC zOerHAzP?zXsYv~>8u?!V$Ge2M-qP$v=2!rzSel=vCr4J2#nl5fDp=G!x~t?td=gh+ zJ31zJqq207i)SZl)?gRQ6UR(@+5bh}$&-X*nf!3pn(#bvDb_l)dRSuEc{RC5D(dzz z@t85=1I#)=?AajwqQ;Sl`KpO+J2S>P*f!478rXWYC@(vkDO0Wd`N}p=yux@R^R`9* zi>%l|^+>-)Ij4Y4(sgOWo^Bv06oQ2%ieq&__r%o|t@VTmIm5%Wpqbdwm{-3Q6NhkqSOwHK$D^8=~+peIba8nqv6r{m=tiT%Bq#i>~lg4M;#yDC9ye`NlI0|h5 z{Std@O!x}*iep01G<&80RGLTj58S9y`I9PPT&K_F5^)Q$*>$T_>0sux?_DhJu_(Sg zhFS4c$qR-5Bn2l`&BjJ{ug{=^E%WFbM-YwwlRa(Ur|D`5pJ9PnPvHj6lXHJ3B_|(S<2ynDE=2& z)HM5S=2R7z4gffM{cn_C1Ay{dE=ZQ@J2lXr z+>i&SFz4z&gk%ic{btO1@8U$!!<-slQmiedA)wDaxJ;kwp!78*e5o(m{>Q)2#xVZa zNEt~;arT(OYYZ!LW24{myEenRcoaCUHimWa>S^{o3Bod3V`y-9a#O$i#f{8sXOemZ ze4S*?v4z zA0>^Ot1u)wJt)*w$W62kqnwS>Jqcwv1Tv-E=ea?%R^5#-D z!X7t=)xts-Zje{1rp!NSQf3t!H5A{`u)tqp$SJUnO2n=e;WmV+jdo}n&!cBLN@_f3 zbhMX4*p-$oQTXN!hxcnV3dK}5~-$2Ta0`Vd>U7Dc?F<(b@p2FaSBQvu~gP6 zm{%XLC(~M04C5`RkkvAjT`X=)Q+bQQqPz*~rx#{5_58K7&K>q2wd%1HS?f1{HQaRB z_WTXnjF~f5lg=zO7-GROp=92B07G78RH>|Q4(2|$)GHJ8IFN7C*QibY9TQ%W!||ul zPs!c8C$;EcP9KE2kO#10_2LgITF5CB%VU5muNq<1^o>O`hvI^;Z$D-x?|LTucEz1+ z_2taqj-gFAJ7@jkbVe4S+jGoR-yM&#%@dH~qAh=p73ibhXp{7?jrP0>sZCuNixb~R z2wzqI=E5wU)n-C?Wg7g~f1-d^ z^O3#C97+IJ8B09C7+P?HGh~@-T;hi!oe7RQdv{k;e^)6d=d6lsvWsl-zNF!PT-r5` z-MY{!K-d%n635hR+gCZ&PSwTgtz3BtC{mAu#1|!vqF&v%e$I^&>TAQj^bezcb?AzEpP4ptGkx=W$so!af2NsC(y+k+6ziHKe$;AK<;S^b23= zvZ>?NKrv%fzE#LpZXUE6xwh33`7n#?z^&#L{-fng=4EV!-=??>Xa!B=b)m)NW=aRuJfFpTkljLFXpg9>=&pR3yZoLQJwUq(Fbj7muTYti`ZZb7uS#DA@U8|gO5m&N(wW4!{R|B7 z=?u88QIGpyJ1T`VY8X5W{ipBfjV`#HOmN5mX6T=4$AhXY5a3;Rl zfPHw*yn$+1)9m3~9T2+sEv4Y{e#(p&s$PsD)HqQ_N5DZ%uk|KeF3QeEbeN}^$8j3O zcp>$V0b(#~ph1^^ef?H*fc!UUn|Sz{2HveyMrn=huMa;NW&-`_->61Ml|QJ)_*-2R zpaO)KCys*+XE=#xu&g>AvL^V{z;h?GOd&xQuvvMYuNuS)hN!5VDcnH`%?+E9Ga!-~ zoM^t!Z9n0pK#RlGz1vnkzU3?an`K=h=nnfAz7US^5kmEvQ z+q)CBR4zBT{i(9;bOk!s@Qer^xOad0PSjRXVc_#72dVV(v43;7;rz|r_LBmmynPxt zd_O)*M%VJe&#}KFXx+e=4@S@)#>X@eEML~%%`n+FcRA^4I5M>L+hDLjv8XLBV$O12Xb`OzBesnU8RPUqU?jnjz+X}dq zaaM)y)AvxE6?9sAli&_Sda|Fu5LrJS1rvUno_hv8SfCz>wD^zJQY=ehQXCo=l5K3C zTjRn*x)nshOW_uG&d+$%hV@Xtn6tu(tDT#L+1>U9oMdABp5PRDr<#Bi;gH2@D_^0;iR9xxDW4s z?Ne>2$2e54Qq)Ju@4ZCZ?w_xDru$5LY&!}Bh&wU&YzzI&?Y~WNFuuLCRc zn#VH?KTs7r6MYHN7dU_DQzbQZhOn*C`BG#3RHRlF2&Y%=)f7 z1;+!pV8Y_W=tPGF_MB@P=xIllD&vk@8@4zhlG`P0{z3(O=^h0_EfQ@#+;-|QWyn2{!CvJ8X17W>}}a`-WPa>Q3be4vIK%@|9i z5aHur{0@V97X=yOuB#Qn0<%n7r@!yor742dVlnrU&UUCWLB^IP`&PDLP2cCLln{^~ zobP>wH*=n=HzDO4oh*A!Ik-0xNmMRfSuvT|&`!toN%JUVCre9}9Yae@>;f>|1($q|;msELe5n zpph@vQgb#IE1<||Z{gWq#v4lL~y3O3Cxz!{R^t~qt_<_S#pL5a6-`wOM#q2yjU zTXU!OIV5LYeL@D4gBXIx9uc8XUsqOA2|D1p0Ma|+wc*O|?)6<&;U+5vAZTx%C|<^z zU7PD@fN!;GXxT)T3~!SAF~E`3V0tMo(S2*)z{lb2>e4ma4a@AG(%`sybr+1QQl8hH zX(J?cKa{)sqgDYnnT96=Ba-#l!@W%-Voc$U_o#GPR7R?&EG&esE(S7qTFme&XaNFw zo~mo*F=kTA18hAs(L2ljD{L?5rJbLmZ#kvlCNw+?Hinh9z+sVA@2ov2N*NQiqax1a zC~RMmM_6v|Q7wSc3=P;RB2V2o+yq){37;yYM@E`@5D+Gn+m^TKv@3TKIrRavSW5i0 zKHsxp^r|vh-x>?^Q%P_x{~PWvZsI5H!!tNz0(ch2vkoc=z;rD;0V29pC6b4->B`r& z9vED&?fU~R)_MZy=Ni3(Yhi_LA^ad_5TGyE+5Nx#9$pXD2O8`#+Nm)D@>ggKx=Ca7 zmTAp(oC`n~rP? z)dUbEN`gifpSSFWv3tK0JhcKjGvoT<+yiyst`V%#@3bpi2zwA;Ss8Ku@xX>16-yPJ z>?{-T3Uyh+llDU|`2&-q4~(=re5d#e0L<^A+S*sq6&$ap_ngJVr^Gr3ch0&j!09VK zzFYfr$PM004&cxIXyE)5C#Q*RU zxf@5;djp&hFZQqb*yMO(ll-CNGO`R4n=3(RdqaV zTbwVDp)Wz=tr#R3oTr~$wM>^jmAQYWY~rYX(Vj6dT0o3&oCh`dzghSA9RF_JBgQAo zEZFc#VK3q0$AO7NsKwe-;)p;cblp0=EXHp&`wN8Yt112dm6-&0H}6u!M=?yIyK))Z z`4S2T$@2}tPQPk0M@8qC(vfw36*slZ$u0Th{a-G;?WUmX8}h#xzT6u%!_6C%HTOoi zG7GKH@oc1@j^&%R{(i3UCI-qkZl5kJLgo6TA@9}*4!C#P6R(6l$gTk>v$R@7-%7p} zb)n$Lv;;o6IT*pU%$_g`_X!849Hh*4&lw(lUB699s~X-bw<{<&H18@Ikb}~Fh54Ie z2}i2WOpddl%y~p0Jo7eM;7W7j1gMSIuE*z30|Fzz=ILmD;7RAFc7*p5UXHN@=uJBU zJ^96--75Wm#PCpGTE|fQ?vF8+%eetiQg}lDOW#l^volJfN)W%7V?2oizU2^_DawTEG(z@Aob&B8sL-)qu^+WE zqFFytWR~1B_ubw0j@A-RUS|WWXNnZk{qH_Ot^T^b>$uK(CvGO>YWheu3OLC$EExrp zWdE5?;40BI5RGDMU0>rtgumoEFonW=#P?yr8>}i2FSnMT zmFKlJFLI5a082&CYZ?+UB6hA-bW59{%egU@d4L|9Nq^7(WD6AI42kVgrNUT(#G`sZ zg*Z|hX9)9XH>cqvF zW3GvGmv+%d>G1p6juh!iJ?kEO6y_bms-yN6dE$9?{&F_`$J-Brk1>;EhI|x2MXPf0 z_7iBQSF*!=`)lR7J+$pQ{L;mHSLZNUT<*Uowq zH2lfF|BmeGV0!Vi>#VBFC%vf(@A2t37A21GB)))tK_{E4-WQZUPz=ce0s)Dm={#va zQ5-A^f3mlFZNT9Y^zO@-1PiY1V%1%9l|HqQP}*SKHd`gS9uxc_nkcea$@|I7)d6Gl z7G0v9;EdHEkb8xHo3!Zmr^huTA_)RHZby|R`MgISA!DWnZ&HlDb-vzNV z_!nI@(p&saaPA%d(-zeVTbPR61&AH?u?#mL4+?U0? z0x8sZTkAomgj6a`xtfV_ee*l)ML^T=Ip~Z8mT>8s;c}AsvDkqy_s!JHECQj8>mDIQ zyVOE64PcT>h74;of2#1GO7RW$0Ze-%0j9l!9tAVn;_&JjM-ji8`@wFs+$tpmw*}3 z;^1*uRMPvF64GLu(MDq&XOI#|T%&lp8Z*pFmy?%-$Hl+4w<18yL^-@Ck2SQ|NiTIm z288m(jjoDn-$edlc);;SKE-S_jCxINV5>;!E6ZNG>WC-6dgqY)!@8Ru*=<_mo7%3b zS5P&3F;vQaj{b3&83kOU4at-^ z1C8)_nj(TfBbQ9mZ<)j=w;3y_ZJeWffI!b^oAFQ3%+FTLBfghnrPn0lil_4{Y8e-X z+Cy?BQqDrbKajTK?H6cL3gy?MINn{Q*$@6x};c*3$try>n){B^En zzg<_!r-!X~JmzVFyY!iufP%N{LD&9e4Bqbj3CH6cx3jYvYsLb}2aP*?FMwRo4iMCw z@c@G*qVo-go=bT*DkrVTq$$f?zaeBeD8S~Z32p3F9lu75I<~aOY>3ndBQnPE)1_FF z?6ZHS$MsTgapzh>1}vK>2TDYaB$KEO{(iyzW}? zKoeHDr}7vCj;{F}o`!&1Yj6XPh?s{$W46iITQ!o1){mZ~-6wHtl)i8=GMMV@rY@(mF}zLL!8)7wOpny}+i! zYNcAUEt3b=Unml~+EM%Xe|nLzsXq=U3^jhShB5KZ_N}gZg%scd%=V{v{^p3+;O+W~ zrgu6cox4VEf&74yZoOwwsr1LOYz5w6>O=o+1KZ*FKRkh?{}=bb`?}daY}IOG)P4nb z9rlQxBsAQ8KA1J8sM`f-?_MTzdiCZpwKnU$9JPudKZJk3dx*(ZA3bSrlA2&=caiKe z62jCPA$9u&M7(f$ycS?QNUZtdce#_yc5t`aoMBsqOL@f&kyA)uZJWn3^&P~2Lp#2} z|CR{p6B%djMP^!+8*XQb*Jf5ltMq{rlkoq&Z?2=S(pG!^QHJks1IQ+rNdZ0};@}HoI6)A{|9Aia%@yT@6U%h?+&I{OwUr*i(7&;f4!tmCmXKLS2PrK~t)cFBr zwsWSP0UpFp-o?uk4U8-&P~q#nW&b-CG;u5isv<>h&I%Bak33XdQBQsR`X4OZeB?** z!h>33-IYi5%^|ZC+e1Fh1(gPBx1;Yf0gx$c`yibxjo}2keG|UTcrPo!@o|vaPyFL) zNBM#ztTub*OiI?>aA!B8r?~5-3xCX7^b>j~u|D>@3Z9DzrN^dNFx&^BnLf`Gx*kKV zlt}7N6K@S$QD07_W|Qfp$v4VyyyXvcHN9hps&QClZx)~H$*!YMRK>> zM1-iD|KnuuBcr)K&bsIq_ca5}{s3bV(#=4NJ0|=TvAhRO?FtXH5=LGc74O>};zhJu zV?VqH360KJXS<|B1j|z~s}lj_(8m46>iv6f?D!f#OsyfoA2pqvjOY2JdYp=7=tY43 zI{@4_AzHBohVzUVH!2f;S-&&E(1afo2Wm8~bU1W+@Z1y^v=r-TbSpE#P=$me0hR17 zMP6vI2ac!F2x4mQCuAE&YxDNBQARy$w*|w_zW-Wmq_uOJ6jE+X#WxdfAX&A=Uasne`(%?;qosH<#jP?R6QsF))IiiCY)(}&_ zF_Q`9ZcZi@?f^r|Ow;QF$ou;-dLAe<=2L2o{}TL}lIZ?KndKj~Z&NxmUppKu|BFtae-B13cxVG{ec;WJ;-HlPtN&6>5YU@B3^%=Mu{<}Nz z86h7>YI;qcz=H!;O*=Dauli`8rWu@v!+F6SH}J0Jig1ASGf*>iwFzb2qaA@VyAFSI zg{y)2vtXJ&;pYL?8sJGNrwt$9hqvk^Rh)O06Ksg=^y(z`$fj3gLF@3&w-E7}E3~Nm z(lFj~3k#i!FOXVa>52?!l*g03AEU4woA@T3h3 zHnCOVY4p{&y+DKrsJqM>{X4w<)A0dI{wwVF{$nQ9Rqei>}8Yuz?9JfmB% z7xAS5S+joXSiQD=FudfadZb4xp11C8Q^1schR8|}p})p}C!u~%`YQGQZLhXftw4dB-ZncipO1_+4+jBVQJ4cdig0 zb=eD`tVw)rC@2B9riWLLaVH$SM>-`F67u|}+246!(xYX^uK>7cc1QA++xa?CiRXU2 z=UJ*)|4|4T|5Dq?8HPs4caFNK#fRA)M!0~1>dRAiA{g8W^9IM(P4?x@gVLI+cG)`}odR0@$fD2u`PFium-z#C6b=7>Ek zud?%iP$fbf01m@3<62jHlN=6^VRz6;!^J)=V4tbN3$R|Hl9OpJ zI!;*`p)N+J44i9U0eoPSi!6Zz)Gvn=&?v1LyY&G-g5mmXz0F*CuCbcus&YeQ6zVMG z1MZ-`DbCkI0U9ZWP;3b1tpB0PI(=}7()(Xom7y*Qbs?uq^gHwKB7O(_>zQtaze7^Y8r29ZH2X{)gu)$Zzgy?5*(Rpe!fTG1p6$?sav>9u^7^S>O9J z;*N3sa6dppXEZ^uRVeE=^_El

    %~%}C4ey}nnSTccs5Q-o-3^;fuX06#YT2) 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 literal 0 HcmV?d00001 diff --git a/courses/foundation/web-architecture-101/Viewing a specific recipe.png b/courses/foundation/web-architecture-101/Viewing a specific recipe.png new file mode 100644 index 0000000000000000000000000000000000000000..35fb06508e6ef2da38c283e56ee37e0ef8fef50f GIT binary patch literal 103468 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 literal 0 HcmV?d00001 diff --git a/courses/foundation/web-architecture-101/Web architecture 101 assignment.pdf b/courses/foundation/web-architecture-101/Web architecture 101 assignment.pdf deleted file mode 100644 index f15bebc4f4adef00b0a9685b5f84c01b1310c50b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 261359 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 gzsV|zxXdJQdf4;O}A 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 Date: Wed, 10 Dec 2025 12:39:18 +0100 Subject: [PATCH 49/62] Add database assignment --- .../databases/DatabaseAssignment.sql | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 courses/foundation/databases/DatabaseAssignment.sql diff --git a/courses/foundation/databases/DatabaseAssignment.sql b/courses/foundation/databases/DatabaseAssignment.sql new file mode 100644 index 000000000..a04ca6226 --- /dev/null +++ b/courses/foundation/databases/DatabaseAssignment.sql @@ -0,0 +1,27 @@ +--1 How many tasks are in the task table? +SELECT Count(*) as total FROM task; +--2 How many tasks in the task table do not have a valid due date? +SELECT count(*) as due_date_not_valid from task where due_date is NULL; +--3 Find all the tasks that are marked as done. +SELECT * FROM task WHERE status_id=3; +--4 Find all the tasks that are not marked as done. +SELECT * FROM task WHERE status_id =1 OR status_id =2; +--5 Get all the tasks, sorted with the most recently created first. +SELECT * FROM task ORDER BY created DESC; +--6 Get the single most recently created task. +SELECT * FROM task ORDER BY created DESC LIMIT 1; +--7 Get the title and due date of all tasks where the title or description contains database. +select title,due_date,description from task where task.description like '%database%' or task.title like '%database%'; +--8 Get the title and status (as text) of all tasks. +SELECT title, +CASE status_id +WHEN 0 THEN 'Not started' +WHEN 1 THEN 'In progress' +WHEN 2 THEN 'Done' +END AS status_text +FROM task; + +--9 Get the name of each status, along with a count of how many tasks have that status. +select (select name from status where status.id=task.status_id) as status_name,count(*) as total_tasks from task group by status_name; +--10 Get the names of all statuses, sorted by the status with most tasks first. +select (select name from status where status.id=task.status_id) as status_name,count(*) as total_tasks from task group by status_name order by total_tasks desc; \ No newline at end of file From 2a52a1b2db4e30fad4014e0948ba8796cd8f96a2 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Fri, 19 Dec 2025 10:58:25 +0100 Subject: [PATCH 50/62] Modify the SQL code based on the mentor comments --- .../databases/DatabaseAssignment.sql | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/courses/foundation/databases/DatabaseAssignment.sql b/courses/foundation/databases/DatabaseAssignment.sql index a04ca6226..9febf2728 100644 --- a/courses/foundation/databases/DatabaseAssignment.sql +++ b/courses/foundation/databases/DatabaseAssignment.sql @@ -3,15 +3,24 @@ SELECT Count(*) as total FROM task; --2 How many tasks in the task table do not have a valid due date? SELECT count(*) as due_date_not_valid from task where due_date is NULL; --3 Find all the tasks that are marked as done. -SELECT * FROM task WHERE status_id=3; +SELECT t.* +FROM task t +JOIN status s ON t.status_id = s.id +WHERE s.name = 'Done'; --4 Find all the tasks that are not marked as done. -SELECT * FROM task WHERE status_id =1 OR status_id =2; +SELECT t.* +FROM task t +JOIN status s ON t.status_id = s.id +WHERE s.name != 'Done'; --5 Get all the tasks, sorted with the most recently created first. SELECT * FROM task ORDER BY created DESC; --6 Get the single most recently created task. SELECT * FROM task ORDER BY created DESC LIMIT 1; --7 Get the title and due date of all tasks where the title or description contains database. -select title,due_date,description from task where task.description like '%database%' or task.title like '%database%'; +SELECT title, due_date, description +FROM task +WHERE task.description LIKE '%database%' + OR task.title LIKE '%database%'; --8 Get the title and status (as text) of all tasks. SELECT title, CASE status_id @@ -22,6 +31,13 @@ END AS status_text FROM task; --9 Get the name of each status, along with a count of how many tasks have that status. -select (select name from status where status.id=task.status_id) as status_name,count(*) as total_tasks from task group by status_name; +SELECT s.name AS status_name, COUNT(t.id) AS total_tasks +FROM status s +LEFT JOIN task t ON t.status_id = s.id +GROUP BY s.name; --10 Get the names of all statuses, sorted by the status with most tasks first. -select (select name from status where status.id=task.status_id) as status_name,count(*) as total_tasks from task group by status_name order by total_tasks desc; \ No newline at end of file +SELECT s.name AS status_name, COUNT(t.id) AS total_tasks +FROM status s +LEFT JOIN task t ON t.status_id = s.id +GROUP BY s.name +ORDER BY total_tasks DESC; \ No newline at end of file From 81cc62adf1e23a8514aebd38395cd97cad980266 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Fri, 19 Dec 2025 11:23:33 +0100 Subject: [PATCH 51/62] Add intro to backend assignment --- ...mentsweb developementHackYourFutureweek-10 | 0 .../introToBackendAssignment/index.js | 165 + .../node_modules/.bin/color-support | 16 + .../node_modules/.bin/color-support.cmd | 17 + .../node_modules/.bin/color-support.ps1 | 28 + .../node_modules/.bin/knex | 16 + .../node_modules/.bin/knex.cmd | 17 + .../node_modules/.bin/knex.ps1 | 28 + .../node_modules/.bin/mkdirp | 16 + .../node_modules/.bin/mkdirp.cmd | 17 + .../node_modules/.bin/mkdirp.ps1 | 28 + .../node_modules/.bin/node-gyp | 16 + .../node_modules/.bin/node-gyp.cmd | 17 + .../node_modules/.bin/node-gyp.ps1 | 28 + .../node_modules/.bin/node-which | 16 + .../node_modules/.bin/node-which.cmd | 17 + .../node_modules/.bin/node-which.ps1 | 28 + .../node_modules/.bin/nopt | 16 + .../node_modules/.bin/nopt.cmd | 17 + .../node_modules/.bin/nopt.ps1 | 28 + .../node_modules/.bin/prebuild-install | 16 + .../node_modules/.bin/prebuild-install.cmd | 17 + .../node_modules/.bin/prebuild-install.ps1 | 28 + .../node_modules/.bin/rc | 16 + .../node_modules/.bin/rc.cmd | 17 + .../node_modules/.bin/rc.ps1 | 28 + .../node_modules/.bin/resolve | 16 + .../node_modules/.bin/resolve.cmd | 17 + .../node_modules/.bin/resolve.ps1 | 28 + .../node_modules/.bin/rimraf | 16 + .../node_modules/.bin/rimraf.cmd | 17 + .../node_modules/.bin/rimraf.ps1 | 28 + .../node_modules/.bin/semver | 16 + .../node_modules/.bin/semver.cmd | 17 + .../node_modules/.bin/semver.ps1 | 28 + .../node_modules/.package-lock.json | 2431 +++ .../node_modules/@gar/promisify/LICENSE.md | 10 + .../node_modules/@gar/promisify/README.md | 65 + .../node_modules/@gar/promisify/index.js | 36 + .../node_modules/@gar/promisify/package.json | 32 + .../node_modules/@npmcli/fs/LICENSE.md | 20 + .../node_modules/@npmcli/fs/README.md | 60 + .../fs/lib/common/file-url-to-path/index.js | 17 + .../lib/common/file-url-to-path/polyfill.js | 121 + .../@npmcli/fs/lib/common/get-options.js | 20 + .../@npmcli/fs/lib/common/node.js | 9 + .../@npmcli/fs/lib/common/owner.js | 92 + .../node_modules/@npmcli/fs/lib/copy-file.js | 22 + .../node_modules/@npmcli/fs/lib/cp/LICENSE | 15 + .../node_modules/@npmcli/fs/lib/cp/index.js | 22 + .../@npmcli/fs/lib/cp/polyfill.js | 428 + .../node_modules/@npmcli/fs/lib/errors.js | 129 + .../node_modules/@npmcli/fs/lib/fs.js | 8 + .../node_modules/@npmcli/fs/lib/index.js | 10 + .../@npmcli/fs/lib/mkdir/index.js | 32 + .../@npmcli/fs/lib/mkdir/polyfill.js | 81 + .../node_modules/@npmcli/fs/lib/mkdtemp.js | 28 + .../node_modules/@npmcli/fs/lib/rm/index.js | 22 + .../@npmcli/fs/lib/rm/polyfill.js | 239 + .../@npmcli/fs/lib/with-temp-dir.js | 39 + .../node_modules/@npmcli/fs/lib/write-file.js | 19 + .../node_modules/@npmcli/fs/package.json | 38 + .../node_modules/@npmcli/move-file/LICENSE.md | 22 + .../node_modules/@npmcli/move-file/README.md | 69 + .../node_modules/@npmcli/move-file/index.js | 162 + .../@npmcli/move-file/package.json | 34 + .../@tootallnate/once/dist/index.d.ts | 14 + .../@tootallnate/once/dist/index.js | 39 + .../@tootallnate/once/dist/index.js.map | 1 + .../@tootallnate/once/package.json | 45 + .../node_modules/abbrev/LICENSE | 46 + .../node_modules/abbrev/README.md | 23 + .../node_modules/abbrev/abbrev.js | 61 + .../node_modules/abbrev/package.json | 21 + .../node_modules/accepts/HISTORY.md | 250 + .../node_modules/accepts/LICENSE | 23 + .../node_modules/accepts/README.md | 140 + .../node_modules/accepts/index.js | 238 + .../node_modules/accepts/package.json | 47 + .../node_modules/agent-base/README.md | 145 + .../agent-base/dist/src/index.d.ts | 78 + .../node_modules/agent-base/dist/src/index.js | 203 + .../agent-base/dist/src/index.js.map | 1 + .../agent-base/dist/src/promisify.d.ts | 4 + .../agent-base/dist/src/promisify.js | 18 + .../agent-base/dist/src/promisify.js.map | 1 + .../node_modules/agent-base/package.json | 64 + .../node_modules/agent-base/src/index.ts | 345 + .../node_modules/agent-base/src/promisify.ts | 33 + .../node_modules/agentkeepalive/LICENSE | 23 + .../node_modules/agentkeepalive/README.md | 256 + .../node_modules/agentkeepalive/browser.js | 5 + .../node_modules/agentkeepalive/index.d.ts | 69 + .../node_modules/agentkeepalive/index.js | 7 + .../node_modules/agentkeepalive/lib/agent.js | 402 + .../agentkeepalive/lib/constants.js | 14 + .../agentkeepalive/lib/https_agent.js | 51 + .../node_modules/agentkeepalive/package.json | 56 + .../node_modules/aggregate-error/index.d.ts | 51 + .../node_modules/aggregate-error/index.js | 47 + .../node_modules/aggregate-error/license | 9 + .../node_modules/aggregate-error/package.json | 41 + .../node_modules/aggregate-error/readme.md | 61 + .../node_modules/ansi-regex/index.d.ts | 37 + .../node_modules/ansi-regex/index.js | 10 + .../node_modules/ansi-regex/license | 9 + .../node_modules/ansi-regex/package.json | 55 + .../node_modules/ansi-regex/readme.md | 78 + .../node_modules/aproba/LICENSE | 14 + .../node_modules/aproba/README.md | 94 + .../node_modules/aproba/index.js | 105 + .../node_modules/aproba/package.json | 35 + .../node_modules/are-we-there-yet/LICENSE.md | 18 + .../node_modules/are-we-there-yet/README.md | 208 + .../are-we-there-yet/lib/index.js | 4 + .../are-we-there-yet/lib/tracker-base.js | 11 + .../are-we-there-yet/lib/tracker-group.js | 116 + .../are-we-there-yet/lib/tracker-stream.js | 36 + .../are-we-there-yet/lib/tracker.js | 32 + .../are-we-there-yet/package.json | 56 + .../balanced-match/.github/FUNDING.yml | 2 + .../node_modules/balanced-match/LICENSE.md | 21 + .../node_modules/balanced-match/README.md | 97 + .../node_modules/balanced-match/index.js | 62 + .../node_modules/balanced-match/package.json | 48 + .../node_modules/base64-js/LICENSE | 21 + .../node_modules/base64-js/README.md | 34 + .../node_modules/base64-js/base64js.min.js | 1 + .../node_modules/base64-js/index.d.ts | 3 + .../node_modules/base64-js/index.js | 150 + .../node_modules/base64-js/package.json | 47 + .../node_modules/bindings/LICENSE.md | 22 + .../node_modules/bindings/README.md | 98 + .../node_modules/bindings/bindings.js | 221 + .../node_modules/bindings/package.json | 28 + .../node_modules/bl/.travis.yml | 17 + .../node_modules/bl/BufferList.js | 396 + .../node_modules/bl/LICENSE.md | 13 + .../node_modules/bl/README.md | 247 + .../node_modules/bl/bl.js | 84 + .../node_modules/bl/package.json | 37 + .../node_modules/bl/test/convert.js | 21 + .../node_modules/bl/test/indexOf.js | 492 + .../node_modules/bl/test/isBufferList.js | 32 + .../node_modules/bl/test/test.js | 869 + .../node_modules/body-parser/LICENSE | 23 + .../node_modules/body-parser/README.md | 494 + .../node_modules/body-parser/index.js | 80 + .../node_modules/body-parser/lib/read.js | 250 + .../body-parser/lib/types/json.js | 166 + .../node_modules/body-parser/lib/types/raw.js | 43 + .../body-parser/lib/types/text.js | 37 + .../body-parser/lib/types/urlencoded.js | 142 + .../node_modules/body-parser/lib/utils.js | 96 + .../node_modules/body-parser/package.json | 52 + .../node_modules/brace-expansion/LICENSE | 21 + .../node_modules/brace-expansion/README.md | 129 + .../node_modules/brace-expansion/index.js | 201 + .../node_modules/brace-expansion/package.json | 50 + .../node_modules/buffer/AUTHORS.md | 70 + .../node_modules/buffer/LICENSE | 21 + .../node_modules/buffer/README.md | 410 + .../node_modules/buffer/index.d.ts | 186 + .../node_modules/buffer/index.js | 1817 ++ .../node_modules/buffer/package.json | 96 + .../node_modules/bytes/History.md | 97 + .../node_modules/bytes/LICENSE | 23 + .../node_modules/bytes/Readme.md | 152 + .../node_modules/bytes/index.js | 170 + .../node_modules/bytes/package.json | 42 + .../node_modules/cacache/LICENSE.md | 16 + .../node_modules/cacache/README.md | 703 + .../node_modules/cacache/get.js | 237 + .../node_modules/cacache/index.js | 46 + .../node_modules/cacache/lib/content/path.js | 29 + .../node_modules/cacache/lib/content/read.js | 244 + .../node_modules/cacache/lib/content/rm.js | 19 + .../node_modules/cacache/lib/content/write.js | 189 + .../node_modules/cacache/lib/entry-index.js | 394 + .../node_modules/cacache/lib/memoization.js | 73 + .../node_modules/cacache/lib/util/disposer.js | 30 + .../cacache/lib/util/fix-owner.js | 142 + .../cacache/lib/util/hash-to-segments.js | 7 + .../cacache/lib/util/move-file.js | 67 + .../node_modules/cacache/lib/util/tmp.js | 35 + .../node_modules/cacache/lib/verify.js | 287 + .../node_modules/cacache/ls.js | 6 + .../node_modules/cacache/package.json | 80 + .../node_modules/cacache/put.js | 83 + .../node_modules/cacache/rm.js | 31 + .../node_modules/cacache/verify.js | 3 + .../call-bind-apply-helpers/.eslintrc | 17 + .../.github/FUNDING.yml | 12 + .../call-bind-apply-helpers/.nycrc | 9 + .../call-bind-apply-helpers/CHANGELOG.md | 30 + .../call-bind-apply-helpers/LICENSE | 21 + .../call-bind-apply-helpers/README.md | 62 + .../call-bind-apply-helpers/actualApply.d.ts | 1 + .../call-bind-apply-helpers/actualApply.js | 10 + .../call-bind-apply-helpers/applyBind.d.ts | 19 + .../call-bind-apply-helpers/applyBind.js | 10 + .../functionApply.d.ts | 1 + .../call-bind-apply-helpers/functionApply.js | 4 + .../call-bind-apply-helpers/functionCall.d.ts | 1 + .../call-bind-apply-helpers/functionCall.js | 4 + .../call-bind-apply-helpers/index.d.ts | 64 + .../call-bind-apply-helpers/index.js | 15 + .../call-bind-apply-helpers/package.json | 85 + .../call-bind-apply-helpers/reflectApply.d.ts | 3 + .../call-bind-apply-helpers/reflectApply.js | 4 + .../call-bind-apply-helpers/test/index.js | 63 + .../call-bind-apply-helpers/tsconfig.json | 9 + .../node_modules/call-bound/.eslintrc | 13 + .../call-bound/.github/FUNDING.yml | 12 + .../node_modules/call-bound/.nycrc | 9 + .../node_modules/call-bound/CHANGELOG.md | 42 + .../node_modules/call-bound/LICENSE | 21 + .../node_modules/call-bound/README.md | 53 + .../node_modules/call-bound/index.d.ts | 94 + .../node_modules/call-bound/index.js | 19 + .../node_modules/call-bound/package.json | 99 + .../node_modules/call-bound/test/index.js | 61 + .../node_modules/call-bound/tsconfig.json | 10 + .../node_modules/chownr/LICENSE | 15 + .../node_modules/chownr/README.md | 3 + .../node_modules/chownr/chownr.js | 167 + .../node_modules/chownr/package.json | 32 + .../node_modules/clean-stack/index.d.ts | 47 + .../node_modules/clean-stack/index.js | 40 + .../node_modules/clean-stack/license | 9 + .../node_modules/clean-stack/package.json | 39 + .../node_modules/clean-stack/readme.md | 76 + .../node_modules/color-support/LICENSE | 15 + .../node_modules/color-support/README.md | 129 + .../node_modules/color-support/bin.js | 3 + .../node_modules/color-support/browser.js | 14 + .../node_modules/color-support/index.js | 134 + .../node_modules/color-support/package.json | 36 + .../node_modules/colorette/LICENSE.md | 7 + .../node_modules/colorette/README.md | 134 + .../node_modules/colorette/index.cjs | 218 + .../node_modules/colorette/index.d.ts | 93 + .../node_modules/colorette/index.js | 150 + .../node_modules/colorette/package.json | 39 + .../node_modules/commander/LICENSE | 22 + .../node_modules/commander/Readme.md | 1134 + .../node_modules/commander/esm.mjs | 16 + .../node_modules/commander/index.js | 27 + .../node_modules/commander/lib/argument.js | 147 + .../node_modules/commander/lib/command.js | 2179 ++ .../node_modules/commander/lib/error.js | 45 + .../node_modules/commander/lib/help.js | 464 + .../node_modules/commander/lib/option.js | 331 + .../commander/lib/suggestSimilar.js | 100 + .../commander/package-support.json | 16 + .../node_modules/commander/package.json | 80 + .../node_modules/commander/typings/index.d.ts | 889 + .../node_modules/concat-map/.travis.yml | 4 + .../node_modules/concat-map/LICENSE | 18 + .../node_modules/concat-map/README.markdown | 62 + .../node_modules/concat-map/example/map.js | 6 + .../node_modules/concat-map/index.js | 13 + .../node_modules/concat-map/package.json | 43 + .../node_modules/concat-map/test/map.js | 39 + .../console-control-strings/LICENSE | 13 + .../console-control-strings/README.md | 145 + .../console-control-strings/README.md~ | 140 + .../console-control-strings/index.js | 125 + .../console-control-strings/package.json | 27 + .../content-disposition/HISTORY.md | 72 + .../node_modules/content-disposition/LICENSE | 22 + .../content-disposition/README.md | 142 + .../node_modules/content-disposition/index.js | 458 + .../content-disposition/package.json | 43 + .../node_modules/content-type/HISTORY.md | 29 + .../node_modules/content-type/LICENSE | 22 + .../node_modules/content-type/README.md | 94 + .../node_modules/content-type/index.js | 225 + .../node_modules/content-type/package.json | 42 + .../node_modules/cookie-signature/History.md | 70 + .../node_modules/cookie-signature/LICENSE | 22 + .../node_modules/cookie-signature/Readme.md | 23 + .../node_modules/cookie-signature/index.js | 47 + .../cookie-signature/package.json | 24 + .../node_modules/cookie/LICENSE | 24 + .../node_modules/cookie/README.md | 317 + .../node_modules/cookie/SECURITY.md | 25 + .../node_modules/cookie/index.js | 335 + .../node_modules/cookie/package.json | 44 + .../node_modules/debug/LICENSE | 20 + .../node_modules/debug/README.md | 481 + .../node_modules/debug/package.json | 64 + .../node_modules/debug/src/browser.js | 272 + .../node_modules/debug/src/common.js | 292 + .../node_modules/debug/src/index.js | 10 + .../node_modules/debug/src/node.js | 263 + .../decompress-response/index.d.ts | 22 + .../node_modules/decompress-response/index.js | 58 + .../node_modules/decompress-response/license | 9 + .../decompress-response/package.json | 56 + .../decompress-response/readme.md | 48 + .../node_modules/deep-extend/CHANGELOG.md | 46 + .../node_modules/deep-extend/LICENSE | 20 + .../node_modules/deep-extend/README.md | 91 + .../node_modules/deep-extend/index.js | 1 + .../deep-extend/lib/deep-extend.js | 150 + .../node_modules/deep-extend/package.json | 62 + .../node_modules/delegates/.npmignore | 1 + .../node_modules/delegates/History.md | 22 + .../node_modules/delegates/License | 20 + .../node_modules/delegates/Makefile | 8 + .../node_modules/delegates/Readme.md | 94 + .../node_modules/delegates/index.js | 121 + .../node_modules/delegates/package.json | 13 + .../node_modules/delegates/test/index.js | 94 + .../node_modules/depd/History.md | 103 + .../node_modules/depd/LICENSE | 22 + .../node_modules/depd/Readme.md | 280 + .../node_modules/depd/index.js | 538 + .../node_modules/depd/lib/browser/index.js | 77 + .../node_modules/depd/package.json | 45 + .../node_modules/detect-libc/LICENSE | 201 + .../node_modules/detect-libc/README.md | 163 + .../node_modules/detect-libc/index.d.ts | 14 + .../detect-libc/lib/detect-libc.js | 313 + .../node_modules/detect-libc/lib/elf.js | 39 + .../detect-libc/lib/filesystem.js | 51 + .../node_modules/detect-libc/lib/process.js | 24 + .../node_modules/detect-libc/package.json | 44 + .../node_modules/dunder-proto/.eslintrc | 5 + .../dunder-proto/.github/FUNDING.yml | 12 + .../node_modules/dunder-proto/.nycrc | 13 + .../node_modules/dunder-proto/CHANGELOG.md | 24 + .../node_modules/dunder-proto/LICENSE | 21 + .../node_modules/dunder-proto/README.md | 54 + .../node_modules/dunder-proto/get.d.ts | 5 + .../node_modules/dunder-proto/get.js | 30 + .../node_modules/dunder-proto/package.json | 76 + .../node_modules/dunder-proto/set.d.ts | 5 + .../node_modules/dunder-proto/set.js | 35 + .../node_modules/dunder-proto/test/get.js | 34 + .../node_modules/dunder-proto/test/index.js | 4 + .../node_modules/dunder-proto/test/set.js | 50 + .../node_modules/dunder-proto/tsconfig.json | 9 + .../node_modules/ee-first/LICENSE | 22 + .../node_modules/ee-first/README.md | 80 + .../node_modules/ee-first/index.js | 95 + .../node_modules/ee-first/package.json | 29 + .../node_modules/emoji-regex/LICENSE-MIT.txt | 20 + .../node_modules/emoji-regex/README.md | 73 + .../node_modules/emoji-regex/es2015/index.js | 6 + .../node_modules/emoji-regex/es2015/text.js | 6 + .../node_modules/emoji-regex/index.d.ts | 23 + .../node_modules/emoji-regex/index.js | 6 + .../node_modules/emoji-regex/package.json | 50 + .../node_modules/emoji-regex/text.js | 6 + .../node_modules/encodeurl/LICENSE | 22 + .../node_modules/encodeurl/README.md | 109 + .../node_modules/encodeurl/index.js | 60 + .../node_modules/encodeurl/package.json | 40 + .../node_modules/encoding/.prettierrc.js | 8 + .../node_modules/encoding/.travis.yml | 25 + .../node_modules/encoding/LICENSE | 16 + .../node_modules/encoding/README.md | 41 + .../node_modules/encoding/lib/encoding.js | 83 + .../iconv-lite/.github/dependabot.yml | 11 + .../iconv-lite/.idea/codeStyles/Project.xml | 47 + .../.idea/codeStyles/codeStyleConfig.xml | 5 + .../iconv-lite/.idea/iconv-lite.iml | 12 + .../inspectionProfiles/Project_Default.xml | 6 + .../node_modules/iconv-lite/.idea/modules.xml | 8 + .../node_modules/iconv-lite/.idea/vcs.xml | 6 + .../node_modules/iconv-lite/Changelog.md | 212 + .../encoding/node_modules/iconv-lite/LICENSE | 21 + .../node_modules/iconv-lite/README.md | 130 + .../iconv-lite/encodings/dbcs-codec.js | 597 + .../iconv-lite/encodings/dbcs-data.js | 188 + .../iconv-lite/encodings/index.js | 23 + .../iconv-lite/encodings/internal.js | 198 + .../iconv-lite/encodings/sbcs-codec.js | 72 + .../encodings/sbcs-data-generated.js | 451 + .../iconv-lite/encodings/sbcs-data.js | 179 + .../encodings/tables/big5-added.json | 122 + .../iconv-lite/encodings/tables/cp936.json | 264 + .../iconv-lite/encodings/tables/cp949.json | 273 + .../iconv-lite/encodings/tables/cp950.json | 177 + .../iconv-lite/encodings/tables/eucjp.json | 182 + .../encodings/tables/gb18030-ranges.json | 1 + .../encodings/tables/gbk-added.json | 56 + .../iconv-lite/encodings/tables/shiftjis.json | 125 + .../iconv-lite/encodings/utf16.js | 197 + .../iconv-lite/encodings/utf32.js | 319 + .../node_modules/iconv-lite/encodings/utf7.js | 290 + .../iconv-lite/lib/bom-handling.js | 52 + .../node_modules/iconv-lite/lib/index.d.ts | 41 + .../node_modules/iconv-lite/lib/index.js | 180 + .../node_modules/iconv-lite/lib/streams.js | 109 + .../node_modules/iconv-lite/package.json | 44 + .../node_modules/encoding/package.json | 18 + .../node_modules/encoding/test/test.js | 49 + .../node_modules/end-of-stream/LICENSE | 21 + .../node_modules/end-of-stream/README.md | 54 + .../node_modules/end-of-stream/index.js | 96 + .../node_modules/end-of-stream/package.json | 37 + .../node_modules/env-paths/index.d.ts | 101 + .../node_modules/env-paths/index.js | 74 + .../node_modules/env-paths/license | 9 + .../node_modules/env-paths/package.json | 45 + .../node_modules/env-paths/readme.md | 115 + .../node_modules/err-code/.editorconfig | 12 + .../node_modules/err-code/.eslintrc.json | 7 + .../node_modules/err-code/.travis.yml | 4 + .../node_modules/err-code/README.md | 70 + .../node_modules/err-code/bower.json | 30 + .../node_modules/err-code/index.js | 47 + .../node_modules/err-code/index.umd.js | 51 + .../node_modules/err-code/package.json | 34 + .../node_modules/err-code/test/.eslintrc.json | 5 + .../node_modules/err-code/test/test.js | 159 + .../node_modules/es-define-property/.eslintrc | 13 + .../es-define-property/.github/FUNDING.yml | 12 + .../node_modules/es-define-property/.nycrc | 9 + .../es-define-property/CHANGELOG.md | 29 + .../node_modules/es-define-property/LICENSE | 21 + .../node_modules/es-define-property/README.md | 49 + .../es-define-property/index.d.ts | 3 + .../node_modules/es-define-property/index.js | 14 + .../es-define-property/package.json | 81 + .../es-define-property/test/index.js | 56 + .../es-define-property/tsconfig.json | 10 + .../node_modules/es-errors/.eslintrc | 5 + .../es-errors/.github/FUNDING.yml | 12 + .../node_modules/es-errors/CHANGELOG.md | 40 + .../node_modules/es-errors/LICENSE | 21 + .../node_modules/es-errors/README.md | 55 + .../node_modules/es-errors/eval.d.ts | 3 + .../node_modules/es-errors/eval.js | 4 + .../node_modules/es-errors/index.d.ts | 3 + .../node_modules/es-errors/index.js | 4 + .../node_modules/es-errors/package.json | 80 + .../node_modules/es-errors/range.d.ts | 3 + .../node_modules/es-errors/range.js | 4 + .../node_modules/es-errors/ref.d.ts | 3 + .../node_modules/es-errors/ref.js | 4 + .../node_modules/es-errors/syntax.d.ts | 3 + .../node_modules/es-errors/syntax.js | 4 + .../node_modules/es-errors/test/index.js | 19 + .../node_modules/es-errors/tsconfig.json | 49 + .../node_modules/es-errors/type.d.ts | 3 + .../node_modules/es-errors/type.js | 4 + .../node_modules/es-errors/uri.d.ts | 3 + .../node_modules/es-errors/uri.js | 4 + .../node_modules/es-object-atoms/.eslintrc | 16 + .../es-object-atoms/.github/FUNDING.yml | 12 + .../node_modules/es-object-atoms/CHANGELOG.md | 37 + .../node_modules/es-object-atoms/LICENSE | 21 + .../node_modules/es-object-atoms/README.md | 63 + .../RequireObjectCoercible.d.ts | 3 + .../es-object-atoms/RequireObjectCoercible.js | 11 + .../es-object-atoms/ToObject.d.ts | 7 + .../node_modules/es-object-atoms/ToObject.js | 10 + .../node_modules/es-object-atoms/index.d.ts | 3 + .../node_modules/es-object-atoms/index.js | 4 + .../es-object-atoms/isObject.d.ts | 3 + .../node_modules/es-object-atoms/isObject.js | 6 + .../node_modules/es-object-atoms/package.json | 80 + .../es-object-atoms/test/index.js | 38 + .../es-object-atoms/tsconfig.json | 6 + .../node_modules/escalade/dist/index.js | 22 + .../node_modules/escalade/dist/index.mjs | 22 + .../node_modules/escalade/index.d.mts | 11 + .../node_modules/escalade/index.d.ts | 15 + .../node_modules/escalade/license | 9 + .../node_modules/escalade/package.json | 74 + .../node_modules/escalade/readme.md | 211 + .../node_modules/escalade/sync/index.d.mts | 9 + .../node_modules/escalade/sync/index.d.ts | 13 + .../node_modules/escalade/sync/index.js | 18 + .../node_modules/escalade/sync/index.mjs | 18 + .../node_modules/escape-html/LICENSE | 24 + .../node_modules/escape-html/Readme.md | 43 + .../node_modules/escape-html/index.js | 78 + .../node_modules/escape-html/package.json | 24 + .../node_modules/esm/LICENSE | 23 + .../node_modules/esm/README.md | 137 + .../node_modules/esm/esm.js | 1 + .../node_modules/esm/esm/loader.js | 1 + .../node_modules/esm/index.js | 1 + .../node_modules/esm/package.json | 27 + .../node_modules/etag/HISTORY.md | 83 + .../node_modules/etag/LICENSE | 22 + .../node_modules/etag/README.md | 159 + .../node_modules/etag/index.js | 131 + .../node_modules/etag/package.json | 47 + .../node_modules/expand-template/.travis.yml | 6 + .../node_modules/expand-template/LICENSE | 21 + .../node_modules/expand-template/README.md | 43 + .../node_modules/expand-template/index.js | 26 + .../node_modules/expand-template/package.json | 29 + .../node_modules/expand-template/test.js | 67 + .../node_modules/express/LICENSE | 24 + .../node_modules/express/Readme.md | 276 + .../node_modules/express/index.js | 11 + .../node_modules/express/lib/application.js | 631 + .../node_modules/express/lib/express.js | 81 + .../node_modules/express/lib/request.js | 514 + .../node_modules/express/lib/response.js | 1053 + .../node_modules/express/lib/utils.js | 271 + .../node_modules/express/lib/view.js | 205 + .../node_modules/express/package.json | 99 + .../node_modules/file-uri-to-path/.npmignore | 1 + .../node_modules/file-uri-to-path/.travis.yml | 30 + .../node_modules/file-uri-to-path/History.md | 21 + .../node_modules/file-uri-to-path/LICENSE | 20 + .../node_modules/file-uri-to-path/README.md | 74 + .../node_modules/file-uri-to-path/index.d.ts | 2 + .../node_modules/file-uri-to-path/index.js | 66 + .../file-uri-to-path/package.json | 32 + .../file-uri-to-path/test/test.js | 24 + .../file-uri-to-path/test/tests.json | 13 + .../node_modules/finalhandler/HISTORY.md | 239 + .../node_modules/finalhandler/LICENSE | 22 + .../node_modules/finalhandler/README.md | 150 + .../node_modules/finalhandler/index.js | 293 + .../node_modules/finalhandler/package.json | 47 + .../node_modules/forwarded/HISTORY.md | 21 + .../node_modules/forwarded/LICENSE | 22 + .../node_modules/forwarded/README.md | 57 + .../node_modules/forwarded/index.js | 90 + .../node_modules/forwarded/package.json | 45 + .../node_modules/fresh/HISTORY.md | 80 + .../node_modules/fresh/LICENSE | 23 + .../node_modules/fresh/README.md | 117 + .../node_modules/fresh/index.js | 136 + .../node_modules/fresh/package.json | 46 + .../node_modules/fs-constants/LICENSE | 21 + .../node_modules/fs-constants/README.md | 26 + .../node_modules/fs-constants/browser.js | 1 + .../node_modules/fs-constants/index.js | 1 + .../node_modules/fs-constants/package.json | 19 + .../node_modules/fs-minipass/LICENSE | 15 + .../node_modules/fs-minipass/README.md | 70 + .../node_modules/fs-minipass/index.js | 422 + .../node_modules/fs-minipass/package.json | 39 + .../node_modules/fs.realpath/LICENSE | 43 + .../node_modules/fs.realpath/README.md | 33 + .../node_modules/fs.realpath/index.js | 66 + .../node_modules/fs.realpath/old.js | 303 + .../node_modules/fs.realpath/package.json | 26 + .../node_modules/function-bind/.eslintrc | 21 + .../function-bind/.github/FUNDING.yml | 12 + .../function-bind/.github/SECURITY.md | 3 + .../node_modules/function-bind/.nycrc | 13 + .../node_modules/function-bind/CHANGELOG.md | 136 + .../node_modules/function-bind/LICENSE | 20 + .../node_modules/function-bind/README.md | 46 + .../function-bind/implementation.js | 84 + .../node_modules/function-bind/index.js | 5 + .../node_modules/function-bind/package.json | 87 + .../node_modules/function-bind/test/.eslintrc | 9 + .../node_modules/function-bind/test/index.js | 252 + .../node_modules/gauge/LICENSE.md | 20 + .../node_modules/gauge/README.md | 402 + .../node_modules/gauge/lib/base-theme.js | 18 + .../node_modules/gauge/lib/error.js | 24 + .../node_modules/gauge/lib/has-color.js | 4 + .../node_modules/gauge/lib/index.js | 289 + .../node_modules/gauge/lib/plumbing.js | 50 + .../node_modules/gauge/lib/process.js | 3 + .../node_modules/gauge/lib/progress-bar.js | 41 + .../node_modules/gauge/lib/render-template.js | 222 + .../node_modules/gauge/lib/set-immediate.js | 7 + .../node_modules/gauge/lib/set-interval.js | 3 + .../node_modules/gauge/lib/spin.js | 5 + .../node_modules/gauge/lib/template-item.js | 87 + .../node_modules/gauge/lib/theme-set.js | 122 + .../node_modules/gauge/lib/themes.js | 56 + .../node_modules/gauge/lib/wide-truncate.js | 31 + .../node_modules/gauge/package.json | 66 + .../node_modules/get-intrinsic/.eslintrc | 42 + .../get-intrinsic/.github/FUNDING.yml | 12 + .../node_modules/get-intrinsic/.nycrc | 9 + .../node_modules/get-intrinsic/CHANGELOG.md | 186 + .../node_modules/get-intrinsic/LICENSE | 21 + .../node_modules/get-intrinsic/README.md | 71 + .../node_modules/get-intrinsic/index.js | 378 + .../node_modules/get-intrinsic/package.json | 97 + .../get-intrinsic/test/GetIntrinsic.js | 274 + .../get-package-type/CHANGELOG.md | 10 + .../node_modules/get-package-type/LICENSE | 21 + .../node_modules/get-package-type/README.md | 32 + .../node_modules/get-package-type/async.cjs | 52 + .../node_modules/get-package-type/cache.cjs | 3 + .../node_modules/get-package-type/index.cjs | 7 + .../get-package-type/is-node-modules.cjs | 15 + .../get-package-type/package.json | 35 + .../node_modules/get-package-type/sync.cjs | 42 + .../node_modules/get-proto/.eslintrc | 10 + .../get-proto/.github/FUNDING.yml | 12 + .../node_modules/get-proto/.nycrc | 9 + .../node_modules/get-proto/CHANGELOG.md | 21 + .../node_modules/get-proto/LICENSE | 21 + .../get-proto/Object.getPrototypeOf.d.ts | 5 + .../get-proto/Object.getPrototypeOf.js | 6 + .../node_modules/get-proto/README.md | 50 + .../get-proto/Reflect.getPrototypeOf.d.ts | 3 + .../get-proto/Reflect.getPrototypeOf.js | 4 + .../node_modules/get-proto/index.d.ts | 5 + .../node_modules/get-proto/index.js | 27 + .../node_modules/get-proto/package.json | 81 + .../node_modules/get-proto/test/index.js | 68 + .../node_modules/get-proto/tsconfig.json | 9 + .../node_modules/getopts/LICENSE.md | 7 + .../node_modules/getopts/README.md | 264 + .../node_modules/getopts/index.cjs | 193 + .../node_modules/getopts/index.d.ts | 27 + .../node_modules/getopts/index.js | 193 + .../node_modules/getopts/package.json | 41 + .../github-from-package/.travis.yml | 4 + .../node_modules/github-from-package/LICENSE | 18 + .../github-from-package/example/package.json | 8 + .../github-from-package/example/url.js | 3 + .../node_modules/github-from-package/index.js | 17 + .../github-from-package/package.json | 30 + .../github-from-package/readme.markdown | 53 + .../github-from-package/test/a.json | 8 + .../github-from-package/test/b.json | 5 + .../github-from-package/test/c.json | 5 + .../github-from-package/test/d.json | 7 + .../github-from-package/test/e.json | 5 + .../github-from-package/test/url.js | 19 + .../node_modules/glob/LICENSE | 21 + .../node_modules/glob/README.md | 378 + .../node_modules/glob/common.js | 238 + .../node_modules/glob/glob.js | 790 + .../node_modules/glob/package.json | 55 + .../node_modules/glob/sync.js | 486 + .../node_modules/gopd/.eslintrc | 16 + .../node_modules/gopd/.github/FUNDING.yml | 12 + .../node_modules/gopd/CHANGELOG.md | 45 + .../node_modules/gopd/LICENSE | 21 + .../node_modules/gopd/README.md | 40 + .../node_modules/gopd/gOPD.d.ts | 1 + .../node_modules/gopd/gOPD.js | 4 + .../node_modules/gopd/index.d.ts | 5 + .../node_modules/gopd/index.js | 15 + .../node_modules/gopd/package.json | 77 + .../node_modules/gopd/test/index.js | 36 + .../node_modules/gopd/tsconfig.json | 9 + .../node_modules/graceful-fs/LICENSE | 15 + .../node_modules/graceful-fs/README.md | 143 + .../node_modules/graceful-fs/clone.js | 23 + .../node_modules/graceful-fs/graceful-fs.js | 448 + .../graceful-fs/legacy-streams.js | 118 + .../node_modules/graceful-fs/package.json | 53 + .../node_modules/graceful-fs/polyfills.js | 355 + .../node_modules/has-symbols/.eslintrc | 11 + .../has-symbols/.github/FUNDING.yml | 12 + .../node_modules/has-symbols/.nycrc | 9 + .../node_modules/has-symbols/CHANGELOG.md | 91 + .../node_modules/has-symbols/LICENSE | 21 + .../node_modules/has-symbols/README.md | 46 + .../node_modules/has-symbols/index.d.ts | 3 + .../node_modules/has-symbols/index.js | 14 + .../node_modules/has-symbols/package.json | 111 + .../node_modules/has-symbols/shams.d.ts | 3 + .../node_modules/has-symbols/shams.js | 45 + .../node_modules/has-symbols/test/index.js | 22 + .../has-symbols/test/shams/core-js.js | 29 + .../test/shams/get-own-property-symbols.js | 29 + .../node_modules/has-symbols/test/tests.js | 58 + .../node_modules/has-symbols/tsconfig.json | 10 + .../node_modules/has-unicode/LICENSE | 14 + .../node_modules/has-unicode/README.md | 43 + .../node_modules/has-unicode/index.js | 16 + .../node_modules/has-unicode/package.json | 30 + .../node_modules/hasown/.eslintrc | 5 + .../node_modules/hasown/.github/FUNDING.yml | 12 + .../node_modules/hasown/.nycrc | 13 + .../node_modules/hasown/CHANGELOG.md | 40 + .../node_modules/hasown/LICENSE | 21 + .../node_modules/hasown/README.md | 40 + .../node_modules/hasown/index.d.ts | 3 + .../node_modules/hasown/index.js | 8 + .../node_modules/hasown/package.json | 92 + .../node_modules/hasown/tsconfig.json | 6 + .../node_modules/http-cache-semantics/LICENSE | 9 + .../http-cache-semantics/README.md | 268 + .../http-cache-semantics/index.js | 928 + .../http-cache-semantics/package.json | 22 + .../node_modules/http-errors/HISTORY.md | 186 + .../node_modules/http-errors/LICENSE | 23 + .../node_modules/http-errors/README.md | 169 + .../node_modules/http-errors/index.js | 290 + .../node_modules/http-errors/package.json | 54 + .../node_modules/http-proxy-agent/README.md | 74 + .../http-proxy-agent/dist/agent.d.ts | 32 + .../http-proxy-agent/dist/agent.js | 145 + .../http-proxy-agent/dist/agent.js.map | 1 + .../http-proxy-agent/dist/index.d.ts | 21 + .../http-proxy-agent/dist/index.js | 14 + .../http-proxy-agent/dist/index.js.map | 1 + .../http-proxy-agent/package.json | 57 + .../node_modules/https-proxy-agent/README.md | 137 + .../https-proxy-agent/dist/agent.d.ts | 30 + .../https-proxy-agent/dist/agent.js | 177 + .../https-proxy-agent/dist/agent.js.map | 1 + .../https-proxy-agent/dist/index.d.ts | 23 + .../https-proxy-agent/dist/index.js | 14 + .../https-proxy-agent/dist/index.js.map | 1 + .../dist/parse-proxy-response.d.ts | 7 + .../dist/parse-proxy-response.js | 66 + .../dist/parse-proxy-response.js.map | 1 + .../https-proxy-agent/package.json | 56 + .../node_modules/humanize-ms/History.md | 25 + .../node_modules/humanize-ms/LICENSE | 17 + .../node_modules/humanize-ms/README.md | 40 + .../node_modules/humanize-ms/index.js | 24 + .../node_modules/humanize-ms/package.json | 37 + .../node_modules/iconv-lite/Changelog.md | 241 + .../node_modules/iconv-lite/LICENSE | 21 + .../node_modules/iconv-lite/README.md | 138 + .../iconv-lite/encodings/dbcs-codec.js | 532 + .../iconv-lite/encodings/dbcs-data.js | 185 + .../iconv-lite/encodings/index.js | 23 + .../iconv-lite/encodings/internal.js | 218 + .../iconv-lite/encodings/sbcs-codec.js | 75 + .../encodings/sbcs-data-generated.js | 451 + .../iconv-lite/encodings/sbcs-data.js | 178 + .../encodings/tables/big5-added.json | 122 + .../iconv-lite/encodings/tables/cp936.json | 264 + .../iconv-lite/encodings/tables/cp949.json | 273 + .../iconv-lite/encodings/tables/cp950.json | 177 + .../iconv-lite/encodings/tables/eucjp.json | 182 + .../encodings/tables/gb18030-ranges.json | 1 + .../encodings/tables/gbk-added.json | 56 + .../iconv-lite/encodings/tables/shiftjis.json | 125 + .../iconv-lite/encodings/utf16.js | 187 + .../iconv-lite/encodings/utf32.js | 307 + .../node_modules/iconv-lite/encodings/utf7.js | 283 + .../iconv-lite/lib/bom-handling.js | 48 + .../iconv-lite/lib/helpers/merge-exports.js | 13 + .../node_modules/iconv-lite/lib/index.d.ts | 131 + .../node_modules/iconv-lite/lib/index.js | 183 + .../node_modules/iconv-lite/lib/streams.js | 105 + .../node_modules/iconv-lite/package.json | 65 + .../iconv-lite/types/encodings.d.ts | 423 + .../node_modules/ieee754/LICENSE | 11 + .../node_modules/ieee754/README.md | 51 + .../node_modules/ieee754/index.d.ts | 10 + .../node_modules/ieee754/index.js | 85 + .../node_modules/ieee754/package.json | 52 + .../node_modules/imurmurhash/README.md | 122 + .../node_modules/imurmurhash/imurmurhash.js | 138 + .../imurmurhash/imurmurhash.min.js | 12 + .../node_modules/imurmurhash/package.json | 40 + .../node_modules/indent-string/index.d.ts | 42 + .../node_modules/indent-string/index.js | 35 + .../node_modules/indent-string/license | 9 + .../node_modules/indent-string/package.json | 37 + .../node_modules/indent-string/readme.md | 70 + .../node_modules/infer-owner/LICENSE | 15 + .../node_modules/infer-owner/README.md | 41 + .../node_modules/infer-owner/index.js | 71 + .../node_modules/infer-owner/package.json | 26 + .../node_modules/inflight/LICENSE | 15 + .../node_modules/inflight/README.md | 37 + .../node_modules/inflight/inflight.js | 54 + .../node_modules/inflight/package.json | 29 + .../node_modules/inherits/LICENSE | 16 + .../node_modules/inherits/README.md | 42 + .../node_modules/inherits/inherits.js | 9 + .../node_modules/inherits/inherits_browser.js | 27 + .../node_modules/inherits/package.json | 29 + .../node_modules/ini/LICENSE | 15 + .../node_modules/ini/README.md | 102 + .../node_modules/ini/ini.js | 206 + .../node_modules/ini/package.json | 33 + .../node_modules/interpret/CHANGELOG | 115 + .../node_modules/interpret/LICENSE | 22 + .../node_modules/interpret/README.md | 229 + .../node_modules/interpret/index.js | 211 + .../node_modules/interpret/mjs-stub.js | 1 + .../node_modules/interpret/package.json | 75 + .../node_modules/ip-address/LICENSE | 19 + .../node_modules/ip-address/README.md | 105 + .../ip-address/dist/address-error.d.ts | 5 + .../ip-address/dist/address-error.d.ts.map | 1 + .../ip-address/dist/address-error.js | 12 + .../ip-address/dist/address-error.js.map | 1 + .../node_modules/ip-address/dist/common.d.ts | 15 + .../ip-address/dist/common.d.ts.map | 1 + .../node_modules/ip-address/dist/common.js | 46 + .../ip-address/dist/common.js.map | 1 + .../ip-address/dist/ip-address.d.ts | 8 + .../ip-address/dist/ip-address.d.ts.map | 1 + .../ip-address/dist/ip-address.js | 35 + .../ip-address/dist/ip-address.js.map | 1 + .../node_modules/ip-address/dist/ipv4.d.ts | 209 + .../ip-address/dist/ipv4.d.ts.map | 1 + .../node_modules/ip-address/dist/ipv4.js | 360 + .../node_modules/ip-address/dist/ipv4.js.map | 1 + .../node_modules/ip-address/dist/ipv6.d.ts | 428 + .../ip-address/dist/ipv6.d.ts.map | 1 + .../node_modules/ip-address/dist/ipv6.js | 1003 + .../node_modules/ip-address/dist/ipv6.js.map | 1 + .../ip-address/dist/v4/constants.d.ts | 5 + .../ip-address/dist/v4/constants.d.ts.map | 1 + .../ip-address/dist/v4/constants.js | 8 + .../ip-address/dist/v4/constants.js.map | 1 + .../ip-address/dist/v6/constants.d.ts | 45 + .../ip-address/dist/v6/constants.d.ts.map | 1 + .../ip-address/dist/v6/constants.js | 76 + .../ip-address/dist/v6/constants.js.map | 1 + .../ip-address/dist/v6/helpers.d.ts | 18 + .../ip-address/dist/v6/helpers.d.ts.map | 1 + .../ip-address/dist/v6/helpers.js | 45 + .../ip-address/dist/v6/helpers.js.map | 1 + .../dist/v6/regular-expressions.d.ts | 6 + .../dist/v6/regular-expressions.d.ts.map | 1 + .../ip-address/dist/v6/regular-expressions.js | 95 + .../dist/v6/regular-expressions.js.map | 1 + .../node_modules/ip-address/package.json | 78 + .../ip-address/src/address-error.ts | 11 + .../node_modules/ip-address/src/common.ts | 55 + .../node_modules/ip-address/src/ip-address.ts | 7 + .../node_modules/ip-address/src/ipv4.ts | 394 + .../node_modules/ip-address/src/ipv6.ts | 1212 ++ .../ip-address/src/v4/constants.ts | 7 + .../ip-address/src/v6/constants.ts | 79 + .../node_modules/ip-address/src/v6/helpers.ts | 48 + .../ip-address/src/v6/regular-expressions.ts | 94 + .../node_modules/ipaddr.js/LICENSE | 19 + .../node_modules/ipaddr.js/README.md | 233 + .../node_modules/ipaddr.js/ipaddr.min.js | 1 + .../node_modules/ipaddr.js/lib/ipaddr.js | 673 + .../node_modules/ipaddr.js/lib/ipaddr.js.d.ts | 68 + .../node_modules/ipaddr.js/package.json | 35 + .../node_modules/is-core-module/.eslintrc | 18 + .../node_modules/is-core-module/.nycrc | 9 + .../node_modules/is-core-module/CHANGELOG.md | 218 + .../node_modules/is-core-module/LICENSE | 20 + .../node_modules/is-core-module/README.md | 40 + .../node_modules/is-core-module/core.json | 162 + .../node_modules/is-core-module/index.js | 69 + .../node_modules/is-core-module/package.json | 76 + .../node_modules/is-core-module/test/index.js | 157 + .../is-fullwidth-code-point/index.d.ts | 17 + .../is-fullwidth-code-point/index.js | 50 + .../is-fullwidth-code-point/license | 9 + .../is-fullwidth-code-point/package.json | 42 + .../is-fullwidth-code-point/readme.md | 39 + .../node_modules/is-lambda/.npmignore | 1 + .../node_modules/is-lambda/.travis.yml | 8 + .../node_modules/is-lambda/LICENSE | 21 + .../node_modules/is-lambda/README.md | 27 + .../node_modules/is-lambda/index.js | 6 + .../node_modules/is-lambda/package.json | 35 + .../node_modules/is-lambda/test.js | 16 + .../node_modules/is-promise/LICENSE | 19 + .../node_modules/is-promise/index.d.ts | 2 + .../node_modules/is-promise/index.js | 6 + .../node_modules/is-promise/index.mjs | 3 + .../node_modules/is-promise/package.json | 30 + .../node_modules/is-promise/readme.md | 33 + .../node_modules/isexe/.npmignore | 2 + .../node_modules/isexe/LICENSE | 15 + .../node_modules/isexe/README.md | 51 + .../node_modules/isexe/index.js | 57 + .../node_modules/isexe/mode.js | 41 + .../node_modules/isexe/package.json | 31 + .../node_modules/isexe/test/basic.js | 221 + .../node_modules/isexe/windows.js | 42 + .../node_modules/knex/CHANGELOG.md | 2380 +++ .../node_modules/knex/CONTRIBUTING.md | 194 + .../node_modules/knex/LICENSE | 22 + .../node_modules/knex/README.md | 149 + .../node_modules/knex/UPGRADING.md | 245 + .../node_modules/knex/bin/cli.js | 475 + .../knex/bin/utils/cli-config-utils.js | 212 + .../node_modules/knex/bin/utils/constants.js | 7 + .../knex/bin/utils/migrationsLister.js | 37 + .../node_modules/knex/knex.js | 23 + .../node_modules/knex/knex.mjs | 11 + .../knex/lib/builder-interface-augmenter.js | 120 + .../node_modules/knex/lib/client.js | 495 + .../node_modules/knex/lib/constants.js | 61 + .../knex/lib/dialects/better-sqlite3/index.js | 77 + .../cockroachdb/crdb-columncompiler.js | 14 + .../dialects/cockroachdb/crdb-querybuilder.js | 11 + .../cockroachdb/crdb-querycompiler.js | 122 + .../cockroachdb/crdb-tablecompiler.js | 37 + .../dialects/cockroachdb/crdb-viewcompiler.js | 15 + .../knex/lib/dialects/cockroachdb/index.js | 86 + .../node_modules/knex/lib/dialects/index.js | 34 + .../knex/lib/dialects/mssql/index.js | 500 + .../lib/dialects/mssql/mssql-formatter.js | 34 + .../mssql/query/mssql-querycompiler.js | 601 + .../mssql/schema/mssql-columncompiler.js | 185 + .../dialects/mssql/schema/mssql-compiler.js | 91 + .../mssql/schema/mssql-tablecompiler.js | 378 + .../mssql/schema/mssql-viewcompiler.js | 55 + .../knex/lib/dialects/mssql/transaction.js | 176 + .../knex/lib/dialects/mysql/index.js | 206 + .../mysql/query/mysql-querybuilder.js | 14 + .../mysql/query/mysql-querycompiler.js | 292 + .../mysql/schema/mysql-columncompiler.js | 193 + .../dialects/mysql/schema/mysql-compiler.js | 60 + .../mysql/schema/mysql-tablecompiler.js | 405 + .../mysql/schema/mysql-viewbuilder.js | 21 + .../mysql/schema/mysql-viewcompiler.js | 15 + .../knex/lib/dialects/mysql/transaction.js | 46 + .../knex/lib/dialects/mysql2/index.js | 53 + .../knex/lib/dialects/mysql2/transaction.js | 44 + .../knex/lib/dialects/oracle/DEAD_CODE.md | 5 + .../knex/lib/dialects/oracle/index.js | 92 + .../oracle/query/oracle-querycompiler.js | 343 + .../oracle/schema/internal/incrementUtils.js | 22 + .../oracle/schema/internal/trigger.js | 155 + .../oracle/schema/oracle-columnbuilder.js | 17 + .../oracle/schema/oracle-columncompiler.js | 126 + .../dialects/oracle/schema/oracle-compiler.js | 124 + .../oracle/schema/oracle-tablecompiler.js | 197 + .../knex/lib/dialects/oracle/utils.js | 106 + .../knex/lib/dialects/oracledb/index.js | 381 + .../oracledb/query/oracledb-querycompiler.js | 481 + .../schema/oracledb-columncompiler.js | 61 + .../oracledb/schema/oracledb-tablecompiler.js | 19 + .../oracledb/schema/oracledb-viewbuilder.js | 13 + .../oracledb/schema/oracledb-viewcompiler.js | 19 + .../knex/lib/dialects/oracledb/transaction.js | 98 + .../knex/lib/dialects/oracledb/utils.js | 208 + .../knex/lib/dialects/pgnative/index.js | 60 + .../postgres/execution/pg-transaction.js | 19 + .../knex/lib/dialects/postgres/index.js | 361 + .../postgres/query/pg-querybuilder.js | 43 + .../postgres/query/pg-querycompiler.js | 400 + .../postgres/schema/pg-columncompiler.js | 156 + .../dialects/postgres/schema/pg-compiler.js | 138 + .../postgres/schema/pg-tablecompiler.js | 304 + .../postgres/schema/pg-viewbuilder.js | 21 + .../postgres/schema/pg-viewcompiler.js | 35 + .../knex/lib/dialects/redshift/index.js | 86 + .../redshift/query/redshift-querycompiler.js | 163 + .../redshift/schema/redshift-columnbuilder.js | 22 + .../schema/redshift-columncompiler.js | 67 + .../redshift/schema/redshift-compiler.js | 14 + .../redshift/schema/redshift-tablecompiler.js | 122 + .../redshift/schema/redshift-viewcompiler.js | 11 + .../knex/lib/dialects/redshift/transaction.js | 32 + .../sqlite3/execution/sqlite-transaction.js | 25 + .../knex/lib/dialects/sqlite3/index.js | 250 + .../sqlite3/query/sqlite-querybuilder.js | 33 + .../sqlite3/query/sqlite-querycompiler.js | 334 + .../knex/lib/dialects/sqlite3/schema/ddl.js | 400 + .../sqlite3/schema/internal/compiler.js | 327 + .../schema/internal/parser-combinator.js | 161 + .../sqlite3/schema/internal/parser.js | 638 + .../schema/internal/sqlite-ddl-operations.js | 41 + .../sqlite3/schema/internal/tokenizer.js | 38 + .../dialects/sqlite3/schema/internal/utils.js | 12 + .../sqlite3/schema/sqlite-columncompiler.js | 50 + .../sqlite3/schema/sqlite-compiler.js | 80 + .../sqlite3/schema/sqlite-tablecompiler.js | 347 + .../sqlite3/schema/sqlite-viewcompiler.js | 40 + .../knex/lib/execution/batch-insert.js | 51 + .../knex/lib/execution/internal/delay.js | 6 + .../internal/ensure-connection-callback.js | 41 + .../execution/internal/query-executioner.js | 62 + .../node_modules/knex/lib/execution/runner.js | 325 + .../knex/lib/execution/transaction.js | 413 + .../node_modules/knex/lib/formatter.js | 25 + .../knex/lib/formatter/formatterUtils.js | 42 + .../knex/lib/formatter/rawFormatter.js | 84 + .../knex/lib/formatter/wrappingFormatter.js | 250 + .../node_modules/knex/lib/index.js | 3 + .../knex/lib/knex-builder/FunctionHelper.js | 80 + .../knex/lib/knex-builder/Knex.js | 59 + .../knex-builder/internal/config-resolver.js | 57 + .../knex-builder/internal/parse-connection.js | 87 + .../knex/lib/knex-builder/make-knex.js | 345 + .../node_modules/knex/lib/logger.js | 76 + .../lib/migrations/common/MigrationsLoader.js | 36 + .../migrations/migrate/MigrationGenerator.js | 84 + .../knex/lib/migrations/migrate/Migrator.js | 599 + .../lib/migrations/migrate/migrate-stub.js | 17 + .../migrate/migration-list-resolver.js | 33 + .../migrate/migrator-configuration-merger.js | 58 + .../migrate/sources/fs-migrations.js | 74 + .../knex/lib/migrations/migrate/stub/cjs.stub | 15 + .../lib/migrations/migrate/stub/coffee.stub | 13 + .../knex/lib/migrations/migrate/stub/eg.stub | 14 + .../migrations/migrate/stub/js-schema.stub | 22 + .../knex/lib/migrations/migrate/stub/js.stub | 22 + .../migrate/stub/knexfile-coffee.stub | 34 + .../migrations/migrate/stub/knexfile-eg.stub | 43 + .../migrations/migrate/stub/knexfile-js.stub | 47 + .../migrations/migrate/stub/knexfile-ls.stub | 35 + .../migrations/migrate/stub/knexfile-ts.stub | 47 + .../knex/lib/migrations/migrate/stub/ls.stub | 14 + .../knex/lib/migrations/migrate/stub/mjs.stub | 23 + .../migrations/migrate/stub/ts-schema.stub | 21 + .../knex/lib/migrations/migrate/stub/ts.stub | 21 + .../lib/migrations/migrate/table-creator.js | 77 + .../lib/migrations/migrate/table-resolver.js | 27 + .../knex/lib/migrations/seed/Seeder.js | 137 + .../knex/lib/migrations/seed/seed-stub.js | 13 + .../seed/seeder-configuration-merger.js | 60 + .../lib/migrations/seed/sources/fs-seeds.js | 65 + .../knex/lib/migrations/seed/stub/coffee.stub | 9 + .../knex/lib/migrations/seed/stub/eg.stub | 11 + .../knex/lib/migrations/seed/stub/js.stub | 13 + .../knex/lib/migrations/seed/stub/ls.stub | 11 + .../knex/lib/migrations/seed/stub/mjs.stub | 12 + .../knex/lib/migrations/seed/stub/ts.stub | 13 + .../knex/lib/migrations/util/fs.js | 86 + .../knex/lib/migrations/util/import-file.js | 12 + .../lib/migrations/util/is-module-type.js | 9 + .../knex/lib/migrations/util/template.js | 52 + .../knex/lib/migrations/util/timestamp.js | 14 + .../node_modules/knex/lib/query/analytic.js | 52 + .../node_modules/knex/lib/query/constants.js | 15 + .../node_modules/knex/lib/query/joinclause.js | 270 + .../knex/lib/query/method-constants.js | 136 + .../knex/lib/query/querybuilder.js | 1793 ++ .../knex/lib/query/querycompiler.js | 1591 ++ .../node_modules/knex/lib/raw.js | 139 + .../node_modules/knex/lib/ref.js | 39 + .../node_modules/knex/lib/schema/builder.js | 115 + .../knex/lib/schema/columnbuilder.js | 146 + .../knex/lib/schema/columncompiler.js | 307 + .../node_modules/knex/lib/schema/compiler.js | 187 + .../knex/lib/schema/internal/helpers.js | 55 + .../knex/lib/schema/tablebuilder.js | 376 + .../knex/lib/schema/tablecompiler.js | 439 + .../knex/lib/schema/viewbuilder.js | 92 + .../knex/lib/schema/viewcompiler.js | 138 + .../knex/lib/util/finally-mixin.js | 13 + .../node_modules/knex/lib/util/helpers.js | 95 + .../node_modules/knex/lib/util/is.js | 32 + .../node_modules/knex/lib/util/nanoid.js | 40 + .../node_modules/knex/lib/util/noop.js | 1 + .../knex/lib/util/save-async-stack.js | 14 + .../node_modules/knex/lib/util/security.js | 26 + .../node_modules/knex/lib/util/string.js | 190 + .../node_modules/knex/lib/util/timeout.js | 29 + .../knex/node_modules/debug/LICENSE | 20 + .../knex/node_modules/debug/README.md | 481 + .../knex/node_modules/debug/package.json | 59 + .../knex/node_modules/debug/src/browser.js | 269 + .../knex/node_modules/debug/src/common.js | 274 + .../knex/node_modules/debug/src/index.js | 10 + .../knex/node_modules/debug/src/node.js | 263 + .../knex/node_modules/ms/index.js | 162 + .../knex/node_modules/ms/license.md | 21 + .../knex/node_modules/ms/package.json | 37 + .../knex/node_modules/ms/readme.md | 60 + .../node_modules/knex/package.json | 267 + .../node_modules/knex/scripts/build.js | 125 + .../node_modules/knex/scripts/clean.js | 31 + .../knex/scripts/docker-compose.yml | 152 + .../knex/scripts/next-release-howto.md | 24 + .../scripts/oracledb-install-driver-libs.sh | 82 + .../node_modules/knex/scripts/release.sh | 36 + .../knex/scripts/runkit-example.js | 35 + .../knex/scripts/stress-test/README.txt | 18 + .../scripts/stress-test/docker-compose.yml | 57 + .../scripts/stress-test/knex-stress-test.js | 212 + ...ysql2-random-hanging-every-now-and-then.js | 149 + .../mysql2-sudden-exit-without-error.js | 101 + .../reconnect-test-mysql-based-drivers.js | 188 + .../update_gitignore_for_tsc_output.js | 90 + .../node_modules/knex/types/index.d.ts | 3275 +++ .../node_modules/knex/types/result.d.ts | 27 + .../node_modules/knex/types/tables.d.ts | 4 + .../node_modules/lodash/LICENSE | 47 + .../node_modules/lodash/README.md | 39 + .../node_modules/lodash/_DataView.js | 7 + .../node_modules/lodash/_Hash.js | 32 + .../node_modules/lodash/_LazyWrapper.js | 28 + .../node_modules/lodash/_ListCache.js | 32 + .../node_modules/lodash/_LodashWrapper.js | 22 + .../node_modules/lodash/_Map.js | 7 + .../node_modules/lodash/_MapCache.js | 32 + .../node_modules/lodash/_Promise.js | 7 + .../node_modules/lodash/_Set.js | 7 + .../node_modules/lodash/_SetCache.js | 27 + .../node_modules/lodash/_Stack.js | 27 + .../node_modules/lodash/_Symbol.js | 6 + .../node_modules/lodash/_Uint8Array.js | 6 + .../node_modules/lodash/_WeakMap.js | 7 + .../node_modules/lodash/_apply.js | 21 + .../node_modules/lodash/_arrayAggregator.js | 22 + .../node_modules/lodash/_arrayEach.js | 22 + .../node_modules/lodash/_arrayEachRight.js | 21 + .../node_modules/lodash/_arrayEvery.js | 23 + .../node_modules/lodash/_arrayFilter.js | 25 + .../node_modules/lodash/_arrayIncludes.js | 17 + .../node_modules/lodash/_arrayIncludesWith.js | 22 + .../node_modules/lodash/_arrayLikeKeys.js | 49 + .../node_modules/lodash/_arrayMap.js | 21 + .../node_modules/lodash/_arrayPush.js | 20 + .../node_modules/lodash/_arrayReduce.js | 26 + .../node_modules/lodash/_arrayReduceRight.js | 24 + .../node_modules/lodash/_arraySample.js | 15 + .../node_modules/lodash/_arraySampleSize.js | 17 + .../node_modules/lodash/_arrayShuffle.js | 15 + .../node_modules/lodash/_arraySome.js | 23 + .../node_modules/lodash/_asciiSize.js | 12 + .../node_modules/lodash/_asciiToArray.js | 12 + .../node_modules/lodash/_asciiWords.js | 15 + .../node_modules/lodash/_assignMergeValue.js | 20 + .../node_modules/lodash/_assignValue.js | 28 + .../node_modules/lodash/_assocIndexOf.js | 21 + .../node_modules/lodash/_baseAggregator.js | 21 + .../node_modules/lodash/_baseAssign.js | 17 + .../node_modules/lodash/_baseAssignIn.js | 17 + .../node_modules/lodash/_baseAssignValue.js | 25 + .../node_modules/lodash/_baseAt.js | 23 + .../node_modules/lodash/_baseClamp.js | 22 + .../node_modules/lodash/_baseClone.js | 166 + .../node_modules/lodash/_baseConforms.js | 18 + .../node_modules/lodash/_baseConformsTo.js | 27 + .../node_modules/lodash/_baseCreate.js | 30 + .../node_modules/lodash/_baseDelay.js | 21 + .../node_modules/lodash/_baseDifference.js | 67 + .../node_modules/lodash/_baseEach.js | 14 + .../node_modules/lodash/_baseEachRight.js | 14 + .../node_modules/lodash/_baseEvery.js | 21 + .../node_modules/lodash/_baseExtremum.js | 32 + .../node_modules/lodash/_baseFill.js | 32 + .../node_modules/lodash/_baseFilter.js | 21 + .../node_modules/lodash/_baseFindIndex.js | 24 + .../node_modules/lodash/_baseFindKey.js | 23 + .../node_modules/lodash/_baseFlatten.js | 38 + .../node_modules/lodash/_baseFor.js | 16 + .../node_modules/lodash/_baseForOwn.js | 16 + .../node_modules/lodash/_baseForOwnRight.js | 16 + .../node_modules/lodash/_baseForRight.js | 15 + .../node_modules/lodash/_baseFunctions.js | 19 + .../node_modules/lodash/_baseGet.js | 24 + .../node_modules/lodash/_baseGetAllKeys.js | 20 + .../node_modules/lodash/_baseGetTag.js | 28 + .../node_modules/lodash/_baseGt.js | 14 + .../node_modules/lodash/_baseHas.js | 19 + .../node_modules/lodash/_baseHasIn.js | 13 + .../node_modules/lodash/_baseInRange.js | 18 + .../node_modules/lodash/_baseIndexOf.js | 20 + .../node_modules/lodash/_baseIndexOfWith.js | 23 + .../node_modules/lodash/_baseIntersection.js | 74 + .../node_modules/lodash/_baseInverter.js | 21 + .../node_modules/lodash/_baseInvoke.js | 24 + .../node_modules/lodash/_baseIsArguments.js | 18 + .../node_modules/lodash/_baseIsArrayBuffer.js | 17 + .../node_modules/lodash/_baseIsDate.js | 18 + .../node_modules/lodash/_baseIsEqual.js | 28 + .../node_modules/lodash/_baseIsEqualDeep.js | 83 + .../node_modules/lodash/_baseIsMap.js | 18 + .../node_modules/lodash/_baseIsMatch.js | 62 + .../node_modules/lodash/_baseIsNaN.js | 12 + .../node_modules/lodash/_baseIsNative.js | 47 + .../node_modules/lodash/_baseIsRegExp.js | 18 + .../node_modules/lodash/_baseIsSet.js | 18 + .../node_modules/lodash/_baseIsTypedArray.js | 60 + .../node_modules/lodash/_baseIteratee.js | 31 + .../node_modules/lodash/_baseKeys.js | 30 + .../node_modules/lodash/_baseKeysIn.js | 33 + .../node_modules/lodash/_baseLodash.js | 10 + .../node_modules/lodash/_baseLt.js | 14 + .../node_modules/lodash/_baseMap.js | 22 + .../node_modules/lodash/_baseMatches.js | 22 + .../lodash/_baseMatchesProperty.js | 33 + .../node_modules/lodash/_baseMean.js | 20 + .../node_modules/lodash/_baseMerge.js | 42 + .../node_modules/lodash/_baseMergeDeep.js | 94 + .../node_modules/lodash/_baseNth.js | 20 + .../node_modules/lodash/_baseOrderBy.js | 49 + .../node_modules/lodash/_basePick.js | 19 + .../node_modules/lodash/_basePickBy.js | 30 + .../node_modules/lodash/_baseProperty.js | 14 + .../node_modules/lodash/_basePropertyDeep.js | 16 + .../node_modules/lodash/_basePropertyOf.js | 14 + .../node_modules/lodash/_basePullAll.js | 51 + .../node_modules/lodash/_basePullAt.js | 37 + .../node_modules/lodash/_baseRandom.js | 18 + .../node_modules/lodash/_baseRange.js | 28 + .../node_modules/lodash/_baseReduce.js | 23 + .../node_modules/lodash/_baseRepeat.js | 35 + .../node_modules/lodash/_baseRest.js | 17 + .../node_modules/lodash/_baseSample.js | 15 + .../node_modules/lodash/_baseSampleSize.js | 18 + .../node_modules/lodash/_baseSet.js | 51 + .../node_modules/lodash/_baseSetData.js | 17 + .../node_modules/lodash/_baseSetToString.js | 22 + .../node_modules/lodash/_baseShuffle.js | 15 + .../node_modules/lodash/_baseSlice.js | 31 + .../node_modules/lodash/_baseSome.js | 22 + .../node_modules/lodash/_baseSortBy.js | 21 + .../node_modules/lodash/_baseSortedIndex.js | 42 + .../node_modules/lodash/_baseSortedIndexBy.js | 67 + .../node_modules/lodash/_baseSortedUniq.js | 30 + .../node_modules/lodash/_baseSum.js | 24 + .../node_modules/lodash/_baseTimes.js | 20 + .../node_modules/lodash/_baseToNumber.js | 24 + .../node_modules/lodash/_baseToPairs.js | 18 + .../node_modules/lodash/_baseToString.js | 37 + .../node_modules/lodash/_baseTrim.js | 19 + .../node_modules/lodash/_baseUnary.js | 14 + .../node_modules/lodash/_baseUniq.js | 72 + .../node_modules/lodash/_baseUnset.js | 20 + .../node_modules/lodash/_baseUpdate.js | 18 + .../node_modules/lodash/_baseValues.js | 19 + .../node_modules/lodash/_baseWhile.js | 26 + .../node_modules/lodash/_baseWrapperValue.js | 25 + .../node_modules/lodash/_baseXor.js | 36 + .../node_modules/lodash/_baseZipObject.js | 23 + .../node_modules/lodash/_cacheHas.js | 13 + .../lodash/_castArrayLikeObject.js | 14 + .../node_modules/lodash/_castFunction.js | 14 + .../node_modules/lodash/_castPath.js | 21 + .../node_modules/lodash/_castRest.js | 14 + .../node_modules/lodash/_castSlice.js | 18 + .../node_modules/lodash/_charsEndIndex.js | 19 + .../node_modules/lodash/_charsStartIndex.js | 20 + .../node_modules/lodash/_cloneArrayBuffer.js | 16 + .../node_modules/lodash/_cloneBuffer.js | 35 + .../node_modules/lodash/_cloneDataView.js | 16 + .../node_modules/lodash/_cloneRegExp.js | 17 + .../node_modules/lodash/_cloneSymbol.js | 18 + .../node_modules/lodash/_cloneTypedArray.js | 16 + .../node_modules/lodash/_compareAscending.js | 41 + .../node_modules/lodash/_compareMultiple.js | 44 + .../node_modules/lodash/_composeArgs.js | 39 + .../node_modules/lodash/_composeArgsRight.js | 41 + .../node_modules/lodash/_copyArray.js | 20 + .../node_modules/lodash/_copyObject.js | 40 + .../node_modules/lodash/_copySymbols.js | 16 + .../node_modules/lodash/_copySymbolsIn.js | 16 + .../node_modules/lodash/_coreJsData.js | 6 + .../node_modules/lodash/_countHolders.js | 21 + .../node_modules/lodash/_createAggregator.js | 23 + .../node_modules/lodash/_createAssigner.js | 37 + .../node_modules/lodash/_createBaseEach.js | 32 + .../node_modules/lodash/_createBaseFor.js | 25 + .../node_modules/lodash/_createBind.js | 28 + .../node_modules/lodash/_createCaseFirst.js | 33 + .../node_modules/lodash/_createCompounder.js | 24 + .../node_modules/lodash/_createCtor.js | 37 + .../node_modules/lodash/_createCurry.js | 46 + .../node_modules/lodash/_createFind.js | 25 + .../node_modules/lodash/_createFlow.js | 78 + .../node_modules/lodash/_createHybrid.js | 92 + .../node_modules/lodash/_createInverter.js | 17 + .../lodash/_createMathOperation.js | 38 + .../node_modules/lodash/_createOver.js | 27 + .../node_modules/lodash/_createPadding.js | 33 + .../node_modules/lodash/_createPartial.js | 43 + .../node_modules/lodash/_createRange.js | 30 + .../node_modules/lodash/_createRecurry.js | 56 + .../lodash/_createRelationalOperation.js | 20 + .../node_modules/lodash/_createRound.js | 35 + .../node_modules/lodash/_createSet.js | 19 + .../node_modules/lodash/_createToPairs.js | 30 + .../node_modules/lodash/_createWrap.js | 106 + .../lodash/_customDefaultsAssignIn.js | 29 + .../lodash/_customDefaultsMerge.js | 28 + .../node_modules/lodash/_customOmitClone.js | 16 + .../node_modules/lodash/_deburrLetter.js | 71 + .../node_modules/lodash/_defineProperty.js | 11 + .../node_modules/lodash/_equalArrays.js | 84 + .../node_modules/lodash/_equalByTag.js | 112 + .../node_modules/lodash/_equalObjects.js | 90 + .../node_modules/lodash/_escapeHtmlChar.js | 21 + .../node_modules/lodash/_escapeStringChar.js | 22 + .../node_modules/lodash/_flatRest.js | 16 + .../node_modules/lodash/_freeGlobal.js | 4 + .../node_modules/lodash/_getAllKeys.js | 16 + .../node_modules/lodash/_getAllKeysIn.js | 17 + .../node_modules/lodash/_getData.js | 15 + .../node_modules/lodash/_getFuncName.js | 31 + .../node_modules/lodash/_getHolder.js | 13 + .../node_modules/lodash/_getMapData.js | 18 + .../node_modules/lodash/_getMatchData.js | 24 + .../node_modules/lodash/_getNative.js | 17 + .../node_modules/lodash/_getPrototype.js | 6 + .../node_modules/lodash/_getRawTag.js | 46 + .../node_modules/lodash/_getSymbols.js | 30 + .../node_modules/lodash/_getSymbolsIn.js | 25 + .../node_modules/lodash/_getTag.js | 58 + .../node_modules/lodash/_getValue.js | 13 + .../node_modules/lodash/_getView.js | 33 + .../node_modules/lodash/_getWrapDetails.js | 17 + .../node_modules/lodash/_hasPath.js | 39 + .../node_modules/lodash/_hasUnicode.js | 26 + .../node_modules/lodash/_hasUnicodeWord.js | 15 + .../node_modules/lodash/_hashClear.js | 15 + .../node_modules/lodash/_hashDelete.js | 17 + .../node_modules/lodash/_hashGet.js | 30 + .../node_modules/lodash/_hashHas.js | 23 + .../node_modules/lodash/_hashSet.js | 23 + .../node_modules/lodash/_initCloneArray.js | 26 + .../node_modules/lodash/_initCloneByTag.js | 77 + .../node_modules/lodash/_initCloneObject.js | 18 + .../node_modules/lodash/_insertWrapDetails.js | 23 + .../node_modules/lodash/_isFlattenable.js | 20 + .../node_modules/lodash/_isIndex.js | 25 + .../node_modules/lodash/_isIterateeCall.js | 30 + .../node_modules/lodash/_isKey.js | 29 + .../node_modules/lodash/_isKeyable.js | 15 + .../node_modules/lodash/_isLaziable.js | 28 + .../node_modules/lodash/_isMaskable.js | 14 + .../node_modules/lodash/_isMasked.js | 20 + .../node_modules/lodash/_isPrototype.js | 18 + .../lodash/_isStrictComparable.js | 15 + .../node_modules/lodash/_iteratorToArray.js | 18 + .../node_modules/lodash/_lazyClone.js | 23 + .../node_modules/lodash/_lazyReverse.js | 23 + .../node_modules/lodash/_lazyValue.js | 69 + .../node_modules/lodash/_listCacheClear.js | 13 + .../node_modules/lodash/_listCacheDelete.js | 35 + .../node_modules/lodash/_listCacheGet.js | 19 + .../node_modules/lodash/_listCacheHas.js | 16 + .../node_modules/lodash/_listCacheSet.js | 26 + .../node_modules/lodash/_mapCacheClear.js | 21 + .../node_modules/lodash/_mapCacheDelete.js | 18 + .../node_modules/lodash/_mapCacheGet.js | 16 + .../node_modules/lodash/_mapCacheHas.js | 16 + .../node_modules/lodash/_mapCacheSet.js | 22 + .../node_modules/lodash/_mapToArray.js | 18 + .../lodash/_matchesStrictComparable.js | 20 + .../node_modules/lodash/_memoizeCapped.js | 26 + .../node_modules/lodash/_mergeData.js | 90 + .../node_modules/lodash/_metaMap.js | 6 + .../node_modules/lodash/_nativeCreate.js | 6 + .../node_modules/lodash/_nativeKeys.js | 6 + .../node_modules/lodash/_nativeKeysIn.js | 20 + .../node_modules/lodash/_nodeUtil.js | 30 + .../node_modules/lodash/_objectToString.js | 22 + .../node_modules/lodash/_overArg.js | 15 + .../node_modules/lodash/_overRest.js | 36 + .../node_modules/lodash/_parent.js | 16 + .../node_modules/lodash/_reEscape.js | 4 + .../node_modules/lodash/_reEvaluate.js | 4 + .../node_modules/lodash/_reInterpolate.js | 4 + .../node_modules/lodash/_realNames.js | 4 + .../node_modules/lodash/_reorder.js | 29 + .../node_modules/lodash/_replaceHolders.js | 29 + .../node_modules/lodash/_root.js | 9 + .../node_modules/lodash/_safeGet.js | 21 + .../node_modules/lodash/_setCacheAdd.js | 19 + .../node_modules/lodash/_setCacheHas.js | 14 + .../node_modules/lodash/_setData.js | 20 + .../node_modules/lodash/_setToArray.js | 18 + .../node_modules/lodash/_setToPairs.js | 18 + .../node_modules/lodash/_setToString.js | 14 + .../node_modules/lodash/_setWrapToString.js | 21 + .../node_modules/lodash/_shortOut.js | 37 + .../node_modules/lodash/_shuffleSelf.js | 28 + .../node_modules/lodash/_stackClear.js | 15 + .../node_modules/lodash/_stackDelete.js | 18 + .../node_modules/lodash/_stackGet.js | 14 + .../node_modules/lodash/_stackHas.js | 14 + .../node_modules/lodash/_stackSet.js | 34 + .../node_modules/lodash/_strictIndexOf.js | 23 + .../node_modules/lodash/_strictLastIndexOf.js | 21 + .../node_modules/lodash/_stringSize.js | 18 + .../node_modules/lodash/_stringToArray.js | 18 + .../node_modules/lodash/_stringToPath.js | 27 + .../node_modules/lodash/_toKey.js | 21 + .../node_modules/lodash/_toSource.js | 26 + .../node_modules/lodash/_trimmedEndIndex.js | 19 + .../node_modules/lodash/_unescapeHtmlChar.js | 21 + .../node_modules/lodash/_unicodeSize.js | 44 + .../node_modules/lodash/_unicodeToArray.js | 40 + .../node_modules/lodash/_unicodeWords.js | 69 + .../node_modules/lodash/_updateWrapDetails.js | 46 + .../node_modules/lodash/_wrapperClone.js | 23 + .../node_modules/lodash/add.js | 22 + .../node_modules/lodash/after.js | 42 + .../node_modules/lodash/array.js | 67 + .../node_modules/lodash/ary.js | 29 + .../node_modules/lodash/assign.js | 58 + .../node_modules/lodash/assignIn.js | 40 + .../node_modules/lodash/assignInWith.js | 38 + .../node_modules/lodash/assignWith.js | 37 + .../node_modules/lodash/at.js | 23 + .../node_modules/lodash/attempt.js | 35 + .../node_modules/lodash/before.js | 40 + .../node_modules/lodash/bind.js | 57 + .../node_modules/lodash/bindAll.js | 41 + .../node_modules/lodash/bindKey.js | 68 + .../node_modules/lodash/camelCase.js | 29 + .../node_modules/lodash/capitalize.js | 23 + .../node_modules/lodash/castArray.js | 44 + .../node_modules/lodash/ceil.js | 26 + .../node_modules/lodash/chain.js | 38 + .../node_modules/lodash/chunk.js | 50 + .../node_modules/lodash/clamp.js | 39 + .../node_modules/lodash/clone.js | 36 + .../node_modules/lodash/cloneDeep.js | 29 + .../node_modules/lodash/cloneDeepWith.js | 40 + .../node_modules/lodash/cloneWith.js | 42 + .../node_modules/lodash/collection.js | 30 + .../node_modules/lodash/commit.js | 33 + .../node_modules/lodash/compact.js | 31 + .../node_modules/lodash/concat.js | 43 + .../node_modules/lodash/cond.js | 60 + .../node_modules/lodash/conforms.js | 35 + .../node_modules/lodash/conformsTo.js | 32 + .../node_modules/lodash/constant.js | 26 + .../node_modules/lodash/core.js | 3877 ++++ .../node_modules/lodash/core.min.js | 29 + .../node_modules/lodash/countBy.js | 40 + .../node_modules/lodash/create.js | 43 + .../node_modules/lodash/curry.js | 57 + .../node_modules/lodash/curryRight.js | 54 + .../node_modules/lodash/date.js | 3 + .../node_modules/lodash/debounce.js | 191 + .../node_modules/lodash/deburr.js | 45 + .../node_modules/lodash/defaultTo.js | 25 + .../node_modules/lodash/defaults.js | 64 + .../node_modules/lodash/defaultsDeep.js | 30 + .../node_modules/lodash/defer.js | 26 + .../node_modules/lodash/delay.js | 28 + .../node_modules/lodash/difference.js | 33 + .../node_modules/lodash/differenceBy.js | 44 + .../node_modules/lodash/differenceWith.js | 40 + .../node_modules/lodash/divide.js | 22 + .../node_modules/lodash/drop.js | 38 + .../node_modules/lodash/dropRight.js | 39 + .../node_modules/lodash/dropRightWhile.js | 45 + .../node_modules/lodash/dropWhile.js | 45 + .../node_modules/lodash/each.js | 1 + .../node_modules/lodash/eachRight.js | 1 + .../node_modules/lodash/endsWith.js | 43 + .../node_modules/lodash/entries.js | 1 + .../node_modules/lodash/entriesIn.js | 1 + .../node_modules/lodash/eq.js | 37 + .../node_modules/lodash/escape.js | 43 + .../node_modules/lodash/escapeRegExp.js | 32 + .../node_modules/lodash/every.js | 56 + .../node_modules/lodash/extend.js | 1 + .../node_modules/lodash/extendWith.js | 1 + .../node_modules/lodash/fill.js | 45 + .../node_modules/lodash/filter.js | 52 + .../node_modules/lodash/find.js | 42 + .../node_modules/lodash/findIndex.js | 55 + .../node_modules/lodash/findKey.js | 44 + .../node_modules/lodash/findLast.js | 25 + .../node_modules/lodash/findLastIndex.js | 59 + .../node_modules/lodash/findLastKey.js | 44 + .../node_modules/lodash/first.js | 1 + .../node_modules/lodash/flake.lock | 40 + .../node_modules/lodash/flake.nix | 20 + .../node_modules/lodash/flatMap.js | 29 + .../node_modules/lodash/flatMapDeep.js | 31 + .../node_modules/lodash/flatMapDepth.js | 31 + .../node_modules/lodash/flatten.js | 22 + .../node_modules/lodash/flattenDeep.js | 25 + .../node_modules/lodash/flattenDepth.js | 33 + .../node_modules/lodash/flip.js | 28 + .../node_modules/lodash/floor.js | 26 + .../node_modules/lodash/flow.js | 27 + .../node_modules/lodash/flowRight.js | 26 + .../node_modules/lodash/forEach.js | 41 + .../node_modules/lodash/forEachRight.js | 31 + .../node_modules/lodash/forIn.js | 39 + .../node_modules/lodash/forInRight.js | 37 + .../node_modules/lodash/forOwn.js | 36 + .../node_modules/lodash/forOwnRight.js | 34 + .../node_modules/lodash/fp.js | 2 + .../node_modules/lodash/fp/F.js | 1 + .../node_modules/lodash/fp/T.js | 1 + .../node_modules/lodash/fp/__.js | 1 + .../node_modules/lodash/fp/_baseConvert.js | 569 + .../node_modules/lodash/fp/_convertBrowser.js | 18 + .../node_modules/lodash/fp/_falseOptions.js | 7 + .../node_modules/lodash/fp/_mapping.js | 358 + .../node_modules/lodash/fp/_util.js | 16 + .../node_modules/lodash/fp/add.js | 5 + .../node_modules/lodash/fp/after.js | 5 + .../node_modules/lodash/fp/all.js | 1 + .../node_modules/lodash/fp/allPass.js | 1 + .../node_modules/lodash/fp/always.js | 1 + .../node_modules/lodash/fp/any.js | 1 + .../node_modules/lodash/fp/anyPass.js | 1 + .../node_modules/lodash/fp/apply.js | 1 + .../node_modules/lodash/fp/array.js | 2 + .../node_modules/lodash/fp/ary.js | 5 + .../node_modules/lodash/fp/assign.js | 5 + .../node_modules/lodash/fp/assignAll.js | 5 + .../node_modules/lodash/fp/assignAllWith.js | 5 + .../node_modules/lodash/fp/assignIn.js | 5 + .../node_modules/lodash/fp/assignInAll.js | 5 + .../node_modules/lodash/fp/assignInAllWith.js | 5 + .../node_modules/lodash/fp/assignInWith.js | 5 + .../node_modules/lodash/fp/assignWith.js | 5 + .../node_modules/lodash/fp/assoc.js | 1 + .../node_modules/lodash/fp/assocPath.js | 1 + .../node_modules/lodash/fp/at.js | 5 + .../node_modules/lodash/fp/attempt.js | 5 + .../node_modules/lodash/fp/before.js | 5 + .../node_modules/lodash/fp/bind.js | 5 + .../node_modules/lodash/fp/bindAll.js | 5 + .../node_modules/lodash/fp/bindKey.js | 5 + .../node_modules/lodash/fp/camelCase.js | 5 + .../node_modules/lodash/fp/capitalize.js | 5 + .../node_modules/lodash/fp/castArray.js | 5 + .../node_modules/lodash/fp/ceil.js | 5 + .../node_modules/lodash/fp/chain.js | 5 + .../node_modules/lodash/fp/chunk.js | 5 + .../node_modules/lodash/fp/clamp.js | 5 + .../node_modules/lodash/fp/clone.js | 5 + .../node_modules/lodash/fp/cloneDeep.js | 5 + .../node_modules/lodash/fp/cloneDeepWith.js | 5 + .../node_modules/lodash/fp/cloneWith.js | 5 + .../node_modules/lodash/fp/collection.js | 2 + .../node_modules/lodash/fp/commit.js | 5 + .../node_modules/lodash/fp/compact.js | 5 + .../node_modules/lodash/fp/complement.js | 1 + .../node_modules/lodash/fp/compose.js | 1 + .../node_modules/lodash/fp/concat.js | 5 + .../node_modules/lodash/fp/cond.js | 5 + .../node_modules/lodash/fp/conforms.js | 1 + .../node_modules/lodash/fp/conformsTo.js | 5 + .../node_modules/lodash/fp/constant.js | 5 + .../node_modules/lodash/fp/contains.js | 1 + .../node_modules/lodash/fp/convert.js | 18 + .../node_modules/lodash/fp/countBy.js | 5 + .../node_modules/lodash/fp/create.js | 5 + .../node_modules/lodash/fp/curry.js | 5 + .../node_modules/lodash/fp/curryN.js | 5 + .../node_modules/lodash/fp/curryRight.js | 5 + .../node_modules/lodash/fp/curryRightN.js | 5 + .../node_modules/lodash/fp/date.js | 2 + .../node_modules/lodash/fp/debounce.js | 5 + .../node_modules/lodash/fp/deburr.js | 5 + .../node_modules/lodash/fp/defaultTo.js | 5 + .../node_modules/lodash/fp/defaults.js | 5 + .../node_modules/lodash/fp/defaultsAll.js | 5 + .../node_modules/lodash/fp/defaultsDeep.js | 5 + .../node_modules/lodash/fp/defaultsDeepAll.js | 5 + .../node_modules/lodash/fp/defer.js | 5 + .../node_modules/lodash/fp/delay.js | 5 + .../node_modules/lodash/fp/difference.js | 5 + .../node_modules/lodash/fp/differenceBy.js | 5 + .../node_modules/lodash/fp/differenceWith.js | 5 + .../node_modules/lodash/fp/dissoc.js | 1 + .../node_modules/lodash/fp/dissocPath.js | 1 + .../node_modules/lodash/fp/divide.js | 5 + .../node_modules/lodash/fp/drop.js | 5 + .../node_modules/lodash/fp/dropLast.js | 1 + .../node_modules/lodash/fp/dropLastWhile.js | 1 + .../node_modules/lodash/fp/dropRight.js | 5 + .../node_modules/lodash/fp/dropRightWhile.js | 5 + .../node_modules/lodash/fp/dropWhile.js | 5 + .../node_modules/lodash/fp/each.js | 1 + .../node_modules/lodash/fp/eachRight.js | 1 + .../node_modules/lodash/fp/endsWith.js | 5 + .../node_modules/lodash/fp/entries.js | 1 + .../node_modules/lodash/fp/entriesIn.js | 1 + .../node_modules/lodash/fp/eq.js | 5 + .../node_modules/lodash/fp/equals.js | 1 + .../node_modules/lodash/fp/escape.js | 5 + .../node_modules/lodash/fp/escapeRegExp.js | 5 + .../node_modules/lodash/fp/every.js | 5 + .../node_modules/lodash/fp/extend.js | 1 + .../node_modules/lodash/fp/extendAll.js | 1 + .../node_modules/lodash/fp/extendAllWith.js | 1 + .../node_modules/lodash/fp/extendWith.js | 1 + .../node_modules/lodash/fp/fill.js | 5 + .../node_modules/lodash/fp/filter.js | 5 + .../node_modules/lodash/fp/find.js | 5 + .../node_modules/lodash/fp/findFrom.js | 5 + .../node_modules/lodash/fp/findIndex.js | 5 + .../node_modules/lodash/fp/findIndexFrom.js | 5 + .../node_modules/lodash/fp/findKey.js | 5 + .../node_modules/lodash/fp/findLast.js | 5 + .../node_modules/lodash/fp/findLastFrom.js | 5 + .../node_modules/lodash/fp/findLastIndex.js | 5 + .../lodash/fp/findLastIndexFrom.js | 5 + .../node_modules/lodash/fp/findLastKey.js | 5 + .../node_modules/lodash/fp/first.js | 1 + .../node_modules/lodash/fp/flatMap.js | 5 + .../node_modules/lodash/fp/flatMapDeep.js | 5 + .../node_modules/lodash/fp/flatMapDepth.js | 5 + .../node_modules/lodash/fp/flatten.js | 5 + .../node_modules/lodash/fp/flattenDeep.js | 5 + .../node_modules/lodash/fp/flattenDepth.js | 5 + .../node_modules/lodash/fp/flip.js | 5 + .../node_modules/lodash/fp/floor.js | 5 + .../node_modules/lodash/fp/flow.js | 5 + .../node_modules/lodash/fp/flowRight.js | 5 + .../node_modules/lodash/fp/forEach.js | 5 + .../node_modules/lodash/fp/forEachRight.js | 5 + .../node_modules/lodash/fp/forIn.js | 5 + .../node_modules/lodash/fp/forInRight.js | 5 + .../node_modules/lodash/fp/forOwn.js | 5 + .../node_modules/lodash/fp/forOwnRight.js | 5 + .../node_modules/lodash/fp/fromPairs.js | 5 + .../node_modules/lodash/fp/function.js | 2 + .../node_modules/lodash/fp/functions.js | 5 + .../node_modules/lodash/fp/functionsIn.js | 5 + .../node_modules/lodash/fp/get.js | 5 + .../node_modules/lodash/fp/getOr.js | 5 + .../node_modules/lodash/fp/groupBy.js | 5 + .../node_modules/lodash/fp/gt.js | 5 + .../node_modules/lodash/fp/gte.js | 5 + .../node_modules/lodash/fp/has.js | 5 + .../node_modules/lodash/fp/hasIn.js | 5 + .../node_modules/lodash/fp/head.js | 5 + .../node_modules/lodash/fp/identical.js | 1 + .../node_modules/lodash/fp/identity.js | 5 + .../node_modules/lodash/fp/inRange.js | 5 + .../node_modules/lodash/fp/includes.js | 5 + .../node_modules/lodash/fp/includesFrom.js | 5 + .../node_modules/lodash/fp/indexBy.js | 1 + .../node_modules/lodash/fp/indexOf.js | 5 + .../node_modules/lodash/fp/indexOfFrom.js | 5 + .../node_modules/lodash/fp/init.js | 1 + .../node_modules/lodash/fp/initial.js | 5 + .../node_modules/lodash/fp/intersection.js | 5 + .../node_modules/lodash/fp/intersectionBy.js | 5 + .../lodash/fp/intersectionWith.js | 5 + .../node_modules/lodash/fp/invert.js | 5 + .../node_modules/lodash/fp/invertBy.js | 5 + .../node_modules/lodash/fp/invertObj.js | 1 + .../node_modules/lodash/fp/invoke.js | 5 + .../node_modules/lodash/fp/invokeArgs.js | 5 + .../node_modules/lodash/fp/invokeArgsMap.js | 5 + .../node_modules/lodash/fp/invokeMap.js | 5 + .../node_modules/lodash/fp/isArguments.js | 5 + .../node_modules/lodash/fp/isArray.js | 5 + .../node_modules/lodash/fp/isArrayBuffer.js | 5 + .../node_modules/lodash/fp/isArrayLike.js | 5 + .../lodash/fp/isArrayLikeObject.js | 5 + .../node_modules/lodash/fp/isBoolean.js | 5 + .../node_modules/lodash/fp/isBuffer.js | 5 + .../node_modules/lodash/fp/isDate.js | 5 + .../node_modules/lodash/fp/isElement.js | 5 + .../node_modules/lodash/fp/isEmpty.js | 5 + .../node_modules/lodash/fp/isEqual.js | 5 + .../node_modules/lodash/fp/isEqualWith.js | 5 + .../node_modules/lodash/fp/isError.js | 5 + .../node_modules/lodash/fp/isFinite.js | 5 + .../node_modules/lodash/fp/isFunction.js | 5 + .../node_modules/lodash/fp/isInteger.js | 5 + .../node_modules/lodash/fp/isLength.js | 5 + .../node_modules/lodash/fp/isMap.js | 5 + .../node_modules/lodash/fp/isMatch.js | 5 + .../node_modules/lodash/fp/isMatchWith.js | 5 + .../node_modules/lodash/fp/isNaN.js | 5 + .../node_modules/lodash/fp/isNative.js | 5 + .../node_modules/lodash/fp/isNil.js | 5 + .../node_modules/lodash/fp/isNull.js | 5 + .../node_modules/lodash/fp/isNumber.js | 5 + .../node_modules/lodash/fp/isObject.js | 5 + .../node_modules/lodash/fp/isObjectLike.js | 5 + .../node_modules/lodash/fp/isPlainObject.js | 5 + .../node_modules/lodash/fp/isRegExp.js | 5 + .../node_modules/lodash/fp/isSafeInteger.js | 5 + .../node_modules/lodash/fp/isSet.js | 5 + .../node_modules/lodash/fp/isString.js | 5 + .../node_modules/lodash/fp/isSymbol.js | 5 + .../node_modules/lodash/fp/isTypedArray.js | 5 + .../node_modules/lodash/fp/isUndefined.js | 5 + .../node_modules/lodash/fp/isWeakMap.js | 5 + .../node_modules/lodash/fp/isWeakSet.js | 5 + .../node_modules/lodash/fp/iteratee.js | 5 + .../node_modules/lodash/fp/join.js | 5 + .../node_modules/lodash/fp/juxt.js | 1 + .../node_modules/lodash/fp/kebabCase.js | 5 + .../node_modules/lodash/fp/keyBy.js | 5 + .../node_modules/lodash/fp/keys.js | 5 + .../node_modules/lodash/fp/keysIn.js | 5 + .../node_modules/lodash/fp/lang.js | 2 + .../node_modules/lodash/fp/last.js | 5 + .../node_modules/lodash/fp/lastIndexOf.js | 5 + .../node_modules/lodash/fp/lastIndexOfFrom.js | 5 + .../node_modules/lodash/fp/lowerCase.js | 5 + .../node_modules/lodash/fp/lowerFirst.js | 5 + .../node_modules/lodash/fp/lt.js | 5 + .../node_modules/lodash/fp/lte.js | 5 + .../node_modules/lodash/fp/map.js | 5 + .../node_modules/lodash/fp/mapKeys.js | 5 + .../node_modules/lodash/fp/mapValues.js | 5 + .../node_modules/lodash/fp/matches.js | 1 + .../node_modules/lodash/fp/matchesProperty.js | 5 + .../node_modules/lodash/fp/math.js | 2 + .../node_modules/lodash/fp/max.js | 5 + .../node_modules/lodash/fp/maxBy.js | 5 + .../node_modules/lodash/fp/mean.js | 5 + .../node_modules/lodash/fp/meanBy.js | 5 + .../node_modules/lodash/fp/memoize.js | 5 + .../node_modules/lodash/fp/merge.js | 5 + .../node_modules/lodash/fp/mergeAll.js | 5 + .../node_modules/lodash/fp/mergeAllWith.js | 5 + .../node_modules/lodash/fp/mergeWith.js | 5 + .../node_modules/lodash/fp/method.js | 5 + .../node_modules/lodash/fp/methodOf.js | 5 + .../node_modules/lodash/fp/min.js | 5 + .../node_modules/lodash/fp/minBy.js | 5 + .../node_modules/lodash/fp/mixin.js | 5 + .../node_modules/lodash/fp/multiply.js | 5 + .../node_modules/lodash/fp/nAry.js | 1 + .../node_modules/lodash/fp/negate.js | 5 + .../node_modules/lodash/fp/next.js | 5 + .../node_modules/lodash/fp/noop.js | 5 + .../node_modules/lodash/fp/now.js | 5 + .../node_modules/lodash/fp/nth.js | 5 + .../node_modules/lodash/fp/nthArg.js | 5 + .../node_modules/lodash/fp/number.js | 2 + .../node_modules/lodash/fp/object.js | 2 + .../node_modules/lodash/fp/omit.js | 5 + .../node_modules/lodash/fp/omitAll.js | 1 + .../node_modules/lodash/fp/omitBy.js | 5 + .../node_modules/lodash/fp/once.js | 5 + .../node_modules/lodash/fp/orderBy.js | 5 + .../node_modules/lodash/fp/over.js | 5 + .../node_modules/lodash/fp/overArgs.js | 5 + .../node_modules/lodash/fp/overEvery.js | 5 + .../node_modules/lodash/fp/overSome.js | 5 + .../node_modules/lodash/fp/pad.js | 5 + .../node_modules/lodash/fp/padChars.js | 5 + .../node_modules/lodash/fp/padCharsEnd.js | 5 + .../node_modules/lodash/fp/padCharsStart.js | 5 + .../node_modules/lodash/fp/padEnd.js | 5 + .../node_modules/lodash/fp/padStart.js | 5 + .../node_modules/lodash/fp/parseInt.js | 5 + .../node_modules/lodash/fp/partial.js | 5 + .../node_modules/lodash/fp/partialRight.js | 5 + .../node_modules/lodash/fp/partition.js | 5 + .../node_modules/lodash/fp/path.js | 1 + .../node_modules/lodash/fp/pathEq.js | 1 + .../node_modules/lodash/fp/pathOr.js | 1 + .../node_modules/lodash/fp/paths.js | 1 + .../node_modules/lodash/fp/pick.js | 5 + .../node_modules/lodash/fp/pickAll.js | 1 + .../node_modules/lodash/fp/pickBy.js | 5 + .../node_modules/lodash/fp/pipe.js | 1 + .../node_modules/lodash/fp/placeholder.js | 6 + .../node_modules/lodash/fp/plant.js | 5 + .../node_modules/lodash/fp/pluck.js | 1 + .../node_modules/lodash/fp/prop.js | 1 + .../node_modules/lodash/fp/propEq.js | 1 + .../node_modules/lodash/fp/propOr.js | 1 + .../node_modules/lodash/fp/property.js | 1 + .../node_modules/lodash/fp/propertyOf.js | 5 + .../node_modules/lodash/fp/props.js | 1 + .../node_modules/lodash/fp/pull.js | 5 + .../node_modules/lodash/fp/pullAll.js | 5 + .../node_modules/lodash/fp/pullAllBy.js | 5 + .../node_modules/lodash/fp/pullAllWith.js | 5 + .../node_modules/lodash/fp/pullAt.js | 5 + .../node_modules/lodash/fp/random.js | 5 + .../node_modules/lodash/fp/range.js | 5 + .../node_modules/lodash/fp/rangeRight.js | 5 + .../node_modules/lodash/fp/rangeStep.js | 5 + .../node_modules/lodash/fp/rangeStepRight.js | 5 + .../node_modules/lodash/fp/rearg.js | 5 + .../node_modules/lodash/fp/reduce.js | 5 + .../node_modules/lodash/fp/reduceRight.js | 5 + .../node_modules/lodash/fp/reject.js | 5 + .../node_modules/lodash/fp/remove.js | 5 + .../node_modules/lodash/fp/repeat.js | 5 + .../node_modules/lodash/fp/replace.js | 5 + .../node_modules/lodash/fp/rest.js | 5 + .../node_modules/lodash/fp/restFrom.js | 5 + .../node_modules/lodash/fp/result.js | 5 + .../node_modules/lodash/fp/reverse.js | 5 + .../node_modules/lodash/fp/round.js | 5 + .../node_modules/lodash/fp/sample.js | 5 + .../node_modules/lodash/fp/sampleSize.js | 5 + .../node_modules/lodash/fp/seq.js | 2 + .../node_modules/lodash/fp/set.js | 5 + .../node_modules/lodash/fp/setWith.js | 5 + .../node_modules/lodash/fp/shuffle.js | 5 + .../node_modules/lodash/fp/size.js | 5 + .../node_modules/lodash/fp/slice.js | 5 + .../node_modules/lodash/fp/snakeCase.js | 5 + .../node_modules/lodash/fp/some.js | 5 + .../node_modules/lodash/fp/sortBy.js | 5 + .../node_modules/lodash/fp/sortedIndex.js | 5 + .../node_modules/lodash/fp/sortedIndexBy.js | 5 + .../node_modules/lodash/fp/sortedIndexOf.js | 5 + .../node_modules/lodash/fp/sortedLastIndex.js | 5 + .../lodash/fp/sortedLastIndexBy.js | 5 + .../lodash/fp/sortedLastIndexOf.js | 5 + .../node_modules/lodash/fp/sortedUniq.js | 5 + .../node_modules/lodash/fp/sortedUniqBy.js | 5 + .../node_modules/lodash/fp/split.js | 5 + .../node_modules/lodash/fp/spread.js | 5 + .../node_modules/lodash/fp/spreadFrom.js | 5 + .../node_modules/lodash/fp/startCase.js | 5 + .../node_modules/lodash/fp/startsWith.js | 5 + .../node_modules/lodash/fp/string.js | 2 + .../node_modules/lodash/fp/stubArray.js | 5 + .../node_modules/lodash/fp/stubFalse.js | 5 + .../node_modules/lodash/fp/stubObject.js | 5 + .../node_modules/lodash/fp/stubString.js | 5 + .../node_modules/lodash/fp/stubTrue.js | 5 + .../node_modules/lodash/fp/subtract.js | 5 + .../node_modules/lodash/fp/sum.js | 5 + .../node_modules/lodash/fp/sumBy.js | 5 + .../lodash/fp/symmetricDifference.js | 1 + .../lodash/fp/symmetricDifferenceBy.js | 1 + .../lodash/fp/symmetricDifferenceWith.js | 1 + .../node_modules/lodash/fp/tail.js | 5 + .../node_modules/lodash/fp/take.js | 5 + .../node_modules/lodash/fp/takeLast.js | 1 + .../node_modules/lodash/fp/takeLastWhile.js | 1 + .../node_modules/lodash/fp/takeRight.js | 5 + .../node_modules/lodash/fp/takeRightWhile.js | 5 + .../node_modules/lodash/fp/takeWhile.js | 5 + .../node_modules/lodash/fp/tap.js | 5 + .../node_modules/lodash/fp/template.js | 5 + .../lodash/fp/templateSettings.js | 5 + .../node_modules/lodash/fp/throttle.js | 5 + .../node_modules/lodash/fp/thru.js | 5 + .../node_modules/lodash/fp/times.js | 5 + .../node_modules/lodash/fp/toArray.js | 5 + .../node_modules/lodash/fp/toFinite.js | 5 + .../node_modules/lodash/fp/toInteger.js | 5 + .../node_modules/lodash/fp/toIterator.js | 5 + .../node_modules/lodash/fp/toJSON.js | 5 + .../node_modules/lodash/fp/toLength.js | 5 + .../node_modules/lodash/fp/toLower.js | 5 + .../node_modules/lodash/fp/toNumber.js | 5 + .../node_modules/lodash/fp/toPairs.js | 5 + .../node_modules/lodash/fp/toPairsIn.js | 5 + .../node_modules/lodash/fp/toPath.js | 5 + .../node_modules/lodash/fp/toPlainObject.js | 5 + .../node_modules/lodash/fp/toSafeInteger.js | 5 + .../node_modules/lodash/fp/toString.js | 5 + .../node_modules/lodash/fp/toUpper.js | 5 + .../node_modules/lodash/fp/transform.js | 5 + .../node_modules/lodash/fp/trim.js | 5 + .../node_modules/lodash/fp/trimChars.js | 5 + .../node_modules/lodash/fp/trimCharsEnd.js | 5 + .../node_modules/lodash/fp/trimCharsStart.js | 5 + .../node_modules/lodash/fp/trimEnd.js | 5 + .../node_modules/lodash/fp/trimStart.js | 5 + .../node_modules/lodash/fp/truncate.js | 5 + .../node_modules/lodash/fp/unapply.js | 1 + .../node_modules/lodash/fp/unary.js | 5 + .../node_modules/lodash/fp/unescape.js | 5 + .../node_modules/lodash/fp/union.js | 5 + .../node_modules/lodash/fp/unionBy.js | 5 + .../node_modules/lodash/fp/unionWith.js | 5 + .../node_modules/lodash/fp/uniq.js | 5 + .../node_modules/lodash/fp/uniqBy.js | 5 + .../node_modules/lodash/fp/uniqWith.js | 5 + .../node_modules/lodash/fp/uniqueId.js | 5 + .../node_modules/lodash/fp/unnest.js | 1 + .../node_modules/lodash/fp/unset.js | 5 + .../node_modules/lodash/fp/unzip.js | 5 + .../node_modules/lodash/fp/unzipWith.js | 5 + .../node_modules/lodash/fp/update.js | 5 + .../node_modules/lodash/fp/updateWith.js | 5 + .../node_modules/lodash/fp/upperCase.js | 5 + .../node_modules/lodash/fp/upperFirst.js | 5 + .../node_modules/lodash/fp/useWith.js | 1 + .../node_modules/lodash/fp/util.js | 2 + .../node_modules/lodash/fp/value.js | 5 + .../node_modules/lodash/fp/valueOf.js | 5 + .../node_modules/lodash/fp/values.js | 5 + .../node_modules/lodash/fp/valuesIn.js | 5 + .../node_modules/lodash/fp/where.js | 1 + .../node_modules/lodash/fp/whereEq.js | 1 + .../node_modules/lodash/fp/without.js | 5 + .../node_modules/lodash/fp/words.js | 5 + .../node_modules/lodash/fp/wrap.js | 5 + .../node_modules/lodash/fp/wrapperAt.js | 5 + .../node_modules/lodash/fp/wrapperChain.js | 5 + .../node_modules/lodash/fp/wrapperLodash.js | 5 + .../node_modules/lodash/fp/wrapperReverse.js | 5 + .../node_modules/lodash/fp/wrapperValue.js | 5 + .../node_modules/lodash/fp/xor.js | 5 + .../node_modules/lodash/fp/xorBy.js | 5 + .../node_modules/lodash/fp/xorWith.js | 5 + .../node_modules/lodash/fp/zip.js | 5 + .../node_modules/lodash/fp/zipAll.js | 5 + .../node_modules/lodash/fp/zipObj.js | 1 + .../node_modules/lodash/fp/zipObject.js | 5 + .../node_modules/lodash/fp/zipObjectDeep.js | 5 + .../node_modules/lodash/fp/zipWith.js | 5 + .../node_modules/lodash/fromPairs.js | 28 + .../node_modules/lodash/function.js | 25 + .../node_modules/lodash/functions.js | 31 + .../node_modules/lodash/functionsIn.js | 31 + .../node_modules/lodash/get.js | 33 + .../node_modules/lodash/groupBy.js | 41 + .../node_modules/lodash/gt.js | 29 + .../node_modules/lodash/gte.js | 30 + .../node_modules/lodash/has.js | 35 + .../node_modules/lodash/hasIn.js | 34 + .../node_modules/lodash/head.js | 23 + .../node_modules/lodash/identity.js | 21 + .../node_modules/lodash/inRange.js | 55 + .../node_modules/lodash/includes.js | 53 + .../node_modules/lodash/index.js | 1 + .../node_modules/lodash/indexOf.js | 42 + .../node_modules/lodash/initial.js | 22 + .../node_modules/lodash/intersection.js | 30 + .../node_modules/lodash/intersectionBy.js | 45 + .../node_modules/lodash/intersectionWith.js | 41 + .../node_modules/lodash/invert.js | 42 + .../node_modules/lodash/invertBy.js | 56 + .../node_modules/lodash/invoke.js | 24 + .../node_modules/lodash/invokeMap.js | 41 + .../node_modules/lodash/isArguments.js | 36 + .../node_modules/lodash/isArray.js | 26 + .../node_modules/lodash/isArrayBuffer.js | 27 + .../node_modules/lodash/isArrayLike.js | 33 + .../node_modules/lodash/isArrayLikeObject.js | 33 + .../node_modules/lodash/isBoolean.js | 29 + .../node_modules/lodash/isBuffer.js | 38 + .../node_modules/lodash/isDate.js | 27 + .../node_modules/lodash/isElement.js | 25 + .../node_modules/lodash/isEmpty.js | 77 + .../node_modules/lodash/isEqual.js | 35 + .../node_modules/lodash/isEqualWith.js | 41 + .../node_modules/lodash/isError.js | 36 + .../node_modules/lodash/isFinite.js | 36 + .../node_modules/lodash/isFunction.js | 37 + .../node_modules/lodash/isInteger.js | 33 + .../node_modules/lodash/isLength.js | 35 + .../node_modules/lodash/isMap.js | 27 + .../node_modules/lodash/isMatch.js | 36 + .../node_modules/lodash/isMatchWith.js | 41 + .../node_modules/lodash/isNaN.js | 38 + .../node_modules/lodash/isNative.js | 40 + .../node_modules/lodash/isNil.js | 25 + .../node_modules/lodash/isNull.js | 22 + .../node_modules/lodash/isNumber.js | 38 + .../node_modules/lodash/isObject.js | 31 + .../node_modules/lodash/isObjectLike.js | 29 + .../node_modules/lodash/isPlainObject.js | 62 + .../node_modules/lodash/isRegExp.js | 27 + .../node_modules/lodash/isSafeInteger.js | 37 + .../node_modules/lodash/isSet.js | 27 + .../node_modules/lodash/isString.js | 30 + .../node_modules/lodash/isSymbol.js | 29 + .../node_modules/lodash/isTypedArray.js | 27 + .../node_modules/lodash/isUndefined.js | 22 + .../node_modules/lodash/isWeakMap.js | 28 + .../node_modules/lodash/isWeakSet.js | 28 + .../node_modules/lodash/iteratee.js | 53 + .../node_modules/lodash/join.js | 26 + .../node_modules/lodash/kebabCase.js | 28 + .../node_modules/lodash/keyBy.js | 36 + .../node_modules/lodash/keys.js | 37 + .../node_modules/lodash/keysIn.js | 32 + .../node_modules/lodash/lang.js | 58 + .../node_modules/lodash/last.js | 20 + .../node_modules/lodash/lastIndexOf.js | 46 + .../node_modules/lodash/lodash.js | 17209 ++++++++++++++++ .../node_modules/lodash/lodash.min.js | 140 + .../node_modules/lodash/lowerCase.js | 27 + .../node_modules/lodash/lowerFirst.js | 22 + .../node_modules/lodash/lt.js | 29 + .../node_modules/lodash/lte.js | 30 + .../node_modules/lodash/map.js | 53 + .../node_modules/lodash/mapKeys.js | 36 + .../node_modules/lodash/mapValues.js | 43 + .../node_modules/lodash/matches.js | 46 + .../node_modules/lodash/matchesProperty.js | 44 + .../node_modules/lodash/math.js | 17 + .../node_modules/lodash/max.js | 29 + .../node_modules/lodash/maxBy.js | 34 + .../node_modules/lodash/mean.js | 22 + .../node_modules/lodash/meanBy.js | 31 + .../node_modules/lodash/memoize.js | 73 + .../node_modules/lodash/merge.js | 39 + .../node_modules/lodash/mergeWith.js | 39 + .../node_modules/lodash/method.js | 34 + .../node_modules/lodash/methodOf.js | 33 + .../node_modules/lodash/min.js | 29 + .../node_modules/lodash/minBy.js | 34 + .../node_modules/lodash/mixin.js | 74 + .../node_modules/lodash/multiply.js | 22 + .../node_modules/lodash/negate.js | 40 + .../node_modules/lodash/next.js | 35 + .../node_modules/lodash/noop.js | 17 + .../node_modules/lodash/now.js | 23 + .../node_modules/lodash/nth.js | 29 + .../node_modules/lodash/nthArg.js | 32 + .../node_modules/lodash/number.js | 5 + .../node_modules/lodash/object.js | 49 + .../node_modules/lodash/omit.js | 57 + .../node_modules/lodash/omitBy.js | 29 + .../node_modules/lodash/once.js | 25 + .../node_modules/lodash/orderBy.js | 47 + .../node_modules/lodash/over.js | 24 + .../node_modules/lodash/overArgs.js | 61 + .../node_modules/lodash/overEvery.js | 34 + .../node_modules/lodash/overSome.js | 37 + .../node_modules/lodash/package.json | 17 + .../node_modules/lodash/pad.js | 49 + .../node_modules/lodash/padEnd.js | 39 + .../node_modules/lodash/padStart.js | 39 + .../node_modules/lodash/parseInt.js | 43 + .../node_modules/lodash/partial.js | 50 + .../node_modules/lodash/partialRight.js | 49 + .../node_modules/lodash/partition.js | 43 + .../node_modules/lodash/pick.js | 25 + .../node_modules/lodash/pickBy.js | 37 + .../node_modules/lodash/plant.js | 48 + .../node_modules/lodash/property.js | 32 + .../node_modules/lodash/propertyOf.js | 30 + .../node_modules/lodash/pull.js | 29 + .../node_modules/lodash/pullAll.js | 29 + .../node_modules/lodash/pullAllBy.js | 33 + .../node_modules/lodash/pullAllWith.js | 32 + .../node_modules/lodash/pullAt.js | 43 + .../node_modules/lodash/random.js | 82 + .../node_modules/lodash/range.js | 46 + .../node_modules/lodash/rangeRight.js | 41 + .../node_modules/lodash/rearg.js | 33 + .../node_modules/lodash/reduce.js | 51 + .../node_modules/lodash/reduceRight.js | 36 + .../node_modules/lodash/reject.js | 46 + .../node_modules/lodash/release.md | 48 + .../node_modules/lodash/remove.js | 53 + .../node_modules/lodash/repeat.js | 37 + .../node_modules/lodash/replace.js | 29 + .../node_modules/lodash/rest.js | 40 + .../node_modules/lodash/result.js | 56 + .../node_modules/lodash/reverse.js | 34 + .../node_modules/lodash/round.js | 26 + .../node_modules/lodash/sample.js | 24 + .../node_modules/lodash/sampleSize.js | 37 + .../node_modules/lodash/seq.js | 16 + .../node_modules/lodash/set.js | 35 + .../node_modules/lodash/setWith.js | 32 + .../node_modules/lodash/shuffle.js | 25 + .../node_modules/lodash/size.js | 46 + .../node_modules/lodash/slice.js | 37 + .../node_modules/lodash/snakeCase.js | 28 + .../node_modules/lodash/some.js | 51 + .../node_modules/lodash/sortBy.js | 48 + .../node_modules/lodash/sortedIndex.js | 24 + .../node_modules/lodash/sortedIndexBy.js | 33 + .../node_modules/lodash/sortedIndexOf.js | 31 + .../node_modules/lodash/sortedLastIndex.js | 25 + .../node_modules/lodash/sortedLastIndexBy.js | 33 + .../node_modules/lodash/sortedLastIndexOf.js | 31 + .../node_modules/lodash/sortedUniq.js | 24 + .../node_modules/lodash/sortedUniqBy.js | 26 + .../node_modules/lodash/split.js | 52 + .../node_modules/lodash/spread.js | 63 + .../node_modules/lodash/startCase.js | 29 + .../node_modules/lodash/startsWith.js | 39 + .../node_modules/lodash/string.js | 33 + .../node_modules/lodash/stubArray.js | 23 + .../node_modules/lodash/stubFalse.js | 18 + .../node_modules/lodash/stubObject.js | 23 + .../node_modules/lodash/stubString.js | 18 + .../node_modules/lodash/stubTrue.js | 18 + .../node_modules/lodash/subtract.js | 22 + .../node_modules/lodash/sum.js | 24 + .../node_modules/lodash/sumBy.js | 33 + .../node_modules/lodash/tail.js | 22 + .../node_modules/lodash/take.js | 37 + .../node_modules/lodash/takeRight.js | 39 + .../node_modules/lodash/takeRightWhile.js | 45 + .../node_modules/lodash/takeWhile.js | 45 + .../node_modules/lodash/tap.js | 29 + .../node_modules/lodash/template.js | 272 + .../node_modules/lodash/templateSettings.js | 67 + .../node_modules/lodash/throttle.js | 69 + .../node_modules/lodash/thru.js | 28 + .../node_modules/lodash/times.js | 51 + .../node_modules/lodash/toArray.js | 58 + .../node_modules/lodash/toFinite.js | 42 + .../node_modules/lodash/toInteger.js | 36 + .../node_modules/lodash/toIterator.js | 23 + .../node_modules/lodash/toJSON.js | 1 + .../node_modules/lodash/toLength.js | 38 + .../node_modules/lodash/toLower.js | 28 + .../node_modules/lodash/toNumber.js | 64 + .../node_modules/lodash/toPairs.js | 30 + .../node_modules/lodash/toPairsIn.js | 30 + .../node_modules/lodash/toPath.js | 33 + .../node_modules/lodash/toPlainObject.js | 32 + .../node_modules/lodash/toSafeInteger.js | 37 + .../node_modules/lodash/toString.js | 28 + .../node_modules/lodash/toUpper.js | 28 + .../node_modules/lodash/transform.js | 65 + .../node_modules/lodash/trim.js | 47 + .../node_modules/lodash/trimEnd.js | 41 + .../node_modules/lodash/trimStart.js | 43 + .../node_modules/lodash/truncate.js | 111 + .../node_modules/lodash/unary.js | 22 + .../node_modules/lodash/unescape.js | 34 + .../node_modules/lodash/union.js | 26 + .../node_modules/lodash/unionBy.js | 39 + .../node_modules/lodash/unionWith.js | 34 + .../node_modules/lodash/uniq.js | 25 + .../node_modules/lodash/uniqBy.js | 31 + .../node_modules/lodash/uniqWith.js | 28 + .../node_modules/lodash/uniqueId.js | 28 + .../node_modules/lodash/unset.js | 34 + .../node_modules/lodash/unzip.js | 45 + .../node_modules/lodash/unzipWith.js | 39 + .../node_modules/lodash/update.js | 35 + .../node_modules/lodash/updateWith.js | 33 + .../node_modules/lodash/upperCase.js | 27 + .../node_modules/lodash/upperFirst.js | 22 + .../node_modules/lodash/util.js | 34 + .../node_modules/lodash/value.js | 1 + .../node_modules/lodash/valueOf.js | 1 + .../node_modules/lodash/values.js | 34 + .../node_modules/lodash/valuesIn.js | 32 + .../node_modules/lodash/without.js | 31 + .../node_modules/lodash/words.js | 35 + .../node_modules/lodash/wrap.js | 30 + .../node_modules/lodash/wrapperAt.js | 48 + .../node_modules/lodash/wrapperChain.js | 34 + .../node_modules/lodash/wrapperLodash.js | 147 + .../node_modules/lodash/wrapperReverse.js | 44 + .../node_modules/lodash/wrapperValue.js | 21 + .../node_modules/lodash/xor.js | 28 + .../node_modules/lodash/xorBy.js | 39 + .../node_modules/lodash/xorWith.js | 34 + .../node_modules/lodash/zip.js | 22 + .../node_modules/lodash/zipObject.js | 24 + .../node_modules/lodash/zipObjectDeep.js | 23 + .../node_modules/lodash/zipWith.js | 32 + .../node_modules/lru-cache/LICENSE | 15 + .../node_modules/lru-cache/README.md | 166 + .../node_modules/lru-cache/index.js | 334 + .../node_modules/lru-cache/package.json | 34 + .../node_modules/make-fetch-happen/LICENSE | 16 + .../node_modules/make-fetch-happen/README.md | 395 + .../make-fetch-happen/lib/agent.js | 194 + .../make-fetch-happen/lib/cache/entry.js | 460 + .../make-fetch-happen/lib/cache/errors.js | 10 + .../make-fetch-happen/lib/cache/index.js | 45 + .../make-fetch-happen/lib/cache/key.js | 17 + .../make-fetch-happen/lib/cache/policy.js | 161 + .../make-fetch-happen/lib/fetch.js | 100 + .../make-fetch-happen/lib/index.js | 40 + .../make-fetch-happen/lib/options.js | 44 + .../make-fetch-happen/lib/remote.js | 102 + .../node_modules/negotiator/HISTORY.md | 113 + .../node_modules/negotiator/LICENSE | 24 + .../node_modules/negotiator/README.md | 212 + .../node_modules/negotiator/index.js | 82 + .../node_modules/negotiator/lib/charset.js | 169 + .../node_modules/negotiator/lib/encoding.js | 205 + .../node_modules/negotiator/lib/language.js | 179 + .../node_modules/negotiator/lib/mediaType.js | 294 + .../node_modules/negotiator/package.json | 42 + .../make-fetch-happen/package.json | 76 + .../node_modules/math-intrinsics/.eslintrc | 16 + .../math-intrinsics/.github/FUNDING.yml | 12 + .../node_modules/math-intrinsics/CHANGELOG.md | 24 + .../node_modules/math-intrinsics/LICENSE | 21 + .../node_modules/math-intrinsics/README.md | 50 + .../node_modules/math-intrinsics/abs.d.ts | 1 + .../node_modules/math-intrinsics/abs.js | 4 + .../constants/maxArrayLength.d.ts | 3 + .../constants/maxArrayLength.js | 4 + .../constants/maxSafeInteger.d.ts | 3 + .../constants/maxSafeInteger.js | 5 + .../math-intrinsics/constants/maxValue.d.ts | 3 + .../math-intrinsics/constants/maxValue.js | 5 + .../node_modules/math-intrinsics/floor.d.ts | 1 + .../node_modules/math-intrinsics/floor.js | 4 + .../math-intrinsics/isFinite.d.ts | 3 + .../node_modules/math-intrinsics/isFinite.js | 12 + .../math-intrinsics/isInteger.d.ts | 3 + .../node_modules/math-intrinsics/isInteger.js | 16 + .../node_modules/math-intrinsics/isNaN.d.ts | 1 + .../node_modules/math-intrinsics/isNaN.js | 6 + .../math-intrinsics/isNegativeZero.d.ts | 3 + .../math-intrinsics/isNegativeZero.js | 6 + .../node_modules/math-intrinsics/max.d.ts | 1 + .../node_modules/math-intrinsics/max.js | 4 + .../node_modules/math-intrinsics/min.d.ts | 1 + .../node_modules/math-intrinsics/min.js | 4 + .../node_modules/math-intrinsics/mod.d.ts | 3 + .../node_modules/math-intrinsics/mod.js | 9 + .../node_modules/math-intrinsics/package.json | 86 + .../node_modules/math-intrinsics/pow.d.ts | 1 + .../node_modules/math-intrinsics/pow.js | 4 + .../node_modules/math-intrinsics/round.d.ts | 1 + .../node_modules/math-intrinsics/round.js | 4 + .../node_modules/math-intrinsics/sign.d.ts | 3 + .../node_modules/math-intrinsics/sign.js | 11 + .../math-intrinsics/test/index.js | 192 + .../math-intrinsics/tsconfig.json | 3 + .../node_modules/media-typer/HISTORY.md | 50 + .../node_modules/media-typer/LICENSE | 22 + .../node_modules/media-typer/README.md | 93 + .../node_modules/media-typer/index.js | 143 + .../node_modules/media-typer/package.json | 33 + .../node_modules/merge-descriptors/index.d.ts | 11 + .../node_modules/merge-descriptors/index.js | 26 + .../node_modules/merge-descriptors/license | 11 + .../merge-descriptors/package.json | 50 + .../node_modules/merge-descriptors/readme.md | 55 + .../node_modules/mime-db/HISTORY.md | 541 + .../node_modules/mime-db/LICENSE | 23 + .../node_modules/mime-db/README.md | 109 + .../node_modules/mime-db/db.json | 9342 +++++++++ .../node_modules/mime-db/index.js | 12 + .../node_modules/mime-db/package.json | 56 + .../node_modules/mime-types/HISTORY.md | 428 + .../node_modules/mime-types/LICENSE | 23 + .../node_modules/mime-types/README.md | 126 + .../node_modules/mime-types/index.js | 211 + .../node_modules/mime-types/mimeScore.js | 57 + .../node_modules/mime-types/package.json | 49 + .../node_modules/mimic-response/index.d.ts | 17 + .../node_modules/mimic-response/index.js | 77 + .../node_modules/mimic-response/license | 9 + .../node_modules/mimic-response/package.json | 42 + .../node_modules/mimic-response/readme.md | 78 + .../node_modules/minimatch/LICENSE | 15 + .../node_modules/minimatch/README.md | 230 + .../node_modules/minimatch/minimatch.js | 947 + .../node_modules/minimatch/package.json | 33 + .../node_modules/minimist/.eslintrc | 29 + .../node_modules/minimist/.github/FUNDING.yml | 12 + .../node_modules/minimist/.nycrc | 14 + .../node_modules/minimist/CHANGELOG.md | 298 + .../node_modules/minimist/LICENSE | 18 + .../node_modules/minimist/README.md | 121 + .../node_modules/minimist/example/parse.js | 4 + .../node_modules/minimist/index.js | 263 + .../node_modules/minimist/package.json | 75 + .../node_modules/minimist/test/all_bool.js | 34 + .../node_modules/minimist/test/bool.js | 177 + .../node_modules/minimist/test/dash.js | 43 + .../minimist/test/default_bool.js | 37 + .../node_modules/minimist/test/dotted.js | 24 + .../node_modules/minimist/test/kv_short.js | 32 + .../node_modules/minimist/test/long.js | 33 + .../node_modules/minimist/test/num.js | 38 + .../node_modules/minimist/test/parse.js | 209 + .../minimist/test/parse_modified.js | 11 + .../node_modules/minimist/test/proto.js | 64 + .../node_modules/minimist/test/short.js | 69 + .../node_modules/minimist/test/stop_early.js | 17 + .../node_modules/minimist/test/unknown.js | 104 + .../node_modules/minimist/test/whitespace.js | 10 + .../node_modules/minipass-collect/LICENSE | 15 + .../node_modules/minipass-collect/README.md | 48 + .../node_modules/minipass-collect/index.js | 71 + .../minipass-collect/package.json | 29 + .../node_modules/minipass-fetch/LICENSE | 28 + .../node_modules/minipass-fetch/README.md | 29 + .../node_modules/minipass-fetch/index.js | 1 + .../minipass-fetch/lib/abort-error.js | 17 + .../node_modules/minipass-fetch/lib/blob.js | 97 + .../node_modules/minipass-fetch/lib/body.js | 334 + .../minipass-fetch/lib/fetch-error.js | 31 + .../minipass-fetch/lib/headers.js | 250 + .../node_modules/minipass-fetch/lib/index.js | 341 + .../minipass-fetch/lib/request.js | 263 + .../minipass-fetch/lib/response.js | 89 + .../node_modules/minipass-fetch/package.json | 53 + .../node_modules/minipass-flush/LICENSE | 15 + .../node_modules/minipass-flush/README.md | 47 + .../node_modules/minipass-flush/index.js | 39 + .../node_modules/minipass-flush/package.json | 39 + .../node_modules/minipass-pipeline/LICENSE | 15 + .../node_modules/minipass-pipeline/README.md | 69 + .../node_modules/minipass-pipeline/index.js | 128 + .../minipass-pipeline/package.json | 29 + .../node_modules/minipass-sized/.npmignore | 22 + .../node_modules/minipass-sized/LICENSE | 15 + .../node_modules/minipass-sized/README.md | 28 + .../node_modules/minipass-sized/index.js | 67 + .../minipass-sized/package-lock.json | 3464 ++++ .../node_modules/minipass-sized/package.json | 39 + .../node_modules/minipass-sized/test/basic.js | 83 + .../node_modules/minipass/LICENSE | 15 + .../node_modules/minipass/README.md | 728 + .../node_modules/minipass/index.d.ts | 155 + .../node_modules/minipass/index.js | 649 + .../node_modules/minipass/package.json | 56 + .../node_modules/minizlib/LICENSE | 26 + .../node_modules/minizlib/README.md | 60 + .../node_modules/minizlib/constants.js | 115 + .../node_modules/minizlib/index.js | 348 + .../node_modules/minizlib/package.json | 42 + .../node_modules/mkdirp-classic/LICENSE | 21 + .../node_modules/mkdirp-classic/README.md | 18 + .../node_modules/mkdirp-classic/index.js | 98 + .../node_modules/mkdirp-classic/package.json | 18 + .../node_modules/mkdirp/CHANGELOG.md | 15 + .../node_modules/mkdirp/LICENSE | 21 + .../node_modules/mkdirp/bin/cmd.js | 68 + .../node_modules/mkdirp/index.js | 31 + .../node_modules/mkdirp/lib/find-made.js | 29 + .../node_modules/mkdirp/lib/mkdirp-manual.js | 64 + .../node_modules/mkdirp/lib/mkdirp-native.js | 39 + .../node_modules/mkdirp/lib/opts-arg.js | 23 + .../node_modules/mkdirp/lib/path-arg.js | 29 + .../node_modules/mkdirp/lib/use-native.js | 10 + .../node_modules/mkdirp/package.json | 44 + .../node_modules/mkdirp/readme.markdown | 266 + .../node_modules/ms/index.js | 162 + .../node_modules/ms/license.md | 21 + .../node_modules/ms/package.json | 38 + .../node_modules/ms/readme.md | 59 + .../.github/workflows/run-npm-tests.yml | 31 + .../node_modules/napi-build-utils/LICENSE | 21 + .../node_modules/napi-build-utils/README.md | 52 + .../node_modules/napi-build-utils/index.js | 214 + .../node_modules/napi-build-utils/index.md | 0 .../napi-build-utils/package.json | 42 + .../node_modules/negotiator/HISTORY.md | 114 + .../node_modules/negotiator/LICENSE | 24 + .../node_modules/negotiator/README.md | 212 + .../node_modules/negotiator/index.js | 83 + .../node_modules/negotiator/lib/charset.js | 169 + .../node_modules/negotiator/lib/encoding.js | 205 + .../node_modules/negotiator/lib/language.js | 179 + .../node_modules/negotiator/lib/mediaType.js | 294 + .../node_modules/negotiator/package.json | 43 + .../node_modules/node-abi/LICENSE | 21 + .../node_modules/node-abi/README.md | 54 + .../node_modules/node-abi/abi_registry.json | 425 + .../node_modules/node-abi/index.js | 179 + .../node_modules/node-abi/package.json | 45 + .../node_modules/node-addon-api/LICENSE.md | 9 + .../node_modules/node-addon-api/README.md | 319 + .../node_modules/node-addon-api/common.gypi | 20 + .../node_modules/node-addon-api/except.gypi | 25 + .../node_modules/node-addon-api/index.js | 12 + .../node-addon-api/napi-inl.deprecated.h | 186 + .../node_modules/node-addon-api/napi-inl.h | 6607 ++++++ .../node_modules/node-addon-api/napi.h | 3201 +++ .../node-addon-api/node_addon_api.gyp | 32 + .../node_modules/node-addon-api/node_api.gyp | 9 + .../node_modules/node-addon-api/noexcept.gypi | 26 + .../node_modules/node-addon-api/nothing.c | 0 .../node-addon-api/package-support.json | 21 + .../node_modules/node-addon-api/package.json | 480 + .../node-addon-api/tools/README.md | 73 + .../node-addon-api/tools/check-napi.js | 99 + .../node-addon-api/tools/clang-format.js | 71 + .../node-addon-api/tools/conversion.js | 301 + .../node-addon-api/tools/eslint-format.js | 79 + .../node-gyp/.github/ISSUE_TEMPLATE.md | 52 + .../node-gyp/.github/PULL_REQUEST_TEMPLATE.md | 17 + .../.github/workflows/release-please.yml | 56 + .../node-gyp/.github/workflows/tests.yml | 45 + .../.github/workflows/visual-studio.yml | 25 + .../node_modules/node-gyp/CHANGELOG.md | 687 + .../node_modules/node-gyp/CONTRIBUTING.md | 34 + .../node_modules/node-gyp/LICENSE | 24 + .../node_modules/node-gyp/README.md | 256 + .../node_modules/node-gyp/addon.gypi | 185 + .../node_modules/node-gyp/bin/node-gyp.js | 140 + .../node-gyp/docs/Common-issues.md | 14 + ...re-versions-of-node-cannot-be-installed.md | 94 + .../node_modules/node-gyp/docs/Home.md | 7 + .../node-gyp/docs/Linking-to-OpenSSL.md | 86 + .../docs/Updating-npm-bundled-node-gyp.md | 45 + .../docs/binding.gyp-files-in-the-wild.md | 48 + .../node_modules/node-gyp/gyp/.flake8 | 4 + .../gyp/.github/workflows/Python_tests.yml | 30 + .../gyp/.github/workflows/node-gyp.yml | 42 + .../gyp/.github/workflows/nodejs-windows.yml | 27 + .../gyp/.github/workflows/release-please.yml | 16 + .../node_modules/node-gyp/gyp/AUTHORS | 16 + .../node_modules/node-gyp/gyp/CHANGELOG.md | 177 + .../node-gyp/gyp/CODE_OF_CONDUCT.md | 4 + .../node_modules/node-gyp/gyp/CONTRIBUTING.md | 32 + .../node_modules/node-gyp/gyp/LICENSE | 28 + .../node_modules/node-gyp/gyp/README.md | 7 + .../node-gyp/gyp/data/win/large-pdb-shim.cc | 12 + .../node_modules/node-gyp/gyp/gyp | 8 + .../node_modules/node-gyp/gyp/gyp.bat | 5 + .../node_modules/node-gyp/gyp/gyp_main.py | 45 + .../node-gyp/gyp/pylib/gyp/MSVSNew.py | 367 + .../node-gyp/gyp/pylib/gyp/MSVSProject.py | 206 + .../node-gyp/gyp/pylib/gyp/MSVSSettings.py | 1270 ++ .../gyp/pylib/gyp/MSVSSettings_test.py | 1547 ++ .../node-gyp/gyp/pylib/gyp/MSVSToolFile.py | 59 + .../node-gyp/gyp/pylib/gyp/MSVSUserFile.py | 153 + .../node-gyp/gyp/pylib/gyp/MSVSUtil.py | 271 + .../node-gyp/gyp/pylib/gyp/MSVSVersion.py | 574 + .../node-gyp/gyp/pylib/gyp/__init__.py | 666 + .../node-gyp/gyp/pylib/gyp/common.py | 654 + .../node-gyp/gyp/pylib/gyp/common_test.py | 78 + .../node-gyp/gyp/pylib/gyp/easy_xml.py | 165 + .../node-gyp/gyp/pylib/gyp/easy_xml_test.py | 109 + .../node-gyp/gyp/pylib/gyp/flock_tool.py | 55 + .../gyp/pylib/gyp/generator/__init__.py | 0 .../gyp/pylib/gyp/generator/analyzer.py | 808 + .../gyp/pylib/gyp/generator/android.py | 1173 ++ .../node-gyp/gyp/pylib/gyp/generator/cmake.py | 1321 ++ .../gyp/generator/compile_commands_json.py | 120 + .../gyp/generator/dump_dependency_json.py | 103 + .../gyp/pylib/gyp/generator/eclipse.py | 464 + .../node-gyp/gyp/pylib/gyp/generator/gypd.py | 89 + .../node-gyp/gyp/pylib/gyp/generator/gypsh.py | 58 + .../node-gyp/gyp/pylib/gyp/generator/make.py | 2518 +++ .../node-gyp/gyp/pylib/gyp/generator/msvs.py | 3978 ++++ .../gyp/pylib/gyp/generator/msvs_test.py | 44 + .../node-gyp/gyp/pylib/gyp/generator/ninja.py | 2936 +++ .../gyp/pylib/gyp/generator/ninja_test.py | 55 + .../node-gyp/gyp/pylib/gyp/generator/xcode.py | 1394 ++ .../gyp/pylib/gyp/generator/xcode_test.py | 25 + .../node-gyp/gyp/pylib/gyp/input.py | 3137 +++ .../node-gyp/gyp/pylib/gyp/input_test.py | 98 + .../node-gyp/gyp/pylib/gyp/mac_tool.py | 771 + .../node-gyp/gyp/pylib/gyp/msvs_emulation.py | 1271 ++ .../node-gyp/gyp/pylib/gyp/ninja_syntax.py | 174 + .../node-gyp/gyp/pylib/gyp/simple_copy.py | 61 + .../node-gyp/gyp/pylib/gyp/win_tool.py | 374 + .../node-gyp/gyp/pylib/gyp/xcode_emulation.py | 1939 ++ .../node-gyp/gyp/pylib/gyp/xcode_ninja.py | 302 + .../node-gyp/gyp/pylib/gyp/xcodeproj_file.py | 3197 +++ .../node-gyp/gyp/pylib/gyp/xml_fix.py | 65 + .../node-gyp/gyp/requirements_dev.txt | 2 + .../node_modules/node-gyp/gyp/setup.py | 42 + .../node_modules/node-gyp/gyp/test_gyp.py | 260 + .../node_modules/node-gyp/gyp/tools/README | 15 + .../node-gyp/gyp/tools/Xcode/README | 5 + .../tools/Xcode/Specifications/gyp.pbfilespec | 27 + .../tools/Xcode/Specifications/gyp.xclangspec | 226 + .../node-gyp/gyp/tools/emacs/README | 12 + .../node-gyp/gyp/tools/emacs/gyp-tests.el | 63 + .../node-gyp/gyp/tools/emacs/gyp.el | 275 + .../gyp/tools/emacs/run-unit-tests.sh | 7 + .../gyp/tools/emacs/testdata/media.gyp | 1105 + .../tools/emacs/testdata/media.gyp.fontified | 1107 + .../node-gyp/gyp/tools/graphviz.py | 102 + .../node-gyp/gyp/tools/pretty_gyp.py | 156 + .../node-gyp/gyp/tools/pretty_sln.py | 181 + .../node-gyp/gyp/tools/pretty_vcproj.py | 339 + .../node-gyp/lib/Find-VisualStudio.cs | 250 + .../node_modules/node-gyp/lib/build.js | 204 + .../node_modules/node-gyp/lib/clean.js | 15 + .../node_modules/node-gyp/lib/configure.js | 294 + .../node-gyp/lib/create-config-gypi.js | 146 + .../node-gyp/lib/find-node-directory.js | 63 + .../node_modules/node-gyp/lib/find-python.js | 344 + .../node-gyp/lib/find-visualstudio.js | 446 + .../node_modules/node-gyp/lib/install.js | 376 + .../node_modules/node-gyp/lib/list.js | 27 + .../node_modules/node-gyp/lib/node-gyp.js | 211 + .../node-gyp/lib/process-release.js | 147 + .../node_modules/node-gyp/lib/rebuild.js | 13 + .../node_modules/node-gyp/lib/remove.js | 46 + .../node_modules/node-gyp/lib/util.js | 64 + .../node_modules/node-gyp/macOS_Catalina.md | 104 + .../node-gyp/macOS_Catalina_acid_test.sh | 21 + .../node_modules/node-gyp/package.json | 50 + .../node-gyp/src/win_delay_load_hook.cc | 39 + .../node_modules/node-gyp/test/common.js | 3 + .../fixtures/VS_2017_BuildTools_minimal.txt | 1 + .../fixtures/VS_2017_Community_workload.txt | 1 + .../test/fixtures/VS_2017_Express.txt | 1 + .../test/fixtures/VS_2017_Unusable.txt | 1 + .../fixtures/VS_2019_BuildTools_minimal.txt | 1 + .../fixtures/VS_2019_Community_workload.txt | 1 + .../test/fixtures/VS_2019_Preview.txt | 1 + .../node-gyp/test/fixtures/ca-bundle.crt | 40 + .../node-gyp/test/fixtures/ca.crt | 21 + .../fixtures/nodedir/include/node/config.gypi | 6 + .../node-gyp/test/fixtures/server.crt | 21 + .../node-gyp/test/fixtures/server.key | 27 + .../node-gyp/test/fixtures/test-charmap.py | 31 + .../node-gyp/test/process-exec-sync.js | 140 + .../node-gyp/test/simple-proxy.js | 27 + .../node_modules/node-gyp/test/test-addon.js | 150 + .../node-gyp/test/test-configure-python.js | 82 + .../node-gyp/test/test-create-config-gypi.js | 70 + .../node-gyp/test/test-download.js | 207 + .../test/test-find-accessible-sync.js | 84 + .../node-gyp/test/test-find-node-directory.js | 119 + .../node-gyp/test/test-find-python.js | 226 + .../node-gyp/test/test-find-visualstudio.js | 676 + .../node-gyp/test/test-install.js | 46 + .../node-gyp/test/test-options.js | 31 + .../node-gyp/test/test-process-release.js | 434 + .../node_modules/node-gyp/update-gyp.py | 46 + .../node_modules/nopt/CHANGELOG.md | 58 + .../node_modules/nopt/LICENSE | 15 + .../node_modules/nopt/README.md | 213 + .../node_modules/nopt/bin/nopt.js | 54 + .../node_modules/nopt/lib/nopt.js | 441 + .../node_modules/nopt/package.json | 34 + .../node_modules/npmlog/LICENSE.md | 20 + .../node_modules/npmlog/README.md | 216 + .../node_modules/npmlog/lib/log.js | 404 + .../node_modules/npmlog/package.json | 51 + .../node_modules/object-inspect/.eslintrc | 53 + .../object-inspect/.github/FUNDING.yml | 12 + .../node_modules/object-inspect/.nycrc | 13 + .../node_modules/object-inspect/CHANGELOG.md | 424 + .../node_modules/object-inspect/LICENSE | 21 + .../object-inspect/example/all.js | 23 + .../object-inspect/example/circular.js | 6 + .../node_modules/object-inspect/example/fn.js | 5 + .../object-inspect/example/inspect.js | 10 + .../node_modules/object-inspect/index.js | 544 + .../object-inspect/package-support.json | 20 + .../node_modules/object-inspect/package.json | 105 + .../object-inspect/readme.markdown | 84 + .../object-inspect/test-core-js.js | 26 + .../object-inspect/test/bigint.js | 58 + .../object-inspect/test/browser/dom.js | 15 + .../object-inspect/test/circular.js | 16 + .../node_modules/object-inspect/test/deep.js | 12 + .../object-inspect/test/element.js | 53 + .../node_modules/object-inspect/test/err.js | 48 + .../node_modules/object-inspect/test/fakes.js | 29 + .../node_modules/object-inspect/test/fn.js | 76 + .../object-inspect/test/global.js | 17 + .../node_modules/object-inspect/test/has.js | 15 + .../node_modules/object-inspect/test/holes.js | 15 + .../object-inspect/test/indent-option.js | 271 + .../object-inspect/test/inspect.js | 139 + .../object-inspect/test/lowbyte.js | 12 + .../object-inspect/test/number.js | 58 + .../object-inspect/test/quoteStyle.js | 26 + .../object-inspect/test/toStringTag.js | 40 + .../node_modules/object-inspect/test/undef.js | 12 + .../object-inspect/test/values.js | 261 + .../object-inspect/util.inspect.js | 1 + .../node_modules/on-finished/HISTORY.md | 98 + .../node_modules/on-finished/LICENSE | 23 + .../node_modules/on-finished/README.md | 162 + .../node_modules/on-finished/index.js | 234 + .../node_modules/on-finished/package.json | 39 + .../node_modules/once/LICENSE | 15 + .../node_modules/once/README.md | 79 + .../node_modules/once/once.js | 42 + .../node_modules/once/package.json | 33 + .../node_modules/p-map/index.d.ts | 67 + .../node_modules/p-map/index.js | 81 + .../node_modules/p-map/license | 9 + .../node_modules/p-map/package.json | 53 + .../node_modules/p-map/readme.md | 89 + .../node_modules/parseurl/HISTORY.md | 58 + .../node_modules/parseurl/LICENSE | 24 + .../node_modules/parseurl/README.md | 133 + .../node_modules/parseurl/index.js | 158 + .../node_modules/parseurl/package.json | 40 + .../node_modules/path-is-absolute/index.js | 20 + .../node_modules/path-is-absolute/license | 21 + .../path-is-absolute/package.json | 43 + .../node_modules/path-is-absolute/readme.md | 59 + .../node_modules/path-parse/LICENSE | 21 + .../node_modules/path-parse/README.md | 42 + .../node_modules/path-parse/index.js | 75 + .../node_modules/path-parse/package.json | 33 + .../node_modules/path-to-regexp/LICENSE | 21 + .../node_modules/path-to-regexp/Readme.md | 224 + .../path-to-regexp/dist/index.d.ts | 144 + .../node_modules/path-to-regexp/dist/index.js | 409 + .../path-to-regexp/dist/index.js.map | 1 + .../node_modules/path-to-regexp/package.json | 64 + .../node_modules/pg-connection-string/LICENSE | 21 + .../pg-connection-string/README.md | 77 + .../pg-connection-string/index.d.ts | 15 + .../pg-connection-string/index.js | 112 + .../pg-connection-string/package.json | 40 + .../prebuild-install/CHANGELOG.md | 131 + .../prebuild-install/CONTRIBUTING.md | 6 + .../node_modules/prebuild-install/LICENSE | 21 + .../node_modules/prebuild-install/README.md | 163 + .../node_modules/prebuild-install/asset.js | 44 + .../node_modules/prebuild-install/bin.js | 78 + .../node_modules/prebuild-install/download.js | 142 + .../node_modules/prebuild-install/error.js | 14 + .../node_modules/prebuild-install/help.txt | 16 + .../node_modules/prebuild-install/index.js | 1 + .../node_modules/prebuild-install/log.js | 33 + .../prebuild-install/package.json | 67 + .../node_modules/prebuild-install/proxy.js | 35 + .../node_modules/prebuild-install/rc.js | 64 + .../node_modules/prebuild-install/util.js | 143 + .../node_modules/promise-inflight/LICENSE | 14 + .../node_modules/promise-inflight/README.md | 34 + .../node_modules/promise-inflight/inflight.js | 36 + .../promise-inflight/package.json | 24 + .../node_modules/promise-retry/.editorconfig | 15 + .../node_modules/promise-retry/.jshintrc | 64 + .../node_modules/promise-retry/.travis.yml | 4 + .../node_modules/promise-retry/LICENSE | 19 + .../node_modules/promise-retry/README.md | 94 + .../node_modules/promise-retry/index.js | 52 + .../node_modules/promise-retry/package.json | 37 + .../node_modules/promise-retry/test/test.js | 263 + .../node_modules/proxy-addr/HISTORY.md | 161 + .../node_modules/proxy-addr/LICENSE | 22 + .../node_modules/proxy-addr/README.md | 139 + .../node_modules/proxy-addr/index.js | 327 + .../node_modules/proxy-addr/package.json | 47 + .../node_modules/pump/.github/FUNDING.yml | 2 + .../node_modules/pump/.travis.yml | 5 + .../node_modules/pump/LICENSE | 21 + .../node_modules/pump/README.md | 74 + .../node_modules/pump/SECURITY.md | 5 + .../node_modules/pump/index.js | 86 + .../node_modules/pump/package.json | 24 + .../node_modules/pump/test-browser.js | 66 + .../node_modules/pump/test-node.js | 53 + .../node_modules/qs/.editorconfig | 46 + .../node_modules/qs/.eslintrc | 39 + .../node_modules/qs/.github/FUNDING.yml | 12 + .../node_modules/qs/.nycrc | 13 + .../node_modules/qs/CHANGELOG.md | 622 + .../node_modules/qs/LICENSE.md | 29 + .../node_modules/qs/README.md | 733 + .../node_modules/qs/dist/qs.js | 141 + .../node_modules/qs/lib/formats.js | 23 + .../node_modules/qs/lib/index.js | 11 + .../node_modules/qs/lib/parse.js | 328 + .../node_modules/qs/lib/stringify.js | 356 + .../node_modules/qs/lib/utils.js | 268 + .../node_modules/qs/package.json | 93 + .../node_modules/qs/test/empty-keys-cases.js | 267 + .../node_modules/qs/test/parse.js | 1276 ++ .../node_modules/qs/test/stringify.js | 1306 ++ .../node_modules/qs/test/utils.js | 262 + .../node_modules/range-parser/HISTORY.md | 56 + .../node_modules/range-parser/LICENSE | 23 + .../node_modules/range-parser/README.md | 84 + .../node_modules/range-parser/index.js | 162 + .../node_modules/range-parser/package.json | 44 + .../node_modules/raw-body/LICENSE | 22 + .../node_modules/raw-body/README.md | 223 + .../node_modules/raw-body/index.d.ts | 85 + .../node_modules/raw-body/index.js | 336 + .../node_modules/raw-body/package.json | 46 + .../node_modules/rc/LICENSE.APACHE2 | 15 + .../node_modules/rc/LICENSE.BSD | 26 + .../node_modules/rc/LICENSE.MIT | 24 + .../node_modules/rc/README.md | 227 + .../node_modules/rc/browser.js | 7 + .../node_modules/rc/cli.js | 4 + .../node_modules/rc/index.js | 53 + .../node_modules/rc/lib/utils.js | 104 + .../node_modules/rc/package.json | 29 + .../node_modules/rc/test/ini.js | 16 + .../node_modules/rc/test/nested-env-vars.js | 50 + .../node_modules/rc/test/test.js | 59 + .../readable-stream/CONTRIBUTING.md | 38 + .../readable-stream/GOVERNANCE.md | 136 + .../node_modules/readable-stream/LICENSE | 47 + .../node_modules/readable-stream/README.md | 106 + .../readable-stream/errors-browser.js | 127 + .../node_modules/readable-stream/errors.js | 116 + .../readable-stream/experimentalWarning.js | 17 + .../readable-stream/lib/_stream_duplex.js | 126 + .../lib/_stream_passthrough.js | 37 + .../readable-stream/lib/_stream_readable.js | 1027 + .../readable-stream/lib/_stream_transform.js | 190 + .../readable-stream/lib/_stream_writable.js | 641 + .../lib/internal/streams/async_iterator.js | 180 + .../lib/internal/streams/buffer_list.js | 183 + .../lib/internal/streams/destroy.js | 96 + .../lib/internal/streams/end-of-stream.js | 86 + .../lib/internal/streams/from-browser.js | 3 + .../lib/internal/streams/from.js | 52 + .../lib/internal/streams/pipeline.js | 86 + .../lib/internal/streams/state.js | 22 + .../lib/internal/streams/stream-browser.js | 1 + .../lib/internal/streams/stream.js | 1 + .../node_modules/readable-stream/package.json | 68 + .../readable-stream/readable-browser.js | 9 + .../node_modules/readable-stream/readable.js | 16 + .../node_modules/rechoir/CHANGELOG.md | 12 + .../node_modules/rechoir/LICENSE | 21 + .../node_modules/rechoir/README.md | 73 + .../node_modules/rechoir/index.js | 69 + .../node_modules/rechoir/lib/extension.js | 44 + .../node_modules/rechoir/lib/normalize.js | 13 + .../node_modules/rechoir/lib/register.js | 15 + .../node_modules/rechoir/package.json | 52 + .../node_modules/resolve-from/index.d.ts | 31 + .../node_modules/resolve-from/index.js | 47 + .../node_modules/resolve-from/license | 9 + .../node_modules/resolve-from/package.json | 36 + .../node_modules/resolve-from/readme.md | 72 + .../node_modules/resolve/.editorconfig | 37 + .../node_modules/resolve/.eslintrc | 65 + .../node_modules/resolve/.github/FUNDING.yml | 12 + .../.github/INCIDENT_RESPONSE_PROCESS.md | 119 + .../resolve/.github/THREAT_MODEL.md | 74 + .../node_modules/resolve/LICENSE | 21 + .../node_modules/resolve/SECURITY.md | 11 + .../node_modules/resolve/async.js | 3 + .../node_modules/resolve/bin/resolve | 50 + .../node_modules/resolve/example/async.js | 5 + .../node_modules/resolve/example/sync.js | 3 + .../node_modules/resolve/index.js | 6 + .../node_modules/resolve/lib/async.js | 333 + .../node_modules/resolve/lib/caller.js | 8 + .../node_modules/resolve/lib/core.js | 12 + .../node_modules/resolve/lib/core.json | 162 + .../node_modules/resolve/lib/homedir.js | 24 + .../node_modules/resolve/lib/is-core.js | 5 + .../resolve/lib/node-modules-paths.js | 45 + .../resolve/lib/normalize-options.js | 10 + .../node_modules/resolve/lib/sync.js | 212 + .../node_modules/resolve/package.json | 75 + .../node_modules/resolve/readme.markdown | 301 + .../node_modules/resolve/sync.js | 3 + .../node_modules/resolve/test/core.js | 88 + .../node_modules/resolve/test/dotdot.js | 29 + .../resolve/test/dotdot/abc/index.js | 2 + .../node_modules/resolve/test/dotdot/index.js | 1 + .../resolve/test/faulty_basedir.js | 29 + .../node_modules/resolve/test/filter.js | 34 + .../node_modules/resolve/test/filter_sync.js | 33 + .../node_modules/resolve/test/home_paths.js | 127 + .../resolve/test/home_paths_sync.js | 114 + .../node_modules/resolve/test/mock.js | 315 + .../node_modules/resolve/test/mock_sync.js | 214 + .../node_modules/resolve/test/module_dir.js | 56 + .../test/module_dir/xmodules/aaa/index.js | 1 + .../test/module_dir/ymodules/aaa/index.js | 1 + .../test/module_dir/zmodules/bbb/main.js | 1 + .../test/module_dir/zmodules/bbb/package.json | 3 + .../resolve/test/node-modules-paths.js | 143 + .../node_modules/resolve/test/node_path.js | 70 + .../resolve/test/node_path/x/aaa/index.js | 1 + .../resolve/test/node_path/x/ccc/index.js | 1 + .../resolve/test/node_path/y/bbb/index.js | 1 + .../resolve/test/node_path/y/ccc/index.js | 1 + .../node_modules/resolve/test/nonstring.js | 9 + .../node_modules/resolve/test/pathfilter.js | 75 + .../resolve/test/pathfilter/deep_ref/main.js | 0 .../node_modules/resolve/test/precedence.js | 23 + .../resolve/test/precedence/aaa.js | 1 + .../resolve/test/precedence/aaa/index.js | 1 + .../resolve/test/precedence/aaa/main.js | 1 + .../resolve/test/precedence/bbb.js | 1 + .../resolve/test/precedence/bbb/main.js | 1 + .../node_modules/resolve/test/resolver.js | 597 + .../resolve/test/resolver/baz/doom.js | 0 .../resolve/test/resolver/baz/package.json | 4 + .../resolve/test/resolver/baz/quux.js | 1 + .../resolve/test/resolver/browser_field/a.js | 0 .../resolve/test/resolver/browser_field/b.js | 0 .../test/resolver/browser_field/package.json | 5 + .../resolve/test/resolver/cup.coffee | 1 + .../resolve/test/resolver/dot_main/index.js | 1 + .../test/resolver/dot_main/package.json | 3 + .../test/resolver/dot_slash_main/index.js | 1 + .../test/resolver/dot_slash_main/package.json | 3 + .../resolve/test/resolver/false_main/index.js | 0 .../test/resolver/false_main/package.json | 4 + .../node_modules/resolve/test/resolver/foo.js | 1 + .../test/resolver/incorrect_main/index.js | 2 + .../test/resolver/incorrect_main/package.json | 3 + .../test/resolver/invalid_main/package.json | 7 + .../resolve/test/resolver/mug.coffee | 0 .../node_modules/resolve/test/resolver/mug.js | 0 .../test/resolver/multirepo/lerna.json | 6 + .../test/resolver/multirepo/package.json | 20 + .../multirepo/packages/package-a/index.js | 35 + .../multirepo/packages/package-a/package.json | 14 + .../multirepo/packages/package-b/index.js | 0 .../multirepo/packages/package-b/package.json | 14 + .../resolver/nested_symlinks/mylib/async.js | 26 + .../nested_symlinks/mylib/package.json | 15 + .../resolver/nested_symlinks/mylib/sync.js | 12 + .../test/resolver/other_path/lib/other-lib.js | 0 .../resolve/test/resolver/other_path/root.js | 0 .../resolve/test/resolver/quux/foo/index.js | 1 + .../resolve/test/resolver/same_names/foo.js | 1 + .../test/resolver/same_names/foo/index.js | 1 + .../resolver/symlinked/_/node_modules/foo.js | 0 .../symlinked/_/symlink_target/.gitkeep | 0 .../test/resolver/symlinked/package/bar.js | 1 + .../resolver/symlinked/package/package.json | 3 + .../test/resolver/without_basedir/main.js | 5 + .../resolve/test/resolver_sync.js | 730 + .../resolve/test/shadowed_core.js | 54 + .../shadowed_core/node_modules/util/index.js | 0 .../node_modules/resolve/test/subdirs.js | 13 + .../node_modules/resolve/test/symlinks.js | 176 + .../node_modules/retry/.npmignore | 3 + .../node_modules/retry/.travis.yml | 15 + .../node_modules/retry/License | 21 + .../node_modules/retry/Makefile | 18 + .../node_modules/retry/README.md | 227 + .../node_modules/retry/equation.gif | Bin 0 -> 1209 bytes .../node_modules/retry/example/dns.js | 31 + .../node_modules/retry/example/stop.js | 40 + .../node_modules/retry/index.js | 1 + .../node_modules/retry/lib/retry.js | 100 + .../node_modules/retry/lib/retry_operation.js | 158 + .../node_modules/retry/package.json | 32 + .../node_modules/retry/test/common.js | 10 + .../retry/test/integration/test-forever.js | 24 + .../test/integration/test-retry-operation.js | 258 + .../retry/test/integration/test-retry-wrap.js | 101 + .../retry/test/integration/test-timeouts.js | 69 + .../node_modules/rimraf/CHANGELOG.md | 65 + .../node_modules/rimraf/LICENSE | 15 + .../node_modules/rimraf/README.md | 101 + .../node_modules/rimraf/bin.js | 68 + .../node_modules/rimraf/package.json | 32 + .../node_modules/rimraf/rimraf.js | 360 + .../node_modules/router/HISTORY.md | 228 + .../node_modules/router/LICENSE | 23 + .../node_modules/router/README.md | 416 + .../node_modules/router/index.js | 748 + .../node_modules/router/lib/layer.js | 247 + .../node_modules/router/lib/route.js | 242 + .../node_modules/router/package.json | 44 + .../node_modules/safe-buffer/LICENSE | 21 + .../node_modules/safe-buffer/README.md | 584 + .../node_modules/safe-buffer/index.d.ts | 187 + .../node_modules/safe-buffer/index.js | 65 + .../node_modules/safe-buffer/package.json | 51 + .../node_modules/safer-buffer/LICENSE | 21 + .../safer-buffer/Porting-Buffer.md | 268 + .../node_modules/safer-buffer/Readme.md | 156 + .../node_modules/safer-buffer/dangerous.js | 58 + .../node_modules/safer-buffer/package.json | 34 + .../node_modules/safer-buffer/safer.js | 77 + .../node_modules/safer-buffer/tests.js | 406 + .../node_modules/semver/LICENSE | 15 + .../node_modules/semver/README.md | 664 + .../node_modules/semver/bin/semver.js | 191 + .../node_modules/semver/classes/comparator.js | 143 + .../node_modules/semver/classes/index.js | 7 + .../node_modules/semver/classes/range.js | 557 + .../node_modules/semver/classes/semver.js | 333 + .../node_modules/semver/functions/clean.js | 8 + .../node_modules/semver/functions/cmp.js | 54 + .../node_modules/semver/functions/coerce.js | 62 + .../semver/functions/compare-build.js | 9 + .../semver/functions/compare-loose.js | 5 + .../node_modules/semver/functions/compare.js | 7 + .../node_modules/semver/functions/diff.js | 60 + .../node_modules/semver/functions/eq.js | 5 + .../node_modules/semver/functions/gt.js | 5 + .../node_modules/semver/functions/gte.js | 5 + .../node_modules/semver/functions/inc.js | 21 + .../node_modules/semver/functions/lt.js | 5 + .../node_modules/semver/functions/lte.js | 5 + .../node_modules/semver/functions/major.js | 5 + .../node_modules/semver/functions/minor.js | 5 + .../node_modules/semver/functions/neq.js | 5 + .../node_modules/semver/functions/parse.js | 18 + .../node_modules/semver/functions/patch.js | 5 + .../semver/functions/prerelease.js | 8 + .../node_modules/semver/functions/rcompare.js | 5 + .../node_modules/semver/functions/rsort.js | 5 + .../semver/functions/satisfies.js | 12 + .../node_modules/semver/functions/sort.js | 5 + .../node_modules/semver/functions/valid.js | 8 + .../node_modules/semver/index.js | 91 + .../node_modules/semver/internal/constants.js | 37 + .../node_modules/semver/internal/debug.js | 11 + .../semver/internal/identifiers.js | 29 + .../node_modules/semver/internal/lrucache.js | 42 + .../semver/internal/parse-options.js | 17 + .../node_modules/semver/internal/re.js | 223 + .../node_modules/semver/package.json | 78 + .../node_modules/semver/preload.js | 4 + .../node_modules/semver/range.bnf | 16 + .../node_modules/semver/ranges/gtr.js | 6 + .../node_modules/semver/ranges/intersects.js | 9 + .../node_modules/semver/ranges/ltr.js | 6 + .../semver/ranges/max-satisfying.js | 27 + .../semver/ranges/min-satisfying.js | 26 + .../node_modules/semver/ranges/min-version.js | 63 + .../node_modules/semver/ranges/outside.js | 82 + .../node_modules/semver/ranges/simplify.js | 49 + .../node_modules/semver/ranges/subset.js | 249 + .../semver/ranges/to-comparators.js | 10 + .../node_modules/semver/ranges/valid.js | 13 + .../node_modules/send/HISTORY.md | 580 + .../node_modules/send/LICENSE | 23 + .../node_modules/send/README.md | 317 + .../node_modules/send/index.js | 997 + .../node_modules/send/package.json | 60 + .../node_modules/serve-static/HISTORY.md | 516 + .../node_modules/serve-static/LICENSE | 25 + .../node_modules/serve-static/README.md | 253 + .../node_modules/serve-static/index.js | 208 + .../node_modules/serve-static/package.json | 41 + .../node_modules/set-blocking/CHANGELOG.md | 26 + .../node_modules/set-blocking/LICENSE.txt | 14 + .../node_modules/set-blocking/README.md | 31 + .../node_modules/set-blocking/index.js | 7 + .../node_modules/set-blocking/package.json | 42 + .../node_modules/setprototypeof/LICENSE | 13 + .../node_modules/setprototypeof/README.md | 31 + .../node_modules/setprototypeof/index.d.ts | 2 + .../node_modules/setprototypeof/index.js | 17 + .../node_modules/setprototypeof/package.json | 38 + .../node_modules/setprototypeof/test/index.js | 24 + .../side-channel-list/.editorconfig | 9 + .../node_modules/side-channel-list/.eslintrc | 11 + .../side-channel-list/.github/FUNDING.yml | 12 + .../node_modules/side-channel-list/.nycrc | 13 + .../side-channel-list/CHANGELOG.md | 15 + .../node_modules/side-channel-list/LICENSE | 21 + .../node_modules/side-channel-list/README.md | 62 + .../node_modules/side-channel-list/index.d.ts | 13 + .../node_modules/side-channel-list/index.js | 113 + .../node_modules/side-channel-list/list.d.ts | 14 + .../side-channel-list/package.json | 77 + .../side-channel-list/test/index.js | 104 + .../side-channel-list/tsconfig.json | 9 + .../side-channel-map/.editorconfig | 9 + .../node_modules/side-channel-map/.eslintrc | 11 + .../side-channel-map/.github/FUNDING.yml | 12 + .../node_modules/side-channel-map/.nycrc | 13 + .../side-channel-map/CHANGELOG.md | 22 + .../node_modules/side-channel-map/LICENSE | 21 + .../node_modules/side-channel-map/README.md | 62 + .../node_modules/side-channel-map/index.d.ts | 15 + .../node_modules/side-channel-map/index.js | 68 + .../side-channel-map/package.json | 80 + .../side-channel-map/test/index.js | 114 + .../side-channel-map/tsconfig.json | 9 + .../side-channel-weakmap/.editorconfig | 9 + .../side-channel-weakmap/.eslintrc | 12 + .../side-channel-weakmap/.github/FUNDING.yml | 12 + .../node_modules/side-channel-weakmap/.nycrc | 13 + .../side-channel-weakmap/CHANGELOG.md | 28 + .../node_modules/side-channel-weakmap/LICENSE | 21 + .../side-channel-weakmap/README.md | 62 + .../side-channel-weakmap/index.d.ts | 15 + .../side-channel-weakmap/index.js | 84 + .../side-channel-weakmap/package.json | 87 + .../side-channel-weakmap/test/index.js | 114 + .../side-channel-weakmap/tsconfig.json | 9 + .../node_modules/side-channel/.editorconfig | 9 + .../node_modules/side-channel/.eslintrc | 12 + .../side-channel/.github/FUNDING.yml | 12 + .../node_modules/side-channel/.nycrc | 13 + .../node_modules/side-channel/CHANGELOG.md | 110 + .../node_modules/side-channel/LICENSE | 21 + .../node_modules/side-channel/README.md | 61 + .../node_modules/side-channel/index.d.ts | 14 + .../node_modules/side-channel/index.js | 43 + .../node_modules/side-channel/package.json | 85 + .../node_modules/side-channel/test/index.js | 104 + .../node_modules/side-channel/tsconfig.json | 9 + .../node_modules/signal-exit/LICENSE.txt | 16 + .../node_modules/signal-exit/README.md | 39 + .../node_modules/signal-exit/index.js | 202 + .../node_modules/signal-exit/package.json | 38 + .../node_modules/signal-exit/signals.js | 53 + .../node_modules/simple-concat/.travis.yml | 3 + .../node_modules/simple-concat/LICENSE | 20 + .../node_modules/simple-concat/README.md | 44 + .../node_modules/simple-concat/index.js | 15 + .../node_modules/simple-concat/package.json | 47 + .../node_modules/simple-concat/test/basic.js | 41 + .../simple-get/.github/dependabot.yml | 15 + .../simple-get/.github/workflows/ci.yml | 23 + .../node_modules/simple-get/LICENSE | 20 + .../node_modules/simple-get/README.md | 333 + .../node_modules/simple-get/index.js | 108 + .../node_modules/simple-get/package.json | 67 + .../smart-buffer/.prettierrc.yaml | 5 + .../node_modules/smart-buffer/.travis.yml | 13 + .../node_modules/smart-buffer/LICENSE | 20 + .../node_modules/smart-buffer/README.md | 633 + .../smart-buffer/build/smartbuffer.js | 1233 ++ .../smart-buffer/build/smartbuffer.js.map | 1 + .../node_modules/smart-buffer/build/utils.js | 108 + .../smart-buffer/build/utils.js.map | 1 + .../smart-buffer/docs/CHANGELOG.md | 70 + .../smart-buffer/docs/README_v3.md | 367 + .../node_modules/smart-buffer/docs/ROADMAP.md | 0 .../node_modules/smart-buffer/package.json | 79 + .../smart-buffer/typings/smartbuffer.d.ts | 755 + .../smart-buffer/typings/utils.d.ts | 66 + .../node_modules/socks-proxy-agent/README.md | 152 + .../socks-proxy-agent/dist/index.d.ts | 38 + .../socks-proxy-agent/dist/index.js | 197 + .../socks-proxy-agent/dist/index.js.map | 1 + .../socks-proxy-agent/package.json | 181 + .../node_modules/socks/.eslintrc.cjs | 11 + .../node_modules/socks/.prettierrc.yaml | 7 + .../node_modules/socks/LICENSE | 20 + .../node_modules/socks/README.md | 686 + .../socks/build/client/socksclient.js | 793 + .../socks/build/client/socksclient.js.map | 1 + .../socks/build/common/constants.js | 108 + .../socks/build/common/constants.js.map | 1 + .../socks/build/common/helpers.js | 167 + .../socks/build/common/helpers.js.map | 1 + .../socks/build/common/receivebuffer.js | 43 + .../socks/build/common/receivebuffer.js.map | 1 + .../node_modules/socks/build/common/util.js | 25 + .../socks/build/common/util.js.map | 1 + .../node_modules/socks/build/index.js | 18 + .../node_modules/socks/build/index.js.map | 1 + .../node_modules/socks/docs/examples/index.md | 17 + .../examples/javascript/associateExample.md | 90 + .../docs/examples/javascript/bindExample.md | 83 + .../examples/javascript/connectExample.md | 258 + .../examples/typescript/associateExample.md | 93 + .../docs/examples/typescript/bindExample.md | 86 + .../examples/typescript/connectExample.md | 265 + .../node_modules/socks/docs/index.md | 5 + .../socks/docs/migratingFromV1.md | 86 + .../node_modules/socks/package.json | 58 + .../socks/typings/client/socksclient.d.ts | 162 + .../socks/typings/common/constants.d.ts | 151 + .../socks/typings/common/helpers.d.ts | 17 + .../socks/typings/common/receivebuffer.d.ts | 12 + .../socks/typings/common/util.d.ts | 14 + .../node_modules/socks/typings/index.d.ts | 1 + .../node_modules/sqlite3/LICENSE | 25 + .../node_modules/sqlite3/README.md | 249 + .../node_modules/sqlite3/binding.gyp | 58 + .../sqlite3/build/Release/node_sqlite3.node | Bin 0 -> 1892864 bytes .../sqlite3/deps/common-sqlite.gypi | 60 + .../node_modules/sqlite3/deps/extract.js | 10 + .../deps/sqlite-autoconf-3440200.tar.gz | Bin 0 -> 3204841 bytes .../node_modules/sqlite3/deps/sqlite3.gyp | 121 + .../sqlite3/lib/sqlite3-binding.js | 1 + .../node_modules/sqlite3/lib/sqlite3.d.ts | 205 + .../node_modules/sqlite3/lib/sqlite3.js | 207 + .../node_modules/sqlite3/lib/trace.js | 38 + .../node_modules/sqlite3/package.json | 89 + .../node_modules/sqlite3/src/async.h | 76 + .../node_modules/sqlite3/src/backup.cc | 418 + .../node_modules/sqlite3/src/backup.h | 209 + .../node_modules/sqlite3/src/database.cc | 751 + .../node_modules/sqlite3/src/database.h | 188 + .../node_modules/sqlite3/src/gcc-preinclude.h | 30 + .../node_modules/sqlite3/src/macros.h | 207 + .../node_modules/sqlite3/src/node_sqlite3.cc | 128 + .../node_modules/sqlite3/src/statement.cc | 939 + .../node_modules/sqlite3/src/statement.h | 244 + .../node_modules/sqlite3/src/threading.h | 10 + .../node_modules/ssri/CHANGELOG.md | 355 + .../node_modules/ssri/LICENSE.md | 16 + .../node_modules/ssri/README.md | 528 + .../node_modules/ssri/index.js | 470 + .../node_modules/ssri/package.json | 52 + .../node_modules/statuses/HISTORY.md | 87 + .../node_modules/statuses/LICENSE | 23 + .../node_modules/statuses/README.md | 139 + .../node_modules/statuses/codes.json | 65 + .../node_modules/statuses/index.js | 146 + .../node_modules/statuses/package.json | 49 + .../node_modules/string-width/index.d.ts | 29 + .../node_modules/string-width/index.js | 47 + .../node_modules/string-width/license | 9 + .../node_modules/string-width/package.json | 56 + .../node_modules/string-width/readme.md | 50 + .../node_modules/string_decoder/LICENSE | 48 + .../node_modules/string_decoder/README.md | 47 + .../string_decoder/lib/string_decoder.js | 296 + .../node_modules/string_decoder/package.json | 34 + .../node_modules/strip-ansi/index.d.ts | 17 + .../node_modules/strip-ansi/index.js | 4 + .../node_modules/strip-ansi/license | 9 + .../node_modules/strip-ansi/package.json | 54 + .../node_modules/strip-ansi/readme.md | 46 + .../node_modules/strip-json-comments/index.js | 70 + .../node_modules/strip-json-comments/license | 21 + .../strip-json-comments/package.json | 42 + .../strip-json-comments/readme.md | 64 + .../supports-preserve-symlinks-flag/.eslintrc | 14 + .../.github/FUNDING.yml | 12 + .../supports-preserve-symlinks-flag/.nycrc | 9 + .../CHANGELOG.md | 22 + .../supports-preserve-symlinks-flag/LICENSE | 21 + .../supports-preserve-symlinks-flag/README.md | 42 + .../browser.js | 3 + .../supports-preserve-symlinks-flag/index.js | 9 + .../package.json | 70 + .../test/index.js | 29 + .../node_modules/tar-fs/.travis.yml | 6 + .../node_modules/tar-fs/LICENSE | 21 + .../node_modules/tar-fs/README.md | 165 + .../node_modules/tar-fs/index.js | 363 + .../tar-fs/node_modules/chownr/LICENSE | 15 + .../tar-fs/node_modules/chownr/README.md | 3 + .../tar-fs/node_modules/chownr/chownr.js | 167 + .../tar-fs/node_modules/chownr/package.json | 29 + .../node_modules/tar-fs/package.json | 41 + .../tar-fs/test/fixtures/a/hello.txt | 1 + .../tar-fs/test/fixtures/b/a/test.txt | 1 + .../node_modules/tar-fs/test/fixtures/d/file1 | 0 .../node_modules/tar-fs/test/fixtures/d/file2 | 0 .../tar-fs/test/fixtures/d/sub-dir/file5 | 0 .../tar-fs/test/fixtures/d/sub-files/file3 | 0 .../tar-fs/test/fixtures/d/sub-files/file4 | 0 .../tar-fs/test/fixtures/e/directory/.ignore | 0 .../node_modules/tar-fs/test/fixtures/e/file | 0 .../tar-fs/test/fixtures/invalid.tar | Bin 0 -> 2560 bytes .../node_modules/tar-fs/test/index.js | 346 + .../node_modules/tar-stream/LICENSE | 21 + .../node_modules/tar-stream/README.md | 168 + .../node_modules/tar-stream/extract.js | 257 + .../node_modules/tar-stream/headers.js | 295 + .../node_modules/tar-stream/index.js | 2 + .../node_modules/tar-stream/pack.js | 255 + .../node_modules/tar-stream/package.json | 58 + .../node_modules/tar-stream/sandbox.js | 11 + .../node_modules/tar/LICENSE | 15 + .../node_modules/tar/README.md | 1080 + .../node_modules/tar/index.js | 18 + .../node_modules/tar/lib/create.js | 111 + .../node_modules/tar/lib/extract.js | 113 + .../node_modules/tar/lib/get-write-flag.js | 20 + .../node_modules/tar/lib/header.js | 304 + .../node_modules/tar/lib/high-level-opt.js | 29 + .../node_modules/tar/lib/large-numbers.js | 104 + .../node_modules/tar/lib/list.js | 139 + .../node_modules/tar/lib/mkdir.js | 229 + .../node_modules/tar/lib/mode-fix.js | 27 + .../node_modules/tar/lib/normalize-unicode.js | 12 + .../tar/lib/normalize-windows-path.js | 8 + .../node_modules/tar/lib/pack.js | 432 + .../node_modules/tar/lib/parse.js | 552 + .../node_modules/tar/lib/path-reservations.js | 156 + .../node_modules/tar/lib/pax.js | 150 + .../node_modules/tar/lib/read-entry.js | 107 + .../node_modules/tar/lib/replace.js | 246 + .../tar/lib/strip-absolute-path.js | 24 + .../tar/lib/strip-trailing-slashes.js | 13 + .../node_modules/tar/lib/types.js | 44 + .../node_modules/tar/lib/unpack.js | 923 + .../node_modules/tar/lib/update.js | 40 + .../node_modules/tar/lib/warn-mixin.js | 24 + .../node_modules/tar/lib/winchars.js | 23 + .../node_modules/tar/lib/write-entry.js | 546 + .../tar/node_modules/minipass/LICENSE | 15 + .../tar/node_modules/minipass/README.md | 769 + .../tar/node_modules/minipass/index.d.ts | 152 + .../tar/node_modules/minipass/index.js | 702 + .../tar/node_modules/minipass/index.mjs | 702 + .../tar/node_modules/minipass/package.json | 76 + .../node_modules/tar/package.json | 70 + .../node_modules/tarn/LICENSE | 22 + .../node_modules/tarn/README.md | 193 + .../tarn/dist/PendingOperation.d.ts | 12 + .../tarn/dist/PendingOperation.js | 48 + .../node_modules/tarn/dist/Pool.d.ts | 98 + .../node_modules/tarn/dist/Pool.js | 516 + .../tarn/dist/PromiseInspection.d.ts | 16 + .../tarn/dist/PromiseInspection.js | 21 + .../node_modules/tarn/dist/Resource.d.ts | 9 + .../node_modules/tarn/dist/Resource.js | 19 + .../node_modules/tarn/dist/TimeoutError.d.ts | 2 + .../node_modules/tarn/dist/TimeoutError.js | 5 + .../node_modules/tarn/dist/tarn.d.ts | 3 + .../node_modules/tarn/dist/tarn.js | 10 + .../node_modules/tarn/dist/utils.d.ts | 14 + .../node_modules/tarn/dist/utils.js | 60 + .../node_modules/tarn/package.json | 66 + .../node_modules/tildify/index.d.ts | 14 + .../node_modules/tildify/index.js | 13 + .../node_modules/tildify/license | 9 + .../node_modules/tildify/package.json | 40 + .../node_modules/tildify/readme.md | 30 + .../node_modules/toidentifier/HISTORY.md | 9 + .../node_modules/toidentifier/LICENSE | 21 + .../node_modules/toidentifier/README.md | 61 + .../node_modules/toidentifier/index.js | 32 + .../node_modules/toidentifier/package.json | 38 + .../node_modules/tunnel-agent/LICENSE | 55 + .../node_modules/tunnel-agent/README.md | 4 + .../node_modules/tunnel-agent/index.js | 244 + .../node_modules/tunnel-agent/package.json | 22 + .../node_modules/type-is/HISTORY.md | 292 + .../node_modules/type-is/LICENSE | 23 + .../node_modules/type-is/README.md | 198 + .../node_modules/type-is/index.js | 250 + .../node_modules/type-is/package.json | 47 + .../unique-filename/.nyc_output/54942.json | 1 + .../unique-filename/.nyc_output/54944.json | 1 + .../node_modules/unique-filename/LICENSE | 5 + .../node_modules/unique-filename/README.md | 33 + .../coverage/__root__/index.html | 73 + .../coverage/__root__/index.js.html | 69 + .../unique-filename/coverage/base.css | 182 + .../unique-filename/coverage/index.html | 73 + .../unique-filename/coverage/prettify.css | 1 + .../unique-filename/coverage/prettify.js | 1 + .../coverage/sort-arrow-sprite.png | Bin 0 -> 209 bytes .../unique-filename/coverage/sorter.js | 156 + .../node_modules/unique-filename/index.js | 8 + .../node_modules/unique-filename/package.json | 27 + .../unique-filename/test/index.js | 23 + .../node_modules/unique-slug/.travis.yml | 10 + .../node_modules/unique-slug/LICENSE | 15 + .../node_modules/unique-slug/README.md | 19 + .../node_modules/unique-slug/index.js | 11 + .../node_modules/unique-slug/package.json | 23 + .../node_modules/unique-slug/test/index.js | 13 + .../node_modules/unpipe/HISTORY.md | 4 + .../node_modules/unpipe/LICENSE | 22 + .../node_modules/unpipe/README.md | 43 + .../node_modules/unpipe/index.js | 69 + .../node_modules/unpipe/package.json | 27 + .../node_modules/util-deprecate/History.md | 16 + .../node_modules/util-deprecate/LICENSE | 24 + .../node_modules/util-deprecate/README.md | 53 + .../node_modules/util-deprecate/browser.js | 67 + .../node_modules/util-deprecate/node.js | 6 + .../node_modules/util-deprecate/package.json | 27 + .../node_modules/vary/HISTORY.md | 39 + .../node_modules/vary/LICENSE | 22 + .../node_modules/vary/README.md | 101 + .../node_modules/vary/index.js | 149 + .../node_modules/vary/package.json | 43 + .../node_modules/which/CHANGELOG.md | 166 + .../node_modules/which/LICENSE | 15 + .../node_modules/which/README.md | 54 + .../node_modules/which/bin/node-which | 52 + .../node_modules/which/package.json | 43 + .../node_modules/which/which.js | 125 + .../node_modules/wide-align/LICENSE | 14 + .../node_modules/wide-align/README.md | 47 + .../node_modules/wide-align/align.js | 65 + .../node_modules/wide-align/package.json | 33 + .../node_modules/wrappy/LICENSE | 15 + .../node_modules/wrappy/README.md | 36 + .../node_modules/wrappy/package.json | 29 + .../node_modules/wrappy/wrappy.js | 33 + .../node_modules/yallist/LICENSE | 15 + .../node_modules/yallist/README.md | 204 + .../node_modules/yallist/iterator.js | 8 + .../node_modules/yallist/package.json | 29 + .../node_modules/yallist/yallist.js | 426 + .../introToBackendAssignment/notes.txt | 19 + .../package-lock.json | 2442 +++ .../introToBackendAssignment/package.json | 19 + .../introToBackendAssignment/users.sqlite3 | 0 3239 files changed, 311662 insertions(+) create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/UsersoumaiDocumentsweb developementHackYourFutureweek-10 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/color-support create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/color-support.cmd create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/color-support.ps1 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/knex create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/knex.cmd create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/knex.ps1 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/mkdirp create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/mkdirp.cmd create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/mkdirp.ps1 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-gyp create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-gyp.cmd create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-gyp.ps1 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-which create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-which.cmd create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-which.ps1 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/nopt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/nopt.cmd create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/nopt.ps1 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/prebuild-install create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/prebuild-install.cmd create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/prebuild-install.ps1 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rc.cmd create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rc.ps1 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/resolve create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/resolve.cmd create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/resolve.ps1 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rimraf create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rimraf.cmd create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rimraf.ps1 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/semver create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/semver.cmd create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/semver.ps1 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.package-lock.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/LICENSE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/LICENSE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/file-url-to-path/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/file-url-to-path/polyfill.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/get-options.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/node.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/owner.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/copy-file.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/cp/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/cp/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/cp/polyfill.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/errors.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/fs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/mkdir/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/mkdir/polyfill.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/mkdtemp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/rm/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/rm/polyfill.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/with-temp-dir.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/write-file.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/LICENSE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/dist/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/dist/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/dist/index.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/abbrev.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/index.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/promisify.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/promisify.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/promisify.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/src/index.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/src/promisify.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/browser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/lib/agent.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/lib/constants.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/lib/https_agent.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/LICENSE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker-base.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker-group.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker-stream.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/LICENSE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/base64js.min.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/LICENSE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/bindings.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/.travis.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/BufferList.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/LICENSE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/bl.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/convert.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/indexOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/isBufferList.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/test.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/read.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/json.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/raw.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/text.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/urlencoded.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/utils.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/AUTHORS.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/History.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/Readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/LICENSE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/get.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/path.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/read.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/rm.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/write.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/entry-index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/memoization.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/disposer.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/fix-owner.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/hash-to-segments.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/move-file.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/tmp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/verify.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/ls.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/put.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/rm.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/verify.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/actualApply.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/actualApply.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/applyBind.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/applyBind.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionApply.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionApply.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionCall.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionCall.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/reflectApply.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/reflectApply.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/tsconfig.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/tsconfig.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/chownr.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/bin.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/browser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/LICENSE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/index.cjs create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/Readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/esm.mjs create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/lib/argument.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/lib/command.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/lib/error.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/lib/help.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/lib/option.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/lib/suggestSimilar.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/package-support.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/typings/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/concat-map/.travis.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/concat-map/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/concat-map/README.markdown create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/concat-map/example/map.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/concat-map/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/concat-map/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/concat-map/test/map.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/console-control-strings/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/console-control-strings/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/console-control-strings/README.md~ create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/console-control-strings/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/console-control-strings/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/content-disposition/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/content-disposition/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/content-disposition/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/content-disposition/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/content-disposition/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/content-type/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/content-type/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/content-type/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/content-type/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/content-type/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cookie-signature/History.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cookie-signature/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cookie-signature/Readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cookie-signature/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cookie-signature/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cookie/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cookie/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cookie/SECURITY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cookie/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cookie/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/debug/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/debug/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/debug/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/debug/src/browser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/debug/src/common.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/debug/src/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/debug/src/node.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/decompress-response/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/decompress-response/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/decompress-response/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/decompress-response/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/decompress-response/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/deep-extend/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/deep-extend/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/deep-extend/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/deep-extend/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/deep-extend/lib/deep-extend.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/deep-extend/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/delegates/.npmignore create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/delegates/History.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/delegates/License create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/delegates/Makefile create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/delegates/Readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/delegates/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/delegates/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/delegates/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/depd/History.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/depd/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/depd/Readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/depd/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/depd/lib/browser/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/depd/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/detect-libc/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/detect-libc/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/detect-libc/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/detect-libc/lib/detect-libc.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/detect-libc/lib/elf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/detect-libc/lib/filesystem.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/detect-libc/lib/process.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/detect-libc/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/dunder-proto/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/dunder-proto/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/dunder-proto/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/dunder-proto/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/dunder-proto/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/dunder-proto/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/dunder-proto/get.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/dunder-proto/get.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/dunder-proto/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/dunder-proto/set.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/dunder-proto/set.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/dunder-proto/test/get.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/dunder-proto/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/dunder-proto/test/set.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/dunder-proto/tsconfig.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ee-first/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ee-first/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ee-first/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ee-first/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/emoji-regex/LICENSE-MIT.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/emoji-regex/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/emoji-regex/es2015/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/emoji-regex/es2015/text.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/emoji-regex/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/emoji-regex/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/emoji-regex/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/emoji-regex/text.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encodeurl/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encodeurl/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encodeurl/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encodeurl/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/.prettierrc.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/.travis.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/lib/encoding.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/.github/dependabot.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/.idea/codeStyles/Project.xml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/.idea/codeStyles/codeStyleConfig.xml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/.idea/iconv-lite.iml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/.idea/inspectionProfiles/Project_Default.xml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/.idea/modules.xml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/.idea/vcs.xml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/Changelog.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/dbcs-codec.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/dbcs-data.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/internal.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/sbcs-codec.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/sbcs-data-generated.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/sbcs-data.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/tables/big5-added.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/tables/cp936.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/tables/cp949.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/tables/cp950.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/tables/eucjp.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/tables/gbk-added.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/tables/shiftjis.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/utf16.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/utf32.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/encodings/utf7.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/lib/bom-handling.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/lib/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/lib/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/lib/streams.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/node_modules/iconv-lite/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/encoding/test/test.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/end-of-stream/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/end-of-stream/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/end-of-stream/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/end-of-stream/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/env-paths/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/env-paths/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/env-paths/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/env-paths/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/env-paths/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/err-code/.editorconfig create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/err-code/.eslintrc.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/err-code/.travis.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/err-code/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/err-code/bower.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/err-code/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/err-code/index.umd.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/err-code/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/err-code/test/.eslintrc.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/err-code/test/test.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-define-property/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-define-property/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-define-property/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-define-property/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-define-property/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-define-property/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-define-property/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-define-property/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-define-property/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-define-property/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-define-property/tsconfig.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/eval.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/eval.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/range.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/range.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/ref.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/ref.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/syntax.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/syntax.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/tsconfig.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/type.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/type.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/uri.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-errors/uri.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/RequireObjectCoercible.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/RequireObjectCoercible.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/ToObject.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/ToObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/isObject.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/isObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/es-object-atoms/tsconfig.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/escalade/dist/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/escalade/dist/index.mjs create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/escalade/index.d.mts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/escalade/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/escalade/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/escalade/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/escalade/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/escalade/sync/index.d.mts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/escalade/sync/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/escalade/sync/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/escalade/sync/index.mjs create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/escape-html/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/escape-html/Readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/escape-html/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/escape-html/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/esm/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/esm/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/esm/esm.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/esm/esm/loader.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/esm/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/esm/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/etag/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/etag/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/etag/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/etag/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/etag/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/expand-template/.travis.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/expand-template/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/expand-template/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/expand-template/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/expand-template/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/expand-template/test.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/express/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/express/Readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/express/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/express/lib/application.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/express/lib/express.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/express/lib/request.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/express/lib/response.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/express/lib/utils.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/express/lib/view.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/express/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/file-uri-to-path/.npmignore create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/file-uri-to-path/.travis.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/file-uri-to-path/History.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/file-uri-to-path/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/file-uri-to-path/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/file-uri-to-path/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/file-uri-to-path/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/file-uri-to-path/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/file-uri-to-path/test/test.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/file-uri-to-path/test/tests.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/finalhandler/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/finalhandler/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/finalhandler/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/finalhandler/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/finalhandler/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/forwarded/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/forwarded/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/forwarded/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/forwarded/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/forwarded/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fresh/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fresh/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fresh/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fresh/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fresh/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fs-constants/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fs-constants/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fs-constants/browser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fs-constants/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fs-constants/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fs-minipass/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fs-minipass/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fs-minipass/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fs-minipass/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fs.realpath/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fs.realpath/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fs.realpath/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fs.realpath/old.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/fs.realpath/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/function-bind/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/function-bind/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/function-bind/.github/SECURITY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/function-bind/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/function-bind/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/function-bind/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/function-bind/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/function-bind/implementation.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/function-bind/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/function-bind/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/function-bind/test/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/function-bind/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/LICENSE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/lib/base-theme.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/lib/error.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/lib/has-color.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/lib/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/lib/plumbing.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/lib/process.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/lib/progress-bar.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/lib/render-template.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/lib/set-immediate.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/lib/set-interval.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/lib/spin.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/lib/template-item.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/lib/theme-set.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/lib/themes.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/lib/wide-truncate.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gauge/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-intrinsic/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-intrinsic/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-intrinsic/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-intrinsic/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-intrinsic/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-intrinsic/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-intrinsic/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-intrinsic/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-intrinsic/test/GetIntrinsic.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-package-type/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-package-type/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-package-type/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-package-type/async.cjs create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-package-type/cache.cjs create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-package-type/index.cjs create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-package-type/is-node-modules.cjs create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-package-type/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-package-type/sync.cjs create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-proto/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-proto/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-proto/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-proto/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-proto/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-proto/Object.getPrototypeOf.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-proto/Object.getPrototypeOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-proto/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-proto/Reflect.getPrototypeOf.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-proto/Reflect.getPrototypeOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-proto/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-proto/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-proto/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-proto/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/get-proto/tsconfig.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/getopts/LICENSE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/getopts/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/getopts/index.cjs create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/getopts/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/getopts/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/getopts/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/github-from-package/.travis.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/github-from-package/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/github-from-package/example/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/github-from-package/example/url.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/github-from-package/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/github-from-package/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/github-from-package/readme.markdown create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/github-from-package/test/a.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/github-from-package/test/b.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/github-from-package/test/c.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/github-from-package/test/d.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/github-from-package/test/e.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/github-from-package/test/url.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/glob/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/glob/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/glob/common.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/glob/glob.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/glob/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/glob/sync.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gopd/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gopd/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gopd/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gopd/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gopd/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gopd/gOPD.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gopd/gOPD.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gopd/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gopd/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gopd/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gopd/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/gopd/tsconfig.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/graceful-fs/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/graceful-fs/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/graceful-fs/clone.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/graceful-fs/graceful-fs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/graceful-fs/legacy-streams.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/graceful-fs/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/graceful-fs/polyfills.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/shams.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/shams.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/test/shams/core-js.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/test/shams/get-own-property-symbols.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/test/tests.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-symbols/tsconfig.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-unicode/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-unicode/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-unicode/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/has-unicode/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/hasown/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/hasown/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/hasown/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/hasown/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/hasown/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/hasown/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/hasown/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/hasown/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/hasown/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/hasown/tsconfig.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-cache-semantics/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-cache-semantics/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-cache-semantics/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-cache-semantics/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-errors/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-errors/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-errors/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-errors/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-errors/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-proxy-agent/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-proxy-agent/dist/agent.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-proxy-agent/dist/agent.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-proxy-agent/dist/agent.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-proxy-agent/dist/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-proxy-agent/dist/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-proxy-agent/dist/index.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/http-proxy-agent/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/https-proxy-agent/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/https-proxy-agent/dist/agent.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/https-proxy-agent/dist/agent.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/https-proxy-agent/dist/agent.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/https-proxy-agent/dist/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/https-proxy-agent/dist/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/https-proxy-agent/dist/index.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/https-proxy-agent/dist/parse-proxy-response.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/https-proxy-agent/dist/parse-proxy-response.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/https-proxy-agent/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/humanize-ms/History.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/humanize-ms/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/humanize-ms/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/humanize-ms/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/humanize-ms/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/Changelog.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/dbcs-codec.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/dbcs-data.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/internal.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/sbcs-codec.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/sbcs-data-generated.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/sbcs-data.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/tables/big5-added.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/tables/cp936.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/tables/cp949.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/tables/cp950.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/tables/eucjp.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/tables/gbk-added.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/tables/shiftjis.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/utf16.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/utf32.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/encodings/utf7.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/lib/bom-handling.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/lib/helpers/merge-exports.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/lib/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/lib/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/lib/streams.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/iconv-lite/types/encodings.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ieee754/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ieee754/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ieee754/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ieee754/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ieee754/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/imurmurhash/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/imurmurhash/imurmurhash.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/imurmurhash/imurmurhash.min.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/imurmurhash/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/inflight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/inherits.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/inherits_browser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/ini.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/CHANGELOG create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/mjs-stub.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.d.ts.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.d.ts.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.d.ts.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.d.ts.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.d.ts.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.d.ts.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.d.ts.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.d.ts.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.d.ts.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/address-error.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/common.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/ip-address.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/ipv4.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/ipv6.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v4/constants.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v6/constants.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v6/helpers.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v6/regular-expressions.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/ipaddr.min.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/lib/ipaddr.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/lib/ipaddr.js.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/core.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/.npmignore create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/.travis.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/test.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/index.mjs create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/.npmignore create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/mode.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/test/basic.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/windows.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/CONTRIBUTING.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/UPGRADING.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/cli.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/utils/cli-config-utils.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/utils/constants.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/utils/migrationsLister.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/knex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/knex.mjs create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/builder-interface-augmenter.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/client.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/constants.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/better-sqlite3/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-columncompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-querybuilder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-querycompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-tablecompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-viewcompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/mssql-formatter.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/query/mssql-querycompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-columncompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-compiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-tablecompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-viewcompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/transaction.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/query/mysql-querybuilder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/query/mysql-querycompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-columncompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-compiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-tablecompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-viewbuilder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-viewcompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/transaction.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql2/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql2/transaction.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/DEAD_CODE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/query/oracle-querycompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/internal/incrementUtils.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/internal/trigger.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-columnbuilder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-columncompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-compiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-tablecompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/utils.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/query/oracledb-querycompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-columncompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-tablecompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-viewbuilder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-viewcompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/transaction.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/utils.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/pgnative/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/execution/pg-transaction.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/query/pg-querybuilder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/query/pg-querycompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-columncompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-compiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-tablecompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-viewbuilder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-viewcompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/query/redshift-querycompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-columnbuilder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-columncompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-compiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-tablecompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-viewcompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/transaction.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/execution/sqlite-transaction.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/query/sqlite-querybuilder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/query/sqlite-querycompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/ddl.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/compiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/parser-combinator.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/parser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/tokenizer.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/utils.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-columncompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-compiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/batch-insert.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/internal/delay.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/internal/ensure-connection-callback.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/internal/query-executioner.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/runner.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/transaction.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter/formatterUtils.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter/rawFormatter.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter/wrappingFormatter.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/FunctionHelper.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/Knex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/internal/config-resolver.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/internal/parse-connection.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/make-knex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/logger.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/common/MigrationsLoader.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/MigrationGenerator.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/Migrator.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/migrate-stub.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/migration-list-resolver.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/migrator-configuration-merger.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/sources/fs-migrations.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/cjs.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/coffee.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/eg.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/js-schema.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/js.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-coffee.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-eg.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-js.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-ls.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-ts.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/ls.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/mjs.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/ts-schema.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/ts.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/table-creator.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/table-resolver.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/Seeder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/seed-stub.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/seeder-configuration-merger.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/sources/fs-seeds.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/coffee.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/eg.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/js.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/ls.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/mjs.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/ts.stub create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/fs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/import-file.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/is-module-type.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/template.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/timestamp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/analytic.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/constants.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/joinclause.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/method-constants.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/querybuilder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/querycompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/raw.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/ref.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/builder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/columnbuilder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/columncompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/compiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/internal/helpers.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/tablebuilder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/tablecompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/viewbuilder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/viewcompiler.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/finally-mixin.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/helpers.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/is.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/nanoid.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/noop.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/save-async-stack.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/security.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/string.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/timeout.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/browser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/common.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/node.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/license.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/build.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/clean.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/docker-compose.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/next-release-howto.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/oracledb-install-driver-libs.sh create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/release.sh create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/runkit-example.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/README.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/docker-compose.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/knex-stress-test.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/mysql2-random-hanging-every-now-and-then.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/mysql2-sudden-exit-without-error.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/reconnect-test-mysql-based-drivers.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/update_gitignore_for_tsc_output.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/types/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/types/result.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/types/tables.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_DataView.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Hash.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_LazyWrapper.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_ListCache.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_LodashWrapper.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Map.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_MapCache.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Promise.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Set.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_SetCache.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Stack.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Symbol.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Uint8Array.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_WeakMap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_apply.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayAggregator.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayEach.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayEachRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayEvery.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayFilter.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayIncludes.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayIncludesWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayLikeKeys.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayMap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayPush.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayReduce.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayReduceRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arraySample.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arraySampleSize.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayShuffle.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arraySome.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_asciiSize.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_asciiToArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_asciiWords.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_assignMergeValue.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_assignValue.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_assocIndexOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAggregator.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAssign.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAssignIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAssignValue.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseClamp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseClone.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseConforms.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseConformsTo.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseCreate.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseDelay.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseDifference.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseEach.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseEachRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseEvery.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseExtremum.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFill.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFilter.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFindIndex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFindKey.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFlatten.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFor.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseForOwn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseForOwnRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseForRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFunctions.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGetAllKeys.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGetTag.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseHas.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseHasIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseInRange.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIndexOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIndexOfWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIntersection.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseInverter.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseInvoke.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsArguments.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsArrayBuffer.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsDate.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsEqual.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsEqualDeep.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsMap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsMatch.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsNaN.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsNative.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsRegExp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsSet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsTypedArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIteratee.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseKeys.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseKeysIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseLodash.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseLt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMatches.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMatchesProperty.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMean.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMerge.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMergeDeep.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseNth.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseOrderBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePick.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePickBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseProperty.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePropertyDeep.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePropertyOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePullAll.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePullAt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRandom.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRange.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseReduce.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRepeat.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRest.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSample.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSampleSize.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSetData.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSetToString.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseShuffle.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSlice.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSome.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortedIndex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortedIndexBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortedUniq.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSum.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseTimes.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseToNumber.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseToPairs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseToString.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseTrim.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUnary.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUniq.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUnset.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUpdate.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseValues.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseWhile.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseWrapperValue.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseXor.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseZipObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cacheHas.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castArrayLikeObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castFunction.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castPath.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castRest.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castSlice.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_charsEndIndex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_charsStartIndex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneArrayBuffer.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneBuffer.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneDataView.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneRegExp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneSymbol.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneTypedArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_compareAscending.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_compareMultiple.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_composeArgs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_composeArgsRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copyArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copyObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copySymbols.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copySymbolsIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_coreJsData.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_countHolders.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createAggregator.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createAssigner.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createBaseEach.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createBaseFor.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createBind.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCaseFirst.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCompounder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCtor.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCurry.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createFind.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createFlow.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createHybrid.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createInverter.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createMathOperation.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createOver.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createPadding.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createPartial.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRange.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRecurry.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRelationalOperation.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRound.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createSet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createToPairs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createWrap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_customDefaultsAssignIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_customDefaultsMerge.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_customOmitClone.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_deburrLetter.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_defineProperty.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_equalArrays.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_equalByTag.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_equalObjects.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_escapeHtmlChar.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_escapeStringChar.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_flatRest.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_freeGlobal.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getAllKeys.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getAllKeysIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getData.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getFuncName.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getHolder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getMapData.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getMatchData.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getNative.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getPrototype.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getRawTag.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getSymbols.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getSymbolsIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getTag.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getValue.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getView.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getWrapDetails.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hasPath.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hasUnicode.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hasUnicodeWord.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashClear.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashDelete.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashGet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashHas.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashSet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_initCloneArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_initCloneByTag.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_initCloneObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_insertWrapDetails.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isFlattenable.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isIndex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isIterateeCall.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isKey.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isKeyable.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isLaziable.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isMaskable.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isMasked.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isPrototype.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isStrictComparable.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_iteratorToArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_lazyClone.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_lazyReverse.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_lazyValue.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheClear.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheDelete.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheGet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheHas.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheSet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheClear.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheDelete.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheGet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheHas.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheSet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapToArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_matchesStrictComparable.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_memoizeCapped.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mergeData.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_metaMap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nativeCreate.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nativeKeys.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nativeKeysIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nodeUtil.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_objectToString.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_overArg.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_overRest.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_parent.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reEscape.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reEvaluate.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reInterpolate.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_realNames.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reorder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_replaceHolders.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_root.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_safeGet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setCacheAdd.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setCacheHas.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setData.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setToArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setToPairs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setToString.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setWrapToString.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_shortOut.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_shuffleSelf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackClear.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackDelete.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackGet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackHas.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackSet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_strictIndexOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_strictLastIndexOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stringSize.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stringToArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stringToPath.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_toKey.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_toSource.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_trimmedEndIndex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unescapeHtmlChar.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unicodeSize.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unicodeToArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unicodeWords.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_updateWrapDetails.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_wrapperClone.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/add.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/after.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/array.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/ary.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assign.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assignIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assignInWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assignWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/at.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/attempt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/before.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/bind.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/bindAll.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/bindKey.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/camelCase.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/capitalize.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/castArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/ceil.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/chain.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/chunk.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/clamp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/clone.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cloneDeep.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cloneDeepWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cloneWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/collection.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/commit.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/compact.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/concat.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cond.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/conforms.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/conformsTo.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/constant.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/core.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/core.min.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/countBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/create.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/curry.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/curryRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/date.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/debounce.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/deburr.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defaultTo.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defaults.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defaultsDeep.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defer.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/delay.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/difference.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/differenceBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/differenceWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/divide.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/drop.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/dropRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/dropRightWhile.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/dropWhile.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/each.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/eachRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/endsWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/entries.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/entriesIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/eq.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/escape.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/escapeRegExp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/every.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/extend.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/extendWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fill.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/filter.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/find.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findIndex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findKey.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findLast.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findLastIndex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findLastKey.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/first.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flake.lock create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flake.nix create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatMap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatMapDeep.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatMapDepth.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatten.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flattenDeep.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flattenDepth.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flip.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/floor.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flow.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flowRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forEach.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forEachRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forInRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forOwn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forOwnRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/F.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/T.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/__.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_baseConvert.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_convertBrowser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_falseOptions.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_mapping.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_util.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/add.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/after.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/all.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/allPass.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/always.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/any.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/anyPass.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/apply.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/array.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/ary.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assign.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignAll.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignAllWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignInAll.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignInAllWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignInWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assoc.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assocPath.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/at.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/attempt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/before.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/bind.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/bindAll.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/bindKey.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/camelCase.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/capitalize.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/castArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/ceil.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/chain.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/chunk.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/clamp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/clone.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cloneDeep.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cloneDeepWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cloneWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/collection.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/commit.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/compact.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/complement.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/compose.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/concat.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cond.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/conforms.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/conformsTo.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/constant.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/contains.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/convert.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/countBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/create.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curry.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curryN.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curryRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curryRightN.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/date.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/debounce.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/deburr.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultTo.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaults.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultsAll.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultsDeep.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultsDeepAll.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defer.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/delay.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/difference.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/differenceBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/differenceWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dissoc.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dissocPath.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/divide.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/drop.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropLast.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropLastWhile.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropRightWhile.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropWhile.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/each.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/eachRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/endsWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/entries.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/entriesIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/eq.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/equals.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/escape.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/escapeRegExp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/every.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extend.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extendAll.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extendAllWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extendWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/fill.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/filter.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/find.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findFrom.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findIndex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findIndexFrom.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findKey.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLast.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastFrom.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastIndex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastIndexFrom.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastKey.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/first.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatMap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatMapDeep.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatMapDepth.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatten.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flattenDeep.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flattenDepth.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flip.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/floor.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flow.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flowRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forEach.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forEachRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forInRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forOwn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forOwnRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/fromPairs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/function.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/functions.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/functionsIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/get.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/getOr.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/groupBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/gt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/gte.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/has.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/hasIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/head.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/identical.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/identity.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/inRange.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/includes.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/includesFrom.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/indexBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/indexOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/indexOfFrom.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/init.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/initial.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/intersection.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/intersectionBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/intersectionWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invert.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invertBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invertObj.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invoke.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invokeArgs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invokeArgsMap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invokeMap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArguments.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArrayBuffer.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArrayLike.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArrayLikeObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isBoolean.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isBuffer.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isDate.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isElement.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isEmpty.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isEqual.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isEqualWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isError.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isFinite.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isFunction.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isInteger.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isLength.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isMap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isMatch.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isMatchWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNaN.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNative.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNil.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNull.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNumber.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isObjectLike.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isPlainObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isRegExp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isSafeInteger.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isSet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isString.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isSymbol.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isTypedArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isUndefined.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isWeakMap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isWeakSet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/iteratee.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/join.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/juxt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/kebabCase.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/keyBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/keys.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/keysIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lang.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/last.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lastIndexOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lastIndexOfFrom.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lowerCase.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lowerFirst.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lte.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/map.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mapKeys.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mapValues.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/matches.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/matchesProperty.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/math.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/max.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/maxBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mean.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/meanBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/memoize.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/merge.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mergeAll.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mergeAllWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mergeWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/method.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/methodOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/min.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/minBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mixin.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/multiply.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/nAry.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/negate.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/next.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/noop.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/now.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/nth.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/nthArg.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/number.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/object.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/omit.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/omitAll.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/omitBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/once.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/orderBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/over.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/overArgs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/overEvery.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/overSome.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pad.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padChars.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padCharsEnd.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padCharsStart.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padEnd.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padStart.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/parseInt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/partial.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/partialRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/partition.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/path.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pathEq.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pathOr.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/paths.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pick.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pickAll.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pickBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pipe.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/placeholder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/plant.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pluck.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/prop.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/propEq.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/propOr.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/property.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/propertyOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/props.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pull.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAll.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAllBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAllWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/random.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/range.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rangeRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rangeStep.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rangeStepRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rearg.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reduce.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reduceRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/remove.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/repeat.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/replace.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rest.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/restFrom.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/result.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reverse.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/round.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sample.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sampleSize.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/seq.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/set.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/setWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/shuffle.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/size.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/slice.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/snakeCase.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/some.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedIndex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedIndexBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedIndexOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedLastIndex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedLastIndexBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedLastIndexOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedUniq.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedUniqBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/split.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/spread.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/spreadFrom.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/startCase.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/startsWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/string.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubFalse.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubString.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubTrue.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/subtract.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sum.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sumBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/symmetricDifference.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/symmetricDifferenceBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/symmetricDifferenceWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/tail.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/take.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeLast.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeLastWhile.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeRightWhile.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeWhile.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/tap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/template.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/templateSettings.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/throttle.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/thru.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/times.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toFinite.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toInteger.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toIterator.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toJSON.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toLength.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toLower.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toNumber.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPairs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPairsIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPath.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPlainObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toSafeInteger.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toString.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toUpper.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/transform.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trim.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimChars.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimCharsEnd.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimCharsStart.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimEnd.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimStart.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/truncate.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unapply.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unary.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unescape.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/union.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unionBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unionWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniq.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniqBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniqWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniqueId.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unnest.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unset.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unzip.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unzipWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/update.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/updateWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/upperCase.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/upperFirst.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/useWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/util.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/value.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/valueOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/values.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/valuesIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/where.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/whereEq.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/without.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/words.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperAt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperChain.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperLodash.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperReverse.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperValue.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/xor.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/xorBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/xorWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zip.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipAll.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipObj.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipObjectDeep.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fromPairs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/function.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/functions.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/functionsIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/get.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/groupBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/gt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/gte.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/has.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/hasIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/head.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/identity.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/inRange.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/includes.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/indexOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/initial.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/intersection.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/intersectionBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/intersectionWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invert.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invertBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invoke.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invokeMap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArguments.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArrayBuffer.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArrayLike.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArrayLikeObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isBoolean.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isBuffer.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isDate.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isElement.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isEmpty.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isEqual.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isEqualWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isError.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isFinite.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isFunction.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isInteger.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isLength.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isMap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isMatch.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isMatchWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNaN.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNative.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNil.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNull.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNumber.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isObjectLike.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isPlainObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isRegExp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isSafeInteger.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isSet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isString.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isSymbol.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isTypedArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isUndefined.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isWeakMap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isWeakSet.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/iteratee.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/join.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/kebabCase.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/keyBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/keys.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/keysIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lang.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/last.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lastIndexOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lodash.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lodash.min.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lowerCase.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lowerFirst.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lte.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/map.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/mapKeys.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/mapValues.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/matches.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/matchesProperty.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/math.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/max.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/maxBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/mean.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/meanBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/memoize.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/merge.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/mergeWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/method.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/methodOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/min.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/minBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/mixin.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/multiply.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/negate.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/next.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/noop.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/now.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/nth.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/nthArg.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/number.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/object.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/omit.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/omitBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/once.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/orderBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/over.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/overArgs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/overEvery.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/overSome.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/pad.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/padEnd.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/padStart.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/parseInt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/partial.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/partialRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/partition.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/pick.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/pickBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/plant.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/property.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/propertyOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/pull.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/pullAll.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/pullAllBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/pullAllWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/pullAt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/random.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/range.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/rangeRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/rearg.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/reduce.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/reduceRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/reject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/release.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/remove.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/repeat.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/replace.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/rest.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/result.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/reverse.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/round.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/sample.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/sampleSize.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/seq.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/set.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/setWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/shuffle.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/size.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/slice.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/snakeCase.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/some.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/sortBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/sortedIndex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/sortedIndexBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/sortedIndexOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/sortedLastIndex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/sortedLastIndexBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/sortedLastIndexOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/sortedUniq.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/sortedUniqBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/split.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/spread.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/startCase.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/startsWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/string.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/stubArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/stubFalse.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/stubObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/stubString.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/stubTrue.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/subtract.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/sum.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/sumBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/tail.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/take.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/takeRight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/takeRightWhile.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/takeWhile.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/tap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/template.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/templateSettings.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/throttle.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/thru.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/times.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/toArray.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/toFinite.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/toInteger.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/toIterator.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/toJSON.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/toLength.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/toLower.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/toNumber.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/toPairs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/toPairsIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/toPath.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/toPlainObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/toSafeInteger.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/toString.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/toUpper.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/transform.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/trim.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/trimEnd.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/trimStart.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/truncate.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/unary.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/unescape.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/union.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/unionBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/unionWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/uniq.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/uniqBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/uniqWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/uniqueId.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/unset.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/unzip.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/unzipWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/update.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/updateWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/upperCase.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/upperFirst.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/util.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/value.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/valueOf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/values.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/valuesIn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/without.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/words.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/wrap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/wrapperAt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/wrapperChain.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/wrapperLodash.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/wrapperReverse.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/wrapperValue.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/xor.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/xorBy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/xorWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/zip.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/zipObject.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/zipObjectDeep.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/zipWith.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lru-cache/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lru-cache/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lru-cache/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lru-cache/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/lib/agent.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/lib/cache/entry.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/lib/cache/errors.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/lib/cache/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/lib/cache/key.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/lib/cache/policy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/lib/fetch.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/lib/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/lib/options.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/lib/remote.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/node_modules/negotiator/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/node_modules/negotiator/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/node_modules/negotiator/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/node_modules/negotiator/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/node_modules/negotiator/lib/charset.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/node_modules/negotiator/lib/encoding.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/node_modules/negotiator/lib/language.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/node_modules/negotiator/lib/mediaType.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/node_modules/negotiator/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/make-fetch-happen/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/abs.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/abs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/constants/maxArrayLength.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/constants/maxArrayLength.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/constants/maxSafeInteger.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/constants/maxSafeInteger.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/constants/maxValue.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/constants/maxValue.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/floor.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/floor.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/isFinite.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/isFinite.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/isInteger.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/isInteger.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/isNaN.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/isNaN.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/isNegativeZero.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/isNegativeZero.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/max.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/max.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/min.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/min.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/mod.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/mod.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/pow.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/pow.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/round.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/round.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/sign.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/sign.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/math-intrinsics/tsconfig.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/media-typer/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/media-typer/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/media-typer/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/media-typer/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/media-typer/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/merge-descriptors/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/merge-descriptors/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/merge-descriptors/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/merge-descriptors/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/merge-descriptors/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mime-db/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mime-db/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mime-db/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mime-db/db.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mime-db/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mime-db/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mime-types/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mime-types/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mime-types/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mime-types/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mime-types/mimeScore.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mime-types/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mimic-response/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mimic-response/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mimic-response/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mimic-response/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mimic-response/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimatch/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimatch/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimatch/minimatch.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimatch/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/example/parse.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/test/all_bool.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/test/bool.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/test/dash.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/test/default_bool.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/test/dotted.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/test/kv_short.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/test/long.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/test/num.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/test/parse.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/test/parse_modified.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/test/proto.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/test/short.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/test/stop_early.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/test/unknown.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minimist/test/whitespace.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-collect/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-collect/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-collect/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-collect/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-fetch/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-fetch/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-fetch/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-fetch/lib/abort-error.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-fetch/lib/blob.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-fetch/lib/body.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-fetch/lib/fetch-error.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-fetch/lib/headers.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-fetch/lib/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-fetch/lib/request.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-fetch/lib/response.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-fetch/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-flush/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-flush/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-flush/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-flush/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-pipeline/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-pipeline/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-pipeline/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-pipeline/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-sized/.npmignore create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-sized/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-sized/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-sized/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-sized/package-lock.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-sized/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass-sized/test/basic.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minipass/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minizlib/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minizlib/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minizlib/constants.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minizlib/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/minizlib/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp-classic/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp-classic/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp-classic/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp-classic/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp/bin/cmd.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp/lib/find-made.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp/lib/mkdirp-manual.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp/lib/mkdirp-native.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp/lib/opts-arg.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp/lib/path-arg.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp/lib/use-native.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/mkdirp/readme.markdown create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ms/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ms/license.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ms/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ms/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/napi-build-utils/.github/workflows/run-npm-tests.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/napi-build-utils/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/napi-build-utils/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/napi-build-utils/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/napi-build-utils/index.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/napi-build-utils/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/negotiator/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/negotiator/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/negotiator/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/negotiator/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/negotiator/lib/charset.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/negotiator/lib/encoding.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/negotiator/lib/language.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/negotiator/lib/mediaType.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/negotiator/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-abi/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-abi/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-abi/abi_registry.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-abi/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-abi/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/LICENSE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/common.gypi create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/except.gypi create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/napi-inl.deprecated.h create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/napi-inl.h create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/napi.h create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/node_addon_api.gyp create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/node_api.gyp create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/noexcept.gypi create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/nothing.c create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/package-support.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/tools/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/tools/check-napi.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/tools/clang-format.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/tools/conversion.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-addon-api/tools/eslint-format.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/.github/ISSUE_TEMPLATE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/.github/workflows/release-please.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/.github/workflows/tests.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/.github/workflows/visual-studio.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/CONTRIBUTING.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/addon.gypi create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/bin/node-gyp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/docs/Common-issues.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/docs/Error-pre-versions-of-node-cannot-be-installed.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/docs/Home.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/docs/Linking-to-OpenSSL.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/docs/Updating-npm-bundled-node-gyp.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/docs/binding.gyp-files-in-the-wild.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/.flake8 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/.github/workflows/Python_tests.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/.github/workflows/node-gyp.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/.github/workflows/nodejs-windows.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/.github/workflows/release-please.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/AUTHORS create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/CODE_OF_CONDUCT.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/CONTRIBUTING.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/data/win/large-pdb-shim.cc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/gyp create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/gyp.bat create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/gyp_main.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/__init__.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/common.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/common_test.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/input.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/input_test.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/requirements_dev.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/setup.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/test_gyp.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/tools/README create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/tools/Xcode/README create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.pbfilespec create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.xclangspec create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/tools/emacs/README create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/tools/emacs/gyp-tests.el create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/tools/emacs/gyp.el create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/tools/emacs/run-unit-tests.sh create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/tools/emacs/testdata/media.gyp create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/tools/emacs/testdata/media.gyp.fontified create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/tools/graphviz.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/tools/pretty_gyp.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/tools/pretty_sln.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/gyp/tools/pretty_vcproj.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/lib/Find-VisualStudio.cs create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/lib/build.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/lib/clean.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/lib/configure.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/lib/create-config-gypi.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/lib/find-node-directory.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/lib/find-python.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/lib/find-visualstudio.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/lib/install.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/lib/list.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/lib/node-gyp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/lib/process-release.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/lib/rebuild.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/lib/remove.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/lib/util.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/macOS_Catalina.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/macOS_Catalina_acid_test.sh create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/src/win_delay_load_hook.cc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/common.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/fixtures/VS_2017_BuildTools_minimal.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/fixtures/VS_2017_Community_workload.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/fixtures/VS_2017_Express.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/fixtures/VS_2017_Unusable.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/fixtures/VS_2019_BuildTools_minimal.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/fixtures/VS_2019_Community_workload.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/fixtures/VS_2019_Preview.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/fixtures/ca-bundle.crt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/fixtures/ca.crt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/fixtures/nodedir/include/node/config.gypi create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/fixtures/server.crt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/fixtures/server.key create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/fixtures/test-charmap.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/process-exec-sync.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/simple-proxy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/test-addon.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/test-configure-python.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/test-create-config-gypi.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/test-download.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/test-find-accessible-sync.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/test-find-node-directory.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/test-find-python.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/test-find-visualstudio.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/test-install.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/test-options.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/test/test-process-release.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/node-gyp/update-gyp.py create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/nopt/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/nopt/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/nopt/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/nopt/bin/nopt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/nopt/lib/nopt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/nopt/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/npmlog/LICENSE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/npmlog/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/npmlog/lib/log.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/npmlog/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/example/all.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/example/circular.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/example/fn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/example/inspect.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/package-support.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/readme.markdown create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test-core-js.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/bigint.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/browser/dom.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/circular.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/deep.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/element.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/err.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/fakes.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/fn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/global.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/has.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/holes.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/indent-option.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/inspect.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/lowbyte.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/number.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/quoteStyle.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/toStringTag.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/undef.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/test/values.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/object-inspect/util.inspect.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/on-finished/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/on-finished/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/on-finished/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/on-finished/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/on-finished/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/once/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/once/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/once/once.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/once/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/p-map/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/p-map/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/p-map/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/p-map/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/p-map/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/parseurl/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/parseurl/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/parseurl/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/parseurl/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/parseurl/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/path-is-absolute/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/path-is-absolute/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/path-is-absolute/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/path-is-absolute/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/path-parse/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/path-parse/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/path-parse/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/path-parse/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/path-to-regexp/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/path-to-regexp/Readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/path-to-regexp/dist/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/path-to-regexp/dist/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/path-to-regexp/dist/index.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/path-to-regexp/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/pg-connection-string/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/pg-connection-string/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/pg-connection-string/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/pg-connection-string/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/pg-connection-string/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/prebuild-install/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/prebuild-install/CONTRIBUTING.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/prebuild-install/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/prebuild-install/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/prebuild-install/asset.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/prebuild-install/bin.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/prebuild-install/download.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/prebuild-install/error.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/prebuild-install/help.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/prebuild-install/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/prebuild-install/log.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/prebuild-install/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/prebuild-install/proxy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/prebuild-install/rc.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/prebuild-install/util.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/promise-inflight/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/promise-inflight/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/promise-inflight/inflight.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/promise-inflight/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/promise-retry/.editorconfig create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/promise-retry/.jshintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/promise-retry/.travis.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/promise-retry/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/promise-retry/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/promise-retry/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/promise-retry/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/promise-retry/test/test.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/proxy-addr/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/proxy-addr/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/proxy-addr/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/proxy-addr/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/proxy-addr/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/pump/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/pump/.travis.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/pump/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/pump/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/pump/SECURITY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/pump/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/pump/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/pump/test-browser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/pump/test-node.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/.editorconfig create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/LICENSE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/dist/qs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/lib/formats.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/lib/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/lib/parse.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/lib/stringify.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/lib/utils.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/test/empty-keys-cases.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/test/parse.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/test/stringify.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/qs/test/utils.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/range-parser/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/range-parser/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/range-parser/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/range-parser/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/range-parser/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/raw-body/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/raw-body/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/raw-body/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/raw-body/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/raw-body/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rc/LICENSE.APACHE2 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rc/LICENSE.BSD create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rc/LICENSE.MIT create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rc/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rc/browser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rc/cli.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rc/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rc/lib/utils.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rc/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rc/test/ini.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rc/test/nested-env-vars.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rc/test/test.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/CONTRIBUTING.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/GOVERNANCE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/errors-browser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/errors.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/experimentalWarning.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/lib/_stream_duplex.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/lib/_stream_passthrough.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/lib/_stream_readable.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/lib/_stream_transform.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/lib/_stream_writable.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/lib/internal/streams/async_iterator.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/lib/internal/streams/buffer_list.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/lib/internal/streams/destroy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/lib/internal/streams/end-of-stream.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/lib/internal/streams/from-browser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/lib/internal/streams/from.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/lib/internal/streams/pipeline.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/lib/internal/streams/state.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/lib/internal/streams/stream-browser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/lib/internal/streams/stream.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/readable-browser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/readable-stream/readable.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rechoir/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rechoir/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rechoir/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rechoir/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rechoir/lib/extension.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rechoir/lib/normalize.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rechoir/lib/register.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rechoir/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve-from/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve-from/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve-from/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve-from/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve-from/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/.editorconfig create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/.github/INCIDENT_RESPONSE_PROCESS.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/.github/THREAT_MODEL.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/SECURITY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/async.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/bin/resolve create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/example/async.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/example/sync.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/lib/async.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/lib/caller.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/lib/core.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/lib/core.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/lib/homedir.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/lib/is-core.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/lib/node-modules-paths.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/lib/normalize-options.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/lib/sync.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/readme.markdown create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/sync.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/core.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/dotdot.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/dotdot/abc/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/dotdot/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/faulty_basedir.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/filter.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/filter_sync.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/home_paths.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/home_paths_sync.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/mock.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/mock_sync.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/module_dir.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/module_dir/xmodules/aaa/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/module_dir/ymodules/aaa/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/module_dir/zmodules/bbb/main.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/module_dir/zmodules/bbb/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/node-modules-paths.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/node_path.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/node_path/x/aaa/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/node_path/x/ccc/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/node_path/y/bbb/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/node_path/y/ccc/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/nonstring.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/pathfilter.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/pathfilter/deep_ref/main.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/precedence.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/precedence/aaa.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/precedence/aaa/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/precedence/aaa/main.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/precedence/bbb.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/precedence/bbb/main.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/baz/doom.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/baz/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/baz/quux.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/browser_field/a.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/browser_field/b.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/browser_field/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/cup.coffee create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/dot_main/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/dot_main/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/dot_slash_main/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/dot_slash_main/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/false_main/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/false_main/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/foo.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/incorrect_main/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/incorrect_main/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/invalid_main/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/mug.coffee create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/mug.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/multirepo/lerna.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/multirepo/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/multirepo/packages/package-a/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/multirepo/packages/package-a/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/multirepo/packages/package-b/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/multirepo/packages/package-b/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/nested_symlinks/mylib/async.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/nested_symlinks/mylib/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/nested_symlinks/mylib/sync.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/other_path/lib/other-lib.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/other_path/root.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/quux/foo/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/same_names/foo.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/same_names/foo/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/symlinked/_/node_modules/foo.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/symlinked/_/symlink_target/.gitkeep create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/symlinked/package/bar.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/symlinked/package/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver/without_basedir/main.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/resolver_sync.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/shadowed_core.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/shadowed_core/node_modules/util/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/subdirs.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/resolve/test/symlinks.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/.npmignore create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/.travis.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/License create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/Makefile create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/equation.gif create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/example/dns.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/example/stop.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/lib/retry.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/lib/retry_operation.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/test/common.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/test/integration/test-forever.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/test/integration/test-retry-operation.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/test/integration/test-retry-wrap.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/retry/test/integration/test-timeouts.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rimraf/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rimraf/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rimraf/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rimraf/bin.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rimraf/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/rimraf/rimraf.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/router/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/router/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/router/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/router/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/router/lib/layer.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/router/lib/route.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/router/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/safe-buffer/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/safe-buffer/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/safe-buffer/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/safe-buffer/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/safe-buffer/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/safer-buffer/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/safer-buffer/Porting-Buffer.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/safer-buffer/Readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/safer-buffer/dangerous.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/safer-buffer/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/safer-buffer/safer.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/safer-buffer/tests.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/bin/semver.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/classes/comparator.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/classes/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/classes/range.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/classes/semver.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/clean.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/cmp.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/coerce.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/compare-build.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/compare-loose.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/compare.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/diff.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/eq.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/gt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/gte.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/inc.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/lt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/lte.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/major.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/minor.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/neq.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/parse.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/patch.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/prerelease.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/rcompare.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/rsort.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/satisfies.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/sort.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/functions/valid.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/internal/constants.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/internal/debug.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/internal/identifiers.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/internal/lrucache.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/internal/parse-options.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/internal/re.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/preload.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/range.bnf create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/ranges/gtr.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/ranges/intersects.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/ranges/ltr.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/ranges/max-satisfying.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/ranges/min-satisfying.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/ranges/min-version.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/ranges/outside.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/ranges/simplify.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/ranges/subset.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/ranges/to-comparators.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/semver/ranges/valid.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/send/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/send/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/send/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/send/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/send/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/serve-static/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/serve-static/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/serve-static/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/serve-static/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/serve-static/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/set-blocking/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/set-blocking/LICENSE.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/set-blocking/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/set-blocking/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/set-blocking/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/setprototypeof/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/setprototypeof/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/setprototypeof/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/setprototypeof/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/setprototypeof/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/setprototypeof/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-list/.editorconfig create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-list/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-list/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-list/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-list/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-list/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-list/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-list/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-list/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-list/list.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-list/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-list/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-list/tsconfig.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-map/.editorconfig create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-map/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-map/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-map/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-map/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-map/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-map/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-map/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-map/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-map/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-map/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-map/tsconfig.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-weakmap/.editorconfig create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-weakmap/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-weakmap/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-weakmap/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-weakmap/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-weakmap/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-weakmap/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-weakmap/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-weakmap/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-weakmap/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-weakmap/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel-weakmap/tsconfig.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel/.editorconfig create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/side-channel/tsconfig.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/signal-exit/LICENSE.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/signal-exit/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/signal-exit/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/signal-exit/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/signal-exit/signals.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/simple-concat/.travis.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/simple-concat/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/simple-concat/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/simple-concat/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/simple-concat/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/simple-concat/test/basic.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/simple-get/.github/dependabot.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/simple-get/.github/workflows/ci.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/simple-get/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/simple-get/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/simple-get/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/simple-get/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/smart-buffer/.prettierrc.yaml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/smart-buffer/.travis.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/smart-buffer/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/smart-buffer/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/smart-buffer/build/smartbuffer.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/smart-buffer/build/smartbuffer.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/smart-buffer/build/utils.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/smart-buffer/build/utils.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/smart-buffer/docs/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/smart-buffer/docs/README_v3.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/smart-buffer/docs/ROADMAP.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/smart-buffer/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/smart-buffer/typings/smartbuffer.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/smart-buffer/typings/utils.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks-proxy-agent/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks-proxy-agent/dist/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks-proxy-agent/dist/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks-proxy-agent/dist/index.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks-proxy-agent/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/.eslintrc.cjs create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/.prettierrc.yaml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/build/client/socksclient.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/build/client/socksclient.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/build/common/constants.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/build/common/constants.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/build/common/helpers.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/build/common/helpers.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/build/common/receivebuffer.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/build/common/receivebuffer.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/build/common/util.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/build/common/util.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/build/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/build/index.js.map create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/docs/examples/index.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/docs/examples/javascript/associateExample.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/docs/examples/javascript/bindExample.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/docs/examples/javascript/connectExample.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/docs/examples/typescript/associateExample.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/docs/examples/typescript/bindExample.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/docs/examples/typescript/connectExample.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/docs/index.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/docs/migratingFromV1.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/typings/client/socksclient.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/typings/common/constants.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/typings/common/helpers.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/typings/common/receivebuffer.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/typings/common/util.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/socks/typings/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/binding.gyp create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/build/Release/node_sqlite3.node create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/deps/common-sqlite.gypi create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/deps/extract.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/deps/sqlite-autoconf-3440200.tar.gz create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/deps/sqlite3.gyp create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/lib/sqlite3-binding.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/lib/sqlite3.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/lib/sqlite3.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/lib/trace.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/src/async.h create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/src/backup.cc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/src/backup.h create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/src/database.cc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/src/database.h create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/src/gcc-preinclude.h create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/src/macros.h create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/src/node_sqlite3.cc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/src/statement.cc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/src/statement.h create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/sqlite3/src/threading.h create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ssri/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ssri/LICENSE.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ssri/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ssri/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ssri/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/statuses/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/statuses/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/statuses/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/statuses/codes.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/statuses/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/statuses/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/string-width/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/string-width/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/string-width/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/string-width/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/string-width/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/string_decoder/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/string_decoder/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/string_decoder/lib/string_decoder.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/string_decoder/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/strip-ansi/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/strip-ansi/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/strip-ansi/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/strip-ansi/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/strip-ansi/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/strip-json-comments/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/strip-json-comments/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/strip-json-comments/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/strip-json-comments/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/supports-preserve-symlinks-flag/.eslintrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/supports-preserve-symlinks-flag/.github/FUNDING.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/supports-preserve-symlinks-flag/.nycrc create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/supports-preserve-symlinks-flag/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/supports-preserve-symlinks-flag/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/supports-preserve-symlinks-flag/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/supports-preserve-symlinks-flag/browser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/supports-preserve-symlinks-flag/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/supports-preserve-symlinks-flag/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/supports-preserve-symlinks-flag/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/.travis.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/node_modules/chownr/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/node_modules/chownr/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/node_modules/chownr/chownr.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/node_modules/chownr/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/test/fixtures/a/hello.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/test/fixtures/b/a/test.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/test/fixtures/d/file1 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/test/fixtures/d/file2 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/test/fixtures/d/sub-dir/file5 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/test/fixtures/d/sub-files/file3 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/test/fixtures/d/sub-files/file4 create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/test/fixtures/e/directory/.ignore create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/test/fixtures/e/file create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/test/fixtures/invalid.tar create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-fs/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-stream/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-stream/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-stream/extract.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-stream/headers.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-stream/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-stream/pack.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-stream/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar-stream/sandbox.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/create.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/extract.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/get-write-flag.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/header.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/high-level-opt.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/large-numbers.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/list.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/mkdir.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/mode-fix.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/normalize-unicode.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/normalize-windows-path.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/pack.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/parse.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/path-reservations.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/pax.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/read-entry.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/replace.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/strip-absolute-path.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/strip-trailing-slashes.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/types.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/unpack.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/update.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/warn-mixin.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/winchars.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/lib/write-entry.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/node_modules/minipass/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/node_modules/minipass/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/node_modules/minipass/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/node_modules/minipass/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/node_modules/minipass/index.mjs create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/node_modules/minipass/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tar/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/dist/PendingOperation.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/dist/PendingOperation.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/dist/Pool.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/dist/Pool.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/dist/PromiseInspection.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/dist/PromiseInspection.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/dist/Resource.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/dist/Resource.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/dist/TimeoutError.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/dist/TimeoutError.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/dist/tarn.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/dist/tarn.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/dist/utils.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/dist/utils.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tarn/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tildify/index.d.ts create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tildify/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tildify/license create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tildify/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tildify/readme.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/toidentifier/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/toidentifier/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/toidentifier/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/toidentifier/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/toidentifier/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tunnel-agent/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tunnel-agent/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tunnel-agent/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/tunnel-agent/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/type-is/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/type-is/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/type-is/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/type-is/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/type-is/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/.nyc_output/54942.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/.nyc_output/54944.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/__root__/index.html create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/__root__/index.js.html create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/base.css create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/index.html create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/prettify.css create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/prettify.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/sort-arrow-sprite.png create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/sorter.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/.travis.yml create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/test/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/History.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/browser.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/node.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/HISTORY.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/index.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/CHANGELOG.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/bin/node-which create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/which.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/align.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/wrappy.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/LICENSE create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/README.md create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/iterator.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/yallist.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/notes.txt create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/package-lock.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/package.json create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/users.sqlite3 diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/UsersoumaiDocumentsweb developementHackYourFutureweek-10 b/courses/foundation/intro-to-backend/introToBackendAssignment/UsersoumaiDocumentsweb developementHackYourFutureweek-10 new file mode 100644 index 000000000..e69de29bb diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/index.js new file mode 100644 index 000000000..58f8d36b4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/index.js @@ -0,0 +1,165 @@ +import express from "express"; +import knexLibrary from "knex"; + +const app = express(); +const port = 3000; + +app.use(express.json()); + +/** + * Knex connection to SQLite database + * Make sure users.sqlite3 exists in this folder + */ +const knexInstance = knexLibrary({ + client: "sqlite3", + connection: { + filename: "C:\Users\oumai\Documents\web developement\HackYourFuture\week-10", + }, + useNullAsDefault: true, +}); + +/** + * HOME ROUTE — HTML PAGE + */ +app.get("/", (req, res) => { + res.send(` + + + + User API + + +

    Welcome to the User API

    +

    Use the endpoints to retrieve user data.

    +

    + Current user count: + Loading... +

    + + + + + `); +}); + +/** + * USER COUNT + */ +app.get("/user-count", async (req, res) => { + try { + const result = await knexInstance.raw( + "SELECT COUNT(*) AS total_users FROM users" + ); + res.json(result); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +/** + * ALL USERS (sorted by id) + */ +app.get("/all-users", async (req, res) => { + try { + const rows = await knexInstance.raw( + "SELECT * FROM users ORDER BY id ASC" + ); + res.json(rows); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +/** + * UNCONFIRMED USERS + */ +app.get("/unconfirmed-users", async (req, res) => { + try { + const rows = await knexInstance.raw( + "SELECT * FROM users WHERE confirmed_at IS NULL" + ); + res.json(rows); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +/** + * GMAIL USERS + */ +app.get("/gmail-users", async (req, res) => { + try { + const rows = await knexInstance.raw( + "SELECT * FROM users WHERE email LIKE '%@gmail.com'" + ); + res.json(rows); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +/** + * USERS CREATED IN 2022 + */ +app.get("/2022-users", async (req, res) => { + try { + const rows = await knexInstance.raw(` + SELECT * FROM users + WHERE created_at >= '2022-01-01' + AND created_at < '2023-01-01' + `); + res.json(rows); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +/** + * FIRST USER + */ +app.get("/first-user", async (req, res) => { + try { + const result = await knexInstance.raw( + "SELECT * FROM users ORDER BY id ASC LIMIT 1" + ); + + if (result.length === 0) { + return res.status(404).send("No users found"); + } + + res.json(result); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +/** + * LAST NAME COUNT + */ +app.get("/last-name-count", async (req, res) => { + try { + const result = await knexInstance.raw(` + SELECT last_name, COUNT(*) AS last_name_count + FROM users + GROUP BY last_name + ORDER BY last_name ASC + `); + res.json(result); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +/** + * START SERVER + */ +app.listen(port, () => { + console.log(`Server running at http://localhost:${port}`); +}); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/color-support b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/color-support new file mode 100644 index 000000000..f77f9d5b8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/color-support @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../color-support/bin.js" "$@" +else + exec node "$basedir/../color-support/bin.js" "$@" +fi diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/color-support.cmd b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/color-support.cmd new file mode 100644 index 000000000..005f9a565 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/color-support.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\color-support\bin.js" %* diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/color-support.ps1 b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/color-support.ps1 new file mode 100644 index 000000000..f5c9fe497 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/color-support.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../color-support/bin.js" $args + } else { + & "$basedir/node$exe" "$basedir/../color-support/bin.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../color-support/bin.js" $args + } else { + & "node$exe" "$basedir/../color-support/bin.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/knex b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/knex new file mode 100644 index 000000000..b2dd7bf09 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/knex @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../knex/bin/cli.js" "$@" +else + exec node "$basedir/../knex/bin/cli.js" "$@" +fi diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/knex.cmd b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/knex.cmd new file mode 100644 index 000000000..b32f35554 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/knex.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\knex\bin\cli.js" %* diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/knex.ps1 b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/knex.ps1 new file mode 100644 index 000000000..0789610b6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/knex.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../knex/bin/cli.js" $args + } else { + & "$basedir/node$exe" "$basedir/../knex/bin/cli.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../knex/bin/cli.js" $args + } else { + & "node$exe" "$basedir/../knex/bin/cli.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/mkdirp b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/mkdirp new file mode 100644 index 000000000..1ab9c81af --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/mkdirp @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../mkdirp/bin/cmd.js" "$@" +else + exec node "$basedir/../mkdirp/bin/cmd.js" "$@" +fi diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/mkdirp.cmd b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/mkdirp.cmd new file mode 100644 index 000000000..a865dd9f3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/mkdirp.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\mkdirp\bin\cmd.js" %* diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/mkdirp.ps1 b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/mkdirp.ps1 new file mode 100644 index 000000000..911e85466 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/mkdirp.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../mkdirp/bin/cmd.js" $args + } else { + & "$basedir/node$exe" "$basedir/../mkdirp/bin/cmd.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../mkdirp/bin/cmd.js" $args + } else { + & "node$exe" "$basedir/../mkdirp/bin/cmd.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-gyp b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-gyp new file mode 100644 index 000000000..dff6cdb4c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-gyp @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../node-gyp/bin/node-gyp.js" "$@" +else + exec node "$basedir/../node-gyp/bin/node-gyp.js" "$@" +fi diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-gyp.cmd b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-gyp.cmd new file mode 100644 index 000000000..9a6a721ef --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-gyp.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\node-gyp\bin\node-gyp.js" %* diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-gyp.ps1 b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-gyp.ps1 new file mode 100644 index 000000000..dd514e275 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-gyp.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../node-gyp/bin/node-gyp.js" $args + } else { + & "$basedir/node$exe" "$basedir/../node-gyp/bin/node-gyp.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../node-gyp/bin/node-gyp.js" $args + } else { + & "node$exe" "$basedir/../node-gyp/bin/node-gyp.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-which b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-which new file mode 100644 index 000000000..b49b03f7d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-which @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../which/bin/node-which" "$@" +else + exec node "$basedir/../which/bin/node-which" "$@" +fi diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-which.cmd b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-which.cmd new file mode 100644 index 000000000..8738aed88 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-which.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\which\bin\node-which" %* diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-which.ps1 b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-which.ps1 new file mode 100644 index 000000000..cfb09e844 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/node-which.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../which/bin/node-which" $args + } else { + & "$basedir/node$exe" "$basedir/../which/bin/node-which" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../which/bin/node-which" $args + } else { + & "node$exe" "$basedir/../which/bin/node-which" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/nopt b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/nopt new file mode 100644 index 000000000..0808130fb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/nopt @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../nopt/bin/nopt.js" "$@" +else + exec node "$basedir/../nopt/bin/nopt.js" "$@" +fi diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/nopt.cmd b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/nopt.cmd new file mode 100644 index 000000000..a7f38b3da --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/nopt.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\nopt\bin\nopt.js" %* diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/nopt.ps1 b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/nopt.ps1 new file mode 100644 index 000000000..9d6ba56f6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/nopt.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../nopt/bin/nopt.js" $args + } else { + & "$basedir/node$exe" "$basedir/../nopt/bin/nopt.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../nopt/bin/nopt.js" $args + } else { + & "node$exe" "$basedir/../nopt/bin/nopt.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/prebuild-install b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/prebuild-install new file mode 100644 index 000000000..154b529ef --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/prebuild-install @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../prebuild-install/bin.js" "$@" +else + exec node "$basedir/../prebuild-install/bin.js" "$@" +fi diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/prebuild-install.cmd b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/prebuild-install.cmd new file mode 100644 index 000000000..21ff9042d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/prebuild-install.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\prebuild-install\bin.js" %* diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/prebuild-install.ps1 b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/prebuild-install.ps1 new file mode 100644 index 000000000..6e657a3b4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/prebuild-install.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../prebuild-install/bin.js" $args + } else { + & "$basedir/node$exe" "$basedir/../prebuild-install/bin.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../prebuild-install/bin.js" $args + } else { + & "node$exe" "$basedir/../prebuild-install/bin.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rc b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rc new file mode 100644 index 000000000..c9d9af684 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rc @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../rc/cli.js" "$@" +else + exec node "$basedir/../rc/cli.js" "$@" +fi diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rc.cmd b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rc.cmd new file mode 100644 index 000000000..be16b7333 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rc.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\rc\cli.js" %* diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rc.ps1 b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rc.ps1 new file mode 100644 index 000000000..9a9b6e376 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rc.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../rc/cli.js" $args + } else { + & "$basedir/node$exe" "$basedir/../rc/cli.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../rc/cli.js" $args + } else { + & "node$exe" "$basedir/../rc/cli.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/resolve b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/resolve new file mode 100644 index 000000000..c043cba00 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/resolve @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../resolve/bin/resolve" "$@" +else + exec node "$basedir/../resolve/bin/resolve" "$@" +fi diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/resolve.cmd b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/resolve.cmd new file mode 100644 index 000000000..1a017c403 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/resolve.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\resolve\bin\resolve" %* diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/resolve.ps1 b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/resolve.ps1 new file mode 100644 index 000000000..f22b2d317 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/resolve.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../resolve/bin/resolve" $args + } else { + & "$basedir/node$exe" "$basedir/../resolve/bin/resolve" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../resolve/bin/resolve" $args + } else { + & "node$exe" "$basedir/../resolve/bin/resolve" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rimraf b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rimraf new file mode 100644 index 000000000..6d6240a87 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rimraf @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../rimraf/bin.js" "$@" +else + exec node "$basedir/../rimraf/bin.js" "$@" +fi diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rimraf.cmd b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rimraf.cmd new file mode 100644 index 000000000..13f45eca3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rimraf.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\rimraf\bin.js" %* diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rimraf.ps1 b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rimraf.ps1 new file mode 100644 index 000000000..17167914f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/rimraf.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../rimraf/bin.js" $args + } else { + & "$basedir/node$exe" "$basedir/../rimraf/bin.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../rimraf/bin.js" $args + } else { + & "node$exe" "$basedir/../rimraf/bin.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/semver b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/semver new file mode 100644 index 000000000..97c53279f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/semver @@ -0,0 +1,16 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../semver/bin/semver.js" "$@" +else + exec node "$basedir/../semver/bin/semver.js" "$@" +fi diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/semver.cmd b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/semver.cmd new file mode 100644 index 000000000..9913fa9d0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/semver.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\semver\bin\semver.js" %* diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/semver.ps1 b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/semver.ps1 new file mode 100644 index 000000000..314717ad4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.bin/semver.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args + } else { + & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../semver/bin/semver.js" $args + } else { + & "node$exe" "$basedir/../semver/bin/semver.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.package-lock.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.package-lock.json new file mode 100644 index 000000000..cbb3231b2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/.package-lock.json @@ -0,0 +1,2431 @@ +{ + "name": "mypackage", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT", + "optional": true + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC", + "optional": true + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "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==", + "license": "MIT", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/aproba": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", + "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", + "license": "ISC", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT", + "optional": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz", + "integrity": "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "license": "MIT" + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT", + "optional": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC", + "optional": true + }, + "node_modules/content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT", + "optional": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/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==", + "license": "MIT", + "optional": true + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT", + "optional": true + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, + "node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC", + "optional": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/getopts": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz", + "integrity": "sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==", + "license": "MIT" + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC", + "optional": true + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC", + "optional": true + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz", + "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8.19" + } + }, + "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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC", + "optional": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "optional": 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==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ip-address": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "license": "MIT", + "optional": true + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC", + "optional": true + }, + "node_modules/knex": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/knex/-/knex-3.1.0.tgz", + "integrity": "sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw==", + "license": "MIT", + "dependencies": { + "colorette": "2.0.19", + "commander": "^10.0.0", + "debug": "4.3.4", + "escalade": "^3.1.1", + "esm": "^3.2.25", + "get-package-type": "^0.1.0", + "getopts": "2.3.0", + "interpret": "^2.2.0", + "lodash": "^4.17.21", + "pg-connection-string": "2.6.2", + "rechoir": "^0.8.0", + "resolve-from": "^5.0.0", + "tarn": "^3.0.2", + "tildify": "2.0.0" + }, + "bin": { + "knex": "bin/cli.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependenciesMeta": { + "better-sqlite3": { + "optional": true + }, + "mysql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/knex/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/knex/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "license": "ISC", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abi": { + "version": "3.85.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz", + "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==", + "license": "MIT" + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "license": "ISC", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "license": "MIT", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC", + "optional": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC", + "optional": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sqlite3": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", + "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "optional": 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==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tarn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tarn/-/tarn-3.0.2.tgz", + "integrity": "sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tildify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", + "integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "optional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + } + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/LICENSE.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/LICENSE.md new file mode 100644 index 000000000..64f773240 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/LICENSE.md @@ -0,0 +1,10 @@ +The MIT License (MIT) + +Copyright © 2020-2022 Michael Garvin + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/README.md new file mode 100644 index 000000000..465c546a4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/README.md @@ -0,0 +1,65 @@ +# @gar/promisify + +### Promisify an entire object or class instance + +This module leverages es6 Proxy and Reflect to promisify every function in an +object or class instance. + +It assumes the callback that the function is expecting is the last +parameter, and that it is an error-first callback with only one value, +i.e. `(err, value) => ...`. This mirrors node's `util.promisify` method. + +In order that you can use it as a one-stop-shop for all your promisify +needs, you can also pass it a function. That function will be +promisified as normal using node's built-in `util.promisify` method. + +[node's custom promisified +functions](https://nodejs.org/api/util.html#util_custom_promisified_functions) +will also be mirrored, further allowing this to be a drop-in replacement +for the built-in `util.promisify`. + +### Examples + +Promisify an entire object + +```javascript + +const promisify = require('@gar/promisify') + +class Foo { + constructor (attr) { + this.attr = attr + } + + double (input, cb) { + cb(null, input * 2) + } + +const foo = new Foo('baz') +const promisified = promisify(foo) + +console.log(promisified.attr) +console.log(await promisified.double(1024)) +``` + +Promisify a function + +```javascript + +const promisify = require('@gar/promisify') + +function foo (a, cb) { + if (a !== 'bad') { + return cb(null, 'ok') + } + return cb('not ok') +} + +const promisified = promisify(foo) + +// This will resolve to 'ok' +promisified('good') + +// this will reject +promisified('bad') +``` diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/index.js new file mode 100644 index 000000000..d0be95f6f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/index.js @@ -0,0 +1,36 @@ +'use strict' + +const { promisify } = require('util') + +const handler = { + get: function (target, prop, receiver) { + if (typeof target[prop] !== 'function') { + return target[prop] + } + if (target[prop][promisify.custom]) { + return function () { + return Reflect.get(target, prop, receiver)[promisify.custom].apply(target, arguments) + } + } + return function () { + return new Promise((resolve, reject) => { + Reflect.get(target, prop, receiver).apply(target, [...arguments, function (err, result) { + if (err) { + return reject(err) + } + resolve(result) + }]) + }) + } + } +} + +module.exports = function (thingToPromisify) { + if (typeof thingToPromisify === 'function') { + return promisify(thingToPromisify) + } + if (typeof thingToPromisify === 'object') { + return new Proxy(thingToPromisify, handler) + } + throw new TypeError('Can only promisify functions or objects') +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/package.json new file mode 100644 index 000000000..d0ce69b2f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@gar/promisify/package.json @@ -0,0 +1,32 @@ +{ + "name": "@gar/promisify", + "version": "1.1.3", + "description": "Promisify an entire class or object", + "main": "index.js", + "repository": { + "type": "git", + "url": "https://github.com/wraithgar/gar-promisify.git" + }, + "scripts": { + "lint": "standard", + "lint:fix": "standard --fix", + "test": "lab -a @hapi/code -t 100", + "posttest": "npm run lint" + }, + "files": [ + "index.js" + ], + "keywords": [ + "promisify", + "all", + "class", + "object" + ], + "author": "Gar ", + "license": "MIT", + "devDependencies": { + "@hapi/code": "^8.0.1", + "@hapi/lab": "^24.1.0", + "standard": "^16.0.3" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/LICENSE.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/LICENSE.md new file mode 100644 index 000000000..5fc208ff1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/LICENSE.md @@ -0,0 +1,20 @@ + + +ISC License + +Copyright npm, Inc. + +Permission to use, copy, modify, and/or distribute this +software for any purpose with or without fee is hereby +granted, provided that the above copyright notice and this +permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND NPM DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO +EVENT SHALL NPM BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE +USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/README.md new file mode 100644 index 000000000..bc71a119b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/README.md @@ -0,0 +1,60 @@ +# @npmcli/fs + +polyfills, and extensions, of the core `fs` module. + +## Features + +- all exposed functions return promises +- `fs.rm` polyfill for node versions < 14.14.0 +- `fs.mkdir` polyfill adding support for the `recursive` and `force` options in node versions < 10.12.0 +- `fs.copyFile` extended to accept an `owner` option +- `fs.mkdir` extended to accept an `owner` option +- `fs.mkdtemp` extended to accept an `owner` option +- `fs.writeFile` extended to accept an `owner` option +- `fs.withTempDir` added +- `fs.cp` polyfill for node < 16.7.0 + +## The `owner` option + +The `copyFile`, `mkdir`, `mkdtemp`, `writeFile`, and `withTempDir` functions +all accept a new `owner` property in their options. It can be used in two ways: + +- `{ owner: { uid: 100, gid: 100 } }` - set the `uid` and `gid` explicitly +- `{ owner: 100 }` - use one value, will set both `uid` and `gid` the same + +The special string `'inherit'` may be passed instead of a number, which will +cause this module to automatically determine the correct `uid` and/or `gid` +from the nearest existing parent directory of the target. + +## `fs.withTempDir(root, fn, options) -> Promise` + +### Parameters + +- `root`: the directory in which to create the temporary directory +- `fn`: a function that will be called with the path to the temporary directory +- `options` + - `tmpPrefix`: a prefix to be used in the generated directory name + +### Usage + +The `withTempDir` function creates a temporary directory, runs the provided +function (`fn`), then removes the temporary directory and resolves or rejects +based on the result of `fn`. + +```js +const fs = require('@npmcli/fs') +const os = require('os') + +// this function will be called with the full path to the temporary directory +// it is called with `await` behind the scenes, so can be async if desired. +const myFunction = async (tempPath) => { + return 'done!' +} + +const main = async () => { + const result = await fs.withTempDir(os.tmpdir(), myFunction) + // result === 'done!' +} + +main() +``` diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/file-url-to-path/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/file-url-to-path/index.js new file mode 100644 index 000000000..7755d1c10 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/file-url-to-path/index.js @@ -0,0 +1,17 @@ +const url = require('url') + +const node = require('../node.js') +const polyfill = require('./polyfill.js') + +const useNative = node.satisfies('>=10.12.0') + +const fileURLToPath = (path) => { + // the polyfill is tested separately from this module, no need to hack + // process.version to try to trigger it just for coverage + // istanbul ignore next + return useNative + ? url.fileURLToPath(path) + : polyfill(path) +} + +module.exports = fileURLToPath diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/file-url-to-path/polyfill.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/file-url-to-path/polyfill.js new file mode 100644 index 000000000..6cc90f0b0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/file-url-to-path/polyfill.js @@ -0,0 +1,121 @@ +const { URL, domainToUnicode } = require('url') + +const CHAR_LOWERCASE_A = 97 +const CHAR_LOWERCASE_Z = 122 + +const isWindows = process.platform === 'win32' + +class ERR_INVALID_FILE_URL_HOST extends TypeError { + constructor (platform) { + super(`File URL host must be "localhost" or empty on ${platform}`) + this.code = 'ERR_INVALID_FILE_URL_HOST' + } + + toString () { + return `${this.name} [${this.code}]: ${this.message}` + } +} + +class ERR_INVALID_FILE_URL_PATH extends TypeError { + constructor (msg) { + super(`File URL path ${msg}`) + this.code = 'ERR_INVALID_FILE_URL_PATH' + } + + toString () { + return `${this.name} [${this.code}]: ${this.message}` + } +} + +class ERR_INVALID_ARG_TYPE extends TypeError { + constructor (name, actual) { + super(`The "${name}" argument must be one of type string or an instance ` + + `of URL. Received type ${typeof actual} ${actual}`) + this.code = 'ERR_INVALID_ARG_TYPE' + } + + toString () { + return `${this.name} [${this.code}]: ${this.message}` + } +} + +class ERR_INVALID_URL_SCHEME extends TypeError { + constructor (expected) { + super(`The URL must be of scheme ${expected}`) + this.code = 'ERR_INVALID_URL_SCHEME' + } + + toString () { + return `${this.name} [${this.code}]: ${this.message}` + } +} + +const isURLInstance = (input) => { + return input != null && input.href && input.origin +} + +const getPathFromURLWin32 = (url) => { + const hostname = url.hostname + let pathname = url.pathname + for (let n = 0; n < pathname.length; n++) { + if (pathname[n] === '%') { + const third = pathname.codePointAt(n + 2) | 0x20 + if ((pathname[n + 1] === '2' && third === 102) || + (pathname[n + 1] === '5' && third === 99)) { + throw new ERR_INVALID_FILE_URL_PATH('must not include encoded \\ or / characters') + } + } + } + + pathname = pathname.replace(/\//g, '\\') + pathname = decodeURIComponent(pathname) + if (hostname !== '') { + return `\\\\${domainToUnicode(hostname)}${pathname}` + } + + const letter = pathname.codePointAt(1) | 0x20 + const sep = pathname[2] + if (letter < CHAR_LOWERCASE_A || letter > CHAR_LOWERCASE_Z || + (sep !== ':')) { + throw new ERR_INVALID_FILE_URL_PATH('must be absolute') + } + + return pathname.slice(1) +} + +const getPathFromURLPosix = (url) => { + if (url.hostname !== '') { + throw new ERR_INVALID_FILE_URL_HOST(process.platform) + } + + const pathname = url.pathname + + for (let n = 0; n < pathname.length; n++) { + if (pathname[n] === '%') { + const third = pathname.codePointAt(n + 2) | 0x20 + if (pathname[n + 1] === '2' && third === 102) { + throw new ERR_INVALID_FILE_URL_PATH('must not include encoded / characters') + } + } + } + + return decodeURIComponent(pathname) +} + +const fileURLToPath = (path) => { + if (typeof path === 'string') { + path = new URL(path) + } else if (!isURLInstance(path)) { + throw new ERR_INVALID_ARG_TYPE('path', ['string', 'URL'], path) + } + + if (path.protocol !== 'file:') { + throw new ERR_INVALID_URL_SCHEME('file') + } + + return isWindows + ? getPathFromURLWin32(path) + : getPathFromURLPosix(path) +} + +module.exports = fileURLToPath diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/get-options.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/get-options.js new file mode 100644 index 000000000..cb5982f79 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/get-options.js @@ -0,0 +1,20 @@ +// given an input that may or may not be an object, return an object that has +// a copy of every defined property listed in 'copy'. if the input is not an +// object, assign it to the property named by 'wrap' +const getOptions = (input, { copy, wrap }) => { + const result = {} + + if (input && typeof input === 'object') { + for (const prop of copy) { + if (input[prop] !== undefined) { + result[prop] = input[prop] + } + } + } else { + result[wrap] = input + } + + return result +} + +module.exports = getOptions diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/node.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/node.js new file mode 100644 index 000000000..4d13bc037 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/node.js @@ -0,0 +1,9 @@ +const semver = require('semver') + +const satisfies = (range) => { + return semver.satisfies(process.version, range, { includePrerelease: true }) +} + +module.exports = { + satisfies, +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/owner.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/owner.js new file mode 100644 index 000000000..e3468b077 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/common/owner.js @@ -0,0 +1,92 @@ +const { dirname, resolve } = require('path') + +const fileURLToPath = require('./file-url-to-path/index.js') +const fs = require('../fs.js') + +// given a path, find the owner of the nearest parent +const find = async (path) => { + // if we have no getuid, permissions are irrelevant on this platform + if (!process.getuid) { + return {} + } + + // fs methods accept URL objects with a scheme of file: so we need to unwrap + // those into an actual path string before we can resolve it + const resolved = path != null && path.href && path.origin + ? resolve(fileURLToPath(path)) + : resolve(path) + + let stat + + try { + stat = await fs.lstat(resolved) + } finally { + // if we got a stat, return its contents + if (stat) { + return { uid: stat.uid, gid: stat.gid } + } + + // try the parent directory + if (resolved !== dirname(resolved)) { + return find(dirname(resolved)) + } + + // no more parents, never got a stat, just return an empty object + return {} + } +} + +// given a path, uid, and gid update the ownership of the path if necessary +const update = async (path, uid, gid) => { + // nothing to update, just exit + if (uid === undefined && gid === undefined) { + return + } + + try { + // see if the permissions are already the same, if they are we don't + // need to do anything, so return early + const stat = await fs.stat(path) + if (uid === stat.uid && gid === stat.gid) { + return + } + } catch (err) {} + + try { + await fs.chown(path, uid, gid) + } catch (err) {} +} + +// accepts a `path` and the `owner` property of an options object and normalizes +// it into an object with numerical `uid` and `gid` +const validate = async (path, input) => { + let uid + let gid + + if (typeof input === 'string' || typeof input === 'number') { + uid = input + gid = input + } else if (input && typeof input === 'object') { + uid = input.uid + gid = input.gid + } + + if (uid === 'inherit' || gid === 'inherit') { + const owner = await find(path) + if (uid === 'inherit') { + uid = owner.uid + } + + if (gid === 'inherit') { + gid = owner.gid + } + } + + return { uid, gid } +} + +module.exports = { + find, + update, + validate, +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/copy-file.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/copy-file.js new file mode 100644 index 000000000..d9875aba1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/copy-file.js @@ -0,0 +1,22 @@ +const fs = require('./fs.js') +const getOptions = require('./common/get-options.js') +const owner = require('./common/owner.js') + +const copyFile = async (src, dest, opts) => { + const options = getOptions(opts, { + copy: ['mode', 'owner'], + wrap: 'mode', + }) + + const { uid, gid } = await owner.validate(dest, options.owner) + + // the node core method as of 16.5.0 does not support the mode being in an + // object, so we have to pass the mode value directly + const result = await fs.copyFile(src, dest, options.mode) + + await owner.update(dest, uid, gid) + + return result +} + +module.exports = copyFile diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/cp/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/cp/LICENSE new file mode 100644 index 000000000..93546dfb7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/cp/LICENSE @@ -0,0 +1,15 @@ +(The MIT License) + +Copyright (c) 2011-2017 JP Richardson + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/cp/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/cp/index.js new file mode 100644 index 000000000..5da4739bd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/cp/index.js @@ -0,0 +1,22 @@ +const fs = require('../fs.js') +const getOptions = require('../common/get-options.js') +const node = require('../common/node.js') +const polyfill = require('./polyfill.js') + +// node 16.7.0 added fs.cp +const useNative = node.satisfies('>=16.7.0') + +const cp = async (src, dest, opts) => { + const options = getOptions(opts, { + copy: ['dereference', 'errorOnExist', 'filter', 'force', 'preserveTimestamps', 'recursive'], + }) + + // the polyfill is tested separately from this module, no need to hack + // process.version to try to trigger it just for coverage + // istanbul ignore next + return useNative + ? fs.cp(src, dest, options) + : polyfill(src, dest, options) +} + +module.exports = cp diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/cp/polyfill.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/cp/polyfill.js new file mode 100644 index 000000000..f83ccbf57 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/cp/polyfill.js @@ -0,0 +1,428 @@ +// this file is a modified version of the code in node 17.2.0 +// which is, in turn, a modified version of the fs-extra module on npm +// node core changes: +// - Use of the assert module has been replaced with core's error system. +// - All code related to the glob dependency has been removed. +// - Bring your own custom fs module is not currently supported. +// - Some basic code cleanup. +// changes here: +// - remove all callback related code +// - drop sync support +// - change assertions back to non-internal methods (see options.js) +// - throws ENOTDIR when rmdir gets an ENOENT for a path that exists in Windows +'use strict' + +const { + ERR_FS_CP_DIR_TO_NON_DIR, + ERR_FS_CP_EEXIST, + ERR_FS_CP_EINVAL, + ERR_FS_CP_FIFO_PIPE, + ERR_FS_CP_NON_DIR_TO_DIR, + ERR_FS_CP_SOCKET, + ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY, + ERR_FS_CP_UNKNOWN, + ERR_FS_EISDIR, + ERR_INVALID_ARG_TYPE, +} = require('../errors.js') +const { + constants: { + errno: { + EEXIST, + EISDIR, + EINVAL, + ENOTDIR, + }, + }, +} = require('os') +const { + chmod, + copyFile, + lstat, + mkdir, + readdir, + readlink, + stat, + symlink, + unlink, + utimes, +} = require('../fs.js') +const { + dirname, + isAbsolute, + join, + parse, + resolve, + sep, + toNamespacedPath, +} = require('path') +const { fileURLToPath } = require('url') + +const defaultOptions = { + dereference: false, + errorOnExist: false, + filter: undefined, + force: true, + preserveTimestamps: false, + recursive: false, +} + +async function cp (src, dest, opts) { + if (opts != null && typeof opts !== 'object') { + throw new ERR_INVALID_ARG_TYPE('options', ['Object'], opts) + } + return cpFn( + toNamespacedPath(getValidatedPath(src)), + toNamespacedPath(getValidatedPath(dest)), + { ...defaultOptions, ...opts }) +} + +function getValidatedPath (fileURLOrPath) { + const path = fileURLOrPath != null && fileURLOrPath.href + && fileURLOrPath.origin + ? fileURLToPath(fileURLOrPath) + : fileURLOrPath + return path +} + +async function cpFn (src, dest, opts) { + // Warn about using preserveTimestamps on 32-bit node + // istanbul ignore next + if (opts.preserveTimestamps && process.arch === 'ia32') { + const warning = 'Using the preserveTimestamps option in 32-bit ' + + 'node is not recommended' + process.emitWarning(warning, 'TimestampPrecisionWarning') + } + const stats = await checkPaths(src, dest, opts) + const { srcStat, destStat } = stats + await checkParentPaths(src, srcStat, dest) + if (opts.filter) { + return handleFilter(checkParentDir, destStat, src, dest, opts) + } + return checkParentDir(destStat, src, dest, opts) +} + +async function checkPaths (src, dest, opts) { + const { 0: srcStat, 1: destStat } = await getStats(src, dest, opts) + if (destStat) { + if (areIdentical(srcStat, destStat)) { + throw new ERR_FS_CP_EINVAL({ + message: 'src and dest cannot be the same', + path: dest, + syscall: 'cp', + errno: EINVAL, + }) + } + if (srcStat.isDirectory() && !destStat.isDirectory()) { + throw new ERR_FS_CP_DIR_TO_NON_DIR({ + message: `cannot overwrite directory ${src} ` + + `with non-directory ${dest}`, + path: dest, + syscall: 'cp', + errno: EISDIR, + }) + } + if (!srcStat.isDirectory() && destStat.isDirectory()) { + throw new ERR_FS_CP_NON_DIR_TO_DIR({ + message: `cannot overwrite non-directory ${src} ` + + `with directory ${dest}`, + path: dest, + syscall: 'cp', + errno: ENOTDIR, + }) + } + } + + if (srcStat.isDirectory() && isSrcSubdir(src, dest)) { + throw new ERR_FS_CP_EINVAL({ + message: `cannot copy ${src} to a subdirectory of self ${dest}`, + path: dest, + syscall: 'cp', + errno: EINVAL, + }) + } + return { srcStat, destStat } +} + +function areIdentical (srcStat, destStat) { + return destStat.ino && destStat.dev && destStat.ino === srcStat.ino && + destStat.dev === srcStat.dev +} + +function getStats (src, dest, opts) { + const statFunc = opts.dereference ? + (file) => stat(file, { bigint: true }) : + (file) => lstat(file, { bigint: true }) + return Promise.all([ + statFunc(src), + statFunc(dest).catch((err) => { + // istanbul ignore next: unsure how to cover. + if (err.code === 'ENOENT') { + return null + } + // istanbul ignore next: unsure how to cover. + throw err + }), + ]) +} + +async function checkParentDir (destStat, src, dest, opts) { + const destParent = dirname(dest) + const dirExists = await pathExists(destParent) + if (dirExists) { + return getStatsForCopy(destStat, src, dest, opts) + } + await mkdir(destParent, { recursive: true }) + return getStatsForCopy(destStat, src, dest, opts) +} + +function pathExists (dest) { + return stat(dest).then( + () => true, + // istanbul ignore next: not sure when this would occur + (err) => (err.code === 'ENOENT' ? false : Promise.reject(err))) +} + +// Recursively check if dest parent is a subdirectory of src. +// It works for all file types including symlinks since it +// checks the src and dest inodes. It starts from the deepest +// parent and stops once it reaches the src parent or the root path. +async function checkParentPaths (src, srcStat, dest) { + const srcParent = resolve(dirname(src)) + const destParent = resolve(dirname(dest)) + if (destParent === srcParent || destParent === parse(destParent).root) { + return + } + let destStat + try { + destStat = await stat(destParent, { bigint: true }) + } catch (err) { + // istanbul ignore else: not sure when this would occur + if (err.code === 'ENOENT') { + return + } + // istanbul ignore next: not sure when this would occur + throw err + } + if (areIdentical(srcStat, destStat)) { + throw new ERR_FS_CP_EINVAL({ + message: `cannot copy ${src} to a subdirectory of self ${dest}`, + path: dest, + syscall: 'cp', + errno: EINVAL, + }) + } + return checkParentPaths(src, srcStat, destParent) +} + +const normalizePathToArray = (path) => + resolve(path).split(sep).filter(Boolean) + +// Return true if dest is a subdir of src, otherwise false. +// It only checks the path strings. +function isSrcSubdir (src, dest) { + const srcArr = normalizePathToArray(src) + const destArr = normalizePathToArray(dest) + return srcArr.every((cur, i) => destArr[i] === cur) +} + +async function handleFilter (onInclude, destStat, src, dest, opts, cb) { + const include = await opts.filter(src, dest) + if (include) { + return onInclude(destStat, src, dest, opts, cb) + } +} + +function startCopy (destStat, src, dest, opts) { + if (opts.filter) { + return handleFilter(getStatsForCopy, destStat, src, dest, opts) + } + return getStatsForCopy(destStat, src, dest, opts) +} + +async function getStatsForCopy (destStat, src, dest, opts) { + const statFn = opts.dereference ? stat : lstat + const srcStat = await statFn(src) + // istanbul ignore else: can't portably test FIFO + if (srcStat.isDirectory() && opts.recursive) { + return onDir(srcStat, destStat, src, dest, opts) + } else if (srcStat.isDirectory()) { + throw new ERR_FS_EISDIR({ + message: `${src} is a directory (not copied)`, + path: src, + syscall: 'cp', + errno: EINVAL, + }) + } else if (srcStat.isFile() || + srcStat.isCharacterDevice() || + srcStat.isBlockDevice()) { + return onFile(srcStat, destStat, src, dest, opts) + } else if (srcStat.isSymbolicLink()) { + return onLink(destStat, src, dest) + } else if (srcStat.isSocket()) { + throw new ERR_FS_CP_SOCKET({ + message: `cannot copy a socket file: ${dest}`, + path: dest, + syscall: 'cp', + errno: EINVAL, + }) + } else if (srcStat.isFIFO()) { + throw new ERR_FS_CP_FIFO_PIPE({ + message: `cannot copy a FIFO pipe: ${dest}`, + path: dest, + syscall: 'cp', + errno: EINVAL, + }) + } + // istanbul ignore next: should be unreachable + throw new ERR_FS_CP_UNKNOWN({ + message: `cannot copy an unknown file type: ${dest}`, + path: dest, + syscall: 'cp', + errno: EINVAL, + }) +} + +function onFile (srcStat, destStat, src, dest, opts) { + if (!destStat) { + return _copyFile(srcStat, src, dest, opts) + } + return mayCopyFile(srcStat, src, dest, opts) +} + +async function mayCopyFile (srcStat, src, dest, opts) { + if (opts.force) { + await unlink(dest) + return _copyFile(srcStat, src, dest, opts) + } else if (opts.errorOnExist) { + throw new ERR_FS_CP_EEXIST({ + message: `${dest} already exists`, + path: dest, + syscall: 'cp', + errno: EEXIST, + }) + } +} + +async function _copyFile (srcStat, src, dest, opts) { + await copyFile(src, dest) + if (opts.preserveTimestamps) { + return handleTimestampsAndMode(srcStat.mode, src, dest) + } + return setDestMode(dest, srcStat.mode) +} + +async function handleTimestampsAndMode (srcMode, src, dest) { + // Make sure the file is writable before setting the timestamp + // otherwise open fails with EPERM when invoked with 'r+' + // (through utimes call) + if (fileIsNotWritable(srcMode)) { + await makeFileWritable(dest, srcMode) + return setDestTimestampsAndMode(srcMode, src, dest) + } + return setDestTimestampsAndMode(srcMode, src, dest) +} + +function fileIsNotWritable (srcMode) { + return (srcMode & 0o200) === 0 +} + +function makeFileWritable (dest, srcMode) { + return setDestMode(dest, srcMode | 0o200) +} + +async function setDestTimestampsAndMode (srcMode, src, dest) { + await setDestTimestamps(src, dest) + return setDestMode(dest, srcMode) +} + +function setDestMode (dest, srcMode) { + return chmod(dest, srcMode) +} + +async function setDestTimestamps (src, dest) { + // The initial srcStat.atime cannot be trusted + // because it is modified by the read(2) system call + // (See https://nodejs.org/api/fs.html#fs_stat_time_values) + const updatedSrcStat = await stat(src) + return utimes(dest, updatedSrcStat.atime, updatedSrcStat.mtime) +} + +function onDir (srcStat, destStat, src, dest, opts) { + if (!destStat) { + return mkDirAndCopy(srcStat.mode, src, dest, opts) + } + return copyDir(src, dest, opts) +} + +async function mkDirAndCopy (srcMode, src, dest, opts) { + await mkdir(dest) + await copyDir(src, dest, opts) + return setDestMode(dest, srcMode) +} + +async function copyDir (src, dest, opts) { + const dir = await readdir(src) + for (let i = 0; i < dir.length; i++) { + const item = dir[i] + const srcItem = join(src, item) + const destItem = join(dest, item) + const { destStat } = await checkPaths(srcItem, destItem, opts) + await startCopy(destStat, srcItem, destItem, opts) + } +} + +async function onLink (destStat, src, dest) { + let resolvedSrc = await readlink(src) + if (!isAbsolute(resolvedSrc)) { + resolvedSrc = resolve(dirname(src), resolvedSrc) + } + if (!destStat) { + return symlink(resolvedSrc, dest) + } + let resolvedDest + try { + resolvedDest = await readlink(dest) + } catch (err) { + // Dest exists and is a regular file or directory, + // Windows may throw UNKNOWN error. If dest already exists, + // fs throws error anyway, so no need to guard against it here. + // istanbul ignore next: can only test on windows + if (err.code === 'EINVAL' || err.code === 'UNKNOWN') { + return symlink(resolvedSrc, dest) + } + // istanbul ignore next: should not be possible + throw err + } + if (!isAbsolute(resolvedDest)) { + resolvedDest = resolve(dirname(dest), resolvedDest) + } + if (isSrcSubdir(resolvedSrc, resolvedDest)) { + throw new ERR_FS_CP_EINVAL({ + message: `cannot copy ${resolvedSrc} to a subdirectory of self ` + + `${resolvedDest}`, + path: dest, + syscall: 'cp', + errno: EINVAL, + }) + } + // Do not copy if src is a subdir of dest since unlinking + // dest in this case would result in removing src contents + // and therefore a broken symlink would be created. + const srcStat = await stat(src) + if (srcStat.isDirectory() && isSrcSubdir(resolvedDest, resolvedSrc)) { + throw new ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY({ + message: `cannot overwrite ${resolvedDest} with ${resolvedSrc}`, + path: dest, + syscall: 'cp', + errno: EINVAL, + }) + } + return copyLink(resolvedSrc, dest) +} + +async function copyLink (resolvedSrc, dest) { + await unlink(dest) + return symlink(resolvedSrc, dest) +} + +module.exports = cp diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/errors.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/errors.js new file mode 100644 index 000000000..1cd1e05d0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/errors.js @@ -0,0 +1,129 @@ +'use strict' +const { inspect } = require('util') + +// adapted from node's internal/errors +// https://github.com/nodejs/node/blob/c8a04049/lib/internal/errors.js + +// close copy of node's internal SystemError class. +class SystemError { + constructor (code, prefix, context) { + // XXX context.code is undefined in all constructors used in cp/polyfill + // that may be a bug copied from node, maybe the constructor should use + // `code` not `errno`? nodejs/node#41104 + let message = `${prefix}: ${context.syscall} returned ` + + `${context.code} (${context.message})` + + if (context.path !== undefined) { + message += ` ${context.path}` + } + if (context.dest !== undefined) { + message += ` => ${context.dest}` + } + + this.code = code + Object.defineProperties(this, { + name: { + value: 'SystemError', + enumerable: false, + writable: true, + configurable: true, + }, + message: { + value: message, + enumerable: false, + writable: true, + configurable: true, + }, + info: { + value: context, + enumerable: true, + configurable: true, + writable: false, + }, + errno: { + get () { + return context.errno + }, + set (value) { + context.errno = value + }, + enumerable: true, + configurable: true, + }, + syscall: { + get () { + return context.syscall + }, + set (value) { + context.syscall = value + }, + enumerable: true, + configurable: true, + }, + }) + + if (context.path !== undefined) { + Object.defineProperty(this, 'path', { + get () { + return context.path + }, + set (value) { + context.path = value + }, + enumerable: true, + configurable: true, + }) + } + + if (context.dest !== undefined) { + Object.defineProperty(this, 'dest', { + get () { + return context.dest + }, + set (value) { + context.dest = value + }, + enumerable: true, + configurable: true, + }) + } + } + + toString () { + return `${this.name} [${this.code}]: ${this.message}` + } + + [Symbol.for('nodejs.util.inspect.custom')] (_recurseTimes, ctx) { + return inspect(this, { + ...ctx, + getters: true, + customInspect: false, + }) + } +} + +function E (code, message) { + module.exports[code] = class NodeError extends SystemError { + constructor (ctx) { + super(code, message, ctx) + } + } +} + +E('ERR_FS_CP_DIR_TO_NON_DIR', 'Cannot overwrite directory with non-directory') +E('ERR_FS_CP_EEXIST', 'Target already exists') +E('ERR_FS_CP_EINVAL', 'Invalid src or dest') +E('ERR_FS_CP_FIFO_PIPE', 'Cannot copy a FIFO pipe') +E('ERR_FS_CP_NON_DIR_TO_DIR', 'Cannot overwrite non-directory with directory') +E('ERR_FS_CP_SOCKET', 'Cannot copy a socket file') +E('ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY', 'Cannot overwrite symlink in subdirectory of self') +E('ERR_FS_CP_UNKNOWN', 'Cannot copy an unknown file type') +E('ERR_FS_EISDIR', 'Path is a directory') + +module.exports.ERR_INVALID_ARG_TYPE = class ERR_INVALID_ARG_TYPE extends Error { + constructor (name, expected, actual) { + super() + this.code = 'ERR_INVALID_ARG_TYPE' + this.message = `The ${name} argument must be ${expected}. Received ${typeof actual}` + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/fs.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/fs.js new file mode 100644 index 000000000..29e5fb573 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/fs.js @@ -0,0 +1,8 @@ +const fs = require('fs') +const promisify = require('@gar/promisify') + +// this module returns the core fs module wrapped in a proxy that promisifies +// method calls within the getter. we keep it in a separate module so that the +// overridden methods have a consistent way to get to promisified fs methods +// without creating a circular dependency +module.exports = promisify(fs) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/index.js new file mode 100644 index 000000000..e40d748a7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/index.js @@ -0,0 +1,10 @@ +module.exports = { + ...require('./fs.js'), + copyFile: require('./copy-file.js'), + cp: require('./cp/index.js'), + mkdir: require('./mkdir/index.js'), + mkdtemp: require('./mkdtemp.js'), + rm: require('./rm/index.js'), + withTempDir: require('./with-temp-dir.js'), + writeFile: require('./write-file.js'), +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/mkdir/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/mkdir/index.js new file mode 100644 index 000000000..04ff44790 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/mkdir/index.js @@ -0,0 +1,32 @@ +const fs = require('../fs.js') +const getOptions = require('../common/get-options.js') +const node = require('../common/node.js') +const owner = require('../common/owner.js') + +const polyfill = require('./polyfill.js') + +// node 10.12.0 added the options parameter, which allows recursive and mode +// properties to be passed +const useNative = node.satisfies('>=10.12.0') + +// extends mkdir with the ability to specify an owner of the new dir +const mkdir = async (path, opts) => { + const options = getOptions(opts, { + copy: ['mode', 'recursive', 'owner'], + wrap: 'mode', + }) + const { uid, gid } = await owner.validate(path, options.owner) + + // the polyfill is tested separately from this module, no need to hack + // process.version to try to trigger it just for coverage + // istanbul ignore next + const result = useNative + ? await fs.mkdir(path, options) + : await polyfill(path, options) + + await owner.update(path, uid, gid) + + return result +} + +module.exports = mkdir diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/mkdir/polyfill.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/mkdir/polyfill.js new file mode 100644 index 000000000..4f8e6f006 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/mkdir/polyfill.js @@ -0,0 +1,81 @@ +const { dirname } = require('path') + +const fileURLToPath = require('../common/file-url-to-path/index.js') +const fs = require('../fs.js') + +const defaultOptions = { + mode: 0o777, + recursive: false, +} + +const mkdir = async (path, opts) => { + const options = { ...defaultOptions, ...opts } + + // if we're not in recursive mode, just call the real mkdir with the path and + // the mode option only + if (!options.recursive) { + return fs.mkdir(path, options.mode) + } + + const makeDirectory = async (dir, mode) => { + // we can't use dirname directly since these functions support URL + // objects with the file: protocol as the path input, so first we get a + // string path, then we can call dirname on that + const parent = dir != null && dir.href && dir.origin + ? dirname(fileURLToPath(dir)) + : dirname(dir) + + // if the parent is the dir itself, try to create it. anything but EISDIR + // should be rethrown + if (parent === dir) { + try { + await fs.mkdir(dir, opts) + } catch (err) { + if (err.code !== 'EISDIR') { + throw err + } + } + return undefined + } + + try { + await fs.mkdir(dir, mode) + return dir + } catch (err) { + // ENOENT means the parent wasn't there, so create that + if (err.code === 'ENOENT') { + const made = await makeDirectory(parent, mode) + await makeDirectory(dir, mode) + // return the shallowest path we created, i.e. the result of creating + // the parent + return made + } + + // an EEXIST means there's already something there + // an EROFS means we have a read-only filesystem and can't create a dir + // any other error is fatal and we should give up now + if (err.code !== 'EEXIST' && err.code !== 'EROFS') { + throw err + } + + // stat the directory, if the result is a directory, then we successfully + // created this one so return its path. otherwise, we reject with the + // original error by ignoring the error in the catch + try { + const stat = await fs.stat(dir) + if (stat.isDirectory()) { + // if it already existed, we didn't create anything so return + // undefined + return undefined + } + } catch (_) {} + + // if the thing that's there isn't a directory, then just re-throw + throw err + } + } + + return makeDirectory(path, options.mode) +} + +module.exports = mkdir diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/mkdtemp.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/mkdtemp.js new file mode 100644 index 000000000..b7f078029 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/mkdtemp.js @@ -0,0 +1,28 @@ +const { dirname, sep } = require('path') + +const fs = require('./fs.js') +const getOptions = require('./common/get-options.js') +const owner = require('./common/owner.js') + +const mkdtemp = async (prefix, opts) => { + const options = getOptions(opts, { + copy: ['encoding', 'owner'], + wrap: 'encoding', + }) + + // mkdtemp relies on the trailing path separator to indicate if it should + // create a directory inside of the prefix. if that's the case then the root + // we infer ownership from is the prefix itself, otherwise it's the dirname + // /tmp -> /tmpABCDEF, infers from / + // /tmp/ -> /tmp/ABCDEF, infers from /tmp + const root = prefix.endsWith(sep) ? prefix : dirname(prefix) + const { uid, gid } = await owner.validate(root, options.owner) + + const result = await fs.mkdtemp(prefix, options) + + await owner.update(result, uid, gid) + + return result +} + +module.exports = mkdtemp diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/rm/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/rm/index.js new file mode 100644 index 000000000..cb81fbdf8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/rm/index.js @@ -0,0 +1,22 @@ +const fs = require('../fs.js') +const getOptions = require('../common/get-options.js') +const node = require('../common/node.js') +const polyfill = require('./polyfill.js') + +// node 14.14.0 added fs.rm, which allows both the force and recursive options +const useNative = node.satisfies('>=14.14.0') + +const rm = async (path, opts) => { + const options = getOptions(opts, { + copy: ['retryDelay', 'maxRetries', 'recursive', 'force'], + }) + + // the polyfill is tested separately from this module, no need to hack + // process.version to try to trigger it just for coverage + // istanbul ignore next + return useNative + ? fs.rm(path, options) + : polyfill(path, options) +} + +module.exports = rm diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/rm/polyfill.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/rm/polyfill.js new file mode 100644 index 000000000..a25c17483 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/rm/polyfill.js @@ -0,0 +1,239 @@ +// this file is a modified version of the code in node core >=14.14.0 +// which is, in turn, a modified version of the rimraf module on npm +// node core changes: +// - Use of the assert module has been replaced with core's error system. +// - All code related to the glob dependency has been removed. +// - Bring your own custom fs module is not currently supported. +// - Some basic code cleanup. +// changes here: +// - remove all callback related code +// - drop sync support +// - change assertions back to non-internal methods (see options.js) +// - throws ENOTDIR when rmdir gets an ENOENT for a path that exists in Windows +const errnos = require('os').constants.errno +const { join } = require('path') +const fs = require('../fs.js') + +// error codes that mean we need to remove contents +const notEmptyCodes = new Set([ + 'ENOTEMPTY', + 'EEXIST', + 'EPERM', +]) + +// error codes we can retry later +const retryCodes = new Set([ + 'EBUSY', + 'EMFILE', + 'ENFILE', + 'ENOTEMPTY', + 'EPERM', +]) + +const isWindows = process.platform === 'win32' + +const defaultOptions = { + retryDelay: 100, + maxRetries: 0, + recursive: false, + force: false, +} + +// this is drastically simplified, but should be roughly equivalent to what +// node core throws +class ERR_FS_EISDIR extends Error { + constructor (path) { + super() + this.info = { + code: 'EISDIR', + message: 'is a directory', + path, + syscall: 'rm', + errno: errnos.EISDIR, + } + this.name = 'SystemError' + this.code = 'ERR_FS_EISDIR' + this.errno = errnos.EISDIR + this.syscall = 'rm' + this.path = path + this.message = `Path is a directory: ${this.syscall} returned ` + + `${this.info.code} (is a directory) ${path}` + } + + toString () { + return `${this.name} [${this.code}]: ${this.message}` + } +} + +class ENOTDIR extends Error { + constructor (path) { + super() + this.name = 'Error' + this.code = 'ENOTDIR' + this.errno = errnos.ENOTDIR + this.syscall = 'rmdir' + this.path = path + this.message = `not a directory, ${this.syscall} '${this.path}'` + } + + toString () { + return `${this.name}: ${this.code}: ${this.message}` + } +} + +// force is passed separately here because we respect it for the first entry +// into rimraf only, any further calls that are spawned as a result (i.e. to +// delete content within the target) will ignore ENOENT errors +const rimraf = async (path, options, isTop = false) => { + const force = isTop ? options.force : true + const stat = await fs.lstat(path) + .catch((err) => { + // we only ignore ENOENT if we're forcing this call + if (err.code === 'ENOENT' && force) { + return + } + + if (isWindows && err.code === 'EPERM') { + return fixEPERM(path, options, err, isTop) + } + + throw err + }) + + // no stat object here means either lstat threw an ENOENT, or lstat threw + // an EPERM and the fixPERM function took care of things. either way, we're + // already done, so return early + if (!stat) { + return + } + + if (stat.isDirectory()) { + return rmdir(path, options, null, isTop) + } + + return fs.unlink(path) + .catch((err) => { + if (err.code === 'ENOENT' && force) { + return + } + + if (err.code === 'EISDIR') { + return rmdir(path, options, err, isTop) + } + + if (err.code === 'EPERM') { + // in windows, we handle this through fixEPERM which will also try to + // delete things again. everywhere else since deleting the target as a + // file didn't work we go ahead and try to delete it as a directory + return isWindows + ? fixEPERM(path, options, err, isTop) + : rmdir(path, options, err, isTop) + } + + throw err + }) +} + +const fixEPERM = async (path, options, originalErr, isTop) => { + const force = isTop ? options.force : true + const targetMissing = await fs.chmod(path, 0o666) + .catch((err) => { + if (err.code === 'ENOENT' && force) { + return true + } + + throw originalErr + }) + + // got an ENOENT above, return now. no file = no problem + if (targetMissing) { + return + } + + // this function does its own lstat rather than calling rimraf again to avoid + // infinite recursion for a repeating EPERM + const stat = await fs.lstat(path) + .catch((err) => { + if (err.code === 'ENOENT' && force) { + return + } + + throw originalErr + }) + + if (!stat) { + return + } + + if (stat.isDirectory()) { + return rmdir(path, options, originalErr, isTop) + } + + return fs.unlink(path) +} + +const rmdir = async (path, options, originalErr, isTop) => { + if (!options.recursive && isTop) { + throw originalErr || new ERR_FS_EISDIR(path) + } + const force = isTop ? options.force : true + + return fs.rmdir(path) + .catch(async (err) => { + // in Windows, calling rmdir on a file path will fail with ENOENT rather + // than ENOTDIR. to determine if that's what happened, we have to do + // another lstat on the path. if the path isn't actually gone, we throw + // away the ENOENT and replace it with our own ENOTDIR + if (isWindows && err.code === 'ENOENT') { + const stillExists = await fs.lstat(path).then(() => true, () => false) + if (stillExists) { + err = new ENOTDIR(path) + } + } + + // not there, not a problem + if (err.code === 'ENOENT' && force) { + return + } + + // we may not have originalErr if lstat tells us our target is a + // directory but that changes before we actually remove it, so + // only throw it here if it's set + if (originalErr && err.code === 'ENOTDIR') { + throw originalErr + } + + // the directory isn't empty, remove the contents and try again + if (notEmptyCodes.has(err.code)) { + const files = await fs.readdir(path) + await Promise.all(files.map((file) => { + const target = join(path, file) + return rimraf(target, options) + })) + return fs.rmdir(path) + } + + throw err + }) +} + +const rm = async (path, opts) => { + const options = { ...defaultOptions, ...opts } + let retries = 0 + + const errHandler = async (err) => { + if (retryCodes.has(err.code) && ++retries < options.maxRetries) { + const delay = retries * options.retryDelay + await promiseTimeout(delay) + return rimraf(path, options, true).catch(errHandler) + } + + throw err + } + + return rimraf(path, options, true).catch(errHandler) +} + +const promiseTimeout = (ms) => new Promise((r) => setTimeout(r, ms)) + +module.exports = rm diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/with-temp-dir.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/with-temp-dir.js new file mode 100644 index 000000000..353d5555d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/with-temp-dir.js @@ -0,0 +1,39 @@ +const { join, sep } = require('path') + +const getOptions = require('./common/get-options.js') +const mkdir = require('./mkdir/index.js') +const mkdtemp = require('./mkdtemp.js') +const rm = require('./rm/index.js') + +// create a temp directory, ensure its permissions match its parent, then call +// the supplied function passing it the path to the directory. clean up after +// the function finishes, whether it throws or not +const withTempDir = async (root, fn, opts) => { + const options = getOptions(opts, { + copy: ['tmpPrefix'], + }) + // create the directory, and fix its ownership + await mkdir(root, { recursive: true, owner: 'inherit' }) + + const target = await mkdtemp(join(`${root}${sep}`, options.tmpPrefix || ''), { owner: 'inherit' }) + let err + let result + + try { + result = await fn(target) + } catch (_err) { + err = _err + } + + try { + await rm(target, { force: true, recursive: true }) + } catch (err) {} + + if (err) { + throw err + } + + return result +} + +module.exports = withTempDir diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/write-file.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/write-file.js new file mode 100644 index 000000000..01de531d9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/lib/write-file.js @@ -0,0 +1,19 @@ +const fs = require('./fs.js') +const getOptions = require('./common/get-options.js') +const owner = require('./common/owner.js') + +const writeFile = async (file, data, opts) => { + const options = getOptions(opts, { + copy: ['encoding', 'mode', 'flag', 'signal', 'owner'], + wrap: 'encoding', + }) + const { uid, gid } = await owner.validate(file, options.owner) + + const result = await fs.writeFile(file, data, options) + + await owner.update(file, uid, gid) + + return result +} + +module.exports = writeFile diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/package.json new file mode 100644 index 000000000..0296aa7f1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/fs/package.json @@ -0,0 +1,38 @@ +{ + "name": "@npmcli/fs", + "version": "1.1.1", + "description": "filesystem utilities for the npm cli", + "main": "lib/index.js", + "files": [ + "bin", + "lib" + ], + "scripts": { + "preversion": "npm test", + "postversion": "npm publish", + "prepublishOnly": "git push origin --follow-tags", + "snap": "tap", + "test": "tap", + "npmclilint": "npmcli-lint", + "lint": "eslint '**/*.js'", + "lintfix": "npm run lint -- --fix", + "posttest": "npm run lint", + "postsnap": "npm run lintfix --", + "postlint": "npm-template-check" + }, + "keywords": [ + "npm", + "oss" + ], + "author": "GitHub Inc.", + "license": "ISC", + "devDependencies": { + "@npmcli/template-oss": "^2.3.1", + "tap": "^15.0.9" + }, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + }, + "templateVersion": "2.3.1" +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/LICENSE.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/LICENSE.md new file mode 100644 index 000000000..072bf2084 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/LICENSE.md @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) Sindre Sorhus (https://sindresorhus.com) +Copyright (c) npm, Inc. + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/README.md new file mode 100644 index 000000000..8a5a57f0f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/README.md @@ -0,0 +1,69 @@ +# @npmcli/move-file + +A fork of [move-file](https://github.com/sindresorhus/move-file) with +compatibility with all node 10.x versions. + +> Move a file (or directory) + +The built-in +[`fs.rename()`](https://nodejs.org/api/fs.html#fs_fs_rename_oldpath_newpath_callback) +is just a JavaScript wrapper for the C `rename(2)` function, which doesn't +support moving files across partitions or devices. This module is what you +would have expected `fs.rename()` to be. + +## Highlights + +- Promise API. +- Supports moving a file across partitions and devices. +- Optionally prevent overwriting an existing file. +- Creates non-existent destination directories for you. +- Support for Node versions that lack built-in recursive `fs.mkdir()` +- Automatically recurses when source is a directory. + +## Install + +``` +$ npm install @npmcli/move-file +``` + +## Usage + +```js +const moveFile = require('@npmcli/move-file'); + +(async () => { + await moveFile('source/unicorn.png', 'destination/unicorn.png'); + console.log('The file has been moved'); +})(); +``` + +## API + +### moveFile(source, destination, options?) + +Returns a `Promise` that resolves when the file has been moved. + +### moveFile.sync(source, destination, options?) + +#### source + +Type: `string` + +File, or directory, you want to move. + +#### destination + +Type: `string` + +Where you want the file or directory moved. + +#### options + +Type: `object` + +##### overwrite + +Type: `boolean`\ +Default: `true` + +Overwrite existing destination file(s). diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/index.js new file mode 100644 index 000000000..95d1888c6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/index.js @@ -0,0 +1,162 @@ +const { dirname, join, resolve, relative, isAbsolute } = require('path') +const rimraf_ = require('rimraf') +const { promisify } = require('util') +const { + access: access_, + accessSync, + copyFile: copyFile_, + copyFileSync, + unlink: unlink_, + unlinkSync, + readdir: readdir_, + readdirSync, + rename: rename_, + renameSync, + stat: stat_, + statSync, + lstat: lstat_, + lstatSync, + symlink: symlink_, + symlinkSync, + readlink: readlink_, + readlinkSync +} = require('fs') + +const access = promisify(access_) +const copyFile = promisify(copyFile_) +const unlink = promisify(unlink_) +const readdir = promisify(readdir_) +const rename = promisify(rename_) +const stat = promisify(stat_) +const lstat = promisify(lstat_) +const symlink = promisify(symlink_) +const readlink = promisify(readlink_) +const rimraf = promisify(rimraf_) +const rimrafSync = rimraf_.sync + +const mkdirp = require('mkdirp') + +const pathExists = async path => { + try { + await access(path) + return true + } catch (er) { + return er.code !== 'ENOENT' + } +} + +const pathExistsSync = path => { + try { + accessSync(path) + return true + } catch (er) { + return er.code !== 'ENOENT' + } +} + +const moveFile = async (source, destination, options = {}, root = true, symlinks = []) => { + if (!source || !destination) { + throw new TypeError('`source` and `destination` file required') + } + + options = { + overwrite: true, + ...options + } + + if (!options.overwrite && await pathExists(destination)) { + throw new Error(`The destination file exists: ${destination}`) + } + + await mkdirp(dirname(destination)) + + try { + await rename(source, destination) + } catch (error) { + if (error.code === 'EXDEV' || error.code === 'EPERM') { + const sourceStat = await lstat(source) + if (sourceStat.isDirectory()) { + const files = await readdir(source) + await Promise.all(files.map((file) => moveFile(join(source, file), join(destination, file), options, false, symlinks))) + } else if (sourceStat.isSymbolicLink()) { + symlinks.push({ source, destination }) + } else { + await copyFile(source, destination) + } + } else { + throw error + } + } + + if (root) { + await Promise.all(symlinks.map(async ({ source, destination }) => { + let target = await readlink(source) + // junction symlinks in windows will be absolute paths, so we need to make sure they point to the destination + if (isAbsolute(target)) + target = resolve(destination, relative(source, target)) + // try to determine what the actual file is so we can create the correct type of symlink in windows + let targetStat + try { + targetStat = await stat(resolve(dirname(source), target)) + } catch (err) {} + await symlink(target, destination, targetStat && targetStat.isDirectory() ? 'junction' : 'file') + })) + await rimraf(source) + } +} + +const moveFileSync = (source, destination, options = {}, root = true, symlinks = []) => { + if (!source || !destination) { + throw new TypeError('`source` and `destination` file required') + } + + options = { + overwrite: true, + ...options + } + + if (!options.overwrite && pathExistsSync(destination)) { + throw new Error(`The destination file exists: ${destination}`) + } + + mkdirp.sync(dirname(destination)) + + try { + renameSync(source, destination) + } catch (error) { + if (error.code === 'EXDEV' || error.code === 'EPERM') { + const sourceStat = lstatSync(source) + if (sourceStat.isDirectory()) { + const files = readdirSync(source) + for (const file of files) { + moveFileSync(join(source, file), join(destination, file), options, false, symlinks) + } + } else if (sourceStat.isSymbolicLink()) { + symlinks.push({ source, destination }) + } else { + copyFileSync(source, destination) + } + } else { + throw error + } + } + + if (root) { + for (const { source, destination } of symlinks) { + let target = readlinkSync(source) + // junction symlinks in windows will be absolute paths, so we need to make sure they point to the destination + if (isAbsolute(target)) + target = resolve(destination, relative(source, target)) + // try to determine what the actual file is so we can create the correct type of symlink in windows + let targetStat + try { + targetStat = statSync(resolve(dirname(source), target)) + } catch (err) {} + symlinkSync(target, destination, targetStat && targetStat.isDirectory() ? 'junction' : 'file') + } + rimrafSync(source) + } +} + +module.exports = moveFile +module.exports.sync = moveFileSync diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/package.json new file mode 100644 index 000000000..0c066dbcf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@npmcli/move-file/package.json @@ -0,0 +1,34 @@ +{ + "name": "@npmcli/move-file", + "version": "1.1.2", + "files": [ + "index.js" + ], + "description": "move a file (fork of move-file)", + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "devDependencies": { + "require-inject": "^1.4.4", + "tap": "^14.10.7" + }, + "scripts": { + "test": "tap", + "snap": "tap", + "preversion": "npm test", + "postversion": "npm publish", + "prepublishOnly": "git push origin --follow-tags" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/npm/move-file" + }, + "tap": { + "check-coverage": true + }, + "license": "MIT", + "engines": { + "node": ">=10" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/dist/index.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/dist/index.d.ts new file mode 100644 index 000000000..a7efe943b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/dist/index.d.ts @@ -0,0 +1,14 @@ +/// +import { EventEmitter } from 'events'; +declare function once(emitter: EventEmitter, name: string): once.CancelablePromise; +declare namespace once { + interface CancelFunction { + (): void; + } + interface CancelablePromise extends Promise { + cancel: CancelFunction; + } + type CancellablePromise = CancelablePromise; + function spread(emitter: EventEmitter, name: string): once.CancelablePromise; +} +export = once; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/dist/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/dist/index.js new file mode 100644 index 000000000..bfd0dc88f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/dist/index.js @@ -0,0 +1,39 @@ +"use strict"; +function noop() { } +function once(emitter, name) { + const o = once.spread(emitter, name); + const r = o.then((args) => args[0]); + r.cancel = o.cancel; + return r; +} +(function (once) { + function spread(emitter, name) { + let c = null; + const p = new Promise((resolve, reject) => { + function cancel() { + emitter.removeListener(name, onEvent); + emitter.removeListener('error', onError); + p.cancel = noop; + } + function onEvent(...args) { + cancel(); + resolve(args); + } + function onError(err) { + cancel(); + reject(err); + } + c = cancel; + emitter.on(name, onEvent); + emitter.on('error', onError); + }); + if (!c) { + throw new TypeError('Could not get `cancel()` function'); + } + p.cancel = c; + return p; + } + once.spread = spread; +})(once || (once = {})); +module.exports = once; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/dist/index.js.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/dist/index.js.map new file mode 100644 index 000000000..30d20491d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,SAAS,IAAI,KAAI,CAAC;AAElB,SAAS,IAAI,CACZ,OAAqB,EACrB,IAAY;IAEZ,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAM,OAAO,EAAE,IAAI,CAAC,CAAC;IAC1C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAA8B,CAAC;IACtE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IACpB,OAAO,CAAC,CAAC;AACV,CAAC;AAED,WAAU,IAAI;IAWb,SAAgB,MAAM,CACrB,OAAqB,EACrB,IAAY;QAEZ,IAAI,CAAC,GAA+B,IAAI,CAAC;QACzC,MAAM,CAAC,GAAG,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC5C,SAAS,MAAM;gBACd,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBACtC,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACzC,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC;YACjB,CAAC;YACD,SAAS,OAAO,CAAC,GAAG,IAAW;gBAC9B,MAAM,EAAE,CAAC;gBACT,OAAO,CAAC,IAAS,CAAC,CAAC;YACpB,CAAC;YACD,SAAS,OAAO,CAAC,GAAU;gBAC1B,MAAM,EAAE,CAAC;gBACT,MAAM,CAAC,GAAG,CAAC,CAAC;YACb,CAAC;YACD,CAAC,GAAG,MAAM,CAAC;YACX,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC1B,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9B,CAAC,CAA8B,CAAC;QAChC,IAAI,CAAC,CAAC,EAAE;YACP,MAAM,IAAI,SAAS,CAAC,mCAAmC,CAAC,CAAC;SACzD;QACD,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QACb,OAAO,CAAC,CAAC;IACV,CAAC;IA5Be,WAAM,SA4BrB,CAAA;AACF,CAAC,EAxCS,IAAI,KAAJ,IAAI,QAwCb;AAED,iBAAS,IAAI,CAAC"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/package.json new file mode 100644 index 000000000..8343f9fad --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/@tootallnate/once/package.json @@ -0,0 +1,45 @@ +{ + "name": "@tootallnate/once", + "version": "1.1.2", + "description": "Creates a Promise that waits for a single event", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "prebuild": "rimraf dist", + "build": "tsc", + "test": "mocha --reporter spec", + "test-lint": "eslint src --ext .js,.ts", + "prepublishOnly": "npm run build" + }, + "repository": { + "type": "git", + "url": "git://github.com/TooTallNate/once.git" + }, + "keywords": [], + "author": "Nathan Rajlich (http://n8.io/)", + "license": "MIT", + "bugs": { + "url": "https://github.com/TooTallNate/once/issues" + }, + "devDependencies": { + "@types/node": "^12.12.11", + "@typescript-eslint/eslint-plugin": "1.6.0", + "@typescript-eslint/parser": "1.1.0", + "eslint": "5.16.0", + "eslint-config-airbnb": "17.1.0", + "eslint-config-prettier": "4.1.0", + "eslint-import-resolver-typescript": "1.1.1", + "eslint-plugin-import": "2.16.0", + "eslint-plugin-jsx-a11y": "6.2.1", + "eslint-plugin-react": "7.12.4", + "mocha": "^6.2.2", + "rimraf": "^3.0.0", + "typescript": "^3.7.3" + }, + "engines": { + "node": ">= 6" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/LICENSE new file mode 100644 index 000000000..9bcfa9d7d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/LICENSE @@ -0,0 +1,46 @@ +This software is dual-licensed under the ISC and MIT licenses. +You may use this software under EITHER of the following licenses. + +---------- + +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +---------- + +Copyright Isaac Z. Schlueter and Contributors +All rights reserved. + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/README.md new file mode 100644 index 000000000..99746fe67 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/README.md @@ -0,0 +1,23 @@ +# abbrev-js + +Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev). + +Usage: + + var abbrev = require("abbrev"); + abbrev("foo", "fool", "folding", "flop"); + + // returns: + { fl: 'flop' + , flo: 'flop' + , flop: 'flop' + , fol: 'folding' + , fold: 'folding' + , foldi: 'folding' + , foldin: 'folding' + , folding: 'folding' + , foo: 'foo' + , fool: 'fool' + } + +This is handy for command-line scripts, or other cases where you want to be able to accept shorthands. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/abbrev.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/abbrev.js new file mode 100644 index 000000000..7b1dc5d67 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/abbrev.js @@ -0,0 +1,61 @@ +module.exports = exports = abbrev.abbrev = abbrev + +abbrev.monkeyPatch = monkeyPatch + +function monkeyPatch () { + Object.defineProperty(Array.prototype, 'abbrev', { + value: function () { return abbrev(this) }, + enumerable: false, configurable: true, writable: true + }) + + Object.defineProperty(Object.prototype, 'abbrev', { + value: function () { return abbrev(Object.keys(this)) }, + enumerable: false, configurable: true, writable: true + }) +} + +function abbrev (list) { + if (arguments.length !== 1 || !Array.isArray(list)) { + list = Array.prototype.slice.call(arguments, 0) + } + for (var i = 0, l = list.length, args = [] ; i < l ; i ++) { + args[i] = typeof list[i] === "string" ? list[i] : String(list[i]) + } + + // sort them lexicographically, so that they're next to their nearest kin + args = args.sort(lexSort) + + // walk through each, seeing how much it has in common with the next and previous + var abbrevs = {} + , prev = "" + for (var i = 0, l = args.length ; i < l ; i ++) { + var current = args[i] + , next = args[i + 1] || "" + , nextMatches = true + , prevMatches = true + if (current === next) continue + for (var j = 0, cl = current.length ; j < cl ; j ++) { + var curChar = current.charAt(j) + nextMatches = nextMatches && curChar === next.charAt(j) + prevMatches = prevMatches && curChar === prev.charAt(j) + if (!nextMatches && !prevMatches) { + j ++ + break + } + } + prev = current + if (j === cl) { + abbrevs[current] = current + continue + } + for (var a = current.substr(0, j) ; j <= cl ; j ++) { + abbrevs[a] = current + a += current.charAt(j) + } + } + return abbrevs +} + +function lexSort (a, b) { + return a === b ? 0 : a > b ? 1 : -1 +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/package.json new file mode 100644 index 000000000..bf4e8015b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/abbrev/package.json @@ -0,0 +1,21 @@ +{ + "name": "abbrev", + "version": "1.1.1", + "description": "Like ruby's abbrev module, but in js", + "author": "Isaac Z. Schlueter ", + "main": "abbrev.js", + "scripts": { + "test": "tap test.js --100", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --all; git push origin --tags" + }, + "repository": "http://github.com/isaacs/abbrev-js", + "license": "ISC", + "devDependencies": { + "tap": "^10.1" + }, + "files": [ + "abbrev.js" + ] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/HISTORY.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/HISTORY.md new file mode 100644 index 000000000..627a81d0c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/HISTORY.md @@ -0,0 +1,250 @@ +2.0.0 / 2024-08-31 +================== + + * Drop node <18 support + * deps: mime-types@^3.0.0 + * deps: negotiator@^1.0.0 + +1.3.8 / 2022-02-02 +================== + + * deps: mime-types@~2.1.34 + - deps: mime-db@~1.51.0 + * deps: negotiator@0.6.3 + +1.3.7 / 2019-04-29 +================== + + * deps: negotiator@0.6.2 + - Fix sorting charset, encoding, and language with extra parameters + +1.3.6 / 2019-04-28 +================== + + * deps: mime-types@~2.1.24 + - deps: mime-db@~1.40.0 + +1.3.5 / 2018-02-28 +================== + + * deps: mime-types@~2.1.18 + - deps: mime-db@~1.33.0 + +1.3.4 / 2017-08-22 +================== + + * deps: mime-types@~2.1.16 + - deps: mime-db@~1.29.0 + +1.3.3 / 2016-05-02 +================== + + * deps: mime-types@~2.1.11 + - deps: mime-db@~1.23.0 + * deps: negotiator@0.6.1 + - perf: improve `Accept` parsing speed + - perf: improve `Accept-Charset` parsing speed + - perf: improve `Accept-Encoding` parsing speed + - perf: improve `Accept-Language` parsing speed + +1.3.2 / 2016-03-08 +================== + + * deps: mime-types@~2.1.10 + - Fix extension of `application/dash+xml` + - Update primary extension for `audio/mp4` + - deps: mime-db@~1.22.0 + +1.3.1 / 2016-01-19 +================== + + * deps: mime-types@~2.1.9 + - deps: mime-db@~1.21.0 + +1.3.0 / 2015-09-29 +================== + + * deps: mime-types@~2.1.7 + - deps: mime-db@~1.19.0 + * deps: negotiator@0.6.0 + - Fix including type extensions in parameters in `Accept` parsing + - Fix parsing `Accept` parameters with quoted equals + - Fix parsing `Accept` parameters with quoted semicolons + - Lazy-load modules from main entry point + - perf: delay type concatenation until needed + - perf: enable strict mode + - perf: hoist regular expressions + - perf: remove closures getting spec properties + - perf: remove a closure from media type parsing + - perf: remove property delete from media type parsing + +1.2.13 / 2015-09-06 +=================== + + * deps: mime-types@~2.1.6 + - deps: mime-db@~1.18.0 + +1.2.12 / 2015-07-30 +=================== + + * deps: mime-types@~2.1.4 + - deps: mime-db@~1.16.0 + +1.2.11 / 2015-07-16 +=================== + + * deps: mime-types@~2.1.3 + - deps: mime-db@~1.15.0 + +1.2.10 / 2015-07-01 +=================== + + * deps: mime-types@~2.1.2 + - deps: mime-db@~1.14.0 + +1.2.9 / 2015-06-08 +================== + + * deps: mime-types@~2.1.1 + - perf: fix deopt during mapping + +1.2.8 / 2015-06-07 +================== + + * deps: mime-types@~2.1.0 + - deps: mime-db@~1.13.0 + * perf: avoid argument reassignment & argument slice + * perf: avoid negotiator recursive construction + * perf: enable strict mode + * perf: remove unnecessary bitwise operator + +1.2.7 / 2015-05-10 +================== + + * deps: negotiator@0.5.3 + - Fix media type parameter matching to be case-insensitive + +1.2.6 / 2015-05-07 +================== + + * deps: mime-types@~2.0.11 + - deps: mime-db@~1.9.1 + * deps: negotiator@0.5.2 + - Fix comparing media types with quoted values + - Fix splitting media types with quoted commas + +1.2.5 / 2015-03-13 +================== + + * deps: mime-types@~2.0.10 + - deps: mime-db@~1.8.0 + +1.2.4 / 2015-02-14 +================== + + * Support Node.js 0.6 + * deps: mime-types@~2.0.9 + - deps: mime-db@~1.7.0 + * deps: negotiator@0.5.1 + - Fix preference sorting to be stable for long acceptable lists + +1.2.3 / 2015-01-31 +================== + + * deps: mime-types@~2.0.8 + - deps: mime-db@~1.6.0 + +1.2.2 / 2014-12-30 +================== + + * deps: mime-types@~2.0.7 + - deps: mime-db@~1.5.0 + +1.2.1 / 2014-12-30 +================== + + * deps: mime-types@~2.0.5 + - deps: mime-db@~1.3.1 + +1.2.0 / 2014-12-19 +================== + + * deps: negotiator@0.5.0 + - Fix list return order when large accepted list + - Fix missing identity encoding when q=0 exists + - Remove dynamic building of Negotiator class + +1.1.4 / 2014-12-10 +================== + + * deps: mime-types@~2.0.4 + - deps: mime-db@~1.3.0 + +1.1.3 / 2014-11-09 +================== + + * deps: mime-types@~2.0.3 + - deps: mime-db@~1.2.0 + +1.1.2 / 2014-10-14 +================== + + * deps: negotiator@0.4.9 + - Fix error when media type has invalid parameter + +1.1.1 / 2014-09-28 +================== + + * deps: mime-types@~2.0.2 + - deps: mime-db@~1.1.0 + * deps: negotiator@0.4.8 + - Fix all negotiations to be case-insensitive + - Stable sort preferences of same quality according to client order + +1.1.0 / 2014-09-02 +================== + + * update `mime-types` + +1.0.7 / 2014-07-04 +================== + + * Fix wrong type returned from `type` when match after unknown extension + +1.0.6 / 2014-06-24 +================== + + * deps: negotiator@0.4.7 + +1.0.5 / 2014-06-20 +================== + + * fix crash when unknown extension given + +1.0.4 / 2014-06-19 +================== + + * use `mime-types` + +1.0.3 / 2014-06-11 +================== + + * deps: negotiator@0.4.6 + - Order by specificity when quality is the same + +1.0.2 / 2014-05-29 +================== + + * Fix interpretation when header not in request + * deps: pin negotiator@0.4.5 + +1.0.1 / 2014-01-18 +================== + + * Identity encoding isn't always acceptable + * deps: negotiator@~0.4.0 + +1.0.0 / 2013-12-27 +================== + + * Genesis diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/LICENSE new file mode 100644 index 000000000..06166077b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2015 Douglas Christopher Wilson + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/README.md new file mode 100644 index 000000000..f3f10c4a4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/README.md @@ -0,0 +1,140 @@ +# accepts + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][github-actions-ci-image]][github-actions-ci-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator). +Extracted from [koa](https://www.npmjs.com/package/koa) for general use. + +In addition to negotiator, it allows: + +- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])` + as well as `('text/html', 'application/json')`. +- Allows type shorthands such as `json`. +- Returns `false` when no types match +- Treats non-existent headers as `*` + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install accepts +``` + +## API + +```js +var accepts = require('accepts') +``` + +### accepts(req) + +Create a new `Accepts` object for the given `req`. + +#### .charset(charsets) + +Return the first accepted charset. If nothing in `charsets` is accepted, +then `false` is returned. + +#### .charsets() + +Return the charsets that the request accepts, in the order of the client's +preference (most preferred first). + +#### .encoding(encodings) + +Return the first accepted encoding. If nothing in `encodings` is accepted, +then `false` is returned. + +#### .encodings() + +Return the encodings that the request accepts, in the order of the client's +preference (most preferred first). + +#### .language(languages) + +Return the first accepted language. If nothing in `languages` is accepted, +then `false` is returned. + +#### .languages() + +Return the languages that the request accepts, in the order of the client's +preference (most preferred first). + +#### .type(types) + +Return the first accepted type (and it is returned as the same text as what +appears in the `types` array). If nothing in `types` is accepted, then `false` +is returned. + +The `types` array can contain full MIME types or file extensions. Any value +that is not a full MIME type is passed to `require('mime-types').lookup`. + +#### .types() + +Return the types that the request accepts, in the order of the client's +preference (most preferred first). + +## Examples + +### Simple type negotiation + +This simple example shows how to use `accepts` to return a different typed +respond body based on what the client wants to accept. The server lists it's +preferences in order and will get back the best match between the client and +server. + +```js +var accepts = require('accepts') +var http = require('http') + +function app (req, res) { + var accept = accepts(req) + + // the order of this list is significant; should be server preferred order + switch (accept.type(['json', 'html'])) { + case 'json': + res.setHeader('Content-Type', 'application/json') + res.write('{"hello":"world!"}') + break + case 'html': + res.setHeader('Content-Type', 'text/html') + res.write('hello, world!') + break + default: + // the fallback is text/plain, so no need to specify it above + res.setHeader('Content-Type', 'text/plain') + res.write('hello, world!') + break + } + + res.end() +} + +http.createServer(app).listen(3000) +``` + +You can test this out with the cURL program: +```sh +curl -I -H'Accept: text/html' http://localhost:3000/ +``` + +## License + +[MIT](LICENSE) + +[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/accepts/master +[coveralls-url]: https://coveralls.io/r/jshttp/accepts?branch=master +[github-actions-ci-image]: https://badgen.net/github/checks/jshttp/accepts/master?label=ci +[github-actions-ci-url]: https://github.com/jshttp/accepts/actions/workflows/ci.yml +[node-version-image]: https://badgen.net/npm/node/accepts +[node-version-url]: https://nodejs.org/en/download +[npm-downloads-image]: https://badgen.net/npm/dm/accepts +[npm-url]: https://npmjs.org/package/accepts +[npm-version-image]: https://badgen.net/npm/v/accepts diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/index.js new file mode 100644 index 000000000..4f2840c0b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/index.js @@ -0,0 +1,238 @@ +/*! + * accepts + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var Negotiator = require('negotiator') +var mime = require('mime-types') + +/** + * Module exports. + * @public + */ + +module.exports = Accepts + +/** + * Create a new Accepts object for the given req. + * + * @param {object} req + * @public + */ + +function Accepts (req) { + if (!(this instanceof Accepts)) { + return new Accepts(req) + } + + this.headers = req.headers + this.negotiator = new Negotiator(req) +} + +/** + * Check if the given `type(s)` is acceptable, returning + * the best match when true, otherwise `undefined`, in which + * case you should respond with 406 "Not Acceptable". + * + * The `type` value may be a single mime type string + * such as "application/json", the extension name + * such as "json" or an array `["json", "html", "text/plain"]`. When a list + * or array is given the _best_ match, if any is returned. + * + * Examples: + * + * // Accept: text/html + * this.types('html'); + * // => "html" + * + * // Accept: text/*, application/json + * this.types('html'); + * // => "html" + * this.types('text/html'); + * // => "text/html" + * this.types('json', 'text'); + * // => "json" + * this.types('application/json'); + * // => "application/json" + * + * // Accept: text/*, application/json + * this.types('image/png'); + * this.types('png'); + * // => undefined + * + * // Accept: text/*;q=.5, application/json + * this.types(['html', 'json']); + * this.types('html', 'json'); + * // => "json" + * + * @param {String|Array} types... + * @return {String|Array|Boolean} + * @public + */ + +Accepts.prototype.type = +Accepts.prototype.types = function (types_) { + var types = types_ + + // support flattened arguments + if (types && !Array.isArray(types)) { + types = new Array(arguments.length) + for (var i = 0; i < types.length; i++) { + types[i] = arguments[i] + } + } + + // no types, return all requested types + if (!types || types.length === 0) { + return this.negotiator.mediaTypes() + } + + // no accept header, return first given type + if (!this.headers.accept) { + return types[0] + } + + var mimes = types.map(extToMime) + var accepts = this.negotiator.mediaTypes(mimes.filter(validMime)) + var first = accepts[0] + + return first + ? types[mimes.indexOf(first)] + : false +} + +/** + * Return accepted encodings or best fit based on `encodings`. + * + * Given `Accept-Encoding: gzip, deflate` + * an array sorted by quality is returned: + * + * ['gzip', 'deflate'] + * + * @param {String|Array} encodings... + * @return {String|Array} + * @public + */ + +Accepts.prototype.encoding = +Accepts.prototype.encodings = function (encodings_) { + var encodings = encodings_ + + // support flattened arguments + if (encodings && !Array.isArray(encodings)) { + encodings = new Array(arguments.length) + for (var i = 0; i < encodings.length; i++) { + encodings[i] = arguments[i] + } + } + + // no encodings, return all requested encodings + if (!encodings || encodings.length === 0) { + return this.negotiator.encodings() + } + + return this.negotiator.encodings(encodings)[0] || false +} + +/** + * Return accepted charsets or best fit based on `charsets`. + * + * Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5` + * an array sorted by quality is returned: + * + * ['utf-8', 'utf-7', 'iso-8859-1'] + * + * @param {String|Array} charsets... + * @return {String|Array} + * @public + */ + +Accepts.prototype.charset = +Accepts.prototype.charsets = function (charsets_) { + var charsets = charsets_ + + // support flattened arguments + if (charsets && !Array.isArray(charsets)) { + charsets = new Array(arguments.length) + for (var i = 0; i < charsets.length; i++) { + charsets[i] = arguments[i] + } + } + + // no charsets, return all requested charsets + if (!charsets || charsets.length === 0) { + return this.negotiator.charsets() + } + + return this.negotiator.charsets(charsets)[0] || false +} + +/** + * Return accepted languages or best fit based on `langs`. + * + * Given `Accept-Language: en;q=0.8, es, pt` + * an array sorted by quality is returned: + * + * ['es', 'pt', 'en'] + * + * @param {String|Array} langs... + * @return {Array|String} + * @public + */ + +Accepts.prototype.lang = +Accepts.prototype.langs = +Accepts.prototype.language = +Accepts.prototype.languages = function (languages_) { + var languages = languages_ + + // support flattened arguments + if (languages && !Array.isArray(languages)) { + languages = new Array(arguments.length) + for (var i = 0; i < languages.length; i++) { + languages[i] = arguments[i] + } + } + + // no languages, return all requested languages + if (!languages || languages.length === 0) { + return this.negotiator.languages() + } + + return this.negotiator.languages(languages)[0] || false +} + +/** + * Convert extnames to mime. + * + * @param {String} type + * @return {String} + * @private + */ + +function extToMime (type) { + return type.indexOf('/') === -1 + ? mime.lookup(type) + : type +} + +/** + * Check if mime is valid. + * + * @param {String} type + * @return {Boolean} + * @private + */ + +function validMime (type) { + return typeof type === 'string' +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/package.json new file mode 100644 index 000000000..b35b262db --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/accepts/package.json @@ -0,0 +1,47 @@ +{ + "name": "accepts", + "description": "Higher-level content negotiation", + "version": "2.0.0", + "contributors": [ + "Douglas Christopher Wilson ", + "Jonathan Ong (http://jongleberry.com)" + ], + "license": "MIT", + "repository": "jshttp/accepts", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "devDependencies": { + "deep-equal": "1.0.1", + "eslint": "7.32.0", + "eslint-config-standard": "14.1.1", + "eslint-plugin-import": "2.25.4", + "eslint-plugin-markdown": "2.2.1", + "eslint-plugin-node": "11.1.0", + "eslint-plugin-promise": "4.3.1", + "eslint-plugin-standard": "4.1.0", + "mocha": "9.2.0", + "nyc": "15.1.0" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "index.js" + ], + "engines": { + "node": ">= 0.6" + }, + "scripts": { + "lint": "eslint .", + "test": "mocha --reporter spec --check-leaks --bail test/", + "test-ci": "nyc --reporter=lcov --reporter=text npm test", + "test-cov": "nyc --reporter=html --reporter=text npm test" + }, + "keywords": [ + "content", + "negotiation", + "accept", + "accepts" + ] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/README.md new file mode 100644 index 000000000..256f1f321 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/README.md @@ -0,0 +1,145 @@ +agent-base +========== +### Turn a function into an [`http.Agent`][http.Agent] instance +[![Build Status](https://github.com/TooTallNate/node-agent-base/workflows/Node%20CI/badge.svg)](https://github.com/TooTallNate/node-agent-base/actions?workflow=Node+CI) + +This module provides an `http.Agent` generator. That is, you pass it an async +callback function, and it returns a new `http.Agent` instance that will invoke the +given callback function when sending outbound HTTP requests. + +#### Some subclasses: + +Here's some more interesting uses of `agent-base`. +Send a pull request to list yours! + + * [`http-proxy-agent`][http-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTP endpoints + * [`https-proxy-agent`][https-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTPS endpoints + * [`pac-proxy-agent`][pac-proxy-agent]: A PAC file proxy `http.Agent` implementation for HTTP and HTTPS + * [`socks-proxy-agent`][socks-proxy-agent]: A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS + + +Installation +------------ + +Install with `npm`: + +``` bash +$ npm install agent-base +``` + + +Example +------- + +Here's a minimal example that creates a new `net.Socket` connection to the server +for every HTTP request (i.e. the equivalent of `agent: false` option): + +```js +var net = require('net'); +var tls = require('tls'); +var url = require('url'); +var http = require('http'); +var agent = require('agent-base'); + +var endpoint = 'http://nodejs.org/api/'; +var parsed = url.parse(endpoint); + +// This is the important part! +parsed.agent = agent(function (req, opts) { + var socket; + // `secureEndpoint` is true when using the https module + if (opts.secureEndpoint) { + socket = tls.connect(opts); + } else { + socket = net.connect(opts); + } + return socket; +}); + +// Everything else works just like normal... +http.get(parsed, function (res) { + console.log('"response" event!', res.headers); + res.pipe(process.stdout); +}); +``` + +Returning a Promise or using an `async` function is also supported: + +```js +agent(async function (req, opts) { + await sleep(1000); + // etc… +}); +``` + +Return another `http.Agent` instance to "pass through" the responsibility +for that HTTP request to that agent: + +```js +agent(function (req, opts) { + return opts.secureEndpoint ? https.globalAgent : http.globalAgent; +}); +``` + + +API +--- + +## Agent(Function callback[, Object options]) → [http.Agent][] + +Creates a base `http.Agent` that will execute the callback function `callback` +for every HTTP request that it is used as the `agent` for. The callback function +is responsible for creating a `stream.Duplex` instance of some kind that will be +used as the underlying socket in the HTTP request. + +The `options` object accepts the following properties: + + * `timeout` - Number - Timeout for the `callback()` function in milliseconds. Defaults to Infinity (optional). + +The callback function should have the following signature: + +### callback(http.ClientRequest req, Object options, Function cb) → undefined + +The ClientRequest `req` can be accessed to read request headers and +and the path, etc. The `options` object contains the options passed +to the `http.request()`/`https.request()` function call, and is formatted +to be directly passed to `net.connect()`/`tls.connect()`, or however +else you want a Socket to be created. Pass the created socket to +the callback function `cb` once created, and the HTTP request will +continue to proceed. + +If the `https` module is used to invoke the HTTP request, then the +`secureEndpoint` property on `options` _will be set to `true`_. + + +License +------- + +(The MIT License) + +Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> + +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. + +[http-proxy-agent]: https://github.com/TooTallNate/node-http-proxy-agent +[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent +[pac-proxy-agent]: https://github.com/TooTallNate/node-pac-proxy-agent +[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent +[http.Agent]: https://nodejs.org/api/http.html#http_class_http_agent diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/index.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/index.d.ts new file mode 100644 index 000000000..bc4ab744c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/index.d.ts @@ -0,0 +1,78 @@ +/// +import net from 'net'; +import http from 'http'; +import https from 'https'; +import { Duplex } from 'stream'; +import { EventEmitter } from 'events'; +declare function createAgent(opts?: createAgent.AgentOptions): createAgent.Agent; +declare function createAgent(callback: createAgent.AgentCallback, opts?: createAgent.AgentOptions): createAgent.Agent; +declare namespace createAgent { + interface ClientRequest extends http.ClientRequest { + _last?: boolean; + _hadError?: boolean; + method: string; + } + interface AgentRequestOptions { + host?: string; + path?: string; + port: number; + } + interface HttpRequestOptions extends AgentRequestOptions, Omit { + secureEndpoint: false; + } + interface HttpsRequestOptions extends AgentRequestOptions, Omit { + secureEndpoint: true; + } + type RequestOptions = HttpRequestOptions | HttpsRequestOptions; + type AgentLike = Pick | http.Agent; + type AgentCallbackReturn = Duplex | AgentLike; + type AgentCallbackCallback = (err?: Error | null, socket?: createAgent.AgentCallbackReturn) => void; + type AgentCallbackPromise = (req: createAgent.ClientRequest, opts: createAgent.RequestOptions) => createAgent.AgentCallbackReturn | Promise; + type AgentCallback = typeof Agent.prototype.callback; + type AgentOptions = { + timeout?: number; + }; + /** + * Base `http.Agent` implementation. + * No pooling/keep-alive is implemented by default. + * + * @param {Function} callback + * @api public + */ + class Agent extends EventEmitter { + timeout: number | null; + maxFreeSockets: number; + maxTotalSockets: number; + maxSockets: number; + sockets: { + [key: string]: net.Socket[]; + }; + freeSockets: { + [key: string]: net.Socket[]; + }; + requests: { + [key: string]: http.IncomingMessage[]; + }; + options: https.AgentOptions; + private promisifiedCallback?; + private explicitDefaultPort?; + private explicitProtocol?; + constructor(callback?: createAgent.AgentCallback | createAgent.AgentOptions, _opts?: createAgent.AgentOptions); + get defaultPort(): number; + set defaultPort(v: number); + get protocol(): string; + set protocol(v: string); + callback(req: createAgent.ClientRequest, opts: createAgent.RequestOptions, fn: createAgent.AgentCallbackCallback): void; + callback(req: createAgent.ClientRequest, opts: createAgent.RequestOptions): createAgent.AgentCallbackReturn | Promise; + /** + * Called by node-core's "_http_client.js" module when creating + * a new HTTP request with this Agent instance. + * + * @api public + */ + addRequest(req: ClientRequest, _opts: RequestOptions): void; + freeSocket(socket: net.Socket, opts: AgentOptions): void; + destroy(): void; + } +} +export = createAgent; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/index.js new file mode 100644 index 000000000..bfd9e2207 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/index.js @@ -0,0 +1,203 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const events_1 = require("events"); +const debug_1 = __importDefault(require("debug")); +const promisify_1 = __importDefault(require("./promisify")); +const debug = debug_1.default('agent-base'); +function isAgent(v) { + return Boolean(v) && typeof v.addRequest === 'function'; +} +function isSecureEndpoint() { + const { stack } = new Error(); + if (typeof stack !== 'string') + return false; + return stack.split('\n').some(l => l.indexOf('(https.js:') !== -1 || l.indexOf('node:https:') !== -1); +} +function createAgent(callback, opts) { + return new createAgent.Agent(callback, opts); +} +(function (createAgent) { + /** + * Base `http.Agent` implementation. + * No pooling/keep-alive is implemented by default. + * + * @param {Function} callback + * @api public + */ + class Agent extends events_1.EventEmitter { + constructor(callback, _opts) { + super(); + let opts = _opts; + if (typeof callback === 'function') { + this.callback = callback; + } + else if (callback) { + opts = callback; + } + // Timeout for the socket to be returned from the callback + this.timeout = null; + if (opts && typeof opts.timeout === 'number') { + this.timeout = opts.timeout; + } + // These aren't actually used by `agent-base`, but are required + // for the TypeScript definition files in `@types/node` :/ + this.maxFreeSockets = 1; + this.maxSockets = 1; + this.maxTotalSockets = Infinity; + this.sockets = {}; + this.freeSockets = {}; + this.requests = {}; + this.options = {}; + } + get defaultPort() { + if (typeof this.explicitDefaultPort === 'number') { + return this.explicitDefaultPort; + } + return isSecureEndpoint() ? 443 : 80; + } + set defaultPort(v) { + this.explicitDefaultPort = v; + } + get protocol() { + if (typeof this.explicitProtocol === 'string') { + return this.explicitProtocol; + } + return isSecureEndpoint() ? 'https:' : 'http:'; + } + set protocol(v) { + this.explicitProtocol = v; + } + callback(req, opts, fn) { + throw new Error('"agent-base" has no default implementation, you must subclass and override `callback()`'); + } + /** + * Called by node-core's "_http_client.js" module when creating + * a new HTTP request with this Agent instance. + * + * @api public + */ + addRequest(req, _opts) { + const opts = Object.assign({}, _opts); + if (typeof opts.secureEndpoint !== 'boolean') { + opts.secureEndpoint = isSecureEndpoint(); + } + if (opts.host == null) { + opts.host = 'localhost'; + } + if (opts.port == null) { + opts.port = opts.secureEndpoint ? 443 : 80; + } + if (opts.protocol == null) { + opts.protocol = opts.secureEndpoint ? 'https:' : 'http:'; + } + if (opts.host && opts.path) { + // If both a `host` and `path` are specified then it's most + // likely the result of a `url.parse()` call... we need to + // remove the `path` portion so that `net.connect()` doesn't + // attempt to open that as a unix socket file. + delete opts.path; + } + delete opts.agent; + delete opts.hostname; + delete opts._defaultAgent; + delete opts.defaultPort; + delete opts.createConnection; + // Hint to use "Connection: close" + // XXX: non-documented `http` module API :( + req._last = true; + req.shouldKeepAlive = false; + let timedOut = false; + let timeoutId = null; + const timeoutMs = opts.timeout || this.timeout; + const onerror = (err) => { + if (req._hadError) + return; + req.emit('error', err); + // For Safety. Some additional errors might fire later on + // and we need to make sure we don't double-fire the error event. + req._hadError = true; + }; + const ontimeout = () => { + timeoutId = null; + timedOut = true; + const err = new Error(`A "socket" was not created for HTTP request before ${timeoutMs}ms`); + err.code = 'ETIMEOUT'; + onerror(err); + }; + const callbackError = (err) => { + if (timedOut) + return; + if (timeoutId !== null) { + clearTimeout(timeoutId); + timeoutId = null; + } + onerror(err); + }; + const onsocket = (socket) => { + if (timedOut) + return; + if (timeoutId != null) { + clearTimeout(timeoutId); + timeoutId = null; + } + if (isAgent(socket)) { + // `socket` is actually an `http.Agent` instance, so + // relinquish responsibility for this `req` to the Agent + // from here on + debug('Callback returned another Agent instance %o', socket.constructor.name); + socket.addRequest(req, opts); + return; + } + if (socket) { + socket.once('free', () => { + this.freeSocket(socket, opts); + }); + req.onSocket(socket); + return; + } + const err = new Error(`no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\``); + onerror(err); + }; + if (typeof this.callback !== 'function') { + onerror(new Error('`callback` is not defined')); + return; + } + if (!this.promisifiedCallback) { + if (this.callback.length >= 3) { + debug('Converting legacy callback function to promise'); + this.promisifiedCallback = promisify_1.default(this.callback); + } + else { + this.promisifiedCallback = this.callback; + } + } + if (typeof timeoutMs === 'number' && timeoutMs > 0) { + timeoutId = setTimeout(ontimeout, timeoutMs); + } + if ('port' in opts && typeof opts.port !== 'number') { + opts.port = Number(opts.port); + } + try { + debug('Resolving socket for %o request: %o', opts.protocol, `${req.method} ${req.path}`); + Promise.resolve(this.promisifiedCallback(req, opts)).then(onsocket, callbackError); + } + catch (err) { + Promise.reject(err).catch(callbackError); + } + } + freeSocket(socket, opts) { + debug('Freeing socket %o %o', socket.constructor.name, opts); + socket.destroy(); + } + destroy() { + debug('Destroying agent %o', this.constructor.name); + } + } + createAgent.Agent = Agent; + // So that `instanceof` works correctly + createAgent.prototype = createAgent.Agent.prototype; +})(createAgent || (createAgent = {})); +module.exports = createAgent; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/index.js.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/index.js.map new file mode 100644 index 000000000..bd118ab6b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/promisify.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/promisify.d.ts new file mode 100644 index 000000000..02688696f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/promisify.d.ts @@ -0,0 +1,4 @@ +import { ClientRequest, RequestOptions, AgentCallbackCallback, AgentCallbackPromise } from './index'; +declare type LegacyCallback = (req: ClientRequest, opts: RequestOptions, fn: AgentCallbackCallback) => void; +export default function promisify(fn: LegacyCallback): AgentCallbackPromise; +export {}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/promisify.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/promisify.js new file mode 100644 index 000000000..b2f6132a7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/promisify.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function promisify(fn) { + return function (req, opts) { + return new Promise((resolve, reject) => { + fn.call(this, req, opts, (err, rtn) => { + if (err) { + reject(err); + } + else { + resolve(rtn); + } + }); + }); + }; +} +exports.default = promisify; +//# sourceMappingURL=promisify.js.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/promisify.js.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/promisify.js.map new file mode 100644 index 000000000..4bff9bfcf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/dist/src/promisify.js.map @@ -0,0 +1 @@ +{"version":3,"file":"promisify.js","sourceRoot":"","sources":["../../src/promisify.ts"],"names":[],"mappings":";;AAeA,SAAwB,SAAS,CAAC,EAAkB;IACnD,OAAO,UAAsB,GAAkB,EAAE,IAAoB;QACpE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACtC,EAAE,CAAC,IAAI,CACN,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,CAAC,GAA6B,EAAE,GAAyB,EAAE,EAAE;gBAC5D,IAAI,GAAG,EAAE;oBACR,MAAM,CAAC,GAAG,CAAC,CAAC;iBACZ;qBAAM;oBACN,OAAO,CAAC,GAAG,CAAC,CAAC;iBACb;YACF,CAAC,CACD,CAAC;QACH,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC;AAjBD,4BAiBC"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/package.json new file mode 100644 index 000000000..fadce3ad9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/package.json @@ -0,0 +1,64 @@ +{ + "name": "agent-base", + "version": "6.0.2", + "description": "Turn a function into an `http.Agent` instance", + "main": "dist/src/index", + "typings": "dist/src/index", + "files": [ + "dist/src", + "src" + ], + "scripts": { + "prebuild": "rimraf dist", + "build": "tsc", + "postbuild": "cpy --parents src test '!**/*.ts' dist", + "test": "mocha --reporter spec dist/test/*.js", + "test-lint": "eslint src --ext .js,.ts", + "prepublishOnly": "npm run build" + }, + "repository": { + "type": "git", + "url": "git://github.com/TooTallNate/node-agent-base.git" + }, + "keywords": [ + "http", + "agent", + "base", + "barebones", + "https" + ], + "author": "Nathan Rajlich (http://n8.io/)", + "license": "MIT", + "bugs": { + "url": "https://github.com/TooTallNate/node-agent-base/issues" + }, + "dependencies": { + "debug": "4" + }, + "devDependencies": { + "@types/debug": "4", + "@types/mocha": "^5.2.7", + "@types/node": "^14.0.20", + "@types/semver": "^7.1.0", + "@types/ws": "^6.0.3", + "@typescript-eslint/eslint-plugin": "1.6.0", + "@typescript-eslint/parser": "1.1.0", + "async-listen": "^1.2.0", + "cpy-cli": "^2.0.0", + "eslint": "5.16.0", + "eslint-config-airbnb": "17.1.0", + "eslint-config-prettier": "4.1.0", + "eslint-import-resolver-typescript": "1.1.1", + "eslint-plugin-import": "2.16.0", + "eslint-plugin-jsx-a11y": "6.2.1", + "eslint-plugin-react": "7.12.4", + "mocha": "^6.2.0", + "rimraf": "^3.0.0", + "semver": "^7.1.2", + "typescript": "^3.5.3", + "ws": "^3.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/src/index.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/src/index.ts new file mode 100644 index 000000000..a47ccd493 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/src/index.ts @@ -0,0 +1,345 @@ +import net from 'net'; +import http from 'http'; +import https from 'https'; +import { Duplex } from 'stream'; +import { EventEmitter } from 'events'; +import createDebug from 'debug'; +import promisify from './promisify'; + +const debug = createDebug('agent-base'); + +function isAgent(v: any): v is createAgent.AgentLike { + return Boolean(v) && typeof v.addRequest === 'function'; +} + +function isSecureEndpoint(): boolean { + const { stack } = new Error(); + if (typeof stack !== 'string') return false; + return stack.split('\n').some(l => l.indexOf('(https.js:') !== -1 || l.indexOf('node:https:') !== -1); +} + +function createAgent(opts?: createAgent.AgentOptions): createAgent.Agent; +function createAgent( + callback: createAgent.AgentCallback, + opts?: createAgent.AgentOptions +): createAgent.Agent; +function createAgent( + callback?: createAgent.AgentCallback | createAgent.AgentOptions, + opts?: createAgent.AgentOptions +) { + return new createAgent.Agent(callback, opts); +} + +namespace createAgent { + export interface ClientRequest extends http.ClientRequest { + _last?: boolean; + _hadError?: boolean; + method: string; + } + + export interface AgentRequestOptions { + host?: string; + path?: string; + // `port` on `http.RequestOptions` can be a string or undefined, + // but `net.TcpNetConnectOpts` expects only a number + port: number; + } + + export interface HttpRequestOptions + extends AgentRequestOptions, + Omit { + secureEndpoint: false; + } + + export interface HttpsRequestOptions + extends AgentRequestOptions, + Omit { + secureEndpoint: true; + } + + export type RequestOptions = HttpRequestOptions | HttpsRequestOptions; + + export type AgentLike = Pick | http.Agent; + + export type AgentCallbackReturn = Duplex | AgentLike; + + export type AgentCallbackCallback = ( + err?: Error | null, + socket?: createAgent.AgentCallbackReturn + ) => void; + + export type AgentCallbackPromise = ( + req: createAgent.ClientRequest, + opts: createAgent.RequestOptions + ) => + | createAgent.AgentCallbackReturn + | Promise; + + export type AgentCallback = typeof Agent.prototype.callback; + + export type AgentOptions = { + timeout?: number; + }; + + /** + * Base `http.Agent` implementation. + * No pooling/keep-alive is implemented by default. + * + * @param {Function} callback + * @api public + */ + export class Agent extends EventEmitter { + public timeout: number | null; + public maxFreeSockets: number; + public maxTotalSockets: number; + public maxSockets: number; + public sockets: { + [key: string]: net.Socket[]; + }; + public freeSockets: { + [key: string]: net.Socket[]; + }; + public requests: { + [key: string]: http.IncomingMessage[]; + }; + public options: https.AgentOptions; + private promisifiedCallback?: createAgent.AgentCallbackPromise; + private explicitDefaultPort?: number; + private explicitProtocol?: string; + + constructor( + callback?: createAgent.AgentCallback | createAgent.AgentOptions, + _opts?: createAgent.AgentOptions + ) { + super(); + + let opts = _opts; + if (typeof callback === 'function') { + this.callback = callback; + } else if (callback) { + opts = callback; + } + + // Timeout for the socket to be returned from the callback + this.timeout = null; + if (opts && typeof opts.timeout === 'number') { + this.timeout = opts.timeout; + } + + // These aren't actually used by `agent-base`, but are required + // for the TypeScript definition files in `@types/node` :/ + this.maxFreeSockets = 1; + this.maxSockets = 1; + this.maxTotalSockets = Infinity; + this.sockets = {}; + this.freeSockets = {}; + this.requests = {}; + this.options = {}; + } + + get defaultPort(): number { + if (typeof this.explicitDefaultPort === 'number') { + return this.explicitDefaultPort; + } + return isSecureEndpoint() ? 443 : 80; + } + + set defaultPort(v: number) { + this.explicitDefaultPort = v; + } + + get protocol(): string { + if (typeof this.explicitProtocol === 'string') { + return this.explicitProtocol; + } + return isSecureEndpoint() ? 'https:' : 'http:'; + } + + set protocol(v: string) { + this.explicitProtocol = v; + } + + callback( + req: createAgent.ClientRequest, + opts: createAgent.RequestOptions, + fn: createAgent.AgentCallbackCallback + ): void; + callback( + req: createAgent.ClientRequest, + opts: createAgent.RequestOptions + ): + | createAgent.AgentCallbackReturn + | Promise; + callback( + req: createAgent.ClientRequest, + opts: createAgent.AgentOptions, + fn?: createAgent.AgentCallbackCallback + ): + | createAgent.AgentCallbackReturn + | Promise + | void { + throw new Error( + '"agent-base" has no default implementation, you must subclass and override `callback()`' + ); + } + + /** + * Called by node-core's "_http_client.js" module when creating + * a new HTTP request with this Agent instance. + * + * @api public + */ + addRequest(req: ClientRequest, _opts: RequestOptions): void { + const opts: RequestOptions = { ..._opts }; + + if (typeof opts.secureEndpoint !== 'boolean') { + opts.secureEndpoint = isSecureEndpoint(); + } + + if (opts.host == null) { + opts.host = 'localhost'; + } + + if (opts.port == null) { + opts.port = opts.secureEndpoint ? 443 : 80; + } + + if (opts.protocol == null) { + opts.protocol = opts.secureEndpoint ? 'https:' : 'http:'; + } + + if (opts.host && opts.path) { + // If both a `host` and `path` are specified then it's most + // likely the result of a `url.parse()` call... we need to + // remove the `path` portion so that `net.connect()` doesn't + // attempt to open that as a unix socket file. + delete opts.path; + } + + delete opts.agent; + delete opts.hostname; + delete opts._defaultAgent; + delete opts.defaultPort; + delete opts.createConnection; + + // Hint to use "Connection: close" + // XXX: non-documented `http` module API :( + req._last = true; + req.shouldKeepAlive = false; + + let timedOut = false; + let timeoutId: ReturnType | null = null; + const timeoutMs = opts.timeout || this.timeout; + + const onerror = (err: NodeJS.ErrnoException) => { + if (req._hadError) return; + req.emit('error', err); + // For Safety. Some additional errors might fire later on + // and we need to make sure we don't double-fire the error event. + req._hadError = true; + }; + + const ontimeout = () => { + timeoutId = null; + timedOut = true; + const err: NodeJS.ErrnoException = new Error( + `A "socket" was not created for HTTP request before ${timeoutMs}ms` + ); + err.code = 'ETIMEOUT'; + onerror(err); + }; + + const callbackError = (err: NodeJS.ErrnoException) => { + if (timedOut) return; + if (timeoutId !== null) { + clearTimeout(timeoutId); + timeoutId = null; + } + onerror(err); + }; + + const onsocket = (socket: AgentCallbackReturn) => { + if (timedOut) return; + if (timeoutId != null) { + clearTimeout(timeoutId); + timeoutId = null; + } + + if (isAgent(socket)) { + // `socket` is actually an `http.Agent` instance, so + // relinquish responsibility for this `req` to the Agent + // from here on + debug( + 'Callback returned another Agent instance %o', + socket.constructor.name + ); + (socket as createAgent.Agent).addRequest(req, opts); + return; + } + + if (socket) { + socket.once('free', () => { + this.freeSocket(socket as net.Socket, opts); + }); + req.onSocket(socket as net.Socket); + return; + } + + const err = new Error( + `no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\`` + ); + onerror(err); + }; + + if (typeof this.callback !== 'function') { + onerror(new Error('`callback` is not defined')); + return; + } + + if (!this.promisifiedCallback) { + if (this.callback.length >= 3) { + debug('Converting legacy callback function to promise'); + this.promisifiedCallback = promisify(this.callback); + } else { + this.promisifiedCallback = this.callback; + } + } + + if (typeof timeoutMs === 'number' && timeoutMs > 0) { + timeoutId = setTimeout(ontimeout, timeoutMs); + } + + if ('port' in opts && typeof opts.port !== 'number') { + opts.port = Number(opts.port); + } + + try { + debug( + 'Resolving socket for %o request: %o', + opts.protocol, + `${req.method} ${req.path}` + ); + Promise.resolve(this.promisifiedCallback(req, opts)).then( + onsocket, + callbackError + ); + } catch (err) { + Promise.reject(err).catch(callbackError); + } + } + + freeSocket(socket: net.Socket, opts: AgentOptions) { + debug('Freeing socket %o %o', socket.constructor.name, opts); + socket.destroy(); + } + + destroy() { + debug('Destroying agent %o', this.constructor.name); + } + } + + // So that `instanceof` works correctly + createAgent.prototype = createAgent.Agent.prototype; +} + +export = createAgent; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/src/promisify.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/src/promisify.ts new file mode 100644 index 000000000..60cc66271 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agent-base/src/promisify.ts @@ -0,0 +1,33 @@ +import { + Agent, + ClientRequest, + RequestOptions, + AgentCallbackCallback, + AgentCallbackPromise, + AgentCallbackReturn +} from './index'; + +type LegacyCallback = ( + req: ClientRequest, + opts: RequestOptions, + fn: AgentCallbackCallback +) => void; + +export default function promisify(fn: LegacyCallback): AgentCallbackPromise { + return function(this: Agent, req: ClientRequest, opts: RequestOptions) { + return new Promise((resolve, reject) => { + fn.call( + this, + req, + opts, + (err: Error | null | undefined, rtn?: AgentCallbackReturn) => { + if (err) { + reject(err); + } else { + resolve(rtn); + } + } + ); + }); + }; +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/LICENSE new file mode 100644 index 000000000..941258ca7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/LICENSE @@ -0,0 +1,23 @@ +The MIT License + +Copyright(c) node-modules and other contributors. +Copyright(c) 2012 - 2015 fengmk2 + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/README.md new file mode 100644 index 000000000..6a7ee5a74 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/README.md @@ -0,0 +1,256 @@ +# agentkeepalive + +[![NPM version][npm-image]][npm-url] +[![Known Vulnerabilities][snyk-image]][snyk-url] +[![Node.js CI](https://github.com/node-modules/agentkeepalive/actions/workflows/nodejs.yml/badge.svg)](https://github.com/node-modules/agentkeepalive/actions/workflows/nodejs.yml) +[![npm download][download-image]][download-url] + +[npm-image]: https://img.shields.io/npm/v/agentkeepalive.svg?style=flat +[npm-url]: https://npmjs.org/package/agentkeepalive +[snyk-image]: https://snyk.io/test/npm/agentkeepalive/badge.svg?style=flat-square +[snyk-url]: https://snyk.io/test/npm/agentkeepalive +[download-image]: https://img.shields.io/npm/dm/agentkeepalive.svg?style=flat-square +[download-url]: https://npmjs.org/package/agentkeepalive + +The enhancement features `keep alive` `http.Agent`. Support `http` and `https`. + +## What's different from original `http.Agent`? + +- `keepAlive=true` by default +- Disable Nagle's algorithm: `socket.setNoDelay(true)` +- Add free socket timeout: avoid long time inactivity socket leak in the free-sockets queue. +- Add active socket timeout: avoid long time inactivity socket leak in the active-sockets queue. +- TTL for active socket. + +## Node.js version required + +Support Node.js >= `8.0.0` + +## Install + +```bash +$ npm install agentkeepalive --save +``` + +## new Agent([options]) + +* `options` {Object} Set of configurable options to set on the agent. + Can have the following fields: + * `keepAlive` {Boolean} Keep sockets around in a pool to be used by + other requests in the future. Default = `true`. + * `keepAliveMsecs` {Number} When using the keepAlive option, specifies the initial delay + for TCP Keep-Alive packets. Ignored when the keepAlive option is false or undefined. Defaults to 1000. + Default = `1000`. Only relevant if `keepAlive` is set to `true`. + * `freeSocketTimeout`: {Number} Sets the free socket to timeout + after `freeSocketTimeout` milliseconds of inactivity on the free socket. + The default [server-side timeout](https://nodejs.org/api/http.html#serverkeepalivetimeout) is 5000 milliseconds, to [avoid ECONNRESET exceptions](https://medium.com/ssense-tech/reduce-networking-errors-in-nodejs-23b4eb9f2d83), we set the default value to `4000` milliseconds. + Only relevant if `keepAlive` is set to `true`. + * `timeout`: {Number} Sets the working socket to timeout + after `timeout` milliseconds of inactivity on the working socket. + Default is `freeSocketTimeout * 2` so long as that value is greater than or equal to 8 seconds, otherwise the default is 8 seconds. + * `maxSockets` {Number} Maximum number of sockets to allow per + host. Default = `Infinity`. + * `maxFreeSockets` {Number} Maximum number of sockets (per host) to leave open + in a free state. Only relevant if `keepAlive` is set to `true`. + Default = `256`. + * `socketActiveTTL` {Number} Sets the socket active time to live, even if it's in use. + If not set, the behaviour keeps the same (the socket will be released only when free) + Default = `null`. + +## Usage + +```js +const http = require('http'); +const HttpAgent = require('agentkeepalive').HttpAgent; + +const keepaliveAgent = new HttpAgent({ + maxSockets: 100, + maxFreeSockets: 10, + timeout: 60000, // active socket keepalive for 60 seconds + freeSocketTimeout: 30000, // free socket keepalive for 30 seconds +}); + +const options = { + host: 'cnodejs.org', + port: 80, + path: '/', + method: 'GET', + agent: keepaliveAgent, +}; + +const req = http.request(options, res => { + console.log('STATUS: ' + res.statusCode); + console.log('HEADERS: ' + JSON.stringify(res.headers)); + res.setEncoding('utf8'); + res.on('data', function (chunk) { + console.log('BODY: ' + chunk); + }); +}); +req.on('error', e => { + console.log('problem with request: ' + e.message); +}); +req.end(); + +setTimeout(() => { + if (keepaliveAgent.statusChanged) { + console.log('[%s] agent status changed: %j', Date(), keepaliveAgent.getCurrentStatus()); + } +}, 2000); + +``` + +### `getter agent.statusChanged` + +counters have change or not after last checkpoint. + +### `agent.getCurrentStatus()` + +`agent.getCurrentStatus()` will return a object to show the status of this agent: + +```js +{ + createSocketCount: 10, + closeSocketCount: 5, + timeoutSocketCount: 0, + requestCount: 5, + freeSockets: { 'localhost:57479:': 3 }, + sockets: { 'localhost:57479:': 5 }, + requests: {} +} +``` + +### Support `https` + +```js +const https = require('https'); +const HttpsAgent = require('agentkeepalive').HttpsAgent; + +const keepaliveAgent = new HttpsAgent(); +// https://www.google.com/search?q=nodejs&sugexp=chrome,mod=12&sourceid=chrome&ie=UTF-8 +const options = { + host: 'www.google.com', + port: 443, + path: '/search?q=nodejs&sugexp=chrome,mod=12&sourceid=chrome&ie=UTF-8', + method: 'GET', + agent: keepaliveAgent, +}; + +const req = https.request(options, res => { + console.log('STATUS: ' + res.statusCode); + console.log('HEADERS: ' + JSON.stringify(res.headers)); + res.setEncoding('utf8'); + res.on('data', chunk => { + console.log('BODY: ' + chunk); + }); +}); + +req.on('error', e => { + console.log('problem with request: ' + e.message); +}); +req.end(); + +setTimeout(() => { + console.log('agent status: %j', keepaliveAgent.getCurrentStatus()); +}, 2000); +``` + +### Support `req.reusedSocket` + +This agent implements the `req.reusedSocket` to determine whether a request is send through a reused socket. + +When server closes connection at unfortunate time ([keep-alive race](https://code-examples.net/en/q/28a8069)), the http client will throw a `ECONNRESET` error. Under this circumstance, `req.reusedSocket` is useful when we want to retry the request automatically. + +```js +const http = require('http'); +const HttpAgent = require('agentkeepalive').HttpAgent; +const agent = new HttpAgent(); + +const req = http + .get('http://localhost:3000', { agent }, (res) => { + // ... + }) + .on('error', (err) => { + if (req.reusedSocket && err.code === 'ECONNRESET') { + // retry the request or anything else... + } + }) +``` + +This behavior is consistent with Node.js core. But through `agentkeepalive`, you can use this feature in older Node.js version. + +## [Benchmark](https://github.com/node-modules/agentkeepalive/tree/master/benchmark) + +run the benchmark: + +```bash +cd benchmark +sh start.sh +``` + +Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz + +node@v0.8.9 + +50 maxSockets, 60 concurrent, 1000 requests per concurrent, 5ms delay + +Keep alive agent (30 seconds): + +```js +Transactions: 60000 hits +Availability: 100.00 % +Elapsed time: 29.70 secs +Data transferred: 14.88 MB +Response time: 0.03 secs +Transaction rate: 2020.20 trans/sec +Throughput: 0.50 MB/sec +Concurrency: 59.84 +Successful transactions: 60000 +Failed transactions: 0 +Longest transaction: 0.15 +Shortest transaction: 0.01 +``` + +Normal agent: + +```js +Transactions: 60000 hits +Availability: 100.00 % +Elapsed time: 46.53 secs +Data transferred: 14.88 MB +Response time: 0.05 secs +Transaction rate: 1289.49 trans/sec +Throughput: 0.32 MB/sec +Concurrency: 59.81 +Successful transactions: 60000 +Failed transactions: 0 +Longest transaction: 0.45 +Shortest transaction: 0.00 +``` + +Socket created: + +```bash +[proxy.js:120000] keepalive, 50 created, 60000 requestFinished, 1200 req/socket, 0 requests, 0 sockets, 0 unusedSockets, 50 timeout +{" <10ms":662," <15ms":17825," <20ms":20552," <30ms":17646," <40ms":2315," <50ms":567," <100ms":377," <150ms":56," <200ms":0," >=200ms+":0} +---------------------------------------------------------------- +[proxy.js:120000] normal , 53866 created, 84260 requestFinished, 1.56 req/socket, 0 requests, 0 sockets +{" <10ms":75," <15ms":1112," <20ms":10947," <30ms":32130," <40ms":8228," <50ms":3002," <100ms":4274," <150ms":181," <200ms":18," >=200ms+":33} +``` + +## License + +[MIT](LICENSE) + + + +## Contributors + +|[
    fengmk2](https://github.com/fengmk2)
    |[
    dead-horse](https://github.com/dead-horse)
    |[
    AndrewLeedham](https://github.com/AndrewLeedham)
    |[
    ngot](https://github.com/ngot)
    |[
    wrynearson](https://github.com/wrynearson)
    |[
    aaronArinder](https://github.com/aaronArinder)
    | +| :---: | :---: | :---: | :---: | :---: | :---: | +|[
    alexpenev-s](https://github.com/alexpenev-s)
    |[
    blemoine](https://github.com/blemoine)
    |[
    bdehamer](https://github.com/bdehamer)
    |[
    DylanPiercey](https://github.com/DylanPiercey)
    |[
    cixel](https://github.com/cixel)
    |[
    HerringtonDarkholme](https://github.com/HerringtonDarkholme)
    | +|[
    denghongcai](https://github.com/denghongcai)
    |[
    kibertoad](https://github.com/kibertoad)
    |[
    pangorgo](https://github.com/pangorgo)
    |[
    mattiash](https://github.com/mattiash)
    |[
    nabeelbukhari](https://github.com/nabeelbukhari)
    |[
    pmalouin](https://github.com/pmalouin)
    | +[
    SimenB](https://github.com/SimenB)
    |[
    vinaybedre](https://github.com/vinaybedre)
    |[
    starkwang](https://github.com/starkwang)
    |[
    killagu](https://github.com/killagu)
    |[
    tony-gutierrez](https://github.com/tony-gutierrez)
    |[
    whxaxes](https://github.com/whxaxes)
    + +This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Sat Aug 05 2023 02:36:31 GMT+0800`. + + diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/browser.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/browser.js new file mode 100644 index 000000000..29c9398aa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/browser.js @@ -0,0 +1,5 @@ +module.exports = noop; +module.exports.HttpsAgent = noop; + +// Noop function for browser since native api's don't use agents. +function noop () {} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/index.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/index.d.ts new file mode 100644 index 000000000..f4dbcec35 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/index.d.ts @@ -0,0 +1,69 @@ +import * as http from 'http'; +import * as https from 'https'; +import * as net from 'net'; + +interface PlainObject { + [key: string]: any; +} + +declare class _HttpAgent extends http.Agent { + constructor(opts?: AgentKeepAlive.HttpOptions); + readonly statusChanged: boolean; + createConnection(options: net.NetConnectOpts, cb?: Function): net.Socket; + createSocket(req: http.IncomingMessage, options: http.RequestOptions, cb: Function): void; + getCurrentStatus(): AgentKeepAlive.AgentStatus; +} + +interface Constants { + CURRENT_ID: Symbol; + CREATE_ID: Symbol; + INIT_SOCKET: Symbol; + CREATE_HTTPS_CONNECTION: Symbol; + SOCKET_CREATED_TIME: Symbol; + SOCKET_NAME: Symbol; + SOCKET_REQUEST_COUNT: Symbol; + SOCKET_REQUEST_FINISHED_COUNT: Symbol; +} + +/** + * @deprecated instead use `import { HttpAgent } from 'agentkeepalive'; or `const HttpAgent = require('agentkeepalive').HttpAgent;` + */ +declare class AgentKeepAlive extends _HttpAgent {} + +declare namespace AgentKeepAlive { + export interface AgentStatus { + createSocketCount: number; + createSocketErrorCount: number; + closeSocketCount: number; + errorSocketCount: number; + timeoutSocketCount: number; + requestCount: number; + freeSockets: PlainObject; + sockets: PlainObject; + requests: PlainObject; + } + + interface CommonHttpOption { + keepAlive?: boolean | undefined; + freeSocketTimeout?: number | undefined; + freeSocketKeepAliveTimeout?: number | undefined; + timeout?: number | undefined; + socketActiveTTL?: number | undefined; + } + + export interface HttpOptions extends http.AgentOptions, CommonHttpOption { } + export interface HttpsOptions extends https.AgentOptions, CommonHttpOption { } + + export class HttpAgent extends _HttpAgent {} + export class HttpsAgent extends https.Agent { + constructor(opts?: HttpsOptions); + readonly statusChanged: boolean; + createConnection(options: net.NetConnectOpts, cb?: Function): net.Socket; + createSocket(req: http.IncomingMessage, options: http.RequestOptions, cb: Function): void; + getCurrentStatus(): AgentStatus; + } + + export const constants: Constants; +} + +export = AgentKeepAlive; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/index.js new file mode 100644 index 000000000..cfe41dce7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/index.js @@ -0,0 +1,7 @@ +'use strict'; + +const HttpAgent = require('./lib/agent'); +module.exports = HttpAgent; +module.exports.HttpAgent = HttpAgent; +module.exports.HttpsAgent = require('./lib/https_agent'); +module.exports.constants = require('./lib/constants'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/lib/agent.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/lib/agent.js new file mode 100644 index 000000000..8bd354eff --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/lib/agent.js @@ -0,0 +1,402 @@ +'use strict'; + +const OriginalAgent = require('http').Agent; +const ms = require('humanize-ms'); +const debug = require('util').debuglog('agentkeepalive'); +const { + INIT_SOCKET, + CURRENT_ID, + CREATE_ID, + SOCKET_CREATED_TIME, + SOCKET_NAME, + SOCKET_REQUEST_COUNT, + SOCKET_REQUEST_FINISHED_COUNT, +} = require('./constants'); + +// OriginalAgent come from +// - https://github.com/nodejs/node/blob/v8.12.0/lib/_http_agent.js +// - https://github.com/nodejs/node/blob/v10.12.0/lib/_http_agent.js + +// node <= 10 +let defaultTimeoutListenerCount = 1; +const majorVersion = parseInt(process.version.split('.', 1)[0].substring(1)); +if (majorVersion >= 11 && majorVersion <= 12) { + defaultTimeoutListenerCount = 2; +} else if (majorVersion >= 13) { + defaultTimeoutListenerCount = 3; +} + +function deprecate(message) { + console.log('[agentkeepalive:deprecated] %s', message); +} + +class Agent extends OriginalAgent { + constructor(options) { + options = options || {}; + options.keepAlive = options.keepAlive !== false; + // default is keep-alive and 4s free socket timeout + // see https://medium.com/ssense-tech/reduce-networking-errors-in-nodejs-23b4eb9f2d83 + if (options.freeSocketTimeout === undefined) { + options.freeSocketTimeout = 4000; + } + // Legacy API: keepAliveTimeout should be rename to `freeSocketTimeout` + if (options.keepAliveTimeout) { + deprecate('options.keepAliveTimeout is deprecated, please use options.freeSocketTimeout instead'); + options.freeSocketTimeout = options.keepAliveTimeout; + delete options.keepAliveTimeout; + } + // Legacy API: freeSocketKeepAliveTimeout should be rename to `freeSocketTimeout` + if (options.freeSocketKeepAliveTimeout) { + deprecate('options.freeSocketKeepAliveTimeout is deprecated, please use options.freeSocketTimeout instead'); + options.freeSocketTimeout = options.freeSocketKeepAliveTimeout; + delete options.freeSocketKeepAliveTimeout; + } + + // Sets the socket to timeout after timeout milliseconds of inactivity on the socket. + // By default is double free socket timeout. + if (options.timeout === undefined) { + // make sure socket default inactivity timeout >= 8s + options.timeout = Math.max(options.freeSocketTimeout * 2, 8000); + } + + // support humanize format + options.timeout = ms(options.timeout); + options.freeSocketTimeout = ms(options.freeSocketTimeout); + options.socketActiveTTL = options.socketActiveTTL ? ms(options.socketActiveTTL) : 0; + + super(options); + + this[CURRENT_ID] = 0; + + // create socket success counter + this.createSocketCount = 0; + this.createSocketCountLastCheck = 0; + + this.createSocketErrorCount = 0; + this.createSocketErrorCountLastCheck = 0; + + this.closeSocketCount = 0; + this.closeSocketCountLastCheck = 0; + + // socket error event count + this.errorSocketCount = 0; + this.errorSocketCountLastCheck = 0; + + // request finished counter + this.requestCount = 0; + this.requestCountLastCheck = 0; + + // including free socket timeout counter + this.timeoutSocketCount = 0; + this.timeoutSocketCountLastCheck = 0; + + this.on('free', socket => { + // https://github.com/nodejs/node/pull/32000 + // Node.js native agent will check socket timeout eqs agent.options.timeout. + // Use the ttl or freeSocketTimeout to overwrite. + const timeout = this.calcSocketTimeout(socket); + if (timeout > 0 && socket.timeout !== timeout) { + socket.setTimeout(timeout); + } + }); + } + + get freeSocketKeepAliveTimeout() { + deprecate('agent.freeSocketKeepAliveTimeout is deprecated, please use agent.options.freeSocketTimeout instead'); + return this.options.freeSocketTimeout; + } + + get timeout() { + deprecate('agent.timeout is deprecated, please use agent.options.timeout instead'); + return this.options.timeout; + } + + get socketActiveTTL() { + deprecate('agent.socketActiveTTL is deprecated, please use agent.options.socketActiveTTL instead'); + return this.options.socketActiveTTL; + } + + calcSocketTimeout(socket) { + /** + * return <= 0: should free socket + * return > 0: should update socket timeout + * return undefined: not find custom timeout + */ + let freeSocketTimeout = this.options.freeSocketTimeout; + const socketActiveTTL = this.options.socketActiveTTL; + if (socketActiveTTL) { + // check socketActiveTTL + const aliveTime = Date.now() - socket[SOCKET_CREATED_TIME]; + const diff = socketActiveTTL - aliveTime; + if (diff <= 0) { + return diff; + } + if (freeSocketTimeout && diff < freeSocketTimeout) { + freeSocketTimeout = diff; + } + } + // set freeSocketTimeout + if (freeSocketTimeout) { + // set free keepalive timer + // try to use socket custom freeSocketTimeout first, support headers['keep-alive'] + // https://github.com/node-modules/urllib/blob/b76053020923f4d99a1c93cf2e16e0c5ba10bacf/lib/urllib.js#L498 + const customFreeSocketTimeout = socket.freeSocketTimeout || socket.freeSocketKeepAliveTimeout; + return customFreeSocketTimeout || freeSocketTimeout; + } + } + + keepSocketAlive(socket) { + const result = super.keepSocketAlive(socket); + // should not keepAlive, do nothing + if (!result) return result; + + const customTimeout = this.calcSocketTimeout(socket); + if (typeof customTimeout === 'undefined') { + return true; + } + if (customTimeout <= 0) { + debug('%s(requests: %s, finished: %s) free but need to destroy by TTL, request count %s, diff is %s', + socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT], customTimeout); + return false; + } + if (socket.timeout !== customTimeout) { + socket.setTimeout(customTimeout); + } + return true; + } + + // only call on addRequest + reuseSocket(...args) { + // reuseSocket(socket, req) + super.reuseSocket(...args); + const socket = args[0]; + const req = args[1]; + req.reusedSocket = true; + const agentTimeout = this.options.timeout; + if (getSocketTimeout(socket) !== agentTimeout) { + // reset timeout before use + socket.setTimeout(agentTimeout); + debug('%s reset timeout to %sms', socket[SOCKET_NAME], agentTimeout); + } + socket[SOCKET_REQUEST_COUNT]++; + debug('%s(requests: %s, finished: %s) reuse on addRequest, timeout %sms', + socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT], + getSocketTimeout(socket)); + } + + [CREATE_ID]() { + const id = this[CURRENT_ID]++; + if (this[CURRENT_ID] === Number.MAX_SAFE_INTEGER) this[CURRENT_ID] = 0; + return id; + } + + [INIT_SOCKET](socket, options) { + // bugfix here. + // https on node 8, 10 won't set agent.options.timeout by default + // TODO: need to fix on node itself + if (options.timeout) { + const timeout = getSocketTimeout(socket); + if (!timeout) { + socket.setTimeout(options.timeout); + } + } + + if (this.options.keepAlive) { + // Disable Nagle's algorithm: http://blog.caustik.com/2012/04/08/scaling-node-js-to-100k-concurrent-connections/ + // https://fengmk2.com/benchmark/nagle-algorithm-delayed-ack-mock.html + socket.setNoDelay(true); + } + this.createSocketCount++; + if (this.options.socketActiveTTL) { + socket[SOCKET_CREATED_TIME] = Date.now(); + } + // don't show the hole '-----BEGIN CERTIFICATE----' key string + socket[SOCKET_NAME] = `sock[${this[CREATE_ID]()}#${options._agentKey}]`.split('-----BEGIN', 1)[0]; + socket[SOCKET_REQUEST_COUNT] = 1; + socket[SOCKET_REQUEST_FINISHED_COUNT] = 0; + installListeners(this, socket, options); + } + + createConnection(options, oncreate) { + let called = false; + const onNewCreate = (err, socket) => { + if (called) return; + called = true; + + if (err) { + this.createSocketErrorCount++; + return oncreate(err); + } + this[INIT_SOCKET](socket, options); + oncreate(err, socket); + }; + + const newSocket = super.createConnection(options, onNewCreate); + if (newSocket) onNewCreate(null, newSocket); + return newSocket; + } + + get statusChanged() { + const changed = this.createSocketCount !== this.createSocketCountLastCheck || + this.createSocketErrorCount !== this.createSocketErrorCountLastCheck || + this.closeSocketCount !== this.closeSocketCountLastCheck || + this.errorSocketCount !== this.errorSocketCountLastCheck || + this.timeoutSocketCount !== this.timeoutSocketCountLastCheck || + this.requestCount !== this.requestCountLastCheck; + if (changed) { + this.createSocketCountLastCheck = this.createSocketCount; + this.createSocketErrorCountLastCheck = this.createSocketErrorCount; + this.closeSocketCountLastCheck = this.closeSocketCount; + this.errorSocketCountLastCheck = this.errorSocketCount; + this.timeoutSocketCountLastCheck = this.timeoutSocketCount; + this.requestCountLastCheck = this.requestCount; + } + return changed; + } + + getCurrentStatus() { + return { + createSocketCount: this.createSocketCount, + createSocketErrorCount: this.createSocketErrorCount, + closeSocketCount: this.closeSocketCount, + errorSocketCount: this.errorSocketCount, + timeoutSocketCount: this.timeoutSocketCount, + requestCount: this.requestCount, + freeSockets: inspect(this.freeSockets), + sockets: inspect(this.sockets), + requests: inspect(this.requests), + }; + } +} + +// node 8 don't has timeout attribute on socket +// https://github.com/nodejs/node/pull/21204/files#diff-e6ef024c3775d787c38487a6309e491dR408 +function getSocketTimeout(socket) { + return socket.timeout || socket._idleTimeout; +} + +function installListeners(agent, socket, options) { + debug('%s create, timeout %sms', socket[SOCKET_NAME], getSocketTimeout(socket)); + + // listener socket events: close, timeout, error, free + function onFree() { + // create and socket.emit('free') logic + // https://github.com/nodejs/node/blob/master/lib/_http_agent.js#L311 + // no req on the socket, it should be the new socket + if (!socket._httpMessage && socket[SOCKET_REQUEST_COUNT] === 1) return; + + socket[SOCKET_REQUEST_FINISHED_COUNT]++; + agent.requestCount++; + debug('%s(requests: %s, finished: %s) free', + socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT]); + + // should reuse on pedding requests? + const name = agent.getName(options); + if (socket.writable && agent.requests[name] && agent.requests[name].length) { + // will be reuse on agent free listener + socket[SOCKET_REQUEST_COUNT]++; + debug('%s(requests: %s, finished: %s) will be reuse on agent free event', + socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT]); + } + } + socket.on('free', onFree); + + function onClose(isError) { + debug('%s(requests: %s, finished: %s) close, isError: %s', + socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT], isError); + agent.closeSocketCount++; + } + socket.on('close', onClose); + + // start socket timeout handler + function onTimeout() { + // onTimeout and emitRequestTimeout(_http_client.js) + // https://github.com/nodejs/node/blob/v12.x/lib/_http_client.js#L711 + const listenerCount = socket.listeners('timeout').length; + // node <= 10, default listenerCount is 1, onTimeout + // 11 < node <= 12, default listenerCount is 2, onTimeout and emitRequestTimeout + // node >= 13, default listenerCount is 3, onTimeout, + // onTimeout(https://github.com/nodejs/node/pull/32000/files#diff-5f7fb0850412c6be189faeddea6c5359R333) + // and emitRequestTimeout + const timeout = getSocketTimeout(socket); + const req = socket._httpMessage; + const reqTimeoutListenerCount = req && req.listeners('timeout').length || 0; + debug('%s(requests: %s, finished: %s) timeout after %sms, listeners %s, defaultTimeoutListenerCount %s, hasHttpRequest %s, HttpRequest timeoutListenerCount %s', + socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT], + timeout, listenerCount, defaultTimeoutListenerCount, !!req, reqTimeoutListenerCount); + if (debug.enabled) { + debug('timeout listeners: %s', socket.listeners('timeout').map(f => f.name).join(', ')); + } + agent.timeoutSocketCount++; + const name = agent.getName(options); + if (agent.freeSockets[name] && agent.freeSockets[name].indexOf(socket) !== -1) { + // free socket timeout, destroy quietly + socket.destroy(); + // Remove it from freeSockets list immediately to prevent new requests + // from being sent through this socket. + agent.removeSocket(socket, options); + debug('%s is free, destroy quietly', socket[SOCKET_NAME]); + } else { + // if there is no any request socket timeout handler, + // agent need to handle socket timeout itself. + // + // custom request socket timeout handle logic must follow these rules: + // 1. Destroy socket first + // 2. Must emit socket 'agentRemove' event tell agent remove socket + // from freeSockets list immediately. + // Otherise you may be get 'socket hang up' error when reuse + // free socket and timeout happen in the same time. + if (reqTimeoutListenerCount === 0) { + const error = new Error('Socket timeout'); + error.code = 'ERR_SOCKET_TIMEOUT'; + error.timeout = timeout; + // must manually call socket.end() or socket.destroy() to end the connection. + // https://nodejs.org/dist/latest-v10.x/docs/api/net.html#net_socket_settimeout_timeout_callback + socket.destroy(error); + agent.removeSocket(socket, options); + debug('%s destroy with timeout error', socket[SOCKET_NAME]); + } + } + } + socket.on('timeout', onTimeout); + + function onError(err) { + const listenerCount = socket.listeners('error').length; + debug('%s(requests: %s, finished: %s) error: %s, listenerCount: %s', + socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT], + err, listenerCount); + agent.errorSocketCount++; + if (listenerCount === 1) { + // if socket don't contain error event handler, don't catch it, emit it again + debug('%s emit uncaught error event', socket[SOCKET_NAME]); + socket.removeListener('error', onError); + socket.emit('error', err); + } + } + socket.on('error', onError); + + function onRemove() { + debug('%s(requests: %s, finished: %s) agentRemove', + socket[SOCKET_NAME], + socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT]); + // We need this function for cases like HTTP 'upgrade' + // (defined by WebSockets) where we need to remove a socket from the + // pool because it'll be locked up indefinitely + socket.removeListener('close', onClose); + socket.removeListener('error', onError); + socket.removeListener('free', onFree); + socket.removeListener('timeout', onTimeout); + socket.removeListener('agentRemove', onRemove); + } + socket.on('agentRemove', onRemove); +} + +module.exports = Agent; + +function inspect(obj) { + const res = {}; + for (const key in obj) { + res[key] = obj[key].length; + } + return res; +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/lib/constants.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/lib/constants.js new file mode 100644 index 000000000..ca7ab97ea --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/lib/constants.js @@ -0,0 +1,14 @@ +'use strict'; + +module.exports = { + // agent + CURRENT_ID: Symbol('agentkeepalive#currentId'), + CREATE_ID: Symbol('agentkeepalive#createId'), + INIT_SOCKET: Symbol('agentkeepalive#initSocket'), + CREATE_HTTPS_CONNECTION: Symbol('agentkeepalive#createHttpsConnection'), + // socket + SOCKET_CREATED_TIME: Symbol('agentkeepalive#socketCreatedTime'), + SOCKET_NAME: Symbol('agentkeepalive#socketName'), + SOCKET_REQUEST_COUNT: Symbol('agentkeepalive#socketRequestCount'), + SOCKET_REQUEST_FINISHED_COUNT: Symbol('agentkeepalive#socketRequestFinishedCount'), +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/lib/https_agent.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/lib/https_agent.js new file mode 100644 index 000000000..344fb32ca --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/lib/https_agent.js @@ -0,0 +1,51 @@ +'use strict'; + +const OriginalHttpsAgent = require('https').Agent; +const HttpAgent = require('./agent'); +const { + INIT_SOCKET, + CREATE_HTTPS_CONNECTION, +} = require('./constants'); + +class HttpsAgent extends HttpAgent { + constructor(options) { + super(options); + + this.defaultPort = 443; + this.protocol = 'https:'; + this.maxCachedSessions = this.options.maxCachedSessions; + /* istanbul ignore next */ + if (this.maxCachedSessions === undefined) { + this.maxCachedSessions = 100; + } + + this._sessionCache = { + map: {}, + list: [], + }; + } + + createConnection(options, oncreate) { + const socket = this[CREATE_HTTPS_CONNECTION](options, oncreate); + this[INIT_SOCKET](socket, options); + return socket; + } +} + +// https://github.com/nodejs/node/blob/master/lib/https.js#L89 +HttpsAgent.prototype[CREATE_HTTPS_CONNECTION] = OriginalHttpsAgent.prototype.createConnection; + +[ + 'getName', + '_getSession', + '_cacheSession', + // https://github.com/nodejs/node/pull/4982 + '_evictSession', +].forEach(function(method) { + /* istanbul ignore next */ + if (typeof OriginalHttpsAgent.prototype[method] === 'function') { + HttpsAgent.prototype[method] = OriginalHttpsAgent.prototype[method]; + } +}); + +module.exports = HttpsAgent; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/package.json new file mode 100644 index 000000000..e6fc7f0e5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/agentkeepalive/package.json @@ -0,0 +1,56 @@ +{ + "name": "agentkeepalive", + "version": "4.6.0", + "description": "Missing keepalive http.Agent", + "main": "index.js", + "browser": "browser.js", + "files": [ + "index.js", + "index.d.ts", + "browser.js", + "lib" + ], + "scripts": { + "contributor": "git-contributor", + "test": "npm run lint && egg-bin test --full-trace", + "test-local": "egg-bin test --full-trace", + "cov": "cross-env NODE_DEBUG=agentkeepalive egg-bin cov --full-trace", + "ci": "npm run lint && npm run cov", + "lint": "eslint lib test index.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/node-modules/agentkeepalive.git" + }, + "bugs": { + "url": "https://github.com/node-modules/agentkeepalive/issues" + }, + "keywords": [ + "http", + "https", + "agent", + "keepalive", + "agentkeepalive", + "HttpAgent", + "HttpsAgent" + ], + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "devDependencies": { + "coffee": "^5.3.0", + "cross-env": "^6.0.3", + "egg-bin": "^4.9.0", + "eslint": "^5.7.0", + "eslint-config-egg": "^7.1.0", + "git-contributor": "^2.0.0", + "mm": "^2.4.1", + "pedding": "^1.1.0", + "typescript": "^3.8.3" + }, + "engines": { + "node": ">= 8.0.0" + }, + "author": "fengmk2 (https://github.com/fengmk2)", + "license": "MIT" +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/index.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/index.d.ts new file mode 100644 index 000000000..502bf7ad1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/index.d.ts @@ -0,0 +1,51 @@ +/** +Create an error from multiple errors. +*/ +declare class AggregateError extends Error implements Iterable { + readonly name: 'AggregateError'; + + /** + @param errors - If a string, a new `Error` is created with the string as the error message. If a non-Error object, a new `Error` is created with all properties from the object copied over. + @returns An Error that is also an [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#Iterables) for the individual errors. + + @example + ``` + import AggregateError = require('aggregate-error'); + + const error = new AggregateError([new Error('foo'), 'bar', {message: 'baz'}]); + + throw error; + + // AggregateError: + // Error: foo + // at Object. (/Users/sindresorhus/dev/aggregate-error/example.js:3:33) + // Error: bar + // at Object. (/Users/sindresorhus/dev/aggregate-error/example.js:3:13) + // Error: baz + // at Object. (/Users/sindresorhus/dev/aggregate-error/example.js:3:13) + // at AggregateError (/Users/sindresorhus/dev/aggregate-error/index.js:19:3) + // at Object. (/Users/sindresorhus/dev/aggregate-error/example.js:3:13) + // at Module._compile (module.js:556:32) + // at Object.Module._extensions..js (module.js:565:10) + // at Module.load (module.js:473:32) + // at tryModuleLoad (module.js:432:12) + // at Function.Module._load (module.js:424:3) + // at Module.runMain (module.js:590:10) + // at run (bootstrap_node.js:394:7) + // at startup (bootstrap_node.js:149:9) + + + for (const individualError of error) { + console.log(individualError); + } + //=> [Error: foo] + //=> [Error: bar] + //=> [Error: baz] + ``` + */ + constructor(errors: ReadonlyArray); + + [Symbol.iterator](): IterableIterator; +} + +export = AggregateError; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/index.js new file mode 100644 index 000000000..ba5bf0221 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/index.js @@ -0,0 +1,47 @@ +'use strict'; +const indentString = require('indent-string'); +const cleanStack = require('clean-stack'); + +const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, ''); + +class AggregateError extends Error { + constructor(errors) { + if (!Array.isArray(errors)) { + throw new TypeError(`Expected input to be an Array, got ${typeof errors}`); + } + + errors = [...errors].map(error => { + if (error instanceof Error) { + return error; + } + + if (error !== null && typeof error === 'object') { + // Handle plain error objects with message property and/or possibly other metadata + return Object.assign(new Error(error.message), error); + } + + return new Error(error); + }); + + let message = errors + .map(error => { + // The `stack` property is not standardized, so we can't assume it exists + return typeof error.stack === 'string' ? cleanInternalStack(cleanStack(error.stack)) : String(error); + }) + .join('\n'); + message = '\n' + indentString(message, 4); + super(message); + + this.name = 'AggregateError'; + + Object.defineProperty(this, '_errors', {value: errors}); + } + + * [Symbol.iterator]() { + for (const error of this._errors) { + yield error; + } + } +} + +module.exports = AggregateError; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/license b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/license new file mode 100644 index 000000000..e7af2f771 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/package.json new file mode 100644 index 000000000..74fcc3761 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/package.json @@ -0,0 +1,41 @@ +{ + "name": "aggregate-error", + "version": "3.1.0", + "description": "Create an error from multiple errors", + "license": "MIT", + "repository": "sindresorhus/aggregate-error", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "aggregate", + "error", + "combine", + "multiple", + "many", + "collection", + "iterable", + "iterator" + ], + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "devDependencies": { + "ava": "^2.4.0", + "tsd": "^0.7.1", + "xo": "^0.25.3" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/readme.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/readme.md new file mode 100644 index 000000000..850de98a8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aggregate-error/readme.md @@ -0,0 +1,61 @@ +# aggregate-error [![Build Status](https://travis-ci.org/sindresorhus/aggregate-error.svg?branch=master)](https://travis-ci.org/sindresorhus/aggregate-error) + +> Create an error from multiple errors + + +## Install + +``` +$ npm install aggregate-error +``` + + +## Usage + +```js +const AggregateError = require('aggregate-error'); + +const error = new AggregateError([new Error('foo'), 'bar', {message: 'baz'}]); + +throw error; +/* +AggregateError: + Error: foo + at Object. (/Users/sindresorhus/dev/aggregate-error/example.js:3:33) + Error: bar + at Object. (/Users/sindresorhus/dev/aggregate-error/example.js:3:13) + Error: baz + at Object. (/Users/sindresorhus/dev/aggregate-error/example.js:3:13) + at AggregateError (/Users/sindresorhus/dev/aggregate-error/index.js:19:3) + at Object. (/Users/sindresorhus/dev/aggregate-error/example.js:3:13) + at Module._compile (module.js:556:32) + at Object.Module._extensions..js (module.js:565:10) + at Module.load (module.js:473:32) + at tryModuleLoad (module.js:432:12) + at Function.Module._load (module.js:424:3) + at Module.runMain (module.js:590:10) + at run (bootstrap_node.js:394:7) + at startup (bootstrap_node.js:149:9) +*/ + +for (const individualError of error) { + console.log(individualError); +} +//=> [Error: foo] +//=> [Error: bar] +//=> [Error: baz] +``` + + +## API + +### AggregateError(errors) + +Returns an `Error` that is also an [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#Iterables) for the individual errors. + +#### errors + +Type: `Array` + +If a string, a new `Error` is created with the string as the error message.
    +If a non-Error object, a new `Error` is created with all properties from the object copied over. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/index.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/index.d.ts new file mode 100644 index 000000000..2dbf6af2b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/index.d.ts @@ -0,0 +1,37 @@ +declare namespace ansiRegex { + interface Options { + /** + Match only the first ANSI escape. + + @default false + */ + onlyFirst: boolean; + } +} + +/** +Regular expression for matching ANSI escape codes. + +@example +``` +import ansiRegex = require('ansi-regex'); + +ansiRegex().test('\u001B[4mcake\u001B[0m'); +//=> true + +ansiRegex().test('cake'); +//=> false + +'\u001B[4mcake\u001B[0m'.match(ansiRegex()); +//=> ['\u001B[4m', '\u001B[0m'] + +'\u001B[4mcake\u001B[0m'.match(ansiRegex({onlyFirst: true})); +//=> ['\u001B[4m'] + +'\u001B]8;;https://github.com\u0007click\u001B]8;;\u0007'.match(ansiRegex()); +//=> ['\u001B]8;;https://github.com\u0007', '\u001B]8;;\u0007'] +``` +*/ +declare function ansiRegex(options?: ansiRegex.Options): RegExp; + +export = ansiRegex; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/index.js new file mode 100644 index 000000000..616ff837d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/index.js @@ -0,0 +1,10 @@ +'use strict'; + +module.exports = ({onlyFirst = false} = {}) => { + const pattern = [ + '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)', + '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))' + ].join('|'); + + return new RegExp(pattern, onlyFirst ? undefined : 'g'); +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/license b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/license new file mode 100644 index 000000000..e7af2f771 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/package.json new file mode 100644 index 000000000..017f53116 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/package.json @@ -0,0 +1,55 @@ +{ + "name": "ansi-regex", + "version": "5.0.1", + "description": "Regular expression for matching ANSI escape codes", + "license": "MIT", + "repository": "chalk/ansi-regex", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd", + "view-supported": "node fixtures/view-codes.js" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "ansi", + "styles", + "color", + "colour", + "colors", + "terminal", + "console", + "cli", + "string", + "tty", + "escape", + "formatting", + "rgb", + "256", + "shell", + "xterm", + "command-line", + "text", + "regex", + "regexp", + "re", + "match", + "test", + "find", + "pattern" + ], + "devDependencies": { + "ava": "^2.4.0", + "tsd": "^0.9.0", + "xo": "^0.25.3" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/readme.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/readme.md new file mode 100644 index 000000000..4d848bc36 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ansi-regex/readme.md @@ -0,0 +1,78 @@ +# ansi-regex + +> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code) + + +## Install + +``` +$ npm install ansi-regex +``` + + +## Usage + +```js +const ansiRegex = require('ansi-regex'); + +ansiRegex().test('\u001B[4mcake\u001B[0m'); +//=> true + +ansiRegex().test('cake'); +//=> false + +'\u001B[4mcake\u001B[0m'.match(ansiRegex()); +//=> ['\u001B[4m', '\u001B[0m'] + +'\u001B[4mcake\u001B[0m'.match(ansiRegex({onlyFirst: true})); +//=> ['\u001B[4m'] + +'\u001B]8;;https://github.com\u0007click\u001B]8;;\u0007'.match(ansiRegex()); +//=> ['\u001B]8;;https://github.com\u0007', '\u001B]8;;\u0007'] +``` + + +## API + +### ansiRegex(options?) + +Returns a regex for matching ANSI escape codes. + +#### options + +Type: `object` + +##### onlyFirst + +Type: `boolean`
    +Default: `false` *(Matches any ANSI escape codes in a string)* + +Match only the first ANSI escape. + + +## FAQ + +### Why do you test for codes not in the ECMA 48 standard? + +Some of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. We test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them. + +On the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of "interrupts" that can mean different things on certain brands of processors, most of which have been phased out. + + +## Maintainers + +- [Sindre Sorhus](https://github.com/sindresorhus) +- [Josh Junon](https://github.com/qix-) + + +--- + +
    diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/LICENSE new file mode 100644 index 000000000..f4be44d88 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/LICENSE @@ -0,0 +1,14 @@ +Copyright (c) 2015, Rebecca Turner + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/README.md new file mode 100644 index 000000000..0bfc594c5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/README.md @@ -0,0 +1,94 @@ +aproba +====== + +A ridiculously light-weight function argument validator + +``` +var validate = require("aproba") + +function myfunc(a, b, c) { + // `a` must be a string, `b` a number, `c` a function + validate('SNF', arguments) // [a,b,c] is also valid +} + +myfunc('test', 23, function () {}) // ok +myfunc(123, 23, function () {}) // type error +myfunc('test', 23) // missing arg error +myfunc('test', 23, function () {}, true) // too many args error + +``` + +Valid types are: + +| type | description +| :--: | :---------- +| * | matches any type +| A | `Array.isArray` OR an `arguments` object +| S | typeof == string +| N | typeof == number +| F | typeof == function +| O | typeof == object and not type A and not type E +| B | typeof == boolean +| E | `instanceof Error` OR `null` **(special: see below)** +| Z | == `null` + +Validation failures throw one of three exception types, distinguished by a +`code` property of `EMISSINGARG`, `EINVALIDTYPE` or `ETOOMANYARGS`. + +If you pass in an invalid type then it will throw with a code of +`EUNKNOWNTYPE`. + +If an **error** argument is found and is not null then the remaining +arguments are optional. That is, if you say `ESO` then that's like using a +non-magical `E` in: `E|ESO|ZSO`. + +### But I have optional arguments?! + +You can provide more than one signature by separating them with pipes `|`. +If any signature matches the arguments then they'll be considered valid. + +So for example, say you wanted to write a signature for +`fs.createWriteStream`. The docs for it describe it thusly: + +``` +fs.createWriteStream(path[, options]) +``` + +This would be a signature of `SO|S`. That is, a string and and object, or +just a string. + +Now, if you read the full `fs` docs, you'll see that actually path can ALSO +be a buffer. And options can be a string, that is: +``` +path | +options | +``` + +To reproduce this you have to fully enumerate all of the possible +combinations and that implies a signature of `SO|SS|OO|OS|S|O`. The +awkwardness is a feature: It reminds you of the complexity you're adding to +your API when you do this sort of thing. + + +### Browser support + +This has no dependencies and should work in browsers, though you'll have +noisier stack traces. + +### Why this exists + +I wanted a very simple argument validator. It needed to do two things: + +1. Be more concise and easier to use than assertions + +2. Not encourage an infinite bikeshed of DSLs + +This is why types are specified by a single character and there's no such +thing as an optional argument. + +This is not intended to validate user data. This is specifically about +asserting the interface of your functions. + +If you need greater validation, I encourage you to write them by hand or +look elsewhere. + diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/index.js new file mode 100644 index 000000000..5a58e8126 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/index.js @@ -0,0 +1,105 @@ +'use strict' +module.exports = validate + +function isArguments (thingy) { + return thingy != null && typeof thingy === 'object' && thingy.hasOwnProperty('callee') +} + +const types = { + '*': {label: 'any', check: () => true}, + A: {label: 'array', check: _ => Array.isArray(_) || isArguments(_)}, + S: {label: 'string', check: _ => typeof _ === 'string'}, + N: {label: 'number', check: _ => typeof _ === 'number'}, + F: {label: 'function', check: _ => typeof _ === 'function'}, + O: {label: 'object', check: _ => typeof _ === 'object' && _ != null && !types.A.check(_) && !types.E.check(_)}, + B: {label: 'boolean', check: _ => typeof _ === 'boolean'}, + E: {label: 'error', check: _ => _ instanceof Error}, + Z: {label: 'null', check: _ => _ == null} +} + +function addSchema (schema, arity) { + const group = arity[schema.length] = arity[schema.length] || [] + if (group.indexOf(schema) === -1) group.push(schema) +} + +function validate (rawSchemas, args) { + if (arguments.length !== 2) throw wrongNumberOfArgs(['SA'], arguments.length) + if (!rawSchemas) throw missingRequiredArg(0, 'rawSchemas') + if (!args) throw missingRequiredArg(1, 'args') + if (!types.S.check(rawSchemas)) throw invalidType(0, ['string'], rawSchemas) + if (!types.A.check(args)) throw invalidType(1, ['array'], args) + const schemas = rawSchemas.split('|') + const arity = {} + + schemas.forEach(schema => { + for (let ii = 0; ii < schema.length; ++ii) { + const type = schema[ii] + if (!types[type]) throw unknownType(ii, type) + } + if (/E.*E/.test(schema)) throw moreThanOneError(schema) + addSchema(schema, arity) + if (/E/.test(schema)) { + addSchema(schema.replace(/E.*$/, 'E'), arity) + addSchema(schema.replace(/E/, 'Z'), arity) + if (schema.length === 1) addSchema('', arity) + } + }) + let matching = arity[args.length] + if (!matching) { + throw wrongNumberOfArgs(Object.keys(arity), args.length) + } + for (let ii = 0; ii < args.length; ++ii) { + let newMatching = matching.filter(schema => { + const type = schema[ii] + const typeCheck = types[type].check + return typeCheck(args[ii]) + }) + if (!newMatching.length) { + const labels = matching.map(_ => types[_[ii]].label).filter(_ => _ != null) + throw invalidType(ii, labels, args[ii]) + } + matching = newMatching + } +} + +function missingRequiredArg (num) { + return newException('EMISSINGARG', 'Missing required argument #' + (num + 1)) +} + +function unknownType (num, type) { + return newException('EUNKNOWNTYPE', 'Unknown type ' + type + ' in argument #' + (num + 1)) +} + +function invalidType (num, expectedTypes, value) { + let valueType + Object.keys(types).forEach(typeCode => { + if (types[typeCode].check(value)) valueType = types[typeCode].label + }) + return newException('EINVALIDTYPE', 'Argument #' + (num + 1) + ': Expected ' + + englishList(expectedTypes) + ' but got ' + valueType) +} + +function englishList (list) { + return list.join(', ').replace(/, ([^,]+)$/, ' or $1') +} + +function wrongNumberOfArgs (expected, got) { + const english = englishList(expected) + const args = expected.every(ex => ex.length === 1) + ? 'argument' + : 'arguments' + return newException('EWRONGARGCOUNT', 'Expected ' + english + ' ' + args + ' but got ' + got) +} + +function moreThanOneError (schema) { + return newException('ETOOMANYERRORTYPES', + 'Only one error type per argument signature is allowed, more than one found in "' + schema + '"') +} + +function newException (code, msg) { + const err = new TypeError(msg) + err.code = code + /* istanbul ignore else */ + if (Error.captureStackTrace) Error.captureStackTrace(err, validate) + return err +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/package.json new file mode 100644 index 000000000..71c7fca58 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/aproba/package.json @@ -0,0 +1,35 @@ +{ + "name": "aproba", + "version": "2.1.0", + "description": "A ridiculously light-weight argument validator (now browser friendly)", + "main": "index.js", + "directories": { + "test": "test" + }, + "dependencies": {}, + "devDependencies": { + "standard": "^11.0.1", + "tap": "^12.0.1" + }, + "files": [ + "index.js" + ], + "scripts": { + "pretest": "standard", + "test": "tap --100 -J test/*.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/iarna/aproba" + }, + "keywords": [ + "argument", + "validate" + ], + "author": "Rebecca Turner ", + "license": "ISC", + "bugs": { + "url": "https://github.com/iarna/aproba/issues" + }, + "homepage": "https://github.com/iarna/aproba" +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/LICENSE.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/LICENSE.md new file mode 100644 index 000000000..845be76f6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/LICENSE.md @@ -0,0 +1,18 @@ +ISC License + +Copyright npm, Inc. + +Permission to use, copy, modify, and/or distribute this +software for any purpose with or without fee is hereby +granted, provided that the above copyright notice and this +permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND NPM DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO +EVENT SHALL NPM BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE +USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/README.md new file mode 100644 index 000000000..caae19b0a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/README.md @@ -0,0 +1,208 @@ +are-we-there-yet +---------------- + +Track complex hierarchies of asynchronous task completion statuses. This is +intended to give you a way of recording and reporting the progress of the big +recursive fan-out and gather type workflows that are so common in async. + +What you do with this completion data is up to you, but the most common use case is to +feed it to one of the many progress bar modules. + +Most progress bar modules include a rudimentary version of this, but my +needs were more complex. + +Usage +===== + +```javascript +var TrackerGroup = require("are-we-there-yet").TrackerGroup + +var top = new TrackerGroup("program") + +var single = top.newItem("one thing", 100) +single.completeWork(20) + +console.log(top.completed()) // 0.2 + +fs.stat("file", function(er, stat) { + if (er) throw er + var stream = top.newStream("file", stat.size) + console.log(top.completed()) // now 0.1 as single is 50% of the job and is 20% complete + // and 50% * 20% == 10% + fs.createReadStream("file").pipe(stream).on("data", function (chunk) { + // do stuff with chunk + }) + top.on("change", function (name) { + // called each time a chunk is read from "file" + // top.completed() will start at 0.1 and fill up to 0.6 as the file is read + }) +}) +``` + +Shared Methods +============== + +* var completed = tracker.completed() + +Implemented in: `Tracker`, `TrackerGroup`, `TrackerStream` + +Returns the ratio of completed work to work to be done. Range of 0 to 1. + +* tracker.finish() + +Implemented in: `Tracker`, `TrackerGroup` + +Marks the tracker as completed. With a TrackerGroup this marks all of its +components as completed. + +Marks all of the components of this tracker as finished, which in turn means +that `tracker.completed()` for this will now be 1. + +This will result in one or more `change` events being emitted. + +Events +====== + +All tracker objects emit `change` events with the following arguments: + +``` +function (name, completed, tracker) +``` + +`name` is the name of the tracker that originally emitted the event, +or if it didn't have one, the first containing tracker group that had one. + +`completed` is the percent complete (as returned by `tracker.completed()` method). + +`tracker` is the tracker object that you are listening for events on. + +TrackerGroup +============ + +* var tracker = new TrackerGroup(**name**) + + * **name** *(optional)* - The name of this tracker group, used in change + notifications if the component updating didn't have a name. Defaults to undefined. + +Creates a new empty tracker aggregation group. These are trackers whose +completion status is determined by the completion status of other trackers added to this aggregation group. + +Ex. + +```javascript +var tracker = new TrackerGroup("parent") +var foo = tracker.newItem("firstChild", 100) +var bar = tracker.newItem("secondChild", 100) + +foo.finish() +console.log(tracker.completed()) // 0.5 +bar.finish() +console.log(tracker.completed()) // 1 +``` + +* tracker.addUnit(**otherTracker**, **weight**) + + * **otherTracker** - Any of the other are-we-there-yet tracker objects + * **weight** *(optional)* - The weight to give the tracker, defaults to 1. + +Adds the **otherTracker** to this aggregation group. The weight determines +how long you expect this tracker to take to complete in proportion to other +units. So for instance, if you add one tracker with a weight of 1 and +another with a weight of 2, you're saying the second will take twice as long +to complete as the first. As such, the first will account for 33% of the +completion of this tracker and the second will account for the other 67%. + +Returns **otherTracker**. + +* var subGroup = tracker.newGroup(**name**, **weight**) + +The above is exactly equivalent to: + +```javascript + var subGroup = tracker.addUnit(new TrackerGroup(name), weight) +``` + +* var subItem = tracker.newItem(**name**, **todo**, **weight**) + +The above is exactly equivalent to: + +```javascript + var subItem = tracker.addUnit(new Tracker(name, todo), weight) +``` + +* var subStream = tracker.newStream(**name**, **todo**, **weight**) + +The above is exactly equivalent to: + +```javascript + var subStream = tracker.addUnit(new TrackerStream(name, todo), weight) +``` + +* console.log( tracker.debug() ) + +Returns a tree showing the completion of this tracker group and all of its +children, including recursively entering all of the children. + +Tracker +======= + +* var tracker = new Tracker(**name**, **todo**) + + * **name** *(optional)* The name of this counter to report in change + events. Defaults to undefined. + * **todo** *(optional)* The amount of work todo (a number). Defaults to 0. + +Ordinarily these are constructed as a part of a tracker group (via +`newItem`). + +* var completed = tracker.completed() + +Returns the ratio of completed work to work to be done. Range of 0 to 1. If +total work to be done is 0 then it will return 0. + +* tracker.addWork(**todo**) + + * **todo** A number to add to the amount of work to be done. + +Increases the amount of work to be done, thus decreasing the completion +percentage. Triggers a `change` event. + +* tracker.completeWork(**completed**) + + * **completed** A number to add to the work complete + +Increase the amount of work complete, thus increasing the completion percentage. +Will never increase the work completed past the amount of work todo. That is, +percentages > 100% are not allowed. Triggers a `change` event. + +* tracker.finish() + +Marks this tracker as finished, tracker.completed() will now be 1. Triggers +a `change` event. + +TrackerStream +============= + +* var tracker = new TrackerStream(**name**, **size**, **options**) + + * **name** *(optional)* The name of this counter to report in change + events. Defaults to undefined. + * **size** *(optional)* The number of bytes being sent through this stream. + * **options** *(optional)* A hash of stream options + +The tracker stream object is a pass through stream that updates an internal +tracker object each time a block passes through. It's intended to track +downloads, file extraction and other related activities. You use it by piping +your data source into it and then using it as your data source. + +If your data has a length attribute then that's used as the amount of work +completed when the chunk is passed through. If it does not (eg, object +streams) then each chunk counts as completing 1 unit of work, so your size +should be the total number of objects being streamed. + +* tracker.addWork(**todo**) + + * **todo** Increase the expected overall size by **todo** bytes. + +Increases the amount of work to be done, thus decreasing the completion +percentage. Triggers a `change` event. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/index.js new file mode 100644 index 000000000..57d8743fd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/index.js @@ -0,0 +1,4 @@ +'use strict' +exports.TrackerGroup = require('./tracker-group.js') +exports.Tracker = require('./tracker.js') +exports.TrackerStream = require('./tracker-stream.js') diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker-base.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker-base.js new file mode 100644 index 000000000..6f4368755 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker-base.js @@ -0,0 +1,11 @@ +'use strict' +var EventEmitter = require('events').EventEmitter +var util = require('util') + +var trackerId = 0 +var TrackerBase = module.exports = function (name) { + EventEmitter.call(this) + this.id = ++trackerId + this.name = name +} +util.inherits(TrackerBase, EventEmitter) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker-group.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker-group.js new file mode 100644 index 000000000..a3c7af804 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker-group.js @@ -0,0 +1,116 @@ +'use strict' +var util = require('util') +var TrackerBase = require('./tracker-base.js') +var Tracker = require('./tracker.js') +var TrackerStream = require('./tracker-stream.js') + +var TrackerGroup = module.exports = function (name) { + TrackerBase.call(this, name) + this.parentGroup = null + this.trackers = [] + this.completion = {} + this.weight = {} + this.totalWeight = 0 + this.finished = false + this.bubbleChange = bubbleChange(this) +} +util.inherits(TrackerGroup, TrackerBase) + +function bubbleChange (trackerGroup) { + return function (name, completed, tracker) { + trackerGroup.completion[tracker.id] = completed + if (trackerGroup.finished) { + return + } + trackerGroup.emit('change', name || trackerGroup.name, trackerGroup.completed(), trackerGroup) + } +} + +TrackerGroup.prototype.nameInTree = function () { + var names = [] + var from = this + while (from) { + names.unshift(from.name) + from = from.parentGroup + } + return names.join('/') +} + +TrackerGroup.prototype.addUnit = function (unit, weight) { + if (unit.addUnit) { + var toTest = this + while (toTest) { + if (unit === toTest) { + throw new Error( + 'Attempted to add tracker group ' + + unit.name + ' to tree that already includes it ' + + this.nameInTree(this)) + } + toTest = toTest.parentGroup + } + unit.parentGroup = this + } + this.weight[unit.id] = weight || 1 + this.totalWeight += this.weight[unit.id] + this.trackers.push(unit) + this.completion[unit.id] = unit.completed() + unit.on('change', this.bubbleChange) + if (!this.finished) { + this.emit('change', unit.name, this.completion[unit.id], unit) + } + return unit +} + +TrackerGroup.prototype.completed = function () { + if (this.trackers.length === 0) { + return 0 + } + var valPerWeight = 1 / this.totalWeight + var completed = 0 + for (var ii = 0; ii < this.trackers.length; ii++) { + var trackerId = this.trackers[ii].id + completed += + valPerWeight * this.weight[trackerId] * this.completion[trackerId] + } + return completed +} + +TrackerGroup.prototype.newGroup = function (name, weight) { + return this.addUnit(new TrackerGroup(name), weight) +} + +TrackerGroup.prototype.newItem = function (name, todo, weight) { + return this.addUnit(new Tracker(name, todo), weight) +} + +TrackerGroup.prototype.newStream = function (name, todo, weight) { + return this.addUnit(new TrackerStream(name, todo), weight) +} + +TrackerGroup.prototype.finish = function () { + this.finished = true + if (!this.trackers.length) { + this.addUnit(new Tracker(), 1, true) + } + for (var ii = 0; ii < this.trackers.length; ii++) { + var tracker = this.trackers[ii] + tracker.finish() + tracker.removeListener('change', this.bubbleChange) + } + this.emit('change', this.name, 1, this) +} + +var buffer = ' ' +TrackerGroup.prototype.debug = function (depth) { + depth = depth || 0 + var indent = depth ? buffer.slice(0, depth) : '' + var output = indent + (this.name || 'top') + ': ' + this.completed() + '\n' + this.trackers.forEach(function (tracker) { + if (tracker instanceof TrackerGroup) { + output += tracker.debug(depth + 1) + } else { + output += indent + ' ' + tracker.name + ': ' + tracker.completed() + '\n' + } + }) + return output +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker-stream.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker-stream.js new file mode 100644 index 000000000..e1cf85055 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker-stream.js @@ -0,0 +1,36 @@ +'use strict' +var util = require('util') +var stream = require('readable-stream') +var delegate = require('delegates') +var Tracker = require('./tracker.js') + +var TrackerStream = module.exports = function (name, size, options) { + stream.Transform.call(this, options) + this.tracker = new Tracker(name, size) + this.name = name + this.id = this.tracker.id + this.tracker.on('change', delegateChange(this)) +} +util.inherits(TrackerStream, stream.Transform) + +function delegateChange (trackerStream) { + return function (name, completion, tracker) { + trackerStream.emit('change', name, completion, trackerStream) + } +} + +TrackerStream.prototype._transform = function (data, encoding, cb) { + this.tracker.completeWork(data.length ? data.length : 1) + this.push(data) + cb() +} + +TrackerStream.prototype._flush = function (cb) { + this.tracker.finish() + cb() +} + +delegate(TrackerStream.prototype, 'tracker') + .method('completed') + .method('addWork') + .method('finish') diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker.js new file mode 100644 index 000000000..a8f8b3ba0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/lib/tracker.js @@ -0,0 +1,32 @@ +'use strict' +var util = require('util') +var TrackerBase = require('./tracker-base.js') + +var Tracker = module.exports = function (name, todo) { + TrackerBase.call(this, name) + this.workDone = 0 + this.workTodo = todo || 0 +} +util.inherits(Tracker, TrackerBase) + +Tracker.prototype.completed = function () { + return this.workTodo === 0 ? 0 : this.workDone / this.workTodo +} + +Tracker.prototype.addWork = function (work) { + this.workTodo += work + this.emit('change', this.name, this.completed(), this) +} + +Tracker.prototype.completeWork = function (work) { + this.workDone += work + if (this.workDone > this.workTodo) { + this.workDone = this.workTodo + } + this.emit('change', this.name, this.completed(), this) +} + +Tracker.prototype.finish = function () { + this.workTodo = this.workDone = 1 + this.emit('change', this.name, 1, this) +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/package.json new file mode 100644 index 000000000..cc3d75042 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/are-we-there-yet/package.json @@ -0,0 +1,56 @@ +{ + "name": "are-we-there-yet", + "version": "3.0.1", + "description": "Keep track of the overall completion of many disparate processes", + "main": "lib/index.js", + "scripts": { + "test": "tap", + "npmclilint": "npmcli-lint", + "lint": "eslint \"**/*.js\"", + "lintfix": "npm run lint -- --fix", + "posttest": "npm run lint", + "postsnap": "npm run lintfix --", + "preversion": "npm test", + "postversion": "npm publish", + "prepublishOnly": "git push origin --follow-tags", + "snap": "tap", + "postlint": "template-oss-check", + "template-oss-apply": "template-oss-apply --force" + }, + "repository": { + "type": "git", + "url": "https://github.com/npm/are-we-there-yet.git" + }, + "author": "GitHub Inc.", + "license": "ISC", + "bugs": { + "url": "https://github.com/npm/are-we-there-yet/issues" + }, + "homepage": "https://github.com/npm/are-we-there-yet", + "devDependencies": { + "@npmcli/eslint-config": "^3.0.1", + "@npmcli/template-oss": "3.5.0", + "tap": "^16.0.1" + }, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "files": [ + "bin/", + "lib/" + ], + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "tap": { + "branches": 68, + "statements": 92, + "functions": 86, + "lines": 92 + }, + "templateOSS": { + "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", + "version": "3.5.0" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/.github/FUNDING.yml b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/.github/FUNDING.yml new file mode 100644 index 000000000..cea8b16e9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/.github/FUNDING.yml @@ -0,0 +1,2 @@ +tidelift: "npm/balanced-match" +patreon: juliangruber diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/LICENSE.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/LICENSE.md new file mode 100644 index 000000000..2cdc8e414 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/LICENSE.md @@ -0,0 +1,21 @@ +(MIT) + +Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/README.md new file mode 100644 index 000000000..d2a48b6b4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/README.md @@ -0,0 +1,97 @@ +# balanced-match + +Match balanced string pairs, like `{` and `}` or `` and ``. Supports regular expressions as well! + +[![build status](https://secure.travis-ci.org/juliangruber/balanced-match.svg)](http://travis-ci.org/juliangruber/balanced-match) +[![downloads](https://img.shields.io/npm/dm/balanced-match.svg)](https://www.npmjs.org/package/balanced-match) + +[![testling badge](https://ci.testling.com/juliangruber/balanced-match.png)](https://ci.testling.com/juliangruber/balanced-match) + +## Example + +Get the first matching pair of braces: + +```js +var balanced = require('balanced-match'); + +console.log(balanced('{', '}', 'pre{in{nested}}post')); +console.log(balanced('{', '}', 'pre{first}between{second}post')); +console.log(balanced(/\s+\{\s+/, /\s+\}\s+/, 'pre { in{nest} } post')); +``` + +The matches are: + +```bash +$ node example.js +{ start: 3, end: 14, pre: 'pre', body: 'in{nested}', post: 'post' } +{ start: 3, + end: 9, + pre: 'pre', + body: 'first', + post: 'between{second}post' } +{ start: 3, end: 17, pre: 'pre', body: 'in{nest}', post: 'post' } +``` + +## API + +### var m = balanced(a, b, str) + +For the first non-nested matching pair of `a` and `b` in `str`, return an +object with those keys: + +* **start** the index of the first match of `a` +* **end** the index of the matching `b` +* **pre** the preamble, `a` and `b` not included +* **body** the match, `a` and `b` not included +* **post** the postscript, `a` and `b` not included + +If there's no match, `undefined` will be returned. + +If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `['{', 'a', '']` and `{a}}` will match `['', 'a', '}']`. + +### var r = balanced.range(a, b, str) + +For the first non-nested matching pair of `a` and `b` in `str`, return an +array with indexes: `[ , ]`. + +If there's no match, `undefined` will be returned. + +If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `[ 1, 3 ]` and `{a}}` will match `[0, 2]`. + +## Installation + +With [npm](https://npmjs.org) do: + +```bash +npm install balanced-match +``` + +## Security contact information + +To report a security vulnerability, please use the +[Tidelift security contact](https://tidelift.com/security). +Tidelift will coordinate the fix and disclosure. + +## License + +(MIT) + +Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/index.js new file mode 100644 index 000000000..c67a64608 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/index.js @@ -0,0 +1,62 @@ +'use strict'; +module.exports = balanced; +function balanced(a, b, str) { + if (a instanceof RegExp) a = maybeMatch(a, str); + if (b instanceof RegExp) b = maybeMatch(b, str); + + var r = range(a, b, str); + + return r && { + start: r[0], + end: r[1], + pre: str.slice(0, r[0]), + body: str.slice(r[0] + a.length, r[1]), + post: str.slice(r[1] + b.length) + }; +} + +function maybeMatch(reg, str) { + var m = str.match(reg); + return m ? m[0] : null; +} + +balanced.range = range; +function range(a, b, str) { + var begs, beg, left, right, result; + var ai = str.indexOf(a); + var bi = str.indexOf(b, ai + 1); + var i = ai; + + if (ai >= 0 && bi > 0) { + if(a===b) { + return [ai, bi]; + } + begs = []; + left = str.length; + + while (i >= 0 && !result) { + if (i == ai) { + begs.push(i); + ai = str.indexOf(a, i + 1); + } else if (begs.length == 1) { + result = [ begs.pop(), bi ]; + } else { + beg = begs.pop(); + if (beg < left) { + left = beg; + right = bi; + } + + bi = str.indexOf(b, i + 1); + } + + i = ai < bi && ai >= 0 ? ai : bi; + } + + if (begs.length) { + result = [ left, right ]; + } + } + + return result; +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/package.json new file mode 100644 index 000000000..ce6073e04 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/balanced-match/package.json @@ -0,0 +1,48 @@ +{ + "name": "balanced-match", + "description": "Match balanced character pairs, like \"{\" and \"}\"", + "version": "1.0.2", + "repository": { + "type": "git", + "url": "git://github.com/juliangruber/balanced-match.git" + }, + "homepage": "https://github.com/juliangruber/balanced-match", + "main": "index.js", + "scripts": { + "test": "tape test/test.js", + "bench": "matcha test/bench.js" + }, + "devDependencies": { + "matcha": "^0.7.0", + "tape": "^4.6.0" + }, + "keywords": [ + "match", + "regexp", + "test", + "balanced", + "parse" + ], + "author": { + "name": "Julian Gruber", + "email": "mail@juliangruber.com", + "url": "http://juliangruber.com" + }, + "license": "MIT", + "testling": { + "files": "test/*.js", + "browsers": [ + "ie/8..latest", + "firefox/20..latest", + "firefox/nightly", + "chrome/25..latest", + "chrome/canary", + "opera/12..latest", + "opera/next", + "safari/5.1..latest", + "ipad/6.0..latest", + "iphone/6.0..latest", + "android-browser/4.2..latest" + ] + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/LICENSE new file mode 100644 index 000000000..6d52b8acf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Jameson Little + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/README.md new file mode 100644 index 000000000..b42a48f41 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/README.md @@ -0,0 +1,34 @@ +base64-js +========= + +`base64-js` does basic base64 encoding/decoding in pure JS. + +[![build status](https://secure.travis-ci.org/beatgammit/base64-js.png)](http://travis-ci.org/beatgammit/base64-js) + +Many browsers already have base64 encoding/decoding functionality, but it is for text data, not all-purpose binary data. + +Sometimes encoding/decoding binary data in the browser is useful, and that is what this module does. + +## install + +With [npm](https://npmjs.org) do: + +`npm install base64-js` and `var base64js = require('base64-js')` + +For use in web browsers do: + +`` + +[Get supported base64-js with the Tidelift Subscription](https://tidelift.com/subscription/pkg/npm-base64-js?utm_source=npm-base64-js&utm_medium=referral&utm_campaign=readme) + +## methods + +`base64js` has three exposed functions, `byteLength`, `toByteArray` and `fromByteArray`, which both take a single argument. + +* `byteLength` - Takes a base64 string and returns length of byte array +* `toByteArray` - Takes a base64 string and returns a byte array +* `fromByteArray` - Takes a byte array and returns a base64 string + +## license + +MIT diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/base64js.min.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/base64js.min.js new file mode 100644 index 000000000..908ac83fd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/base64js.min.js @@ -0,0 +1 @@ +(function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"==typeof window?"undefined"==typeof global?"undefined"==typeof self?this:self:global:window,b.base64js=a()}})(function(){return function(){function b(d,e,g){function a(j,i){if(!e[j]){if(!d[j]){var f="function"==typeof require&&require;if(!i&&f)return f(j,!0);if(h)return h(j,!0);var c=new Error("Cannot find module '"+j+"'");throw c.code="MODULE_NOT_FOUND",c}var k=e[j]={exports:{}};d[j][0].call(k.exports,function(b){var c=d[j][1][b];return a(c||b)},k,k.exports,b,d,e,g)}return e[j].exports}for(var h="function"==typeof require&&require,c=0;c>16,j[k++]=255&b>>8,j[k++]=255&b;return 2===h&&(b=l[a.charCodeAt(c)]<<2|l[a.charCodeAt(c+1)]>>4,j[k++]=255&b),1===h&&(b=l[a.charCodeAt(c)]<<10|l[a.charCodeAt(c+1)]<<4|l[a.charCodeAt(c+2)]>>2,j[k++]=255&b>>8,j[k++]=255&b),j}function g(a){return k[63&a>>18]+k[63&a>>12]+k[63&a>>6]+k[63&a]}function h(a,b,c){for(var d,e=[],f=b;fj?j:g+f));return 1===d?(b=a[c-1],e.push(k[b>>2]+k[63&b<<4]+"==")):2===d&&(b=(a[c-2]<<8)+a[c-1],e.push(k[b>>10]+k[63&b>>4]+k[63&b<<2]+"=")),e.join("")}c.byteLength=function(a){var b=d(a),c=b[0],e=b[1];return 3*(c+e)/4-e},c.toByteArray=f,c.fromByteArray=j;for(var k=[],l=[],m="undefined"==typeof Uint8Array?Array:Uint8Array,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",o=0,p=n.length;o 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('=') + if (validLen === -1) validLen = len + + var placeHoldersLen = validLen === len + ? 0 + : 4 - (validLen % 4) + + return [validLen, placeHoldersLen] +} + +// base64 is 4/3 + up to two characters of the original data +function byteLength (b64) { + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function _byteLength (b64, validLen, placeHoldersLen) { + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function toByteArray (b64) { + var tmp + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) + + var curByte = 0 + + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 + ? validLen - 4 + : validLen + + var i + for (i = 0; i < len; i += 4) { + tmp = + (revLookup[b64.charCodeAt(i)] << 18) | + (revLookup[b64.charCodeAt(i + 1)] << 12) | + (revLookup[b64.charCodeAt(i + 2)] << 6) | + revLookup[b64.charCodeAt(i + 3)] + arr[curByte++] = (tmp >> 16) & 0xFF + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 2) { + tmp = + (revLookup[b64.charCodeAt(i)] << 2) | + (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 1) { + tmp = + (revLookup[b64.charCodeAt(i)] << 10) | + (revLookup[b64.charCodeAt(i + 1)] << 4) | + (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + return arr +} + +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + + lookup[num >> 12 & 0x3F] + + lookup[num >> 6 & 0x3F] + + lookup[num & 0x3F] +} + +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = + ((uint8[i] << 16) & 0xFF0000) + + ((uint8[i + 1] << 8) & 0xFF00) + + (uint8[i + 2] & 0xFF) + output.push(tripletToBase64(tmp)) + } + return output.join('') +} + +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + parts.push( + lookup[tmp >> 2] + + lookup[(tmp << 4) & 0x3F] + + '==' + ) + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1] + parts.push( + lookup[tmp >> 10] + + lookup[(tmp >> 4) & 0x3F] + + lookup[(tmp << 2) & 0x3F] + + '=' + ) + } + + return parts.join('') +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/package.json new file mode 100644 index 000000000..c3972e39f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/base64-js/package.json @@ -0,0 +1,47 @@ +{ + "name": "base64-js", + "description": "Base64 encoding/decoding in pure JS", + "version": "1.5.1", + "author": "T. Jameson Little ", + "typings": "index.d.ts", + "bugs": { + "url": "https://github.com/beatgammit/base64-js/issues" + }, + "devDependencies": { + "babel-minify": "^0.5.1", + "benchmark": "^2.1.4", + "browserify": "^16.3.0", + "standard": "*", + "tape": "4.x" + }, + "homepage": "https://github.com/beatgammit/base64-js", + "keywords": [ + "base64" + ], + "license": "MIT", + "main": "index.js", + "repository": { + "type": "git", + "url": "git://github.com/beatgammit/base64-js.git" + }, + "scripts": { + "build": "browserify -s base64js -r ./ | minify > base64js.min.js", + "lint": "standard", + "test": "npm run lint && npm run unit", + "unit": "tape test/*.js" + }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/LICENSE.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/LICENSE.md new file mode 100644 index 000000000..5a92289f6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/LICENSE.md @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net> + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/README.md new file mode 100644 index 000000000..5b3e7a81b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/README.md @@ -0,0 +1,98 @@ +node-bindings +============= +### Helper module for loading your native module's `.node` file + +This is a helper module for authors of Node.js native addon modules. +It is basically the "swiss army knife" of `require()`ing your native module's +`.node` file. + +Throughout the course of Node's native addon history, addons have ended up being +compiled in a variety of different places, depending on which build tool and which +version of node was used. To make matters worse, now the `gyp` build tool can +produce either a __Release__ or __Debug__ build, each being built into different +locations. + +This module checks _all_ the possible locations that a native addon would be built +at, and returns the first one that loads successfully. + + +Installation +------------ + +Install with `npm`: + +``` bash +$ npm install --save bindings +``` + +Or add it to the `"dependencies"` section of your `package.json` file. + + +Example +------- + +`require()`ing the proper bindings file for the current node version, platform +and architecture is as simple as: + +``` js +var bindings = require('bindings')('binding.node') + +// Use your bindings defined in your C files +bindings.your_c_function() +``` + + +Nice Error Output +----------------- + +When the `.node` file could not be loaded, `node-bindings` throws an Error with +a nice error message telling you exactly what was tried. You can also check the +`err.tries` Array property. + +``` +Error: Could not load the bindings file. Tried: + → /Users/nrajlich/ref/build/binding.node + → /Users/nrajlich/ref/build/Debug/binding.node + → /Users/nrajlich/ref/build/Release/binding.node + → /Users/nrajlich/ref/out/Debug/binding.node + → /Users/nrajlich/ref/Debug/binding.node + → /Users/nrajlich/ref/out/Release/binding.node + → /Users/nrajlich/ref/Release/binding.node + → /Users/nrajlich/ref/build/default/binding.node + → /Users/nrajlich/ref/compiled/0.8.2/darwin/x64/binding.node + at bindings (/Users/nrajlich/ref/node_modules/bindings/bindings.js:84:13) + at Object. (/Users/nrajlich/ref/lib/ref.js:5:47) + at Module._compile (module.js:449:26) + at Object.Module._extensions..js (module.js:467:10) + at Module.load (module.js:356:32) + at Function.Module._load (module.js:312:12) + ... +``` + +The searching for the `.node` file will originate from the first directory in which has a `package.json` file is found. + +License +------- + +(The MIT License) + +Copyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net> + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/bindings.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/bindings.js new file mode 100644 index 000000000..727413a19 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/bindings.js @@ -0,0 +1,221 @@ +/** + * Module dependencies. + */ + +var fs = require('fs'), + path = require('path'), + fileURLToPath = require('file-uri-to-path'), + join = path.join, + dirname = path.dirname, + exists = + (fs.accessSync && + function(path) { + try { + fs.accessSync(path); + } catch (e) { + return false; + } + return true; + }) || + fs.existsSync || + path.existsSync, + defaults = { + arrow: process.env.NODE_BINDINGS_ARROW || ' → ', + compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled', + platform: process.platform, + arch: process.arch, + nodePreGyp: + 'node-v' + + process.versions.modules + + '-' + + process.platform + + '-' + + process.arch, + version: process.versions.node, + bindings: 'bindings.node', + try: [ + // node-gyp's linked version in the "build" dir + ['module_root', 'build', 'bindings'], + // node-waf and gyp_addon (a.k.a node-gyp) + ['module_root', 'build', 'Debug', 'bindings'], + ['module_root', 'build', 'Release', 'bindings'], + // Debug files, for development (legacy behavior, remove for node v0.9) + ['module_root', 'out', 'Debug', 'bindings'], + ['module_root', 'Debug', 'bindings'], + // Release files, but manually compiled (legacy behavior, remove for node v0.9) + ['module_root', 'out', 'Release', 'bindings'], + ['module_root', 'Release', 'bindings'], + // Legacy from node-waf, node <= 0.4.x + ['module_root', 'build', 'default', 'bindings'], + // Production "Release" buildtype binary (meh...) + ['module_root', 'compiled', 'version', 'platform', 'arch', 'bindings'], + // node-qbs builds + ['module_root', 'addon-build', 'release', 'install-root', 'bindings'], + ['module_root', 'addon-build', 'debug', 'install-root', 'bindings'], + ['module_root', 'addon-build', 'default', 'install-root', 'bindings'], + // node-pre-gyp path ./lib/binding/{node_abi}-{platform}-{arch} + ['module_root', 'lib', 'binding', 'nodePreGyp', 'bindings'] + ] + }; + +/** + * The main `bindings()` function loads the compiled bindings for a given module. + * It uses V8's Error API to determine the parent filename that this function is + * being invoked from, which is then used to find the root directory. + */ + +function bindings(opts) { + // Argument surgery + if (typeof opts == 'string') { + opts = { bindings: opts }; + } else if (!opts) { + opts = {}; + } + + // maps `defaults` onto `opts` object + Object.keys(defaults).map(function(i) { + if (!(i in opts)) opts[i] = defaults[i]; + }); + + // Get the module root + if (!opts.module_root) { + opts.module_root = exports.getRoot(exports.getFileName()); + } + + // Ensure the given bindings name ends with .node + if (path.extname(opts.bindings) != '.node') { + opts.bindings += '.node'; + } + + // https://github.com/webpack/webpack/issues/4175#issuecomment-342931035 + var requireFunc = + typeof __webpack_require__ === 'function' + ? __non_webpack_require__ + : require; + + var tries = [], + i = 0, + l = opts.try.length, + n, + b, + err; + + for (; i < l; i++) { + n = join.apply( + null, + opts.try[i].map(function(p) { + return opts[p] || p; + }) + ); + tries.push(n); + try { + b = opts.path ? requireFunc.resolve(n) : requireFunc(n); + if (!opts.path) { + b.path = n; + } + return b; + } catch (e) { + if (e.code !== 'MODULE_NOT_FOUND' && + e.code !== 'QUALIFIED_PATH_RESOLUTION_FAILED' && + !/not find/i.test(e.message)) { + throw e; + } + } + } + + err = new Error( + 'Could not locate the bindings file. Tried:\n' + + tries + .map(function(a) { + return opts.arrow + a; + }) + .join('\n') + ); + err.tries = tries; + throw err; +} +module.exports = exports = bindings; + +/** + * Gets the filename of the JavaScript file that invokes this function. + * Used to help find the root directory of a module. + * Optionally accepts an filename argument to skip when searching for the invoking filename + */ + +exports.getFileName = function getFileName(calling_file) { + var origPST = Error.prepareStackTrace, + origSTL = Error.stackTraceLimit, + dummy = {}, + fileName; + + Error.stackTraceLimit = 10; + + Error.prepareStackTrace = function(e, st) { + for (var i = 0, l = st.length; i < l; i++) { + fileName = st[i].getFileName(); + if (fileName !== __filename) { + if (calling_file) { + if (fileName !== calling_file) { + return; + } + } else { + return; + } + } + } + }; + + // run the 'prepareStackTrace' function above + Error.captureStackTrace(dummy); + dummy.stack; + + // cleanup + Error.prepareStackTrace = origPST; + Error.stackTraceLimit = origSTL; + + // handle filename that starts with "file://" + var fileSchema = 'file://'; + if (fileName.indexOf(fileSchema) === 0) { + fileName = fileURLToPath(fileName); + } + + return fileName; +}; + +/** + * Gets the root directory of a module, given an arbitrary filename + * somewhere in the module tree. The "root directory" is the directory + * containing the `package.json` file. + * + * In: /home/nate/node-native-module/lib/index.js + * Out: /home/nate/node-native-module + */ + +exports.getRoot = function getRoot(file) { + var dir = dirname(file), + prev; + while (true) { + if (dir === '.') { + // Avoids an infinite loop in rare cases, like the REPL + dir = process.cwd(); + } + if ( + exists(join(dir, 'package.json')) || + exists(join(dir, 'node_modules')) + ) { + // Found the 'package.json' file or 'node_modules' dir; we're done + return dir; + } + if (prev === dir) { + // Got to the top + throw new Error( + 'Could not find module root given file: "' + + file + + '". Do you have a `package.json` file? ' + ); + } + // Try the parent dir next + prev = dir; + dir = join(dir, '..'); + } +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/package.json new file mode 100644 index 000000000..d027ee78a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bindings/package.json @@ -0,0 +1,28 @@ +{ + "name": "bindings", + "description": "Helper module for loading your native module's .node file", + "keywords": [ + "native", + "addon", + "bindings", + "gyp", + "waf", + "c", + "c++" + ], + "version": "1.5.0", + "author": "Nathan Rajlich (http://tootallnate.net)", + "repository": { + "type": "git", + "url": "git://github.com/TooTallNate/node-bindings.git" + }, + "main": "./bindings.js", + "bugs": { + "url": "https://github.com/TooTallNate/node-bindings/issues" + }, + "homepage": "https://github.com/TooTallNate/node-bindings", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/.travis.yml b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/.travis.yml new file mode 100644 index 000000000..016eaf556 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/.travis.yml @@ -0,0 +1,17 @@ +sudo: false +arch: + - amd64 + - ppc64le +language: node_js +node_js: + - '6' + - '8' + - '10' + - '12' + - '14' + - '15' + - lts/* +notifications: + email: + - rod@vagg.org + - matteo.collina@gmail.com diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/BufferList.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/BufferList.js new file mode 100644 index 000000000..471ee7788 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/BufferList.js @@ -0,0 +1,396 @@ +'use strict' + +const { Buffer } = require('buffer') +const symbol = Symbol.for('BufferList') + +function BufferList (buf) { + if (!(this instanceof BufferList)) { + return new BufferList(buf) + } + + BufferList._init.call(this, buf) +} + +BufferList._init = function _init (buf) { + Object.defineProperty(this, symbol, { value: true }) + + this._bufs = [] + this.length = 0 + + if (buf) { + this.append(buf) + } +} + +BufferList.prototype._new = function _new (buf) { + return new BufferList(buf) +} + +BufferList.prototype._offset = function _offset (offset) { + if (offset === 0) { + return [0, 0] + } + + let tot = 0 + + for (let i = 0; i < this._bufs.length; i++) { + const _t = tot + this._bufs[i].length + if (offset < _t || i === this._bufs.length - 1) { + return [i, offset - tot] + } + tot = _t + } +} + +BufferList.prototype._reverseOffset = function (blOffset) { + const bufferId = blOffset[0] + let offset = blOffset[1] + + for (let i = 0; i < bufferId; i++) { + offset += this._bufs[i].length + } + + return offset +} + +BufferList.prototype.get = function get (index) { + if (index > this.length || index < 0) { + return undefined + } + + const offset = this._offset(index) + + return this._bufs[offset[0]][offset[1]] +} + +BufferList.prototype.slice = function slice (start, end) { + if (typeof start === 'number' && start < 0) { + start += this.length + } + + if (typeof end === 'number' && end < 0) { + end += this.length + } + + return this.copy(null, 0, start, end) +} + +BufferList.prototype.copy = function copy (dst, dstStart, srcStart, srcEnd) { + if (typeof srcStart !== 'number' || srcStart < 0) { + srcStart = 0 + } + + if (typeof srcEnd !== 'number' || srcEnd > this.length) { + srcEnd = this.length + } + + if (srcStart >= this.length) { + return dst || Buffer.alloc(0) + } + + if (srcEnd <= 0) { + return dst || Buffer.alloc(0) + } + + const copy = !!dst + const off = this._offset(srcStart) + const len = srcEnd - srcStart + let bytes = len + let bufoff = (copy && dstStart) || 0 + let start = off[1] + + // copy/slice everything + if (srcStart === 0 && srcEnd === this.length) { + if (!copy) { + // slice, but full concat if multiple buffers + return this._bufs.length === 1 + ? this._bufs[0] + : Buffer.concat(this._bufs, this.length) + } + + // copy, need to copy individual buffers + for (let i = 0; i < this._bufs.length; i++) { + this._bufs[i].copy(dst, bufoff) + bufoff += this._bufs[i].length + } + + return dst + } + + // easy, cheap case where it's a subset of one of the buffers + if (bytes <= this._bufs[off[0]].length - start) { + return copy + ? this._bufs[off[0]].copy(dst, dstStart, start, start + bytes) + : this._bufs[off[0]].slice(start, start + bytes) + } + + if (!copy) { + // a slice, we need something to copy in to + dst = Buffer.allocUnsafe(len) + } + + for (let i = off[0]; i < this._bufs.length; i++) { + const l = this._bufs[i].length - start + + if (bytes > l) { + this._bufs[i].copy(dst, bufoff, start) + bufoff += l + } else { + this._bufs[i].copy(dst, bufoff, start, start + bytes) + bufoff += l + break + } + + bytes -= l + + if (start) { + start = 0 + } + } + + // safeguard so that we don't return uninitialized memory + if (dst.length > bufoff) return dst.slice(0, bufoff) + + return dst +} + +BufferList.prototype.shallowSlice = function shallowSlice (start, end) { + start = start || 0 + end = typeof end !== 'number' ? this.length : end + + if (start < 0) { + start += this.length + } + + if (end < 0) { + end += this.length + } + + if (start === end) { + return this._new() + } + + const startOffset = this._offset(start) + const endOffset = this._offset(end) + const buffers = this._bufs.slice(startOffset[0], endOffset[0] + 1) + + if (endOffset[1] === 0) { + buffers.pop() + } else { + buffers[buffers.length - 1] = buffers[buffers.length - 1].slice(0, endOffset[1]) + } + + if (startOffset[1] !== 0) { + buffers[0] = buffers[0].slice(startOffset[1]) + } + + return this._new(buffers) +} + +BufferList.prototype.toString = function toString (encoding, start, end) { + return this.slice(start, end).toString(encoding) +} + +BufferList.prototype.consume = function consume (bytes) { + // first, normalize the argument, in accordance with how Buffer does it + bytes = Math.trunc(bytes) + // do nothing if not a positive number + if (Number.isNaN(bytes) || bytes <= 0) return this + + while (this._bufs.length) { + if (bytes >= this._bufs[0].length) { + bytes -= this._bufs[0].length + this.length -= this._bufs[0].length + this._bufs.shift() + } else { + this._bufs[0] = this._bufs[0].slice(bytes) + this.length -= bytes + break + } + } + + return this +} + +BufferList.prototype.duplicate = function duplicate () { + const copy = this._new() + + for (let i = 0; i < this._bufs.length; i++) { + copy.append(this._bufs[i]) + } + + return copy +} + +BufferList.prototype.append = function append (buf) { + if (buf == null) { + return this + } + + if (buf.buffer) { + // append a view of the underlying ArrayBuffer + this._appendBuffer(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength)) + } else if (Array.isArray(buf)) { + for (let i = 0; i < buf.length; i++) { + this.append(buf[i]) + } + } else if (this._isBufferList(buf)) { + // unwrap argument into individual BufferLists + for (let i = 0; i < buf._bufs.length; i++) { + this.append(buf._bufs[i]) + } + } else { + // coerce number arguments to strings, since Buffer(number) does + // uninitialized memory allocation + if (typeof buf === 'number') { + buf = buf.toString() + } + + this._appendBuffer(Buffer.from(buf)) + } + + return this +} + +BufferList.prototype._appendBuffer = function appendBuffer (buf) { + this._bufs.push(buf) + this.length += buf.length +} + +BufferList.prototype.indexOf = function (search, offset, encoding) { + if (encoding === undefined && typeof offset === 'string') { + encoding = offset + offset = undefined + } + + if (typeof search === 'function' || Array.isArray(search)) { + throw new TypeError('The "value" argument must be one of type string, Buffer, BufferList, or Uint8Array.') + } else if (typeof search === 'number') { + search = Buffer.from([search]) + } else if (typeof search === 'string') { + search = Buffer.from(search, encoding) + } else if (this._isBufferList(search)) { + search = search.slice() + } else if (Array.isArray(search.buffer)) { + search = Buffer.from(search.buffer, search.byteOffset, search.byteLength) + } else if (!Buffer.isBuffer(search)) { + search = Buffer.from(search) + } + + offset = Number(offset || 0) + + if (isNaN(offset)) { + offset = 0 + } + + if (offset < 0) { + offset = this.length + offset + } + + if (offset < 0) { + offset = 0 + } + + if (search.length === 0) { + return offset > this.length ? this.length : offset + } + + const blOffset = this._offset(offset) + let blIndex = blOffset[0] // index of which internal buffer we're working on + let buffOffset = blOffset[1] // offset of the internal buffer we're working on + + // scan over each buffer + for (; blIndex < this._bufs.length; blIndex++) { + const buff = this._bufs[blIndex] + + while (buffOffset < buff.length) { + const availableWindow = buff.length - buffOffset + + if (availableWindow >= search.length) { + const nativeSearchResult = buff.indexOf(search, buffOffset) + + if (nativeSearchResult !== -1) { + return this._reverseOffset([blIndex, nativeSearchResult]) + } + + buffOffset = buff.length - search.length + 1 // end of native search window + } else { + const revOffset = this._reverseOffset([blIndex, buffOffset]) + + if (this._match(revOffset, search)) { + return revOffset + } + + buffOffset++ + } + } + + buffOffset = 0 + } + + return -1 +} + +BufferList.prototype._match = function (offset, search) { + if (this.length - offset < search.length) { + return false + } + + for (let searchOffset = 0; searchOffset < search.length; searchOffset++) { + if (this.get(offset + searchOffset) !== search[searchOffset]) { + return false + } + } + return true +} + +;(function () { + const methods = { + readDoubleBE: 8, + readDoubleLE: 8, + readFloatBE: 4, + readFloatLE: 4, + readInt32BE: 4, + readInt32LE: 4, + readUInt32BE: 4, + readUInt32LE: 4, + readInt16BE: 2, + readInt16LE: 2, + readUInt16BE: 2, + readUInt16LE: 2, + readInt8: 1, + readUInt8: 1, + readIntBE: null, + readIntLE: null, + readUIntBE: null, + readUIntLE: null + } + + for (const m in methods) { + (function (m) { + if (methods[m] === null) { + BufferList.prototype[m] = function (offset, byteLength) { + return this.slice(offset, offset + byteLength)[m](0, byteLength) + } + } else { + BufferList.prototype[m] = function (offset = 0) { + return this.slice(offset, offset + methods[m])[m](0) + } + } + }(m)) + } +}()) + +// Used internally by the class and also as an indicator of this object being +// a `BufferList`. It's not possible to use `instanceof BufferList` in a browser +// environment because there could be multiple different copies of the +// BufferList class and some `BufferList`s might be `BufferList`s. +BufferList.prototype._isBufferList = function _isBufferList (b) { + return b instanceof BufferList || BufferList.isBufferList(b) +} + +BufferList.isBufferList = function isBufferList (b) { + return b != null && b[symbol] +} + +module.exports = BufferList diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/LICENSE.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/LICENSE.md new file mode 100644 index 000000000..ecbe51637 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/LICENSE.md @@ -0,0 +1,13 @@ +The MIT License (MIT) +===================== + +Copyright (c) 2013-2019 bl contributors +---------------------------------- + +*bl contributors listed at * + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/README.md new file mode 100644 index 000000000..9680b1dcb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/README.md @@ -0,0 +1,247 @@ +# bl *(BufferList)* + +[![Build Status](https://api.travis-ci.com/rvagg/bl.svg?branch=master)](https://travis-ci.com/rvagg/bl/) + +**A Node.js Buffer list collector, reader and streamer thingy.** + +[![NPM](https://nodei.co/npm/bl.svg)](https://nodei.co/npm/bl/) + +**bl** is a storage object for collections of Node Buffers, exposing them with the main Buffer readable API. Also works as a duplex stream so you can collect buffers from a stream that emits them and emit buffers to a stream that consumes them! + +The original buffers are kept intact and copies are only done as necessary. Any reads that require the use of a single original buffer will return a slice of that buffer only (which references the same memory as the original buffer). Reads that span buffers perform concatenation as required and return the results transparently. + +```js +const { BufferList } = require('bl') + +const bl = new BufferList() +bl.append(Buffer.from('abcd')) +bl.append(Buffer.from('efg')) +bl.append('hi') // bl will also accept & convert Strings +bl.append(Buffer.from('j')) +bl.append(Buffer.from([ 0x3, 0x4 ])) + +console.log(bl.length) // 12 + +console.log(bl.slice(0, 10).toString('ascii')) // 'abcdefghij' +console.log(bl.slice(3, 10).toString('ascii')) // 'defghij' +console.log(bl.slice(3, 6).toString('ascii')) // 'def' +console.log(bl.slice(3, 8).toString('ascii')) // 'defgh' +console.log(bl.slice(5, 10).toString('ascii')) // 'fghij' + +console.log(bl.indexOf('def')) // 3 +console.log(bl.indexOf('asdf')) // -1 + +// or just use toString! +console.log(bl.toString()) // 'abcdefghij\u0003\u0004' +console.log(bl.toString('ascii', 3, 8)) // 'defgh' +console.log(bl.toString('ascii', 5, 10)) // 'fghij' + +// other standard Buffer readables +console.log(bl.readUInt16BE(10)) // 0x0304 +console.log(bl.readUInt16LE(10)) // 0x0403 +``` + +Give it a callback in the constructor and use it just like **[concat-stream](https://github.com/maxogden/node-concat-stream)**: + +```js +const { BufferListStream } = require('bl') +const fs = require('fs') + +fs.createReadStream('README.md') + .pipe(BufferListStream((err, data) => { // note 'new' isn't strictly required + // `data` is a complete Buffer object containing the full data + console.log(data.toString()) + })) +``` + +Note that when you use the *callback* method like this, the resulting `data` parameter is a concatenation of all `Buffer` objects in the list. If you want to avoid the overhead of this concatenation (in cases of extreme performance consciousness), then avoid the *callback* method and just listen to `'end'` instead, like a standard Stream. + +Or to fetch a URL using [hyperquest](https://github.com/substack/hyperquest) (should work with [request](http://github.com/mikeal/request) and even plain Node http too!): + +```js +const hyperquest = require('hyperquest') +const { BufferListStream } = require('bl') + +const url = 'https://raw.github.com/rvagg/bl/master/README.md' + +hyperquest(url).pipe(BufferListStream((err, data) => { + console.log(data.toString()) +})) +``` + +Or, use it as a readable stream to recompose a list of Buffers to an output source: + +```js +const { BufferListStream } = require('bl') +const fs = require('fs') + +var bl = new BufferListStream() +bl.append(Buffer.from('abcd')) +bl.append(Buffer.from('efg')) +bl.append(Buffer.from('hi')) +bl.append(Buffer.from('j')) + +bl.pipe(fs.createWriteStream('gibberish.txt')) +``` + +## API + + * new BufferList([ buf ]) + * BufferList.isBufferList(obj) + * bl.length + * bl.append(buffer) + * bl.get(index) + * bl.indexOf(value[, byteOffset][, encoding]) + * bl.slice([ start[, end ] ]) + * bl.shallowSlice([ start[, end ] ]) + * bl.copy(dest, [ destStart, [ srcStart [, srcEnd ] ] ]) + * bl.duplicate() + * bl.consume(bytes) + * bl.toString([encoding, [ start, [ end ]]]) + * bl.readDoubleBE(), bl.readDoubleLE(), bl.readFloatBE(), bl.readFloatLE(), bl.readInt32BE(), bl.readInt32LE(), bl.readUInt32BE(), bl.readUInt32LE(), bl.readInt16BE(), bl.readInt16LE(), bl.readUInt16BE(), bl.readUInt16LE(), bl.readInt8(), bl.readUInt8() + * new BufferListStream([ callback ]) + +-------------------------------------------------------- + +### new BufferList([ Buffer | Buffer array | BufferList | BufferList array | String ]) +No arguments are _required_ for the constructor, but you can initialise the list by passing in a single `Buffer` object or an array of `Buffer` objects. + +`new` is not strictly required, if you don't instantiate a new object, it will be done automatically for you so you can create a new instance simply with: + +```js +const { BufferList } = require('bl') +const bl = BufferList() + +// equivalent to: + +const { BufferList } = require('bl') +const bl = new BufferList() +``` + +-------------------------------------------------------- + +### BufferList.isBufferList(obj) +Determines if the passed object is a `BufferList`. It will return `true` if the passed object is an instance of `BufferList` **or** `BufferListStream` and `false` otherwise. + +N.B. this won't return `true` for `BufferList` or `BufferListStream` instances created by versions of this library before this static method was added. + +-------------------------------------------------------- + +### bl.length +Get the length of the list in bytes. This is the sum of the lengths of all of the buffers contained in the list, minus any initial offset for a semi-consumed buffer at the beginning. Should accurately represent the total number of bytes that can be read from the list. + +-------------------------------------------------------- + +### bl.append(Buffer | Buffer array | BufferList | BufferList array | String) +`append(buffer)` adds an additional buffer or BufferList to the internal list. `this` is returned so it can be chained. + +-------------------------------------------------------- + +### bl.get(index) +`get()` will return the byte at the specified index. + +-------------------------------------------------------- + +### bl.indexOf(value[, byteOffset][, encoding]) +`get()` will return the byte at the specified index. +`indexOf()` method returns the first index at which a given element can be found in the BufferList, or -1 if it is not present. + +-------------------------------------------------------- + +### bl.slice([ start, [ end ] ]) +`slice()` returns a new `Buffer` object containing the bytes within the range specified. Both `start` and `end` are optional and will default to the beginning and end of the list respectively. + +If the requested range spans a single internal buffer then a slice of that buffer will be returned which shares the original memory range of that Buffer. If the range spans multiple buffers then copy operations will likely occur to give you a uniform Buffer. + +-------------------------------------------------------- + +### bl.shallowSlice([ start, [ end ] ]) +`shallowSlice()` returns a new `BufferList` object containing the bytes within the range specified. Both `start` and `end` are optional and will default to the beginning and end of the list respectively. + +No copies will be performed. All buffers in the result share memory with the original list. + +-------------------------------------------------------- + +### bl.copy(dest, [ destStart, [ srcStart [, srcEnd ] ] ]) +`copy()` copies the content of the list in the `dest` buffer, starting from `destStart` and containing the bytes within the range specified with `srcStart` to `srcEnd`. `destStart`, `start` and `end` are optional and will default to the beginning of the `dest` buffer, and the beginning and end of the list respectively. + +-------------------------------------------------------- + +### bl.duplicate() +`duplicate()` performs a **shallow-copy** of the list. The internal Buffers remains the same, so if you change the underlying Buffers, the change will be reflected in both the original and the duplicate. This method is needed if you want to call `consume()` or `pipe()` and still keep the original list.Example: + +```js +var bl = new BufferListStream() + +bl.append('hello') +bl.append(' world') +bl.append('\n') + +bl.duplicate().pipe(process.stdout, { end: false }) + +console.log(bl.toString()) +``` + +-------------------------------------------------------- + +### bl.consume(bytes) +`consume()` will shift bytes *off the start of the list*. The number of bytes consumed don't need to line up with the sizes of the internal Buffers—initial offsets will be calculated accordingly in order to give you a consistent view of the data. + +-------------------------------------------------------- + +### bl.toString([encoding, [ start, [ end ]]]) +`toString()` will return a string representation of the buffer. The optional `start` and `end` arguments are passed on to `slice()`, while the `encoding` is passed on to `toString()` of the resulting Buffer. See the [Buffer#toString()](http://nodejs.org/docs/latest/api/buffer.html#buffer_buf_tostring_encoding_start_end) documentation for more information. + +-------------------------------------------------------- + +### bl.readDoubleBE(), bl.readDoubleLE(), bl.readFloatBE(), bl.readFloatLE(), bl.readInt32BE(), bl.readInt32LE(), bl.readUInt32BE(), bl.readUInt32LE(), bl.readInt16BE(), bl.readInt16LE(), bl.readUInt16BE(), bl.readUInt16LE(), bl.readInt8(), bl.readUInt8() + +All of the standard byte-reading methods of the `Buffer` interface are implemented and will operate across internal Buffer boundaries transparently. + +See the [Buffer](http://nodejs.org/docs/latest/api/buffer.html) documentation for how these work. + +-------------------------------------------------------- + +### new BufferListStream([ callback | Buffer | Buffer array | BufferList | BufferList array | String ]) +**BufferListStream** is a Node **[Duplex Stream](http://nodejs.org/docs/latest/api/stream.html#stream_class_stream_duplex)**, so it can be read from and written to like a standard Node stream. You can also `pipe()` to and from a **BufferListStream** instance. + +The constructor takes an optional callback, if supplied, the callback will be called with an error argument followed by a reference to the **bl** instance, when `bl.end()` is called (i.e. from a piped stream). This is a convenient method of collecting the entire contents of a stream, particularly when the stream is *chunky*, such as a network stream. + +Normally, no arguments are required for the constructor, but you can initialise the list by passing in a single `Buffer` object or an array of `Buffer` object. + +`new` is not strictly required, if you don't instantiate a new object, it will be done automatically for you so you can create a new instance simply with: + +```js +const { BufferListStream } = require('bl') +const bl = BufferListStream() + +// equivalent to: + +const { BufferListStream } = require('bl') +const bl = new BufferListStream() +``` + +N.B. For backwards compatibility reasons, `BufferListStream` is the **default** export when you `require('bl')`: + +```js +const { BufferListStream } = require('bl') +// equivalent to: +const BufferListStream = require('bl') +``` + +-------------------------------------------------------- + +## Contributors + +**bl** is brought to you by the following hackers: + + * [Rod Vagg](https://github.com/rvagg) + * [Matteo Collina](https://github.com/mcollina) + * [Jarett Cruger](https://github.com/jcrugzz) + + +## License & copyright + +Copyright (c) 2013-2019 bl contributors (listed above). + +bl is licensed under the MIT license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE.md file for more details. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/bl.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/bl.js new file mode 100644 index 000000000..40228f879 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/bl.js @@ -0,0 +1,84 @@ +'use strict' + +const DuplexStream = require('readable-stream').Duplex +const inherits = require('inherits') +const BufferList = require('./BufferList') + +function BufferListStream (callback) { + if (!(this instanceof BufferListStream)) { + return new BufferListStream(callback) + } + + if (typeof callback === 'function') { + this._callback = callback + + const piper = function piper (err) { + if (this._callback) { + this._callback(err) + this._callback = null + } + }.bind(this) + + this.on('pipe', function onPipe (src) { + src.on('error', piper) + }) + this.on('unpipe', function onUnpipe (src) { + src.removeListener('error', piper) + }) + + callback = null + } + + BufferList._init.call(this, callback) + DuplexStream.call(this) +} + +inherits(BufferListStream, DuplexStream) +Object.assign(BufferListStream.prototype, BufferList.prototype) + +BufferListStream.prototype._new = function _new (callback) { + return new BufferListStream(callback) +} + +BufferListStream.prototype._write = function _write (buf, encoding, callback) { + this._appendBuffer(buf) + + if (typeof callback === 'function') { + callback() + } +} + +BufferListStream.prototype._read = function _read (size) { + if (!this.length) { + return this.push(null) + } + + size = Math.min(size, this.length) + this.push(this.slice(0, size)) + this.consume(size) +} + +BufferListStream.prototype.end = function end (chunk) { + DuplexStream.prototype.end.call(this, chunk) + + if (this._callback) { + this._callback(null, this.slice()) + this._callback = null + } +} + +BufferListStream.prototype._destroy = function _destroy (err, cb) { + this._bufs.length = 0 + this.length = 0 + cb(err) +} + +BufferListStream.prototype._isBufferList = function _isBufferList (b) { + return b instanceof BufferListStream || b instanceof BufferList || BufferListStream.isBufferList(b) +} + +BufferListStream.isBufferList = BufferList.isBufferList + +module.exports = BufferListStream +module.exports.BufferListStream = BufferListStream +module.exports.BufferList = BufferList diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/package.json new file mode 100644 index 000000000..3b2be3f48 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/package.json @@ -0,0 +1,37 @@ +{ + "name": "bl", + "version": "4.1.0", + "description": "Buffer List: collect buffers and access with a standard readable Buffer interface, streamable too!", + "license": "MIT", + "main": "bl.js", + "scripts": { + "lint": "standard *.js test/*.js", + "test": "npm run lint && node test/test.js | faucet" + }, + "repository": { + "type": "git", + "url": "https://github.com/rvagg/bl.git" + }, + "homepage": "https://github.com/rvagg/bl", + "authors": [ + "Rod Vagg (https://github.com/rvagg)", + "Matteo Collina (https://github.com/mcollina)", + "Jarett Cruger (https://github.com/jcrugzz)" + ], + "keywords": [ + "buffer", + "buffers", + "stream", + "awesomesauce" + ], + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "devDependencies": { + "faucet": "~0.0.1", + "standard": "^14.3.0", + "tape": "^4.11.0" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/convert.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/convert.js new file mode 100644 index 000000000..9f3e23599 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/convert.js @@ -0,0 +1,21 @@ +'use strict' + +const tape = require('tape') +const { BufferList, BufferListStream } = require('../') +const { Buffer } = require('buffer') + +tape('convert from BufferList to BufferListStream', (t) => { + const data = Buffer.from(`TEST-${Date.now()}`) + const bl = new BufferList(data) + const bls = new BufferListStream(bl) + t.ok(bl.slice().equals(bls.slice())) + t.end() +}) + +tape('convert from BufferListStream to BufferList', (t) => { + const data = Buffer.from(`TEST-${Date.now()}`) + const bls = new BufferListStream(data) + const bl = new BufferList(bls) + t.ok(bl.slice().equals(bls.slice())) + t.end() +}) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/indexOf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/indexOf.js new file mode 100644 index 000000000..62dcb01f3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/indexOf.js @@ -0,0 +1,492 @@ +'use strict' + +const tape = require('tape') +const BufferList = require('../') +const { Buffer } = require('buffer') + +tape('indexOf single byte needle', (t) => { + const bl = new BufferList(['abcdefg', 'abcdefg', '12345']) + + t.equal(bl.indexOf('e'), 4) + t.equal(bl.indexOf('e', 5), 11) + t.equal(bl.indexOf('e', 12), -1) + t.equal(bl.indexOf('5'), 18) + + t.end() +}) + +tape('indexOf multiple byte needle', (t) => { + const bl = new BufferList(['abcdefg', 'abcdefg']) + + t.equal(bl.indexOf('ef'), 4) + t.equal(bl.indexOf('ef', 5), 11) + + t.end() +}) + +tape('indexOf multiple byte needles across buffer boundaries', (t) => { + const bl = new BufferList(['abcdefg', 'abcdefg']) + + t.equal(bl.indexOf('fgabc'), 5) + + t.end() +}) + +tape('indexOf takes a Uint8Array search', (t) => { + const bl = new BufferList(['abcdefg', 'abcdefg']) + const search = new Uint8Array([102, 103, 97, 98, 99]) // fgabc + + t.equal(bl.indexOf(search), 5) + + t.end() +}) + +tape('indexOf takes a buffer list search', (t) => { + const bl = new BufferList(['abcdefg', 'abcdefg']) + const search = new BufferList('fgabc') + + t.equal(bl.indexOf(search), 5) + + t.end() +}) + +tape('indexOf a zero byte needle', (t) => { + const b = new BufferList('abcdef') + const bufEmpty = Buffer.from('') + + t.equal(b.indexOf(''), 0) + t.equal(b.indexOf('', 1), 1) + t.equal(b.indexOf('', b.length + 1), b.length) + t.equal(b.indexOf('', Infinity), b.length) + t.equal(b.indexOf(bufEmpty), 0) + t.equal(b.indexOf(bufEmpty, 1), 1) + t.equal(b.indexOf(bufEmpty, b.length + 1), b.length) + t.equal(b.indexOf(bufEmpty, Infinity), b.length) + + t.end() +}) + +tape('indexOf buffers smaller and larger than the needle', (t) => { + const bl = new BufferList(['abcdefg', 'a', 'bcdefg', 'a', 'bcfgab']) + + t.equal(bl.indexOf('fgabc'), 5) + t.equal(bl.indexOf('fgabc', 6), 12) + t.equal(bl.indexOf('fgabc', 13), -1) + + t.end() +}) + +// only present in node 6+ +;(process.version.substr(1).split('.')[0] >= 6) && tape('indexOf latin1 and binary encoding', (t) => { + const b = new BufferList('abcdef') + + // test latin1 encoding + t.equal( + new BufferList(Buffer.from(b.toString('latin1'), 'latin1')) + .indexOf('d', 0, 'latin1'), + 3 + ) + t.equal( + new BufferList(Buffer.from(b.toString('latin1'), 'latin1')) + .indexOf(Buffer.from('d', 'latin1'), 0, 'latin1'), + 3 + ) + t.equal( + new BufferList(Buffer.from('aa\u00e8aa', 'latin1')) + .indexOf('\u00e8', 'latin1'), + 2 + ) + t.equal( + new BufferList(Buffer.from('\u00e8', 'latin1')) + .indexOf('\u00e8', 'latin1'), + 0 + ) + t.equal( + new BufferList(Buffer.from('\u00e8', 'latin1')) + .indexOf(Buffer.from('\u00e8', 'latin1'), 'latin1'), + 0 + ) + + // test binary encoding + t.equal( + new BufferList(Buffer.from(b.toString('binary'), 'binary')) + .indexOf('d', 0, 'binary'), + 3 + ) + t.equal( + new BufferList(Buffer.from(b.toString('binary'), 'binary')) + .indexOf(Buffer.from('d', 'binary'), 0, 'binary'), + 3 + ) + t.equal( + new BufferList(Buffer.from('aa\u00e8aa', 'binary')) + .indexOf('\u00e8', 'binary'), + 2 + ) + t.equal( + new BufferList(Buffer.from('\u00e8', 'binary')) + .indexOf('\u00e8', 'binary'), + 0 + ) + t.equal( + new BufferList(Buffer.from('\u00e8', 'binary')) + .indexOf(Buffer.from('\u00e8', 'binary'), 'binary'), + 0 + ) + + t.end() +}) + +tape('indexOf the entire nodejs10 buffer test suite', (t) => { + const b = new BufferList('abcdef') + const bufA = Buffer.from('a') + const bufBc = Buffer.from('bc') + const bufF = Buffer.from('f') + const bufZ = Buffer.from('z') + + const stringComparison = 'abcdef' + + t.equal(b.indexOf('a'), 0) + t.equal(b.indexOf('a', 1), -1) + t.equal(b.indexOf('a', -1), -1) + t.equal(b.indexOf('a', -4), -1) + t.equal(b.indexOf('a', -b.length), 0) + t.equal(b.indexOf('a', NaN), 0) + t.equal(b.indexOf('a', -Infinity), 0) + t.equal(b.indexOf('a', Infinity), -1) + t.equal(b.indexOf('bc'), 1) + t.equal(b.indexOf('bc', 2), -1) + t.equal(b.indexOf('bc', -1), -1) + t.equal(b.indexOf('bc', -3), -1) + t.equal(b.indexOf('bc', -5), 1) + t.equal(b.indexOf('bc', NaN), 1) + t.equal(b.indexOf('bc', -Infinity), 1) + t.equal(b.indexOf('bc', Infinity), -1) + t.equal(b.indexOf('f'), b.length - 1) + t.equal(b.indexOf('z'), -1) + + // empty search tests + t.equal(b.indexOf(bufA), 0) + t.equal(b.indexOf(bufA, 1), -1) + t.equal(b.indexOf(bufA, -1), -1) + t.equal(b.indexOf(bufA, -4), -1) + t.equal(b.indexOf(bufA, -b.length), 0) + t.equal(b.indexOf(bufA, NaN), 0) + t.equal(b.indexOf(bufA, -Infinity), 0) + t.equal(b.indexOf(bufA, Infinity), -1) + t.equal(b.indexOf(bufBc), 1) + t.equal(b.indexOf(bufBc, 2), -1) + t.equal(b.indexOf(bufBc, -1), -1) + t.equal(b.indexOf(bufBc, -3), -1) + t.equal(b.indexOf(bufBc, -5), 1) + t.equal(b.indexOf(bufBc, NaN), 1) + t.equal(b.indexOf(bufBc, -Infinity), 1) + t.equal(b.indexOf(bufBc, Infinity), -1) + t.equal(b.indexOf(bufF), b.length - 1) + t.equal(b.indexOf(bufZ), -1) + t.equal(b.indexOf(0x61), 0) + t.equal(b.indexOf(0x61, 1), -1) + t.equal(b.indexOf(0x61, -1), -1) + t.equal(b.indexOf(0x61, -4), -1) + t.equal(b.indexOf(0x61, -b.length), 0) + t.equal(b.indexOf(0x61, NaN), 0) + t.equal(b.indexOf(0x61, -Infinity), 0) + t.equal(b.indexOf(0x61, Infinity), -1) + t.equal(b.indexOf(0x0), -1) + + // test offsets + t.equal(b.indexOf('d', 2), 3) + t.equal(b.indexOf('f', 5), 5) + t.equal(b.indexOf('f', -1), 5) + t.equal(b.indexOf('f', 6), -1) + + t.equal(b.indexOf(Buffer.from('d'), 2), 3) + t.equal(b.indexOf(Buffer.from('f'), 5), 5) + t.equal(b.indexOf(Buffer.from('f'), -1), 5) + t.equal(b.indexOf(Buffer.from('f'), 6), -1) + + t.equal(Buffer.from('ff').indexOf(Buffer.from('f'), 1, 'ucs2'), -1) + + // test invalid and uppercase encoding + t.equal(b.indexOf('b', 'utf8'), 1) + t.equal(b.indexOf('b', 'UTF8'), 1) + t.equal(b.indexOf('62', 'HEX'), 1) + t.throws(() => b.indexOf('bad', 'enc'), TypeError) + + // test hex encoding + t.equal( + Buffer.from(b.toString('hex'), 'hex') + .indexOf('64', 0, 'hex'), + 3 + ) + t.equal( + Buffer.from(b.toString('hex'), 'hex') + .indexOf(Buffer.from('64', 'hex'), 0, 'hex'), + 3 + ) + + // test base64 encoding + t.equal( + Buffer.from(b.toString('base64'), 'base64') + .indexOf('ZA==', 0, 'base64'), + 3 + ) + t.equal( + Buffer.from(b.toString('base64'), 'base64') + .indexOf(Buffer.from('ZA==', 'base64'), 0, 'base64'), + 3 + ) + + // test ascii encoding + t.equal( + Buffer.from(b.toString('ascii'), 'ascii') + .indexOf('d', 0, 'ascii'), + 3 + ) + t.equal( + Buffer.from(b.toString('ascii'), 'ascii') + .indexOf(Buffer.from('d', 'ascii'), 0, 'ascii'), + 3 + ) + + // test optional offset with passed encoding + t.equal(Buffer.from('aaaa0').indexOf('30', 'hex'), 4) + t.equal(Buffer.from('aaaa00a').indexOf('3030', 'hex'), 4) + + { + // test usc2 encoding + const twoByteString = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2') + + t.equal(8, twoByteString.indexOf('\u0395', 4, 'ucs2')) + t.equal(6, twoByteString.indexOf('\u03a3', -4, 'ucs2')) + t.equal(4, twoByteString.indexOf('\u03a3', -6, 'ucs2')) + t.equal(4, twoByteString.indexOf( + Buffer.from('\u03a3', 'ucs2'), -6, 'ucs2')) + t.equal(-1, twoByteString.indexOf('\u03a3', -2, 'ucs2')) + } + + const mixedByteStringUcs2 = + Buffer.from('\u039a\u0391abc\u03a3\u03a3\u0395', 'ucs2') + + t.equal(6, mixedByteStringUcs2.indexOf('bc', 0, 'ucs2')) + t.equal(10, mixedByteStringUcs2.indexOf('\u03a3', 0, 'ucs2')) + t.equal(-1, mixedByteStringUcs2.indexOf('\u0396', 0, 'ucs2')) + + t.equal( + 6, mixedByteStringUcs2.indexOf(Buffer.from('bc', 'ucs2'), 0, 'ucs2')) + t.equal( + 10, mixedByteStringUcs2.indexOf(Buffer.from('\u03a3', 'ucs2'), 0, 'ucs2')) + t.equal( + -1, mixedByteStringUcs2.indexOf(Buffer.from('\u0396', 'ucs2'), 0, 'ucs2')) + + { + const twoByteString = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2') + + // Test single char pattern + t.equal(0, twoByteString.indexOf('\u039a', 0, 'ucs2')) + let index = twoByteString.indexOf('\u0391', 0, 'ucs2') + t.equal(2, index, `Alpha - at index ${index}`) + index = twoByteString.indexOf('\u03a3', 0, 'ucs2') + t.equal(4, index, `First Sigma - at index ${index}`) + index = twoByteString.indexOf('\u03a3', 6, 'ucs2') + t.equal(6, index, `Second Sigma - at index ${index}`) + index = twoByteString.indexOf('\u0395', 0, 'ucs2') + t.equal(8, index, `Epsilon - at index ${index}`) + index = twoByteString.indexOf('\u0392', 0, 'ucs2') + t.equal(-1, index, `Not beta - at index ${index}`) + + // Test multi-char pattern + index = twoByteString.indexOf('\u039a\u0391', 0, 'ucs2') + t.equal(0, index, `Lambda Alpha - at index ${index}`) + index = twoByteString.indexOf('\u0391\u03a3', 0, 'ucs2') + t.equal(2, index, `Alpha Sigma - at index ${index}`) + index = twoByteString.indexOf('\u03a3\u03a3', 0, 'ucs2') + t.equal(4, index, `Sigma Sigma - at index ${index}`) + index = twoByteString.indexOf('\u03a3\u0395', 0, 'ucs2') + t.equal(6, index, `Sigma Epsilon - at index ${index}`) + } + + const mixedByteStringUtf8 = Buffer.from('\u039a\u0391abc\u03a3\u03a3\u0395') + + t.equal(5, mixedByteStringUtf8.indexOf('bc')) + t.equal(5, mixedByteStringUtf8.indexOf('bc', 5)) + t.equal(5, mixedByteStringUtf8.indexOf('bc', -8)) + t.equal(7, mixedByteStringUtf8.indexOf('\u03a3')) + t.equal(-1, mixedByteStringUtf8.indexOf('\u0396')) + + // Test complex string indexOf algorithms. Only trigger for long strings. + // Long string that isn't a simple repeat of a shorter string. + let longString = 'A' + for (let i = 66; i < 76; i++) { // from 'B' to 'K' + longString = longString + String.fromCharCode(i) + longString + } + + const longBufferString = Buffer.from(longString) + + // pattern of 15 chars, repeated every 16 chars in long + let pattern = 'ABACABADABACABA' + for (let i = 0; i < longBufferString.length - pattern.length; i += 7) { + const index = longBufferString.indexOf(pattern, i) + t.equal((i + 15) & ~0xf, index, + `Long ABACABA...-string at index ${i}`) + } + + let index = longBufferString.indexOf('AJABACA') + t.equal(510, index, `Long AJABACA, First J - at index ${index}`) + index = longBufferString.indexOf('AJABACA', 511) + t.equal(1534, index, `Long AJABACA, Second J - at index ${index}`) + + pattern = 'JABACABADABACABA' + index = longBufferString.indexOf(pattern) + t.equal(511, index, `Long JABACABA..., First J - at index ${index}`) + index = longBufferString.indexOf(pattern, 512) + t.equal( + 1535, index, `Long JABACABA..., Second J - at index ${index}`) + + // Search for a non-ASCII string in a pure ASCII string. + const asciiString = Buffer.from( + 'somethingnotatallsinisterwhichalsoworks') + t.equal(-1, asciiString.indexOf('\x2061')) + t.equal(3, asciiString.indexOf('eth', 0)) + + // Search in string containing many non-ASCII chars. + const allCodePoints = [] + for (let i = 0; i < 65536; i++) { + allCodePoints[i] = i + } + + const allCharsString = String.fromCharCode.apply(String, allCodePoints) + const allCharsBufferUtf8 = Buffer.from(allCharsString) + const allCharsBufferUcs2 = Buffer.from(allCharsString, 'ucs2') + + // Search for string long enough to trigger complex search with ASCII pattern + // and UC16 subject. + t.equal(-1, allCharsBufferUtf8.indexOf('notfound')) + t.equal(-1, allCharsBufferUcs2.indexOf('notfound')) + + // Needle is longer than haystack, but only because it's encoded as UTF-16 + t.equal(Buffer.from('aaaa').indexOf('a'.repeat(4), 'ucs2'), -1) + + t.equal(Buffer.from('aaaa').indexOf('a'.repeat(4), 'utf8'), 0) + t.equal(Buffer.from('aaaa').indexOf('你好', 'ucs2'), -1) + + // Haystack has odd length, but the needle is UCS2. + t.equal(Buffer.from('aaaaa').indexOf('b', 'ucs2'), -1) + + { + // Find substrings in Utf8. + const lengths = [1, 3, 15] // Single char, simple and complex. + const indices = [0x5, 0x60, 0x400, 0x680, 0x7ee, 0xFF02, 0x16610, 0x2f77b] + for (let lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) { + for (let i = 0; i < indices.length; i++) { + const index = indices[i] + let length = lengths[lengthIndex] + + if (index + length > 0x7F) { + length = 2 * length + } + + if (index + length > 0x7FF) { + length = 3 * length + } + + if (index + length > 0xFFFF) { + length = 4 * length + } + + const patternBufferUtf8 = allCharsBufferUtf8.slice(index, index + length) + t.equal(index, allCharsBufferUtf8.indexOf(patternBufferUtf8)) + + const patternStringUtf8 = patternBufferUtf8.toString() + t.equal(index, allCharsBufferUtf8.indexOf(patternStringUtf8)) + } + } + } + + { + // Find substrings in Usc2. + const lengths = [2, 4, 16] // Single char, simple and complex. + const indices = [0x5, 0x65, 0x105, 0x205, 0x285, 0x2005, 0x2085, 0xfff0] + + for (let lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) { + for (let i = 0; i < indices.length; i++) { + const index = indices[i] * 2 + const length = lengths[lengthIndex] + + const patternBufferUcs2 = + allCharsBufferUcs2.slice(index, index + length) + t.equal( + index, allCharsBufferUcs2.indexOf(patternBufferUcs2, 0, 'ucs2')) + + const patternStringUcs2 = patternBufferUcs2.toString('ucs2') + t.equal( + index, allCharsBufferUcs2.indexOf(patternStringUcs2, 0, 'ucs2')) + } + } + } + + [ + () => {}, + {}, + [] + ].forEach((val) => { + t.throws(() => b.indexOf(val), TypeError, `"${JSON.stringify(val)}" should throw`) + }) + + // Test weird offset arguments. + // The following offsets coerce to NaN or 0, searching the whole Buffer + t.equal(b.indexOf('b', undefined), 1) + t.equal(b.indexOf('b', {}), 1) + t.equal(b.indexOf('b', 0), 1) + t.equal(b.indexOf('b', null), 1) + t.equal(b.indexOf('b', []), 1) + + // The following offset coerces to 2, in other words +[2] === 2 + t.equal(b.indexOf('b', [2]), -1) + + // Behavior should match String.indexOf() + t.equal( + b.indexOf('b', undefined), + stringComparison.indexOf('b', undefined)) + t.equal( + b.indexOf('b', {}), + stringComparison.indexOf('b', {})) + t.equal( + b.indexOf('b', 0), + stringComparison.indexOf('b', 0)) + t.equal( + b.indexOf('b', null), + stringComparison.indexOf('b', null)) + t.equal( + b.indexOf('b', []), + stringComparison.indexOf('b', [])) + t.equal( + b.indexOf('b', [2]), + stringComparison.indexOf('b', [2])) + + // test truncation of Number arguments to uint8 + { + const buf = Buffer.from('this is a test') + + t.equal(buf.indexOf(0x6973), 3) + t.equal(buf.indexOf(0x697320), 4) + t.equal(buf.indexOf(0x69732069), 2) + t.equal(buf.indexOf(0x697374657374), 0) + t.equal(buf.indexOf(0x69737374), 0) + t.equal(buf.indexOf(0x69737465), 11) + t.equal(buf.indexOf(0x69737465), 11) + t.equal(buf.indexOf(-140), 0) + t.equal(buf.indexOf(-152), 1) + t.equal(buf.indexOf(0xff), -1) + t.equal(buf.indexOf(0xffff), -1) + } + + // Test that Uint8Array arguments are okay. + { + const needle = new Uint8Array([0x66, 0x6f, 0x6f]) + const haystack = new BufferList(Buffer.from('a foo b foo')) + t.equal(haystack.indexOf(needle), 2) + } + + t.end() +}) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/isBufferList.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/isBufferList.js new file mode 100644 index 000000000..9d895d59b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/isBufferList.js @@ -0,0 +1,32 @@ +'use strict' + +const tape = require('tape') +const { BufferList, BufferListStream } = require('../') +const { Buffer } = require('buffer') + +tape('isBufferList positives', (t) => { + t.ok(BufferList.isBufferList(new BufferList())) + t.ok(BufferList.isBufferList(new BufferListStream())) + + t.end() +}) + +tape('isBufferList negatives', (t) => { + const types = [ + null, + undefined, + NaN, + true, + false, + {}, + [], + Buffer.alloc(0), + [Buffer.alloc(0)] + ] + + for (const obj of types) { + t.notOk(BufferList.isBufferList(obj)) + } + + t.end() +}) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/test.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/test.js new file mode 100644 index 000000000..e523d0c3f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bl/test/test.js @@ -0,0 +1,869 @@ +'use strict' + +const tape = require('tape') +const crypto = require('crypto') +const fs = require('fs') +const path = require('path') +const BufferList = require('../') +const { Buffer } = require('buffer') + +const encodings = + ('hex utf8 utf-8 ascii binary base64' + + (process.browser ? '' : ' ucs2 ucs-2 utf16le utf-16le')).split(' ') + +require('./indexOf') +require('./isBufferList') +require('./convert') + +tape('single bytes from single buffer', function (t) { + const bl = new BufferList() + + bl.append(Buffer.from('abcd')) + + t.equal(bl.length, 4) + t.equal(bl.get(-1), undefined) + t.equal(bl.get(0), 97) + t.equal(bl.get(1), 98) + t.equal(bl.get(2), 99) + t.equal(bl.get(3), 100) + t.equal(bl.get(4), undefined) + + t.end() +}) + +tape('single bytes from multiple buffers', function (t) { + const bl = new BufferList() + + bl.append(Buffer.from('abcd')) + bl.append(Buffer.from('efg')) + bl.append(Buffer.from('hi')) + bl.append(Buffer.from('j')) + + t.equal(bl.length, 10) + + t.equal(bl.get(0), 97) + t.equal(bl.get(1), 98) + t.equal(bl.get(2), 99) + t.equal(bl.get(3), 100) + t.equal(bl.get(4), 101) + t.equal(bl.get(5), 102) + t.equal(bl.get(6), 103) + t.equal(bl.get(7), 104) + t.equal(bl.get(8), 105) + t.equal(bl.get(9), 106) + + t.end() +}) + +tape('multi bytes from single buffer', function (t) { + const bl = new BufferList() + + bl.append(Buffer.from('abcd')) + + t.equal(bl.length, 4) + + t.equal(bl.slice(0, 4).toString('ascii'), 'abcd') + t.equal(bl.slice(0, 3).toString('ascii'), 'abc') + t.equal(bl.slice(1, 4).toString('ascii'), 'bcd') + t.equal(bl.slice(-4, -1).toString('ascii'), 'abc') + + t.end() +}) + +tape('multi bytes from single buffer (negative indexes)', function (t) { + const bl = new BufferList() + + bl.append(Buffer.from('buffer')) + + t.equal(bl.length, 6) + + t.equal(bl.slice(-6, -1).toString('ascii'), 'buffe') + t.equal(bl.slice(-6, -2).toString('ascii'), 'buff') + t.equal(bl.slice(-5, -2).toString('ascii'), 'uff') + + t.end() +}) + +tape('multiple bytes from multiple buffers', function (t) { + const bl = new BufferList() + + bl.append(Buffer.from('abcd')) + bl.append(Buffer.from('efg')) + bl.append(Buffer.from('hi')) + bl.append(Buffer.from('j')) + + t.equal(bl.length, 10) + + t.equal(bl.slice(0, 10).toString('ascii'), 'abcdefghij') + t.equal(bl.slice(3, 10).toString('ascii'), 'defghij') + t.equal(bl.slice(3, 6).toString('ascii'), 'def') + t.equal(bl.slice(3, 8).toString('ascii'), 'defgh') + t.equal(bl.slice(5, 10).toString('ascii'), 'fghij') + t.equal(bl.slice(-7, -4).toString('ascii'), 'def') + + t.end() +}) + +tape('multiple bytes from multiple buffer lists', function (t) { + const bl = new BufferList() + + bl.append(new BufferList([Buffer.from('abcd'), Buffer.from('efg')])) + bl.append(new BufferList([Buffer.from('hi'), Buffer.from('j')])) + + t.equal(bl.length, 10) + + t.equal(bl.slice(0, 10).toString('ascii'), 'abcdefghij') + + t.equal(bl.slice(3, 10).toString('ascii'), 'defghij') + t.equal(bl.slice(3, 6).toString('ascii'), 'def') + t.equal(bl.slice(3, 8).toString('ascii'), 'defgh') + t.equal(bl.slice(5, 10).toString('ascii'), 'fghij') + + t.end() +}) + +// same data as previous test, just using nested constructors +tape('multiple bytes from crazy nested buffer lists', function (t) { + const bl = new BufferList() + + bl.append(new BufferList([ + new BufferList([ + new BufferList(Buffer.from('abc')), + Buffer.from('d'), + new BufferList(Buffer.from('efg')) + ]), + new BufferList([Buffer.from('hi')]), + new BufferList(Buffer.from('j')) + ])) + + t.equal(bl.length, 10) + + t.equal(bl.slice(0, 10).toString('ascii'), 'abcdefghij') + + t.equal(bl.slice(3, 10).toString('ascii'), 'defghij') + t.equal(bl.slice(3, 6).toString('ascii'), 'def') + t.equal(bl.slice(3, 8).toString('ascii'), 'defgh') + t.equal(bl.slice(5, 10).toString('ascii'), 'fghij') + + t.end() +}) + +tape('append accepts arrays of Buffers', function (t) { + const bl = new BufferList() + + bl.append(Buffer.from('abc')) + bl.append([Buffer.from('def')]) + bl.append([Buffer.from('ghi'), Buffer.from('jkl')]) + bl.append([Buffer.from('mnop'), Buffer.from('qrstu'), Buffer.from('vwxyz')]) + t.equal(bl.length, 26) + t.equal(bl.slice().toString('ascii'), 'abcdefghijklmnopqrstuvwxyz') + + t.end() +}) + +tape('append accepts arrays of Uint8Arrays', function (t) { + const bl = new BufferList() + + bl.append(new Uint8Array([97, 98, 99])) + bl.append([Uint8Array.from([100, 101, 102])]) + bl.append([new Uint8Array([103, 104, 105]), new Uint8Array([106, 107, 108])]) + bl.append([new Uint8Array([109, 110, 111, 112]), new Uint8Array([113, 114, 115, 116, 117]), new Uint8Array([118, 119, 120, 121, 122])]) + t.equal(bl.length, 26) + t.equal(bl.slice().toString('ascii'), 'abcdefghijklmnopqrstuvwxyz') + + t.end() +}) + +tape('append accepts arrays of BufferLists', function (t) { + const bl = new BufferList() + + bl.append(Buffer.from('abc')) + bl.append([new BufferList('def')]) + bl.append(new BufferList([Buffer.from('ghi'), new BufferList('jkl')])) + bl.append([Buffer.from('mnop'), new BufferList([Buffer.from('qrstu'), Buffer.from('vwxyz')])]) + t.equal(bl.length, 26) + t.equal(bl.slice().toString('ascii'), 'abcdefghijklmnopqrstuvwxyz') + + t.end() +}) + +tape('append chainable', function (t) { + const bl = new BufferList() + + t.ok(bl.append(Buffer.from('abcd')) === bl) + t.ok(bl.append([Buffer.from('abcd')]) === bl) + t.ok(bl.append(new BufferList(Buffer.from('abcd'))) === bl) + t.ok(bl.append([new BufferList(Buffer.from('abcd'))]) === bl) + + t.end() +}) + +tape('append chainable (test results)', function (t) { + const bl = new BufferList('abc') + .append([new BufferList('def')]) + .append(new BufferList([Buffer.from('ghi'), new BufferList('jkl')])) + .append([Buffer.from('mnop'), new BufferList([Buffer.from('qrstu'), Buffer.from('vwxyz')])]) + + t.equal(bl.length, 26) + t.equal(bl.slice().toString('ascii'), 'abcdefghijklmnopqrstuvwxyz') + + t.end() +}) + +tape('consuming from multiple buffers', function (t) { + const bl = new BufferList() + + bl.append(Buffer.from('abcd')) + bl.append(Buffer.from('efg')) + bl.append(Buffer.from('hi')) + bl.append(Buffer.from('j')) + + t.equal(bl.length, 10) + + t.equal(bl.slice(0, 10).toString('ascii'), 'abcdefghij') + + bl.consume(3) + t.equal(bl.length, 7) + t.equal(bl.slice(0, 7).toString('ascii'), 'defghij') + + bl.consume(2) + t.equal(bl.length, 5) + t.equal(bl.slice(0, 5).toString('ascii'), 'fghij') + + bl.consume(1) + t.equal(bl.length, 4) + t.equal(bl.slice(0, 4).toString('ascii'), 'ghij') + + bl.consume(1) + t.equal(bl.length, 3) + t.equal(bl.slice(0, 3).toString('ascii'), 'hij') + + bl.consume(2) + t.equal(bl.length, 1) + t.equal(bl.slice(0, 1).toString('ascii'), 'j') + + t.end() +}) + +tape('complete consumption', function (t) { + const bl = new BufferList() + + bl.append(Buffer.from('a')) + bl.append(Buffer.from('b')) + + bl.consume(2) + + t.equal(bl.length, 0) + t.equal(bl._bufs.length, 0) + + t.end() +}) + +tape('test readUInt8 / readInt8', function (t) { + const buf1 = Buffer.alloc(1) + const buf2 = Buffer.alloc(3) + const buf3 = Buffer.alloc(3) + const bl = new BufferList() + + buf1[0] = 0x1 + buf2[1] = 0x3 + buf2[2] = 0x4 + buf3[0] = 0x23 + buf3[1] = 0x42 + + bl.append(buf1) + bl.append(buf2) + bl.append(buf3) + + t.equal(bl.readUInt8(), 0x1) + t.equal(bl.readUInt8(2), 0x3) + t.equal(bl.readInt8(2), 0x3) + t.equal(bl.readUInt8(3), 0x4) + t.equal(bl.readInt8(3), 0x4) + t.equal(bl.readUInt8(4), 0x23) + t.equal(bl.readInt8(4), 0x23) + t.equal(bl.readUInt8(5), 0x42) + t.equal(bl.readInt8(5), 0x42) + + t.end() +}) + +tape('test readUInt16LE / readUInt16BE / readInt16LE / readInt16BE', function (t) { + const buf1 = Buffer.alloc(1) + const buf2 = Buffer.alloc(3) + const buf3 = Buffer.alloc(3) + const bl = new BufferList() + + buf1[0] = 0x1 + buf2[1] = 0x3 + buf2[2] = 0x4 + buf3[0] = 0x23 + buf3[1] = 0x42 + + bl.append(buf1) + bl.append(buf2) + bl.append(buf3) + + t.equal(bl.readUInt16BE(), 0x0100) + t.equal(bl.readUInt16LE(), 0x0001) + t.equal(bl.readUInt16BE(2), 0x0304) + t.equal(bl.readUInt16LE(2), 0x0403) + t.equal(bl.readInt16BE(2), 0x0304) + t.equal(bl.readInt16LE(2), 0x0403) + t.equal(bl.readUInt16BE(3), 0x0423) + t.equal(bl.readUInt16LE(3), 0x2304) + t.equal(bl.readInt16BE(3), 0x0423) + t.equal(bl.readInt16LE(3), 0x2304) + t.equal(bl.readUInt16BE(4), 0x2342) + t.equal(bl.readUInt16LE(4), 0x4223) + t.equal(bl.readInt16BE(4), 0x2342) + t.equal(bl.readInt16LE(4), 0x4223) + + t.end() +}) + +tape('test readUInt32LE / readUInt32BE / readInt32LE / readInt32BE', function (t) { + const buf1 = Buffer.alloc(1) + const buf2 = Buffer.alloc(3) + const buf3 = Buffer.alloc(3) + const bl = new BufferList() + + buf1[0] = 0x1 + buf2[1] = 0x3 + buf2[2] = 0x4 + buf3[0] = 0x23 + buf3[1] = 0x42 + + bl.append(buf1) + bl.append(buf2) + bl.append(buf3) + + t.equal(bl.readUInt32BE(), 0x01000304) + t.equal(bl.readUInt32LE(), 0x04030001) + t.equal(bl.readUInt32BE(2), 0x03042342) + t.equal(bl.readUInt32LE(2), 0x42230403) + t.equal(bl.readInt32BE(2), 0x03042342) + t.equal(bl.readInt32LE(2), 0x42230403) + + t.end() +}) + +tape('test readUIntLE / readUIntBE / readIntLE / readIntBE', function (t) { + const buf1 = Buffer.alloc(1) + const buf2 = Buffer.alloc(3) + const buf3 = Buffer.alloc(3) + const bl = new BufferList() + + buf2[0] = 0x2 + buf2[1] = 0x3 + buf2[2] = 0x4 + buf3[0] = 0x23 + buf3[1] = 0x42 + buf3[2] = 0x61 + + bl.append(buf1) + bl.append(buf2) + bl.append(buf3) + + t.equal(bl.readUIntBE(1, 1), 0x02) + t.equal(bl.readUIntBE(1, 2), 0x0203) + t.equal(bl.readUIntBE(1, 3), 0x020304) + t.equal(bl.readUIntBE(1, 4), 0x02030423) + t.equal(bl.readUIntBE(1, 5), 0x0203042342) + t.equal(bl.readUIntBE(1, 6), 0x020304234261) + t.equal(bl.readUIntLE(1, 1), 0x02) + t.equal(bl.readUIntLE(1, 2), 0x0302) + t.equal(bl.readUIntLE(1, 3), 0x040302) + t.equal(bl.readUIntLE(1, 4), 0x23040302) + t.equal(bl.readUIntLE(1, 5), 0x4223040302) + t.equal(bl.readUIntLE(1, 6), 0x614223040302) + t.equal(bl.readIntBE(1, 1), 0x02) + t.equal(bl.readIntBE(1, 2), 0x0203) + t.equal(bl.readIntBE(1, 3), 0x020304) + t.equal(bl.readIntBE(1, 4), 0x02030423) + t.equal(bl.readIntBE(1, 5), 0x0203042342) + t.equal(bl.readIntBE(1, 6), 0x020304234261) + t.equal(bl.readIntLE(1, 1), 0x02) + t.equal(bl.readIntLE(1, 2), 0x0302) + t.equal(bl.readIntLE(1, 3), 0x040302) + t.equal(bl.readIntLE(1, 4), 0x23040302) + t.equal(bl.readIntLE(1, 5), 0x4223040302) + t.equal(bl.readIntLE(1, 6), 0x614223040302) + + t.end() +}) + +tape('test readFloatLE / readFloatBE', function (t) { + const buf1 = Buffer.alloc(1) + const buf2 = Buffer.alloc(3) + const buf3 = Buffer.alloc(3) + const bl = new BufferList() + + buf1[0] = 0x01 + buf2[1] = 0x00 + buf2[2] = 0x00 + buf3[0] = 0x80 + buf3[1] = 0x3f + + bl.append(buf1) + bl.append(buf2) + bl.append(buf3) + + const canonical = Buffer.concat([buf1, buf2, buf3]) + t.equal(bl.readFloatLE(), canonical.readFloatLE()) + t.equal(bl.readFloatBE(), canonical.readFloatBE()) + t.equal(bl.readFloatLE(2), canonical.readFloatLE(2)) + t.equal(bl.readFloatBE(2), canonical.readFloatBE(2)) + + t.end() +}) + +tape('test readDoubleLE / readDoubleBE', function (t) { + const buf1 = Buffer.alloc(1) + const buf2 = Buffer.alloc(3) + const buf3 = Buffer.alloc(10) + const bl = new BufferList() + + buf1[0] = 0x01 + buf2[1] = 0x55 + buf2[2] = 0x55 + buf3[0] = 0x55 + buf3[1] = 0x55 + buf3[2] = 0x55 + buf3[3] = 0x55 + buf3[4] = 0xd5 + buf3[5] = 0x3f + + bl.append(buf1) + bl.append(buf2) + bl.append(buf3) + + const canonical = Buffer.concat([buf1, buf2, buf3]) + t.equal(bl.readDoubleBE(), canonical.readDoubleBE()) + t.equal(bl.readDoubleLE(), canonical.readDoubleLE()) + t.equal(bl.readDoubleBE(2), canonical.readDoubleBE(2)) + t.equal(bl.readDoubleLE(2), canonical.readDoubleLE(2)) + + t.end() +}) + +tape('test toString', function (t) { + const bl = new BufferList() + + bl.append(Buffer.from('abcd')) + bl.append(Buffer.from('efg')) + bl.append(Buffer.from('hi')) + bl.append(Buffer.from('j')) + + t.equal(bl.toString('ascii', 0, 10), 'abcdefghij') + t.equal(bl.toString('ascii', 3, 10), 'defghij') + t.equal(bl.toString('ascii', 3, 6), 'def') + t.equal(bl.toString('ascii', 3, 8), 'defgh') + t.equal(bl.toString('ascii', 5, 10), 'fghij') + + t.end() +}) + +tape('test toString encoding', function (t) { + const bl = new BufferList() + const b = Buffer.from('abcdefghij\xff\x00') + + bl.append(Buffer.from('abcd')) + bl.append(Buffer.from('efg')) + bl.append(Buffer.from('hi')) + bl.append(Buffer.from('j')) + bl.append(Buffer.from('\xff\x00')) + + encodings.forEach(function (enc) { + t.equal(bl.toString(enc), b.toString(enc), enc) + }) + + t.end() +}) + +tape('uninitialized memory', function (t) { + const secret = crypto.randomBytes(256) + for (let i = 0; i < 1e6; i++) { + const clone = Buffer.from(secret) + const bl = new BufferList() + bl.append(Buffer.from('a')) + bl.consume(-1024) + const buf = bl.slice(1) + if (buf.indexOf(clone) !== -1) { + t.fail(`Match (at ${i})`) + break + } + } + t.end() +}) + +!process.browser && tape('test stream', function (t) { + const random = crypto.randomBytes(65534) + + const bl = new BufferList((err, buf) => { + t.ok(Buffer.isBuffer(buf)) + t.ok(err === null) + t.ok(random.equals(bl.slice())) + t.ok(random.equals(buf.slice())) + + bl.pipe(fs.createWriteStream('/tmp/bl_test_rnd_out.dat')) + .on('close', function () { + const rndhash = crypto.createHash('md5').update(random).digest('hex') + const md5sum = crypto.createHash('md5') + const s = fs.createReadStream('/tmp/bl_test_rnd_out.dat') + + s.on('data', md5sum.update.bind(md5sum)) + s.on('end', function () { + t.equal(rndhash, md5sum.digest('hex'), 'woohoo! correct hash!') + t.end() + }) + }) + }) + + fs.writeFileSync('/tmp/bl_test_rnd.dat', random) + fs.createReadStream('/tmp/bl_test_rnd.dat').pipe(bl) +}) + +tape('instantiation with Buffer', function (t) { + const buf = crypto.randomBytes(1024) + const buf2 = crypto.randomBytes(1024) + let b = BufferList(buf) + + t.equal(buf.toString('hex'), b.slice().toString('hex'), 'same buffer') + b = BufferList([buf, buf2]) + t.equal(b.slice().toString('hex'), Buffer.concat([buf, buf2]).toString('hex'), 'same buffer') + + t.end() +}) + +tape('test String appendage', function (t) { + const bl = new BufferList() + const b = Buffer.from('abcdefghij\xff\x00') + + bl.append('abcd') + bl.append('efg') + bl.append('hi') + bl.append('j') + bl.append('\xff\x00') + + encodings.forEach(function (enc) { + t.equal(bl.toString(enc), b.toString(enc)) + }) + + t.end() +}) + +tape('test Number appendage', function (t) { + const bl = new BufferList() + const b = Buffer.from('1234567890') + + bl.append(1234) + bl.append(567) + bl.append(89) + bl.append(0) + + encodings.forEach(function (enc) { + t.equal(bl.toString(enc), b.toString(enc)) + }) + + t.end() +}) + +tape('write nothing, should get empty buffer', function (t) { + t.plan(3) + BufferList(function (err, data) { + t.notOk(err, 'no error') + t.ok(Buffer.isBuffer(data), 'got a buffer') + t.equal(0, data.length, 'got a zero-length buffer') + t.end() + }).end() +}) + +tape('unicode string', function (t) { + t.plan(2) + + const inp1 = '\u2600' + const inp2 = '\u2603' + const exp = inp1 + ' and ' + inp2 + const bl = BufferList() + + bl.write(inp1) + bl.write(' and ') + bl.write(inp2) + t.equal(exp, bl.toString()) + t.equal(Buffer.from(exp).toString('hex'), bl.toString('hex')) +}) + +tape('should emit finish', function (t) { + const source = BufferList() + const dest = BufferList() + + source.write('hello') + source.pipe(dest) + + dest.on('finish', function () { + t.equal(dest.toString('utf8'), 'hello') + t.end() + }) +}) + +tape('basic copy', function (t) { + const buf = crypto.randomBytes(1024) + const buf2 = Buffer.alloc(1024) + const b = BufferList(buf) + + b.copy(buf2) + t.equal(b.slice().toString('hex'), buf2.toString('hex'), 'same buffer') + + t.end() +}) + +tape('copy after many appends', function (t) { + const buf = crypto.randomBytes(512) + const buf2 = Buffer.alloc(1024) + const b = BufferList(buf) + + b.append(buf) + b.copy(buf2) + t.equal(b.slice().toString('hex'), buf2.toString('hex'), 'same buffer') + + t.end() +}) + +tape('copy at a precise position', function (t) { + const buf = crypto.randomBytes(1004) + const buf2 = Buffer.alloc(1024) + const b = BufferList(buf) + + b.copy(buf2, 20) + t.equal(b.slice().toString('hex'), buf2.slice(20).toString('hex'), 'same buffer') + + t.end() +}) + +tape('copy starting from a precise location', function (t) { + const buf = crypto.randomBytes(10) + const buf2 = Buffer.alloc(5) + const b = BufferList(buf) + + b.copy(buf2, 0, 5) + t.equal(b.slice(5).toString('hex'), buf2.toString('hex'), 'same buffer') + + t.end() +}) + +tape('copy in an interval', function (t) { + const rnd = crypto.randomBytes(10) + const b = BufferList(rnd) // put the random bytes there + const actual = Buffer.alloc(3) + const expected = Buffer.alloc(3) + + rnd.copy(expected, 0, 5, 8) + b.copy(actual, 0, 5, 8) + + t.equal(actual.toString('hex'), expected.toString('hex'), 'same buffer') + + t.end() +}) + +tape('copy an interval between two buffers', function (t) { + const buf = crypto.randomBytes(10) + const buf2 = Buffer.alloc(10) + const b = BufferList(buf) + + b.append(buf) + b.copy(buf2, 0, 5, 15) + + t.equal(b.slice(5, 15).toString('hex'), buf2.toString('hex'), 'same buffer') + + t.end() +}) + +tape('shallow slice across buffer boundaries', function (t) { + const bl = new BufferList(['First', 'Second', 'Third']) + + t.equal(bl.shallowSlice(3, 13).toString(), 'stSecondTh') + + t.end() +}) + +tape('shallow slice within single buffer', function (t) { + t.plan(2) + + const bl = new BufferList(['First', 'Second', 'Third']) + + t.equal(bl.shallowSlice(5, 10).toString(), 'Secon') + t.equal(bl.shallowSlice(7, 10).toString(), 'con') + + t.end() +}) + +tape('shallow slice single buffer', function (t) { + t.plan(3) + + const bl = new BufferList(['First', 'Second', 'Third']) + + t.equal(bl.shallowSlice(0, 5).toString(), 'First') + t.equal(bl.shallowSlice(5, 11).toString(), 'Second') + t.equal(bl.shallowSlice(11, 16).toString(), 'Third') +}) + +tape('shallow slice with negative or omitted indices', function (t) { + t.plan(4) + + const bl = new BufferList(['First', 'Second', 'Third']) + + t.equal(bl.shallowSlice().toString(), 'FirstSecondThird') + t.equal(bl.shallowSlice(5).toString(), 'SecondThird') + t.equal(bl.shallowSlice(5, -3).toString(), 'SecondTh') + t.equal(bl.shallowSlice(-8).toString(), 'ondThird') +}) + +tape('shallow slice does not make a copy', function (t) { + t.plan(1) + + const buffers = [Buffer.from('First'), Buffer.from('Second'), Buffer.from('Third')] + const bl = (new BufferList(buffers)).shallowSlice(5, -3) + + buffers[1].fill('h') + buffers[2].fill('h') + + t.equal(bl.toString(), 'hhhhhhhh') +}) + +tape('shallow slice with 0 length', function (t) { + t.plan(1) + + const buffers = [Buffer.from('First'), Buffer.from('Second'), Buffer.from('Third')] + const bl = (new BufferList(buffers)).shallowSlice(0, 0) + + t.equal(bl.length, 0) +}) + +tape('shallow slice with 0 length from middle', function (t) { + t.plan(1) + + const buffers = [Buffer.from('First'), Buffer.from('Second'), Buffer.from('Third')] + const bl = (new BufferList(buffers)).shallowSlice(10, 10) + + t.equal(bl.length, 0) +}) + +tape('duplicate', function (t) { + t.plan(2) + + const bl = new BufferList('abcdefghij\xff\x00') + const dup = bl.duplicate() + + t.equal(bl.prototype, dup.prototype) + t.equal(bl.toString('hex'), dup.toString('hex')) +}) + +tape('destroy no pipe', function (t) { + t.plan(2) + + const bl = new BufferList('alsdkfja;lsdkfja;lsdk') + + bl.destroy() + + t.equal(bl._bufs.length, 0) + t.equal(bl.length, 0) +}) + +tape('destroy with error', function (t) { + t.plan(3) + + const bl = new BufferList('alsdkfja;lsdkfja;lsdk') + const err = new Error('kaboom') + + bl.destroy(err) + bl.on('error', function (_err) { + t.equal(_err, err) + }) + + t.equal(bl._bufs.length, 0) + t.equal(bl.length, 0) +}) + +!process.browser && tape('destroy with pipe before read end', function (t) { + t.plan(2) + + const bl = new BufferList() + fs.createReadStream(path.join(__dirname, '/test.js')) + .pipe(bl) + + bl.destroy() + + t.equal(bl._bufs.length, 0) + t.equal(bl.length, 0) +}) + +!process.browser && tape('destroy with pipe before read end with race', function (t) { + t.plan(2) + + const bl = new BufferList() + + fs.createReadStream(path.join(__dirname, '/test.js')) + .pipe(bl) + + setTimeout(function () { + bl.destroy() + setTimeout(function () { + t.equal(bl._bufs.length, 0) + t.equal(bl.length, 0) + }, 500) + }, 500) +}) + +!process.browser && tape('destroy with pipe after read end', function (t) { + t.plan(2) + + const bl = new BufferList() + + fs.createReadStream(path.join(__dirname, '/test.js')) + .on('end', onEnd) + .pipe(bl) + + function onEnd () { + bl.destroy() + + t.equal(bl._bufs.length, 0) + t.equal(bl.length, 0) + } +}) + +!process.browser && tape('destroy with pipe while writing to a destination', function (t) { + t.plan(4) + + const bl = new BufferList() + const ds = new BufferList() + + fs.createReadStream(path.join(__dirname, '/test.js')) + .on('end', onEnd) + .pipe(bl) + + function onEnd () { + bl.pipe(ds) + + setTimeout(function () { + bl.destroy() + + t.equals(bl._bufs.length, 0) + t.equals(bl.length, 0) + + ds.destroy() + + t.equals(bl._bufs.length, 0) + t.equals(bl.length, 0) + }, 100) + } +}) + +!process.browser && tape('handle error', function (t) { + t.plan(2) + + fs.createReadStream('/does/not/exist').pipe(BufferList(function (err, data) { + t.ok(err instanceof Error, 'has error') + t.notOk(data, 'no data') + })) +}) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/LICENSE new file mode 100644 index 000000000..386b7b694 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2015 Douglas Christopher Wilson + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/README.md new file mode 100644 index 000000000..31b66ce06 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/README.md @@ -0,0 +1,494 @@ +# body-parser + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Build Status][ci-image]][ci-url] +[![Test Coverage][coveralls-image]][coveralls-url] +[![OpenSSF Scorecard Badge][ossf-scorecard-badge]][ossf-scorecard-visualizer] + +Node.js body parsing middleware. + +Parse incoming request bodies in a middleware before your handlers, available +under the `req.body` property. + +**Note** As `req.body`'s shape is based on user-controlled input, all +properties and values in this object are untrusted and should be validated +before trusting. For example, `req.body.foo.toString()` may fail in multiple +ways, for example the `foo` property may not be there or may not be a string, +and `toString` may not be a function and instead a string or other user input. + +[Learn about the anatomy of an HTTP transaction in Node.js](https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/). + +_This does not handle multipart bodies_, due to their complex and typically +large nature. For multipart bodies, you may be interested in the following +modules: + + * [busboy](https://www.npmjs.org/package/busboy#readme) and + [connect-busboy](https://www.npmjs.org/package/connect-busboy#readme) + * [multiparty](https://www.npmjs.org/package/multiparty#readme) and + [connect-multiparty](https://www.npmjs.org/package/connect-multiparty#readme) + * [formidable](https://www.npmjs.org/package/formidable#readme) + * [multer](https://www.npmjs.org/package/multer#readme) + +This module provides the following parsers: + + * [JSON body parser](#bodyparserjsonoptions) + * [Raw body parser](#bodyparserrawoptions) + * [Text body parser](#bodyparsertextoptions) + * [URL-encoded form body parser](#bodyparserurlencodedoptions) + +Other body parsers you might be interested in: + +- [body](https://www.npmjs.org/package/body#readme) +- [co-body](https://www.npmjs.org/package/co-body#readme) + +## Installation + +```sh +$ npm install body-parser +``` + +## API + +```js +const bodyParser = require('body-parser') +``` + +The `bodyParser` object exposes various factories to create middlewares. All +middlewares will populate the `req.body` property with the parsed body when +the `Content-Type` request header matches the `type` option. + +The various errors returned by this module are described in the +[errors section](#errors). + +### bodyParser.json([options]) + +Returns middleware that only parses `json` and only looks at requests where +the `Content-Type` header matches the `type` option. This parser accepts any +Unicode encoding of the body and supports automatic inflation of `gzip`, +`br` (brotli) and `deflate` encodings. + +A new `body` object containing the parsed data is populated on the `request` +object after the middleware (i.e. `req.body`). + +#### Options + +The `json` function takes an optional `options` object that may contain any of +the following keys: + +##### defaultCharset + +Specify the default character set for the json content if the charset is not +specified in the `Content-Type` header of the request. Defaults to `utf-8`. + +##### inflate + +When set to `true`, then deflated (compressed) bodies will be inflated; when +`false`, deflated bodies are rejected. Defaults to `true`. + +##### limit + +Controls the maximum request body size. If this is a number, then the value +specifies the number of bytes; if it is a string, the value is passed to the +[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults +to `'100kb'`. + +##### reviver + +The `reviver` option is passed directly to `JSON.parse` as the second +argument. You can find more information on this argument +[in the MDN documentation about JSON.parse](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Example.3A_Using_the_reviver_parameter). + +##### strict + +When set to `true`, will only accept arrays and objects; when `false` will +accept anything `JSON.parse` accepts. Defaults to `true`. + +##### type + +The `type` option is used to determine what media type the middleware will +parse. This option can be a string, array of strings, or a function. If not a +function, `type` option is passed directly to the +[type-is](https://www.npmjs.org/package/type-is#readme) library and this can +be an extension name (like `json`), a mime type (like `application/json`), or +a mime type with a wildcard (like `*/*` or `*/json`). If a function, the `type` +option is called as `fn(req)` and the request is parsed if it returns a truthy +value. Defaults to `application/json`. + +##### verify + +The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, +where `buf` is a `Buffer` of the raw request body and `encoding` is the +encoding of the request. The parsing can be aborted by throwing an error. + +### bodyParser.raw([options]) + +Returns middleware that parses all bodies as a `Buffer` and only looks at +requests where the `Content-Type` header matches the `type` option. This +parser supports automatic inflation of `gzip`, `br` (brotli) and `deflate` +encodings. + +A new `body` object containing the parsed data is populated on the `request` +object after the middleware (i.e. `req.body`). This will be a `Buffer` object +of the body. + +#### Options + +The `raw` function takes an optional `options` object that may contain any of +the following keys: + +##### inflate + +When set to `true`, then deflated (compressed) bodies will be inflated; when +`false`, deflated bodies are rejected. Defaults to `true`. + +##### limit + +Controls the maximum request body size. If this is a number, then the value +specifies the number of bytes; if it is a string, the value is passed to the +[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults +to `'100kb'`. + +##### type + +The `type` option is used to determine what media type the middleware will +parse. This option can be a string, array of strings, or a function. +If not a function, `type` option is passed directly to the +[type-is](https://www.npmjs.org/package/type-is#readme) library and this +can be an extension name (like `bin`), a mime type (like +`application/octet-stream`), or a mime type with a wildcard (like `*/*` or +`application/*`). If a function, the `type` option is called as `fn(req)` +and the request is parsed if it returns a truthy value. Defaults to +`application/octet-stream`. + +##### verify + +The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, +where `buf` is a `Buffer` of the raw request body and `encoding` is the +encoding of the request. The parsing can be aborted by throwing an error. + +### bodyParser.text([options]) + +Returns middleware that parses all bodies as a string and only looks at +requests where the `Content-Type` header matches the `type` option. This +parser supports automatic inflation of `gzip`, `br` (brotli) and `deflate` +encodings. + +A new `body` string containing the parsed data is populated on the `request` +object after the middleware (i.e. `req.body`). This will be a string of the +body. + +#### Options + +The `text` function takes an optional `options` object that may contain any of +the following keys: + +##### defaultCharset + +Specify the default character set for the text content if the charset is not +specified in the `Content-Type` header of the request. Defaults to `utf-8`. + +##### inflate + +When set to `true`, then deflated (compressed) bodies will be inflated; when +`false`, deflated bodies are rejected. Defaults to `true`. + +##### limit + +Controls the maximum request body size. If this is a number, then the value +specifies the number of bytes; if it is a string, the value is passed to the +[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults +to `'100kb'`. + +##### type + +The `type` option is used to determine what media type the middleware will +parse. This option can be a string, array of strings, or a function. If not +a function, `type` option is passed directly to the +[type-is](https://www.npmjs.org/package/type-is#readme) library and this can +be an extension name (like `txt`), a mime type (like `text/plain`), or a mime +type with a wildcard (like `*/*` or `text/*`). If a function, the `type` +option is called as `fn(req)` and the request is parsed if it returns a +truthy value. Defaults to `text/plain`. + +##### verify + +The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, +where `buf` is a `Buffer` of the raw request body and `encoding` is the +encoding of the request. The parsing can be aborted by throwing an error. + +### bodyParser.urlencoded([options]) + +Returns middleware that only parses `urlencoded` bodies and only looks at +requests where the `Content-Type` header matches the `type` option. This +parser accepts only UTF-8 encoding of the body and supports automatic +inflation of `gzip`, `br` (brotli) and `deflate` encodings. + +A new `body` object containing the parsed data is populated on the `request` +object after the middleware (i.e. `req.body`). This object will contain +key-value pairs, where the value can be a string or array (when `extended` is +`false`), or any type (when `extended` is `true`). + +#### Options + +The `urlencoded` function takes an optional `options` object that may contain +any of the following keys: + +##### extended + +The "extended" syntax allows for rich objects and arrays to be encoded into the +URL-encoded format, allowing for a JSON-like experience with URL-encoded. For +more information, please [see the qs +library](https://www.npmjs.org/package/qs#readme). + +Defaults to `false`. + +##### inflate + +When set to `true`, then deflated (compressed) bodies will be inflated; when +`false`, deflated bodies are rejected. Defaults to `true`. + +##### limit + +Controls the maximum request body size. If this is a number, then the value +specifies the number of bytes; if it is a string, the value is passed to the +[bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults +to `'100kb'`. + +##### parameterLimit + +The `parameterLimit` option controls the maximum number of parameters that +are allowed in the URL-encoded data. If a request contains more parameters +than this value, a 413 will be returned to the client. Defaults to `1000`. + +##### type + +The `type` option is used to determine what media type the middleware will +parse. This option can be a string, array of strings, or a function. If not +a function, `type` option is passed directly to the +[type-is](https://www.npmjs.org/package/type-is#readme) library and this can +be an extension name (like `urlencoded`), a mime type (like +`application/x-www-form-urlencoded`), or a mime type with a wildcard (like +`*/x-www-form-urlencoded`). If a function, the `type` option is called as +`fn(req)` and the request is parsed if it returns a truthy value. Defaults +to `application/x-www-form-urlencoded`. + +##### verify + +The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, +where `buf` is a `Buffer` of the raw request body and `encoding` is the +encoding of the request. The parsing can be aborted by throwing an error. + +##### defaultCharset + +The default charset to parse as, if not specified in content-type. Must be +either `utf-8` or `iso-8859-1`. Defaults to `utf-8`. + +##### charsetSentinel + +Whether to let the value of the `utf8` parameter take precedence as the charset +selector. It requires the form to contain a parameter named `utf8` with a value +of `✓`. Defaults to `false`. + +##### interpretNumericEntities + +Whether to decode numeric entities such as `☺` when parsing an iso-8859-1 +form. Defaults to `false`. + + +##### depth + +The `depth` option is used to configure the maximum depth of the `qs` library when `extended` is `true`. This allows you to limit the amount of keys that are parsed and can be useful to prevent certain types of abuse. Defaults to `32`. It is recommended to keep this value as low as possible. + +## Errors + +The middlewares provided by this module create errors using the +[`http-errors` module](https://www.npmjs.com/package/http-errors). The errors +will typically have a `status`/`statusCode` property that contains the suggested +HTTP response code, an `expose` property to determine if the `message` property +should be displayed to the client, a `type` property to determine the type of +error without matching against the `message`, and a `body` property containing +the read body, if available. + +The following are the common errors created, though any error can come through +for various reasons. + +### content encoding unsupported + +This error will occur when the request had a `Content-Encoding` header that +contained an encoding but the "inflation" option was set to `false`. The +`status` property is set to `415`, the `type` property is set to +`'encoding.unsupported'`, and the `charset` property will be set to the +encoding that is unsupported. + +### entity parse failed + +This error will occur when the request contained an entity that could not be +parsed by the middleware. The `status` property is set to `400`, the `type` +property is set to `'entity.parse.failed'`, and the `body` property is set to +the entity value that failed parsing. + +### entity verify failed + +This error will occur when the request contained an entity that could not be +failed verification by the defined `verify` option. The `status` property is +set to `403`, the `type` property is set to `'entity.verify.failed'`, and the +`body` property is set to the entity value that failed verification. + +### request aborted + +This error will occur when the request is aborted by the client before reading +the body has finished. The `received` property will be set to the number of +bytes received before the request was aborted and the `expected` property is +set to the number of expected bytes. The `status` property is set to `400` +and `type` property is set to `'request.aborted'`. + +### request entity too large + +This error will occur when the request body's size is larger than the "limit" +option. The `limit` property will be set to the byte limit and the `length` +property will be set to the request body's length. The `status` property is +set to `413` and the `type` property is set to `'entity.too.large'`. + +### request size did not match content length + +This error will occur when the request's length did not match the length from +the `Content-Length` header. This typically occurs when the request is malformed, +typically when the `Content-Length` header was calculated based on characters +instead of bytes. The `status` property is set to `400` and the `type` property +is set to `'request.size.invalid'`. + +### stream encoding should not be set + +This error will occur when something called the `req.setEncoding` method prior +to this middleware. This module operates directly on bytes only and you cannot +call `req.setEncoding` when using this module. The `status` property is set to +`500` and the `type` property is set to `'stream.encoding.set'`. + +### stream is not readable + +This error will occur when the request is no longer readable when this middleware +attempts to read it. This typically means something other than a middleware from +this module read the request body already and the middleware was also configured to +read the same request. The `status` property is set to `500` and the `type` +property is set to `'stream.not.readable'`. + +### too many parameters + +This error will occur when the content of the request exceeds the configured +`parameterLimit` for the `urlencoded` parser. The `status` property is set to +`413` and the `type` property is set to `'parameters.too.many'`. + +### unsupported charset "BOGUS" + +This error will occur when the request had a charset parameter in the +`Content-Type` header, but the `iconv-lite` module does not support it OR the +parser does not support it. The charset is contained in the message as well +as in the `charset` property. The `status` property is set to `415`, the +`type` property is set to `'charset.unsupported'`, and the `charset` property +is set to the charset that is unsupported. + +### unsupported content encoding "bogus" + +This error will occur when the request had a `Content-Encoding` header that +contained an unsupported encoding. The encoding is contained in the message +as well as in the `encoding` property. The `status` property is set to `415`, +the `type` property is set to `'encoding.unsupported'`, and the `encoding` +property is set to the encoding that is unsupported. + +### The input exceeded the depth + +This error occurs when using `bodyParser.urlencoded` with the `extended` property set to `true` and the input exceeds the configured `depth` option. The `status` property is set to `400`. It is recommended to review the `depth` option and evaluate if it requires a higher value. When the `depth` option is set to `32` (default value), the error will not be thrown. + +## Examples + +### Express/Connect top-level generic + +This example demonstrates adding a generic JSON and URL-encoded parser as a +top-level middleware, which will parse the bodies of all incoming requests. +This is the simplest setup. + +```js +const express = require('express') +const bodyParser = require('body-parser') + +const app = express() + +// parse application/x-www-form-urlencoded +app.use(bodyParser.urlencoded()) + +// parse application/json +app.use(bodyParser.json()) + +app.use(function (req, res) { + res.setHeader('Content-Type', 'text/plain') + res.write('you posted:\n') + res.end(String(JSON.stringify(req.body, null, 2))) +}) +``` + +### Express route-specific + +This example demonstrates adding body parsers specifically to the routes that +need them. In general, this is the most recommended way to use body-parser with +Express. + +```js +const express = require('express') +const bodyParser = require('body-parser') + +const app = express() + +// create application/json parser +const jsonParser = bodyParser.json() + +// create application/x-www-form-urlencoded parser +const urlencodedParser = bodyParser.urlencoded() + +// POST /login gets urlencoded bodies +app.post('/login', urlencodedParser, function (req, res) { + if (!req.body || !req.body.username) res.sendStatus(400) + res.send('welcome, ' + req.body.username) +}) + +// POST /api/users gets JSON bodies +app.post('/api/users', jsonParser, function (req, res) { + if (!req.body) res.sendStatus(400) + // create user in req.body +}) +``` + +### Change accepted type for parsers + +All the parsers accept a `type` option which allows you to change the +`Content-Type` that the middleware will parse. + +```js +const express = require('express') +const bodyParser = require('body-parser') + +const app = express() + +// parse various different custom JSON types as JSON +app.use(bodyParser.json({ type: 'application/*+json' })) + +// parse some custom thing into a Buffer +app.use(bodyParser.raw({ type: 'application/vnd.custom-type' })) + +// parse an HTML body into a string +app.use(bodyParser.text({ type: 'text/html' })) +``` + +## License + +[MIT](LICENSE) + +[ci-image]: https://img.shields.io/github/actions/workflow/status/expressjs/body-parser/ci.yml?branch=master&label=ci +[ci-url]: https://github.com/expressjs/body-parser/actions/workflows/ci.yml +[coveralls-image]: https://img.shields.io/coverallsCoverage/github/expressjs/body-parser?branch=master +[coveralls-url]: https://coveralls.io/r/expressjs/body-parser?branch=master +[npm-downloads-image]: https://img.shields.io/npm/dm/body-parser +[npm-url]: https://npmjs.org/package/body-parser +[npm-version-image]: https://img.shields.io/npm/v/body-parser +[ossf-scorecard-badge]: https://api.scorecard.dev/projects/github.com/expressjs/body-parser/badge +[ossf-scorecard-visualizer]: https://ossf.github.io/scorecard-visualizer/#/projects/github.com/expressjs/body-parser \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/index.js new file mode 100644 index 000000000..d722d0b23 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/index.js @@ -0,0 +1,80 @@ +/*! + * body-parser + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * @typedef Parsers + * @type {function} + * @property {function} json + * @property {function} raw + * @property {function} text + * @property {function} urlencoded + */ + +/** + * Module exports. + * @type {Parsers} + */ + +exports = module.exports = bodyParser + +/** + * JSON parser. + * @public + */ + +Object.defineProperty(exports, 'json', { + configurable: true, + enumerable: true, + get: () => require('./lib/types/json') +}) + +/** + * Raw parser. + * @public + */ + +Object.defineProperty(exports, 'raw', { + configurable: true, + enumerable: true, + get: () => require('./lib/types/raw') +}) + +/** + * Text parser. + * @public + */ + +Object.defineProperty(exports, 'text', { + configurable: true, + enumerable: true, + get: () => require('./lib/types/text') +}) + +/** + * URL-encoded parser. + * @public + */ + +Object.defineProperty(exports, 'urlencoded', { + configurable: true, + enumerable: true, + get: () => require('./lib/types/urlencoded') +}) + +/** + * Create a middleware to parse json and urlencoded bodies. + * + * @param {object} [options] + * @return {function} + * @deprecated + * @public + */ + +function bodyParser () { + throw new Error('The bodyParser() generic has been split into individual middleware to use instead.') +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/read.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/read.js new file mode 100644 index 000000000..b3f2345f2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/read.js @@ -0,0 +1,250 @@ +/*! + * body-parser + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var createError = require('http-errors') +var getBody = require('raw-body') +var iconv = require('iconv-lite') +var onFinished = require('on-finished') +var zlib = require('node:zlib') +var hasBody = require('type-is').hasBody +var { getCharset } = require('./utils') + +/** + * Module exports. + */ + +module.exports = read + +/** + * Read a request into a buffer and parse. + * + * @param {object} req + * @param {object} res + * @param {function} next + * @param {function} parse + * @param {function} debug + * @param {object} options + * @private + */ + +function read (req, res, next, parse, debug, options) { + if (onFinished.isFinished(req)) { + debug('body already parsed') + next() + return + } + + if (!('body' in req)) { + req.body = undefined + } + + // skip requests without bodies + if (!hasBody(req)) { + debug('skip empty body') + next() + return + } + + debug('content-type %j', req.headers['content-type']) + + // determine if request should be parsed + if (!options.shouldParse(req)) { + debug('skip parsing') + next() + return + } + + var encoding = null + if (options?.skipCharset !== true) { + encoding = getCharset(req) || options.defaultCharset + + // validate charset + if (!!options?.isValidCharset && !options.isValidCharset(encoding)) { + debug('invalid charset') + next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', { + charset: encoding, + type: 'charset.unsupported' + })) + return + } + } + + var length + var opts = options + var stream + + // read options + var verify = opts.verify + + try { + // get the content stream + stream = contentstream(req, debug, opts.inflate) + length = stream.length + stream.length = undefined + } catch (err) { + return next(err) + } + + // set raw-body options + opts.length = length + opts.encoding = verify + ? null + : encoding + + // assert charset is supported + if (opts.encoding === null && encoding !== null && !iconv.encodingExists(encoding)) { + return next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', { + charset: encoding.toLowerCase(), + type: 'charset.unsupported' + })) + } + + // read body + debug('read body') + getBody(stream, opts, function (error, body) { + if (error) { + var _error + + if (error.type === 'encoding.unsupported') { + // echo back charset + _error = createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', { + charset: encoding.toLowerCase(), + type: 'charset.unsupported' + }) + } else { + // set status code on error + _error = createError(400, error) + } + + // unpipe from stream and destroy + if (stream !== req) { + req.unpipe() + stream.destroy() + } + + // read off entire request + dump(req, function onfinished () { + next(createError(400, _error)) + }) + return + } + + // verify + if (verify) { + try { + debug('verify body') + verify(req, res, body, encoding) + } catch (err) { + next(createError(403, err, { + body: body, + type: err.type || 'entity.verify.failed' + })) + return + } + } + + // parse + var str = body + try { + debug('parse body') + str = typeof body !== 'string' && encoding !== null + ? iconv.decode(body, encoding) + : body + req.body = parse(str, encoding) + } catch (err) { + next(createError(400, err, { + body: str, + type: err.type || 'entity.parse.failed' + })) + return + } + + next() + }) +} + +/** + * Get the content stream of the request. + * + * @param {object} req + * @param {function} debug + * @param {boolean} [inflate=true] + * @return {object} + * @api private + */ + +function contentstream (req, debug, inflate) { + var encoding = (req.headers['content-encoding'] || 'identity').toLowerCase() + var length = req.headers['content-length'] + + debug('content-encoding "%s"', encoding) + + if (inflate === false && encoding !== 'identity') { + throw createError(415, 'content encoding unsupported', { + encoding: encoding, + type: 'encoding.unsupported' + }) + } + + if (encoding === 'identity') { + req.length = length + return req + } + + var stream = createDecompressionStream(encoding, debug) + req.pipe(stream) + return stream +} + +/** + * Create a decompression stream for the given encoding. + * @param {string} encoding + * @param {function} debug + * @return {object} + * @api private + */ +function createDecompressionStream (encoding, debug) { + switch (encoding) { + case 'deflate': + debug('inflate body') + return zlib.createInflate() + case 'gzip': + debug('gunzip body') + return zlib.createGunzip() + case 'br': + debug('brotli decompress body') + return zlib.createBrotliDecompress() + default: + throw createError(415, 'unsupported content encoding "' + encoding + '"', { + encoding: encoding, + type: 'encoding.unsupported' + }) + } +} + +/** + * Dump the contents of a request. + * + * @param {object} req + * @param {function} callback + * @api private + */ + +function dump (req, callback) { + if (onFinished.isFinished(req)) { + callback(null) + } else { + onFinished(req, callback) + req.resume() + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/json.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/json.js new file mode 100644 index 000000000..15c54bb4b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/json.js @@ -0,0 +1,166 @@ +/*! + * body-parser + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var debug = require('debug')('body-parser:json') +var read = require('../read') +var { normalizeOptions } = require('../utils') + +/** + * Module exports. + */ + +module.exports = json + +/** + * RegExp to match the first non-space in a string. + * + * Allowed whitespace is defined in RFC 7159: + * + * ws = *( + * %x20 / ; Space + * %x09 / ; Horizontal tab + * %x0A / ; Line feed or New line + * %x0D ) ; Carriage return + */ + +var FIRST_CHAR_REGEXP = /^[\x20\x09\x0a\x0d]*([^\x20\x09\x0a\x0d])/ // eslint-disable-line no-control-regex + +var JSON_SYNTAX_CHAR = '#' +var JSON_SYNTAX_REGEXP = /#+/g + +/** + * Create a middleware to parse JSON bodies. + * + * @param {object} [options] + * @return {function} + * @public + */ + +function json (options) { + const normalizedOptions = normalizeOptions(options, 'application/json') + + var reviver = options?.reviver + var strict = options?.strict !== false + + function parse (body) { + if (body.length === 0) { + // special-case empty json body, as it's a common client-side mistake + // TODO: maybe make this configurable or part of "strict" option + return {} + } + + if (strict) { + var first = firstchar(body) + + if (first !== '{' && first !== '[') { + debug('strict violation') + throw createStrictSyntaxError(body, first) + } + } + + try { + debug('parse json') + return JSON.parse(body, reviver) + } catch (e) { + throw normalizeJsonSyntaxError(e, { + message: e.message, + stack: e.stack + }) + } + } + + const readOptions = { + ...normalizedOptions, + // assert charset per RFC 7159 sec 8.1 + isValidCharset: (charset) => charset.slice(0, 4) === 'utf-' + } + + return function jsonParser (req, res, next) { + read(req, res, next, parse, debug, readOptions) + } +} + +/** + * Create strict violation syntax error matching native error. + * + * @param {string} str + * @param {string} char + * @return {Error} + * @private + */ + +function createStrictSyntaxError (str, char) { + var index = str.indexOf(char) + var partial = '' + + if (index !== -1) { + partial = str.substring(0, index) + JSON_SYNTAX_CHAR + + for (var i = index + 1; i < str.length; i++) { + partial += JSON_SYNTAX_CHAR + } + } + + try { + JSON.parse(partial); /* istanbul ignore next */ throw new SyntaxError('strict violation') + } catch (e) { + return normalizeJsonSyntaxError(e, { + message: e.message.replace(JSON_SYNTAX_REGEXP, function (placeholder) { + return str.substring(index, index + placeholder.length) + }), + stack: e.stack + }) + } +} + +/** + * Get the first non-whitespace character in a string. + * + * @param {string} str + * @return {function} + * @private + */ + +function firstchar (str) { + var match = FIRST_CHAR_REGEXP.exec(str) + + return match + ? match[1] + : undefined +} + +/** + * Normalize a SyntaxError for JSON.parse. + * + * @param {SyntaxError} error + * @param {object} obj + * @return {SyntaxError} + */ + +function normalizeJsonSyntaxError (error, obj) { + var keys = Object.getOwnPropertyNames(error) + + for (var i = 0; i < keys.length; i++) { + var key = keys[i] + if (key !== 'stack' && key !== 'message') { + delete error[key] + } + } + + // replace stack before message for Node.js 0.10 and below + error.stack = obj.stack.replace(error.message, obj.message) + error.message = obj.message + + return error +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/raw.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/raw.js new file mode 100644 index 000000000..04b1b88fa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/raw.js @@ -0,0 +1,43 @@ +/*! + * body-parser + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + */ + +var debug = require('debug')('body-parser:raw') +var read = require('../read') +var { normalizeOptions, passthrough } = require('../utils') + +/** + * Module exports. + */ + +module.exports = raw + +/** + * Create a middleware to parse raw bodies. + * + * @param {object} [options] + * @return {function} + * @api public + */ + +function raw (options) { + const normalizedOptions = normalizeOptions(options, 'application/octet-stream') + + const readOptions = { + ...normalizedOptions, + // Skip charset validation and parse the body as is + skipCharset: true + } + + return function rawParser (req, res, next) { + read(req, res, next, passthrough, debug, readOptions) + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/text.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/text.js new file mode 100644 index 000000000..d4c7e3b64 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/text.js @@ -0,0 +1,37 @@ +/*! + * body-parser + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + */ + +var debug = require('debug')('body-parser:text') +var read = require('../read') +var { normalizeOptions, passthrough } = require('../utils') + +/** + * Module exports. + */ + +module.exports = text + +/** + * Create a middleware to parse text bodies. + * + * @param {object} [options] + * @return {function} + * @api public + */ + +function text (options) { + const normalizedOptions = normalizeOptions(options, 'text/plain') + + return function textParser (req, res, next) { + read(req, res, next, passthrough, debug, normalizedOptions) + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/urlencoded.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/urlencoded.js new file mode 100644 index 000000000..924093736 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/types/urlencoded.js @@ -0,0 +1,142 @@ +/*! + * body-parser + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var createError = require('http-errors') +var debug = require('debug')('body-parser:urlencoded') +var read = require('../read') +var qs = require('qs') +var { normalizeOptions } = require('../utils') + +/** + * Module exports. + */ + +module.exports = urlencoded + +/** + * Create a middleware to parse urlencoded bodies. + * + * @param {object} [options] + * @return {function} + * @public + */ + +function urlencoded (options) { + const normalizedOptions = normalizeOptions(options, 'application/x-www-form-urlencoded') + + if (normalizedOptions.defaultCharset !== 'utf-8' && normalizedOptions.defaultCharset !== 'iso-8859-1') { + throw new TypeError('option defaultCharset must be either utf-8 or iso-8859-1') + } + + // create the appropriate query parser + var queryparse = createQueryParser(options) + + function parse (body, encoding) { + return body.length + ? queryparse(body, encoding) + : {} + } + + const readOptions = { + ...normalizedOptions, + // assert charset + isValidCharset: (charset) => charset === 'utf-8' || charset === 'iso-8859-1' + } + + return function urlencodedParser (req, res, next) { + read(req, res, next, parse, debug, readOptions) + } +} + +/** + * Get the extended query parser. + * + * @param {object} options + */ + +function createQueryParser (options) { + var extended = Boolean(options?.extended) + var parameterLimit = options?.parameterLimit !== undefined + ? options?.parameterLimit + : 1000 + var charsetSentinel = options?.charsetSentinel + var interpretNumericEntities = options?.interpretNumericEntities + var depth = extended ? (options?.depth !== undefined ? options?.depth : 32) : 0 + + if (isNaN(parameterLimit) || parameterLimit < 1) { + throw new TypeError('option parameterLimit must be a positive number') + } + + if (isNaN(depth) || depth < 0) { + throw new TypeError('option depth must be a zero or a positive number') + } + + if (isFinite(parameterLimit)) { + parameterLimit = parameterLimit | 0 + } + + return function queryparse (body, encoding) { + var paramCount = parameterCount(body, parameterLimit) + + if (paramCount === undefined) { + debug('too many parameters') + throw createError(413, 'too many parameters', { + type: 'parameters.too.many' + }) + } + + var arrayLimit = extended ? Math.max(100, paramCount) : 0 + + debug('parse ' + (extended ? 'extended ' : '') + 'urlencoding') + try { + return qs.parse(body, { + allowPrototypes: true, + arrayLimit: arrayLimit, + depth: depth, + charsetSentinel: charsetSentinel, + interpretNumericEntities: interpretNumericEntities, + charset: encoding, + parameterLimit: parameterLimit, + strictDepth: true + }) + } catch (err) { + if (err instanceof RangeError) { + throw createError(400, 'The input exceeded the depth', { + type: 'querystring.parse.rangeError' + }) + } else { + throw err + } + } + } +} + +/** + * Count the number of parameters, stopping once limit reached + * + * @param {string} body + * @param {number} limit + * @return {number|undefined} Returns undefined if limit exceeded + * @api private + */ +function parameterCount (body, limit) { + let count = 0 + let index = -1 + do { + count++ + if (count > limit) return undefined // Early exit if limit exceeded + index = body.indexOf('&', index + 1) + } while (index !== -1) + return count +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/utils.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/utils.js new file mode 100644 index 000000000..5634005f0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/lib/utils.js @@ -0,0 +1,96 @@ +'use strict' + +/** + * Module dependencies. + */ + +var bytes = require('bytes') +var contentType = require('content-type') +var typeis = require('type-is') + +/** + * Module exports. + */ +module.exports = { + getCharset, + normalizeOptions, + passthrough +} + +/** + * Get the charset of a request. + * + * @param {object} req + * @api private + */ + +function getCharset (req) { + try { + return (contentType.parse(req).parameters.charset || '').toLowerCase() + } catch { + return undefined + } +} + +/** + * Get the simple type checker. + * + * @param {string | string[]} type + * @return {function} + */ + +function typeChecker (type) { + return function checkType (req) { + return Boolean(typeis(req, type)) + } +} + +/** + * Normalizes the common options for all parsers. + * + * @param {object} options options to normalize + * @param {string | string[] | function} defaultType default content type(s) or a function to determine it + * @returns {object} + */ +function normalizeOptions (options, defaultType) { + if (!defaultType) { + // Parsers must define a default content type + throw new TypeError('defaultType must be provided') + } + + var inflate = options?.inflate !== false + var limit = typeof options?.limit !== 'number' + ? bytes.parse(options?.limit || '100kb') + : options?.limit + var type = options?.type || defaultType + var verify = options?.verify || false + var defaultCharset = options?.defaultCharset || 'utf-8' + + if (verify !== false && typeof verify !== 'function') { + throw new TypeError('option verify must be function') + } + + // create the appropriate type checking function + var shouldParse = typeof type !== 'function' + ? typeChecker(type) + : type + + return { + inflate, + limit, + verify, + defaultCharset, + shouldParse + } +} + +/** + * Passthrough function that returns input unchanged. + * Used by parsers that don't need to transform the data. + * + * @param {*} value + * @return {*} + */ +function passthrough (value) { + return value +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/package.json new file mode 100644 index 000000000..596133cd7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/body-parser/package.json @@ -0,0 +1,52 @@ +{ + "name": "body-parser", + "description": "Node.js body parsing middleware", + "version": "2.2.1", + "contributors": [ + "Douglas Christopher Wilson ", + "Jonathan Ong (http://jongleberry.com)" + ], + "license": "MIT", + "repository": "expressjs/body-parser", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + }, + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "devDependencies": { + "eslint": "^8.57.1", + "eslint-config-standard": "^14.1.1", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-markdown": "^3.0.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^6.6.0", + "eslint-plugin-standard": "^4.1.0", + "mocha": "^11.1.0", + "nyc": "^17.1.0", + "supertest": "^7.0.0" + }, + "files": [ + "lib/", + "LICENSE", + "index.js" + ], + "engines": { + "node": ">=18" + }, + "scripts": { + "lint": "eslint .", + "test": "mocha --reporter spec --check-leaks test/", + "test-ci": "nyc --reporter=lcovonly --reporter=text npm test", + "test-cov": "nyc --reporter=html --reporter=text npm test" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/LICENSE new file mode 100644 index 000000000..de3226673 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013 Julian Gruber + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/README.md new file mode 100644 index 000000000..6b4e0e164 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/README.md @@ -0,0 +1,129 @@ +# brace-expansion + +[Brace expansion](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html), +as known from sh/bash, in JavaScript. + +[![build status](https://secure.travis-ci.org/juliangruber/brace-expansion.svg)](http://travis-ci.org/juliangruber/brace-expansion) +[![downloads](https://img.shields.io/npm/dm/brace-expansion.svg)](https://www.npmjs.org/package/brace-expansion) +[![Greenkeeper badge](https://badges.greenkeeper.io/juliangruber/brace-expansion.svg)](https://greenkeeper.io/) + +[![testling badge](https://ci.testling.com/juliangruber/brace-expansion.png)](https://ci.testling.com/juliangruber/brace-expansion) + +## Example + +```js +var expand = require('brace-expansion'); + +expand('file-{a,b,c}.jpg') +// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg'] + +expand('-v{,,}') +// => ['-v', '-v', '-v'] + +expand('file{0..2}.jpg') +// => ['file0.jpg', 'file1.jpg', 'file2.jpg'] + +expand('file-{a..c}.jpg') +// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg'] + +expand('file{2..0}.jpg') +// => ['file2.jpg', 'file1.jpg', 'file0.jpg'] + +expand('file{0..4..2}.jpg') +// => ['file0.jpg', 'file2.jpg', 'file4.jpg'] + +expand('file-{a..e..2}.jpg') +// => ['file-a.jpg', 'file-c.jpg', 'file-e.jpg'] + +expand('file{00..10..5}.jpg') +// => ['file00.jpg', 'file05.jpg', 'file10.jpg'] + +expand('{{A..C},{a..c}}') +// => ['A', 'B', 'C', 'a', 'b', 'c'] + +expand('ppp{,config,oe{,conf}}') +// => ['ppp', 'pppconfig', 'pppoe', 'pppoeconf'] +``` + +## API + +```js +var expand = require('brace-expansion'); +``` + +### var expanded = expand(str) + +Return an array of all possible and valid expansions of `str`. If none are +found, `[str]` is returned. + +Valid expansions are: + +```js +/^(.*,)+(.+)?$/ +// {a,b,...} +``` + +A comma separated list of options, like `{a,b}` or `{a,{b,c}}` or `{,a,}`. + +```js +/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/ +// {x..y[..incr]} +``` + +A numeric sequence from `x` to `y` inclusive, with optional increment. +If `x` or `y` start with a leading `0`, all the numbers will be padded +to have equal length. Negative numbers and backwards iteration work too. + +```js +/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/ +// {x..y[..incr]} +``` + +An alphabetic sequence from `x` to `y` inclusive, with optional increment. +`x` and `y` must be exactly one character, and if given, `incr` must be a +number. + +For compatibility reasons, the string `${` is not eligible for brace expansion. + +## Installation + +With [npm](https://npmjs.org) do: + +```bash +npm install brace-expansion +``` + +## Contributors + +- [Julian Gruber](https://github.com/juliangruber) +- [Isaac Z. Schlueter](https://github.com/isaacs) + +## Sponsors + +This module is proudly supported by my [Sponsors](https://github.com/juliangruber/sponsors)! + +Do you want to support modules like this to improve their quality, stability and weigh in on new features? Then please consider donating to my [Patreon](https://www.patreon.com/juliangruber). Not sure how much of my modules you're using? Try [feross/thanks](https://github.com/feross/thanks)! + +## License + +(MIT) + +Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/index.js new file mode 100644 index 000000000..bd19fe685 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/index.js @@ -0,0 +1,201 @@ +var concatMap = require('concat-map'); +var balanced = require('balanced-match'); + +module.exports = expandTop; + +var escSlash = '\0SLASH'+Math.random()+'\0'; +var escOpen = '\0OPEN'+Math.random()+'\0'; +var escClose = '\0CLOSE'+Math.random()+'\0'; +var escComma = '\0COMMA'+Math.random()+'\0'; +var escPeriod = '\0PERIOD'+Math.random()+'\0'; + +function numeric(str) { + return parseInt(str, 10) == str + ? parseInt(str, 10) + : str.charCodeAt(0); +} + +function escapeBraces(str) { + return str.split('\\\\').join(escSlash) + .split('\\{').join(escOpen) + .split('\\}').join(escClose) + .split('\\,').join(escComma) + .split('\\.').join(escPeriod); +} + +function unescapeBraces(str) { + return str.split(escSlash).join('\\') + .split(escOpen).join('{') + .split(escClose).join('}') + .split(escComma).join(',') + .split(escPeriod).join('.'); +} + + +// Basically just str.split(","), but handling cases +// where we have nested braced sections, which should be +// treated as individual members, like {a,{b,c},d} +function parseCommaParts(str) { + if (!str) + return ['']; + + var parts = []; + var m = balanced('{', '}', str); + + if (!m) + return str.split(','); + + var pre = m.pre; + var body = m.body; + var post = m.post; + var p = pre.split(','); + + p[p.length-1] += '{' + body + '}'; + var postParts = parseCommaParts(post); + if (post.length) { + p[p.length-1] += postParts.shift(); + p.push.apply(p, postParts); + } + + parts.push.apply(parts, p); + + return parts; +} + +function expandTop(str) { + if (!str) + return []; + + // I don't know why Bash 4.3 does this, but it does. + // Anything starting with {} will have the first two bytes preserved + // but *only* at the top level, so {},a}b will not expand to anything, + // but a{},b}c will be expanded to [a}c,abc]. + // One could argue that this is a bug in Bash, but since the goal of + // this module is to match Bash's rules, we escape a leading {} + if (str.substr(0, 2) === '{}') { + str = '\\{\\}' + str.substr(2); + } + + return expand(escapeBraces(str), true).map(unescapeBraces); +} + +function identity(e) { + return e; +} + +function embrace(str) { + return '{' + str + '}'; +} +function isPadded(el) { + return /^-?0\d/.test(el); +} + +function lte(i, y) { + return i <= y; +} +function gte(i, y) { + return i >= y; +} + +function expand(str, isTop) { + var expansions = []; + + var m = balanced('{', '}', str); + if (!m || /\$$/.test(m.pre)) return [str]; + + var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body); + var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body); + var isSequence = isNumericSequence || isAlphaSequence; + var isOptions = m.body.indexOf(',') >= 0; + if (!isSequence && !isOptions) { + // {a},b} + if (m.post.match(/,(?!,).*\}/)) { + str = m.pre + '{' + m.body + escClose + m.post; + return expand(str); + } + return [str]; + } + + var n; + if (isSequence) { + n = m.body.split(/\.\./); + } else { + n = parseCommaParts(m.body); + if (n.length === 1) { + // x{{a,b}}y ==> x{a}y x{b}y + n = expand(n[0], false).map(embrace); + if (n.length === 1) { + var post = m.post.length + ? expand(m.post, false) + : ['']; + return post.map(function(p) { + return m.pre + n[0] + p; + }); + } + } + } + + // at this point, n is the parts, and we know it's not a comma set + // with a single entry. + + // no need to expand pre, since it is guaranteed to be free of brace-sets + var pre = m.pre; + var post = m.post.length + ? expand(m.post, false) + : ['']; + + var N; + + if (isSequence) { + var x = numeric(n[0]); + var y = numeric(n[1]); + var width = Math.max(n[0].length, n[1].length) + var incr = n.length == 3 + ? Math.abs(numeric(n[2])) + : 1; + var test = lte; + var reverse = y < x; + if (reverse) { + incr *= -1; + test = gte; + } + var pad = n.some(isPadded); + + N = []; + + for (var i = x; test(i, y); i += incr) { + var c; + if (isAlphaSequence) { + c = String.fromCharCode(i); + if (c === '\\') + c = ''; + } else { + c = String(i); + if (pad) { + var need = width - c.length; + if (need > 0) { + var z = new Array(need + 1).join('0'); + if (i < 0) + c = '-' + z + c.slice(1); + else + c = z + c; + } + } + } + N.push(c); + } + } else { + N = concatMap(n, function(el) { return expand(el, false) }); + } + + for (var j = 0; j < N.length; j++) { + for (var k = 0; k < post.length; k++) { + var expansion = pre + N[j] + post[k]; + if (!isTop || isSequence || expansion) + expansions.push(expansion); + } + } + + return expansions; +} + diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/package.json new file mode 100644 index 000000000..344788817 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/brace-expansion/package.json @@ -0,0 +1,50 @@ +{ + "name": "brace-expansion", + "description": "Brace expansion as known from sh/bash", + "version": "1.1.12", + "repository": { + "type": "git", + "url": "git://github.com/juliangruber/brace-expansion.git" + }, + "homepage": "https://github.com/juliangruber/brace-expansion", + "main": "index.js", + "scripts": { + "test": "tape test/*.js", + "gentest": "bash test/generate.sh", + "bench": "matcha test/perf/bench.js" + }, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + }, + "devDependencies": { + "matcha": "^0.7.0", + "tape": "^4.6.0" + }, + "keywords": [], + "author": { + "name": "Julian Gruber", + "email": "mail@juliangruber.com", + "url": "http://juliangruber.com" + }, + "license": "MIT", + "testling": { + "files": "test/*.js", + "browsers": [ + "ie/8..latest", + "firefox/20..latest", + "firefox/nightly", + "chrome/25..latest", + "chrome/canary", + "opera/12..latest", + "opera/next", + "safari/5.1..latest", + "ipad/6.0..latest", + "iphone/6.0..latest", + "android-browser/4.2..latest" + ] + }, + "publishConfig": { + "tag": "1.x" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/AUTHORS.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/AUTHORS.md new file mode 100644 index 000000000..22eb17129 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/AUTHORS.md @@ -0,0 +1,70 @@ +# Authors + +#### Ordered by first contribution. + +- Romain Beauxis (toots@rastageeks.org) +- Tobias Koppers (tobias.koppers@googlemail.com) +- Janus (ysangkok@gmail.com) +- Rainer Dreyer (rdrey1@gmail.com) +- Tõnis Tiigi (tonistiigi@gmail.com) +- James Halliday (mail@substack.net) +- Michael Williamson (mike@zwobble.org) +- elliottcable (github@elliottcable.name) +- rafael (rvalle@livelens.net) +- Andrew Kelley (superjoe30@gmail.com) +- Andreas Madsen (amwebdk@gmail.com) +- Mike Brevoort (mike.brevoort@pearson.com) +- Brian White (mscdex@mscdex.net) +- Feross Aboukhadijeh (feross@feross.org) +- Ruben Verborgh (ruben@verborgh.org) +- eliang (eliang.cs@gmail.com) +- Jesse Tane (jesse.tane@gmail.com) +- Alfonso Boza (alfonso@cloud.com) +- Mathias Buus (mathiasbuus@gmail.com) +- Devon Govett (devongovett@gmail.com) +- Daniel Cousens (github@dcousens.com) +- Joseph Dykstra (josephdykstra@gmail.com) +- Parsha Pourkhomami (parshap+git@gmail.com) +- Damjan Košir (damjan.kosir@gmail.com) +- daverayment (dave.rayment@gmail.com) +- kawanet (u-suke@kawa.net) +- Linus Unnebäck (linus@folkdatorn.se) +- Nolan Lawson (nolan.lawson@gmail.com) +- Calvin Metcalf (calvin.metcalf@gmail.com) +- Koki Takahashi (hakatasiloving@gmail.com) +- Guy Bedford (guybedford@gmail.com) +- Jan Schär (jscissr@gmail.com) +- RaulTsc (tomescu.raul@gmail.com) +- Matthieu Monsch (monsch@alum.mit.edu) +- Dan Ehrenberg (littledan@chromium.org) +- Kirill Fomichev (fanatid@ya.ru) +- Yusuke Kawasaki (u-suke@kawa.net) +- DC (dcposch@dcpos.ch) +- John-David Dalton (john.david.dalton@gmail.com) +- adventure-yunfei (adventure030@gmail.com) +- Emil Bay (github@tixz.dk) +- Sam Sudar (sudar.sam@gmail.com) +- Volker Mische (volker.mische@gmail.com) +- David Walton (support@geekstocks.com) +- Сковорода Никита Андреевич (chalkerx@gmail.com) +- greenkeeper[bot] (greenkeeper[bot]@users.noreply.github.com) +- ukstv (sergey.ukustov@machinomy.com) +- Renée Kooi (renee@kooi.me) +- ranbochen (ranbochen@qq.com) +- Vladimir Borovik (bobahbdb@gmail.com) +- greenkeeper[bot] (23040076+greenkeeper[bot]@users.noreply.github.com) +- kumavis (aaron@kumavis.me) +- Sergey Ukustov (sergey.ukustov@machinomy.com) +- Fei Liu (liu.feiwood@gmail.com) +- Blaine Bublitz (blaine.bublitz@gmail.com) +- clement (clement@seald.io) +- Koushik Dutta (koushd@gmail.com) +- Jordan Harband (ljharb@gmail.com) +- Niklas Mischkulnig (mischnic@users.noreply.github.com) +- Nikolai Vavilov (vvnicholas@gmail.com) +- Fedor Nezhivoi (gyzerok@users.noreply.github.com) +- Peter Newman (peternewman@users.noreply.github.com) +- mathmakgakpak (44949126+mathmakgakpak@users.noreply.github.com) +- jkkang (jkkang@smartauth.kr) + +#### Generated by bin/update-authors.sh. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/LICENSE new file mode 100644 index 000000000..d6bf75dcf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Feross Aboukhadijeh, and other contributors. + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/README.md new file mode 100644 index 000000000..9a23d7cfa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/README.md @@ -0,0 +1,410 @@ +# buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url] + +[travis-image]: https://img.shields.io/travis/feross/buffer/master.svg +[travis-url]: https://travis-ci.org/feross/buffer +[npm-image]: https://img.shields.io/npm/v/buffer.svg +[npm-url]: https://npmjs.org/package/buffer +[downloads-image]: https://img.shields.io/npm/dm/buffer.svg +[downloads-url]: https://npmjs.org/package/buffer +[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg +[standard-url]: https://standardjs.com + +#### The buffer module from [node.js](https://nodejs.org/), for the browser. + +[![saucelabs][saucelabs-image]][saucelabs-url] + +[saucelabs-image]: https://saucelabs.com/browser-matrix/buffer.svg +[saucelabs-url]: https://saucelabs.com/u/buffer + +With [browserify](http://browserify.org), simply `require('buffer')` or use the `Buffer` global and you will get this module. + +The goal is to provide an API that is 100% identical to +[node's Buffer API](https://nodejs.org/api/buffer.html). Read the +[official docs](https://nodejs.org/api/buffer.html) for the full list of properties, +instance methods, and class methods that are supported. + +## features + +- Manipulate binary data like a boss, in all browsers! +- Super fast. Backed by Typed Arrays (`Uint8Array`/`ArrayBuffer`, not `Object`) +- Extremely small bundle size (**6.75KB minified + gzipped**, 51.9KB with comments) +- Excellent browser support (Chrome, Firefox, Edge, Safari 9+, IE 11, iOS 9+, Android, etc.) +- Preserves Node API exactly, with one minor difference (see below) +- Square-bracket `buf[4]` notation works! +- Does not modify any browser prototypes or put anything on `window` +- Comprehensive test suite (including all buffer tests from node.js core) + +## install + +To use this module directly (without browserify), install it: + +```bash +npm install buffer +``` + +This module was previously called **native-buffer-browserify**, but please use **buffer** +from now on. + +If you do not use a bundler, you can use the [standalone script](https://bundle.run/buffer). + +## usage + +The module's API is identical to node's `Buffer` API. Read the +[official docs](https://nodejs.org/api/buffer.html) for the full list of properties, +instance methods, and class methods that are supported. + +As mentioned above, `require('buffer')` or use the `Buffer` global with +[browserify](http://browserify.org) and this module will automatically be included +in your bundle. Almost any npm module will work in the browser, even if it assumes that +the node `Buffer` API will be available. + +To depend on this module explicitly (without browserify), require it like this: + +```js +var Buffer = require('buffer/').Buffer // note: the trailing slash is important! +``` + +To require this module explicitly, use `require('buffer/')` which tells the node.js module +lookup algorithm (also used by browserify) to use the **npm module** named `buffer` +instead of the **node.js core** module named `buffer`! + + +## how does it work? + +The Buffer constructor returns instances of `Uint8Array` that have their prototype +changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of `Uint8Array`, +so the returned instances will have all the node `Buffer` methods and the +`Uint8Array` methods. Square bracket notation works as expected -- it returns a +single octet. + +The `Uint8Array` prototype remains unmodified. + + +## tracking the latest node api + +This module tracks the Buffer API in the latest (unstable) version of node.js. The Buffer +API is considered **stable** in the +[node stability index](https://nodejs.org/docs/latest/api/documentation.html#documentation_stability_index), +so it is unlikely that there will ever be breaking changes. +Nonetheless, when/if the Buffer API changes in node, this module's API will change +accordingly. + +## related packages + +- [`buffer-reverse`](https://www.npmjs.com/package/buffer-reverse) - Reverse a buffer +- [`buffer-xor`](https://www.npmjs.com/package/buffer-xor) - Bitwise xor a buffer +- [`is-buffer`](https://www.npmjs.com/package/is-buffer) - Determine if an object is a Buffer without including the whole `Buffer` package + +## conversion packages + +### convert typed array to buffer + +Use [`typedarray-to-buffer`](https://www.npmjs.com/package/typedarray-to-buffer) to convert any kind of typed array to a `Buffer`. Does not perform a copy, so it's super fast. + +### convert buffer to typed array + +`Buffer` is a subclass of `Uint8Array` (which is a typed array). So there is no need to explicitly convert to typed array. Just use the buffer as a `Uint8Array`. + +### convert blob to buffer + +Use [`blob-to-buffer`](https://www.npmjs.com/package/blob-to-buffer) to convert a `Blob` to a `Buffer`. + +### convert buffer to blob + +To convert a `Buffer` to a `Blob`, use the `Blob` constructor: + +```js +var blob = new Blob([ buffer ]) +``` + +Optionally, specify a mimetype: + +```js +var blob = new Blob([ buffer ], { type: 'text/html' }) +``` + +### convert arraybuffer to buffer + +To convert an `ArrayBuffer` to a `Buffer`, use the `Buffer.from` function. Does not perform a copy, so it's super fast. + +```js +var buffer = Buffer.from(arrayBuffer) +``` + +### convert buffer to arraybuffer + +To convert a `Buffer` to an `ArrayBuffer`, use the `.buffer` property (which is present on all `Uint8Array` objects): + +```js +var arrayBuffer = buffer.buffer.slice( + buffer.byteOffset, buffer.byteOffset + buffer.byteLength +) +``` + +Alternatively, use the [`to-arraybuffer`](https://www.npmjs.com/package/to-arraybuffer) module. + +## performance + +See perf tests in `/perf`. + +`BrowserBuffer` is the browser `buffer` module (this repo). `Uint8Array` is included as a +sanity check (since `BrowserBuffer` uses `Uint8Array` under the hood, `Uint8Array` will +always be at least a bit faster). Finally, `NodeBuffer` is the node.js buffer module, +which is included to compare against. + +NOTE: Performance has improved since these benchmarks were taken. PR welcome to update the README. + +### Chrome 38 + +| Method | Operations | Accuracy | Sampled | Fastest | +|:-------|:-----------|:---------|:--------|:-------:| +| BrowserBuffer#bracket-notation | 11,457,464 ops/sec | ±0.86% | 66 | ✓ | +| Uint8Array#bracket-notation | 10,824,332 ops/sec | ±0.74% | 65 | | +| | | | | +| BrowserBuffer#concat | 450,532 ops/sec | ±0.76% | 68 | | +| Uint8Array#concat | 1,368,911 ops/sec | ±1.50% | 62 | ✓ | +| | | | | +| BrowserBuffer#copy(16000) | 903,001 ops/sec | ±0.96% | 67 | | +| Uint8Array#copy(16000) | 1,422,441 ops/sec | ±1.04% | 66 | ✓ | +| | | | | +| BrowserBuffer#copy(16) | 11,431,358 ops/sec | ±0.46% | 69 | | +| Uint8Array#copy(16) | 13,944,163 ops/sec | ±1.12% | 68 | ✓ | +| | | | | +| BrowserBuffer#new(16000) | 106,329 ops/sec | ±6.70% | 44 | | +| Uint8Array#new(16000) | 131,001 ops/sec | ±2.85% | 31 | ✓ | +| | | | | +| BrowserBuffer#new(16) | 1,554,491 ops/sec | ±1.60% | 65 | | +| Uint8Array#new(16) | 6,623,930 ops/sec | ±1.66% | 65 | ✓ | +| | | | | +| BrowserBuffer#readDoubleBE | 112,830 ops/sec | ±0.51% | 69 | ✓ | +| DataView#getFloat64 | 93,500 ops/sec | ±0.57% | 68 | | +| | | | | +| BrowserBuffer#readFloatBE | 146,678 ops/sec | ±0.95% | 68 | ✓ | +| DataView#getFloat32 | 99,311 ops/sec | ±0.41% | 67 | | +| | | | | +| BrowserBuffer#readUInt32LE | 843,214 ops/sec | ±0.70% | 69 | ✓ | +| DataView#getUint32 | 103,024 ops/sec | ±0.64% | 67 | | +| | | | | +| BrowserBuffer#slice | 1,013,941 ops/sec | ±0.75% | 67 | | +| Uint8Array#subarray | 1,903,928 ops/sec | ±0.53% | 67 | ✓ | +| | | | | +| BrowserBuffer#writeFloatBE | 61,387 ops/sec | ±0.90% | 67 | | +| DataView#setFloat32 | 141,249 ops/sec | ±0.40% | 66 | ✓ | + + +### Firefox 33 + +| Method | Operations | Accuracy | Sampled | Fastest | +|:-------|:-----------|:---------|:--------|:-------:| +| BrowserBuffer#bracket-notation | 20,800,421 ops/sec | ±1.84% | 60 | | +| Uint8Array#bracket-notation | 20,826,235 ops/sec | ±2.02% | 61 | ✓ | +| | | | | +| BrowserBuffer#concat | 153,076 ops/sec | ±2.32% | 61 | | +| Uint8Array#concat | 1,255,674 ops/sec | ±8.65% | 52 | ✓ | +| | | | | +| BrowserBuffer#copy(16000) | 1,105,312 ops/sec | ±1.16% | 63 | | +| Uint8Array#copy(16000) | 1,615,911 ops/sec | ±0.55% | 66 | ✓ | +| | | | | +| BrowserBuffer#copy(16) | 16,357,599 ops/sec | ±0.73% | 68 | | +| Uint8Array#copy(16) | 31,436,281 ops/sec | ±1.05% | 68 | ✓ | +| | | | | +| BrowserBuffer#new(16000) | 52,995 ops/sec | ±6.01% | 35 | | +| Uint8Array#new(16000) | 87,686 ops/sec | ±5.68% | 45 | ✓ | +| | | | | +| BrowserBuffer#new(16) | 252,031 ops/sec | ±1.61% | 66 | | +| Uint8Array#new(16) | 8,477,026 ops/sec | ±0.49% | 68 | ✓ | +| | | | | +| BrowserBuffer#readDoubleBE | 99,871 ops/sec | ±0.41% | 69 | | +| DataView#getFloat64 | 285,663 ops/sec | ±0.70% | 68 | ✓ | +| | | | | +| BrowserBuffer#readFloatBE | 115,540 ops/sec | ±0.42% | 69 | | +| DataView#getFloat32 | 288,722 ops/sec | ±0.82% | 68 | ✓ | +| | | | | +| BrowserBuffer#readUInt32LE | 633,926 ops/sec | ±1.08% | 67 | ✓ | +| DataView#getUint32 | 294,808 ops/sec | ±0.79% | 64 | | +| | | | | +| BrowserBuffer#slice | 349,425 ops/sec | ±0.46% | 69 | | +| Uint8Array#subarray | 5,965,819 ops/sec | ±0.60% | 65 | ✓ | +| | | | | +| BrowserBuffer#writeFloatBE | 59,980 ops/sec | ±0.41% | 67 | | +| DataView#setFloat32 | 317,634 ops/sec | ±0.63% | 68 | ✓ | + +### Safari 8 + +| Method | Operations | Accuracy | Sampled | Fastest | +|:-------|:-----------|:---------|:--------|:-------:| +| BrowserBuffer#bracket-notation | 10,279,729 ops/sec | ±2.25% | 56 | ✓ | +| Uint8Array#bracket-notation | 10,030,767 ops/sec | ±2.23% | 59 | | +| | | | | +| BrowserBuffer#concat | 144,138 ops/sec | ±1.38% | 65 | | +| Uint8Array#concat | 4,950,764 ops/sec | ±1.70% | 63 | ✓ | +| | | | | +| BrowserBuffer#copy(16000) | 1,058,548 ops/sec | ±1.51% | 64 | | +| Uint8Array#copy(16000) | 1,409,666 ops/sec | ±1.17% | 65 | ✓ | +| | | | | +| BrowserBuffer#copy(16) | 6,282,529 ops/sec | ±1.88% | 58 | | +| Uint8Array#copy(16) | 11,907,128 ops/sec | ±2.87% | 58 | ✓ | +| | | | | +| BrowserBuffer#new(16000) | 101,663 ops/sec | ±3.89% | 57 | | +| Uint8Array#new(16000) | 22,050,818 ops/sec | ±6.51% | 46 | ✓ | +| | | | | +| BrowserBuffer#new(16) | 176,072 ops/sec | ±2.13% | 64 | | +| Uint8Array#new(16) | 24,385,731 ops/sec | ±5.01% | 51 | ✓ | +| | | | | +| BrowserBuffer#readDoubleBE | 41,341 ops/sec | ±1.06% | 67 | | +| DataView#getFloat64 | 322,280 ops/sec | ±0.84% | 68 | ✓ | +| | | | | +| BrowserBuffer#readFloatBE | 46,141 ops/sec | ±1.06% | 65 | | +| DataView#getFloat32 | 337,025 ops/sec | ±0.43% | 69 | ✓ | +| | | | | +| BrowserBuffer#readUInt32LE | 151,551 ops/sec | ±1.02% | 66 | | +| DataView#getUint32 | 308,278 ops/sec | ±0.94% | 67 | ✓ | +| | | | | +| BrowserBuffer#slice | 197,365 ops/sec | ±0.95% | 66 | | +| Uint8Array#subarray | 9,558,024 ops/sec | ±3.08% | 58 | ✓ | +| | | | | +| BrowserBuffer#writeFloatBE | 17,518 ops/sec | ±1.03% | 63 | | +| DataView#setFloat32 | 319,751 ops/sec | ±0.48% | 68 | ✓ | + + +### Node 0.11.14 + +| Method | Operations | Accuracy | Sampled | Fastest | +|:-------|:-----------|:---------|:--------|:-------:| +| BrowserBuffer#bracket-notation | 10,489,828 ops/sec | ±3.25% | 90 | | +| Uint8Array#bracket-notation | 10,534,884 ops/sec | ±0.81% | 92 | ✓ | +| NodeBuffer#bracket-notation | 10,389,910 ops/sec | ±0.97% | 87 | | +| | | | | +| BrowserBuffer#concat | 487,830 ops/sec | ±2.58% | 88 | | +| Uint8Array#concat | 1,814,327 ops/sec | ±1.28% | 88 | ✓ | +| NodeBuffer#concat | 1,636,523 ops/sec | ±1.88% | 73 | | +| | | | | +| BrowserBuffer#copy(16000) | 1,073,665 ops/sec | ±0.77% | 90 | | +| Uint8Array#copy(16000) | 1,348,517 ops/sec | ±0.84% | 89 | ✓ | +| NodeBuffer#copy(16000) | 1,289,533 ops/sec | ±0.82% | 93 | | +| | | | | +| BrowserBuffer#copy(16) | 12,782,706 ops/sec | ±0.74% | 85 | | +| Uint8Array#copy(16) | 14,180,427 ops/sec | ±0.93% | 92 | ✓ | +| NodeBuffer#copy(16) | 11,083,134 ops/sec | ±1.06% | 89 | | +| | | | | +| BrowserBuffer#new(16000) | 141,678 ops/sec | ±3.30% | 67 | | +| Uint8Array#new(16000) | 161,491 ops/sec | ±2.96% | 60 | | +| NodeBuffer#new(16000) | 292,699 ops/sec | ±3.20% | 55 | ✓ | +| | | | | +| BrowserBuffer#new(16) | 1,655,466 ops/sec | ±2.41% | 82 | | +| Uint8Array#new(16) | 14,399,926 ops/sec | ±0.91% | 94 | ✓ | +| NodeBuffer#new(16) | 3,894,696 ops/sec | ±0.88% | 92 | | +| | | | | +| BrowserBuffer#readDoubleBE | 109,582 ops/sec | ±0.75% | 93 | ✓ | +| DataView#getFloat64 | 91,235 ops/sec | ±0.81% | 90 | | +| NodeBuffer#readDoubleBE | 88,593 ops/sec | ±0.96% | 81 | | +| | | | | +| BrowserBuffer#readFloatBE | 139,854 ops/sec | ±1.03% | 85 | ✓ | +| DataView#getFloat32 | 98,744 ops/sec | ±0.80% | 89 | | +| NodeBuffer#readFloatBE | 92,769 ops/sec | ±0.94% | 93 | | +| | | | | +| BrowserBuffer#readUInt32LE | 710,861 ops/sec | ±0.82% | 92 | | +| DataView#getUint32 | 117,893 ops/sec | ±0.84% | 91 | | +| NodeBuffer#readUInt32LE | 851,412 ops/sec | ±0.72% | 93 | ✓ | +| | | | | +| BrowserBuffer#slice | 1,673,877 ops/sec | ±0.73% | 94 | | +| Uint8Array#subarray | 6,919,243 ops/sec | ±0.67% | 90 | ✓ | +| NodeBuffer#slice | 4,617,604 ops/sec | ±0.79% | 93 | | +| | | | | +| BrowserBuffer#writeFloatBE | 66,011 ops/sec | ±0.75% | 93 | | +| DataView#setFloat32 | 127,760 ops/sec | ±0.72% | 93 | ✓ | +| NodeBuffer#writeFloatBE | 103,352 ops/sec | ±0.83% | 93 | | + +### iojs 1.8.1 + +| Method | Operations | Accuracy | Sampled | Fastest | +|:-------|:-----------|:---------|:--------|:-------:| +| BrowserBuffer#bracket-notation | 10,990,488 ops/sec | ±1.11% | 91 | | +| Uint8Array#bracket-notation | 11,268,757 ops/sec | ±0.65% | 97 | | +| NodeBuffer#bracket-notation | 11,353,260 ops/sec | ±0.83% | 94 | ✓ | +| | | | | +| BrowserBuffer#concat | 378,954 ops/sec | ±0.74% | 94 | | +| Uint8Array#concat | 1,358,288 ops/sec | ±0.97% | 87 | | +| NodeBuffer#concat | 1,934,050 ops/sec | ±1.11% | 78 | ✓ | +| | | | | +| BrowserBuffer#copy(16000) | 894,538 ops/sec | ±0.56% | 84 | | +| Uint8Array#copy(16000) | 1,442,656 ops/sec | ±0.71% | 96 | | +| NodeBuffer#copy(16000) | 1,457,898 ops/sec | ±0.53% | 92 | ✓ | +| | | | | +| BrowserBuffer#copy(16) | 12,870,457 ops/sec | ±0.67% | 95 | | +| Uint8Array#copy(16) | 16,643,989 ops/sec | ±0.61% | 93 | ✓ | +| NodeBuffer#copy(16) | 14,885,848 ops/sec | ±0.74% | 94 | | +| | | | | +| BrowserBuffer#new(16000) | 109,264 ops/sec | ±4.21% | 63 | | +| Uint8Array#new(16000) | 138,916 ops/sec | ±1.87% | 61 | | +| NodeBuffer#new(16000) | 281,449 ops/sec | ±3.58% | 51 | ✓ | +| | | | | +| BrowserBuffer#new(16) | 1,362,935 ops/sec | ±0.56% | 99 | | +| Uint8Array#new(16) | 6,193,090 ops/sec | ±0.64% | 95 | ✓ | +| NodeBuffer#new(16) | 4,745,425 ops/sec | ±1.56% | 90 | | +| | | | | +| BrowserBuffer#readDoubleBE | 118,127 ops/sec | ±0.59% | 93 | ✓ | +| DataView#getFloat64 | 107,332 ops/sec | ±0.65% | 91 | | +| NodeBuffer#readDoubleBE | 116,274 ops/sec | ±0.94% | 95 | | +| | | | | +| BrowserBuffer#readFloatBE | 150,326 ops/sec | ±0.58% | 95 | ✓ | +| DataView#getFloat32 | 110,541 ops/sec | ±0.57% | 98 | | +| NodeBuffer#readFloatBE | 121,599 ops/sec | ±0.60% | 87 | | +| | | | | +| BrowserBuffer#readUInt32LE | 814,147 ops/sec | ±0.62% | 93 | | +| DataView#getUint32 | 137,592 ops/sec | ±0.64% | 90 | | +| NodeBuffer#readUInt32LE | 931,650 ops/sec | ±0.71% | 96 | ✓ | +| | | | | +| BrowserBuffer#slice | 878,590 ops/sec | ±0.68% | 93 | | +| Uint8Array#subarray | 2,843,308 ops/sec | ±1.02% | 90 | | +| NodeBuffer#slice | 4,998,316 ops/sec | ±0.68% | 90 | ✓ | +| | | | | +| BrowserBuffer#writeFloatBE | 65,927 ops/sec | ±0.74% | 93 | | +| DataView#setFloat32 | 139,823 ops/sec | ±0.97% | 89 | ✓ | +| NodeBuffer#writeFloatBE | 135,763 ops/sec | ±0.65% | 96 | | +| | | | | + +## Testing the project + +First, install the project: + + npm install + +Then, to run tests in Node.js, run: + + npm run test-node + +To test locally in a browser, you can run: + + npm run test-browser-es5-local # For ES5 browsers that don't support ES6 + npm run test-browser-es6-local # For ES6 compliant browsers + +This will print out a URL that you can then open in a browser to run the tests, using [airtap](https://www.npmjs.com/package/airtap). + +To run automated browser tests using Saucelabs, ensure that your `SAUCE_USERNAME` and `SAUCE_ACCESS_KEY` environment variables are set, then run: + + npm test + +This is what's run in Travis, to check against various browsers. The list of browsers is kept in the `bin/airtap-es5.yml` and `bin/airtap-es6.yml` files. + +## JavaScript Standard Style + +This module uses [JavaScript Standard Style](https://github.com/feross/standard). + +[![JavaScript Style Guide](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) + +To test that the code conforms to the style, `npm install` and run: + + ./node_modules/.bin/standard + +## credit + +This was originally forked from [buffer-browserify](https://github.com/toots/buffer-browserify). + +## Security Policies and Procedures + +The `buffer` team and community take all security bugs in `buffer` seriously. Please see our [security policies and procedures](https://github.com/feross/security) document to learn how to report issues. + +## license + +MIT. Copyright (C) [Feross Aboukhadijeh](http://feross.org), and other contributors. Originally forked from an MIT-licensed module by Romain Beauxis. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/index.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/index.d.ts new file mode 100644 index 000000000..5d1a804e5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/index.d.ts @@ -0,0 +1,186 @@ +export class Buffer extends Uint8Array { + length: number + write(string: string, offset?: number, length?: number, encoding?: string): number; + toString(encoding?: string, start?: number, end?: number): string; + toJSON(): { type: 'Buffer', data: any[] }; + equals(otherBuffer: Buffer): boolean; + compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number; + copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; + slice(start?: number, end?: number): Buffer; + writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number; + readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number; + readIntLE(offset: number, byteLength: number, noAssert?: boolean): number; + readIntBE(offset: number, byteLength: number, noAssert?: boolean): number; + readUInt8(offset: number, noAssert?: boolean): number; + readUInt16LE(offset: number, noAssert?: boolean): number; + readUInt16BE(offset: number, noAssert?: boolean): number; + readUInt32LE(offset: number, noAssert?: boolean): number; + readUInt32BE(offset: number, noAssert?: boolean): number; + readInt8(offset: number, noAssert?: boolean): number; + readInt16LE(offset: number, noAssert?: boolean): number; + readInt16BE(offset: number, noAssert?: boolean): number; + readInt32LE(offset: number, noAssert?: boolean): number; + readInt32BE(offset: number, noAssert?: boolean): number; + readFloatLE(offset: number, noAssert?: boolean): number; + readFloatBE(offset: number, noAssert?: boolean): number; + readDoubleLE(offset: number, noAssert?: boolean): number; + readDoubleBE(offset: number, noAssert?: boolean): number; + reverse(): this; + swap16(): Buffer; + swap32(): Buffer; + swap64(): Buffer; + writeUInt8(value: number, offset: number, noAssert?: boolean): number; + writeUInt16LE(value: number, offset: number, noAssert?: boolean): number; + writeUInt16BE(value: number, offset: number, noAssert?: boolean): number; + writeUInt32LE(value: number, offset: number, noAssert?: boolean): number; + writeUInt32BE(value: number, offset: number, noAssert?: boolean): number; + writeInt8(value: number, offset: number, noAssert?: boolean): number; + writeInt16LE(value: number, offset: number, noAssert?: boolean): number; + writeInt16BE(value: number, offset: number, noAssert?: boolean): number; + writeInt32LE(value: number, offset: number, noAssert?: boolean): number; + writeInt32BE(value: number, offset: number, noAssert?: boolean): number; + writeFloatLE(value: number, offset: number, noAssert?: boolean): number; + writeFloatBE(value: number, offset: number, noAssert?: boolean): number; + writeDoubleLE(value: number, offset: number, noAssert?: boolean): number; + writeDoubleBE(value: number, offset: number, noAssert?: boolean): number; + fill(value: any, offset?: number, end?: number): this; + indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; + lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; + includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean; + + /** + * Allocates a new buffer containing the given {str}. + * + * @param str String to store in buffer. + * @param encoding encoding to use, optional. Default is 'utf8' + */ + constructor (str: string, encoding?: string); + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + */ + constructor (size: number); + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + */ + constructor (array: Uint8Array); + /** + * Produces a Buffer backed by the same allocated memory as + * the given {ArrayBuffer}. + * + * + * @param arrayBuffer The ArrayBuffer with which to share memory. + */ + constructor (arrayBuffer: ArrayBuffer); + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + */ + constructor (array: any[]); + /** + * Copies the passed {buffer} data onto a new {Buffer} instance. + * + * @param buffer The buffer to copy. + */ + constructor (buffer: Buffer); + prototype: Buffer; + /** + * Allocates a new Buffer using an {array} of octets. + * + * @param array + */ + static from(array: any[]): Buffer; + /** + * When passed a reference to the .buffer property of a TypedArray instance, + * the newly created Buffer will share the same allocated memory as the TypedArray. + * The optional {byteOffset} and {length} arguments specify a memory range + * within the {arrayBuffer} that will be shared by the Buffer. + * + * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer() + * @param byteOffset + * @param length + */ + static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer; + /** + * Copies the passed {buffer} data onto a new Buffer instance. + * + * @param buffer + */ + static from(buffer: Buffer | Uint8Array): Buffer; + /** + * Creates a new Buffer containing the given JavaScript string {str}. + * If provided, the {encoding} parameter identifies the character encoding. + * If not provided, {encoding} defaults to 'utf8'. + * + * @param str + */ + static from(str: string, encoding?: string): Buffer; + /** + * Returns true if {obj} is a Buffer + * + * @param obj object to test. + */ + static isBuffer(obj: any): obj is Buffer; + /** + * Returns true if {encoding} is a valid encoding argument. + * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' + * + * @param encoding string to test. + */ + static isEncoding(encoding: string): boolean; + /** + * Gives the actual byte length of a string. encoding defaults to 'utf8'. + * This is not the same as String.prototype.length since that returns the number of characters in a string. + * + * @param string string to test. + * @param encoding encoding used to evaluate (defaults to 'utf8') + */ + static byteLength(string: string, encoding?: string): number; + /** + * Returns a buffer which is the result of concatenating all the buffers in the list together. + * + * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer. + * If the list has exactly one item, then the first item of the list is returned. + * If the list has more than one item, then a new Buffer is created. + * + * @param list An array of Buffer objects to concatenate + * @param totalLength Total length of the buffers when concatenated. + * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly. + */ + static concat(list: Buffer[], totalLength?: number): Buffer; + /** + * The same as buf1.compare(buf2). + */ + static compare(buf1: Buffer, buf2: Buffer): number; + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + * @param fill if specified, buffer will be initialized by calling buf.fill(fill). + * If parameter is omitted, buffer will be filled with zeros. + * @param encoding encoding used for call to buf.fill while initializing + */ + static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer; + /** + * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents + * of the newly created Buffer are unknown and may contain sensitive data. + * + * @param size count of octets to allocate + */ + static allocUnsafe(size: number): Buffer; + /** + * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents + * of the newly created Buffer are unknown and may contain sensitive data. + * + * @param size count of octets to allocate + */ + static allocUnsafeSlow(size: number): Buffer; +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/index.js new file mode 100644 index 000000000..609cf3113 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/index.js @@ -0,0 +1,1817 @@ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + +'use strict' + +var base64 = require('base64-js') +var ieee754 = require('ieee754') +var customInspectSymbol = + (typeof Symbol === 'function' && typeof Symbol['for'] === 'function') // eslint-disable-line dot-notation + ? Symbol['for']('nodejs.util.inspect.custom') // eslint-disable-line dot-notation + : null + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 + +var K_MAX_LENGTH = 0x7fffffff +exports.kMaxLength = K_MAX_LENGTH + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Print warning and recommend using `buffer` v4.x which has an Object + * implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * We report that the browser does not support typed arrays if the are not subclassable + * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` + * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support + * for __proto__ and has a buggy typed array implementation. + */ +Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() + +if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && + typeof console.error === 'function') { + console.error( + 'This browser lacks typed array (Uint8Array) support which is required by ' + + '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' + ) +} + +function typedArraySupport () { + // Can typed array instances can be augmented? + try { + var arr = new Uint8Array(1) + var proto = { foo: function () { return 42 } } + Object.setPrototypeOf(proto, Uint8Array.prototype) + Object.setPrototypeOf(arr, proto) + return arr.foo() === 42 + } catch (e) { + return false + } +} + +Object.defineProperty(Buffer.prototype, 'parent', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.buffer + } +}) + +Object.defineProperty(Buffer.prototype, 'offset', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.byteOffset + } +}) + +function createBuffer (length) { + if (length > K_MAX_LENGTH) { + throw new RangeError('The value "' + length + '" is invalid for option "size"') + } + // Return an augmented `Uint8Array` instance + var buf = new Uint8Array(length) + Object.setPrototypeOf(buf, Buffer.prototype) + return buf +} + +/** + * The Buffer constructor returns instances of `Uint8Array` that have their + * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of + * `Uint8Array`, so the returned instances will have all the node `Buffer` methods + * and the `Uint8Array` methods. Square bracket notation works as expected -- it + * returns a single octet. + * + * The `Uint8Array` prototype remains unmodified. + */ + +function Buffer (arg, encodingOrOffset, length) { + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new TypeError( + 'The "string" argument must be of type string. Received type number' + ) + } + return allocUnsafe(arg) + } + return from(arg, encodingOrOffset, length) +} + +Buffer.poolSize = 8192 // not used by this implementation + +function from (value, encodingOrOffset, length) { + if (typeof value === 'string') { + return fromString(value, encodingOrOffset) + } + + if (ArrayBuffer.isView(value)) { + return fromArrayView(value) + } + + if (value == null) { + throw new TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) + } + + if (isInstance(value, ArrayBuffer) || + (value && isInstance(value.buffer, ArrayBuffer))) { + return fromArrayBuffer(value, encodingOrOffset, length) + } + + if (typeof SharedArrayBuffer !== 'undefined' && + (isInstance(value, SharedArrayBuffer) || + (value && isInstance(value.buffer, SharedArrayBuffer)))) { + return fromArrayBuffer(value, encodingOrOffset, length) + } + + if (typeof value === 'number') { + throw new TypeError( + 'The "value" argument must not be of type number. Received type number' + ) + } + + var valueOf = value.valueOf && value.valueOf() + if (valueOf != null && valueOf !== value) { + return Buffer.from(valueOf, encodingOrOffset, length) + } + + var b = fromObject(value) + if (b) return b + + if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && + typeof value[Symbol.toPrimitive] === 'function') { + return Buffer.from( + value[Symbol.toPrimitive]('string'), encodingOrOffset, length + ) + } + + throw new TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) +} + +/** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ +Buffer.from = function (value, encodingOrOffset, length) { + return from(value, encodingOrOffset, length) +} + +// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: +// https://github.com/feross/buffer/pull/148 +Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype) +Object.setPrototypeOf(Buffer, Uint8Array) + +function assertSize (size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be of type number') + } else if (size < 0) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } +} + +function alloc (size, fill, encoding) { + assertSize(size) + if (size <= 0) { + return createBuffer(size) + } + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpreted as a start offset. + return typeof encoding === 'string' + ? createBuffer(size).fill(fill, encoding) + : createBuffer(size).fill(fill) + } + return createBuffer(size) +} + +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ +Buffer.alloc = function (size, fill, encoding) { + return alloc(size, fill, encoding) +} + +function allocUnsafe (size) { + assertSize(size) + return createBuffer(size < 0 ? 0 : checked(size) | 0) +} + +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ +Buffer.allocUnsafe = function (size) { + return allocUnsafe(size) +} +/** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ +Buffer.allocUnsafeSlow = function (size) { + return allocUnsafe(size) +} + +function fromString (string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8' + } + + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + + var length = byteLength(string, encoding) | 0 + var buf = createBuffer(length) + + var actual = buf.write(string, encoding) + + if (actual !== length) { + // Writing a hex string, for example, that contains invalid characters will + // cause everything after the first invalid character to be ignored. (e.g. + // 'abxxcd' will be treated as 'ab') + buf = buf.slice(0, actual) + } + + return buf +} + +function fromArrayLike (array) { + var length = array.length < 0 ? 0 : checked(array.length) | 0 + var buf = createBuffer(length) + for (var i = 0; i < length; i += 1) { + buf[i] = array[i] & 255 + } + return buf +} + +function fromArrayView (arrayView) { + if (isInstance(arrayView, Uint8Array)) { + var copy = new Uint8Array(arrayView) + return fromArrayBuffer(copy.buffer, copy.byteOffset, copy.byteLength) + } + return fromArrayLike(arrayView) +} + +function fromArrayBuffer (array, byteOffset, length) { + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('"offset" is outside of buffer bounds') + } + + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('"length" is outside of buffer bounds') + } + + var buf + if (byteOffset === undefined && length === undefined) { + buf = new Uint8Array(array) + } else if (length === undefined) { + buf = new Uint8Array(array, byteOffset) + } else { + buf = new Uint8Array(array, byteOffset, length) + } + + // Return an augmented `Uint8Array` instance + Object.setPrototypeOf(buf, Buffer.prototype) + + return buf +} + +function fromObject (obj) { + if (Buffer.isBuffer(obj)) { + var len = checked(obj.length) | 0 + var buf = createBuffer(len) + + if (buf.length === 0) { + return buf + } + + obj.copy(buf, 0, 0, len) + return buf + } + + if (obj.length !== undefined) { + if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { + return createBuffer(0) + } + return fromArrayLike(obj) + } + + if (obj.type === 'Buffer' && Array.isArray(obj.data)) { + return fromArrayLike(obj.data) + } +} + +function checked (length) { + // Note: cannot use `length < K_MAX_LENGTH` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= K_MAX_LENGTH) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') + } + return length | 0 +} + +function SlowBuffer (length) { + if (+length != length) { // eslint-disable-line eqeqeq + length = 0 + } + return Buffer.alloc(+length) +} + +Buffer.isBuffer = function isBuffer (b) { + return b != null && b._isBuffer === true && + b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false +} + +Buffer.compare = function compare (a, b) { + if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength) + if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength) + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError( + 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' + ) + } + + if (a === b) return 0 + + var x = a.length + var y = b.length + + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i] + y = b[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function isEncoding (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'latin1': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function concat (list, length) { + if (!Array.isArray(list)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + + if (list.length === 0) { + return Buffer.alloc(0) + } + + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; ++i) { + length += list[i].length + } + } + + var buffer = Buffer.allocUnsafe(length) + var pos = 0 + for (i = 0; i < list.length; ++i) { + var buf = list[i] + if (isInstance(buf, Uint8Array)) { + if (pos + buf.length > buffer.length) { + Buffer.from(buf).copy(buffer, pos) + } else { + Uint8Array.prototype.set.call( + buffer, + buf, + pos + ) + } + } else if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } else { + buf.copy(buffer, pos) + } + pos += buf.length + } + return buffer +} + +function byteLength (string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length + } + if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { + return string.byteLength + } + if (typeof string !== 'string') { + throw new TypeError( + 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + + 'Received type ' + typeof string + ) + } + + var len = string.length + var mustMatch = (arguments.length > 2 && arguments[2] === true) + if (!mustMatch && len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len + case 'utf8': + case 'utf-8': + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) { + return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8 + } + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} +Buffer.byteLength = byteLength + +function slowToString (encoding, start, end) { + var loweredCase = false + + // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // property of a typed array. + + // This behaves neither like String nor Uint8Array in that we set start/end + // to their upper/lower bounds if the value passed is out of range. + // undefined is handled specially as per ECMA-262 6th Edition, + // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. + if (start === undefined || start < 0) { + start = 0 + } + // Return early if start > this.length. Done here to prevent potential uint32 + // coercion fail below. + if (start > this.length) { + return '' + } + + if (end === undefined || end > this.length) { + end = this.length + } + + if (end <= 0) { + return '' + } + + // Force coercion to uint32. This will also coerce falsey/NaN values to 0. + end >>>= 0 + start >>>= 0 + + if (end <= start) { + return '' + } + + if (!encoding) encoding = 'utf8' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'latin1': + case 'binary': + return latin1Slice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) +// to detect a Buffer instance. It's not possible to use `instanceof Buffer` +// reliably in a browserify context because there could be multiple different +// copies of the 'buffer' package in use. This method works even for Buffer +// instances that were created from another copy of the `buffer` package. +// See: https://github.com/feross/buffer/issues/154 +Buffer.prototype._isBuffer = true + +function swap (b, n, m) { + var i = b[n] + b[n] = b[m] + b[m] = i +} + +Buffer.prototype.swap16 = function swap16 () { + var len = this.length + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits') + } + for (var i = 0; i < len; i += 2) { + swap(this, i, i + 1) + } + return this +} + +Buffer.prototype.swap32 = function swap32 () { + var len = this.length + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits') + } + for (var i = 0; i < len; i += 4) { + swap(this, i, i + 3) + swap(this, i + 1, i + 2) + } + return this +} + +Buffer.prototype.swap64 = function swap64 () { + var len = this.length + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits') + } + for (var i = 0; i < len; i += 8) { + swap(this, i, i + 7) + swap(this, i + 1, i + 6) + swap(this, i + 2, i + 5) + swap(this, i + 3, i + 4) + } + return this +} + +Buffer.prototype.toString = function toString () { + var length = this.length + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} + +Buffer.prototype.toLocaleString = Buffer.prototype.toString + +Buffer.prototype.equals = function equals (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function inspect () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim() + if (this.length > max) str += ' ... ' + return '' +} +if (customInspectSymbol) { + Buffer.prototype[customInspectSymbol] = Buffer.prototype.inspect +} + +Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { + if (isInstance(target, Uint8Array)) { + target = Buffer.from(target, target.offset, target.byteLength) + } + if (!Buffer.isBuffer(target)) { + throw new TypeError( + 'The "target" argument must be one of type Buffer or Uint8Array. ' + + 'Received type ' + (typeof target) + ) + } + + if (start === undefined) { + start = 0 + } + if (end === undefined) { + end = target ? target.length : 0 + } + if (thisStart === undefined) { + thisStart = 0 + } + if (thisEnd === undefined) { + thisEnd = this.length + } + + if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { + throw new RangeError('out of range index') + } + + if (thisStart >= thisEnd && start >= end) { + return 0 + } + if (thisStart >= thisEnd) { + return -1 + } + if (start >= end) { + return 1 + } + + start >>>= 0 + end >>>= 0 + thisStart >>>= 0 + thisEnd >>>= 0 + + if (this === target) return 0 + + var x = thisEnd - thisStart + var y = end - start + var len = Math.min(x, y) + + var thisCopy = this.slice(thisStart, thisEnd) + var targetCopy = target.slice(start, end) + + for (var i = 0; i < len; ++i) { + if (thisCopy[i] !== targetCopy[i]) { + x = thisCopy[i] + y = targetCopy[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, +// OR the last index of `val` in `buffer` at offset <= `byteOffset`. +// +// Arguments: +// - buffer - a Buffer to search +// - val - a string, Buffer, or number +// - byteOffset - an index into `buffer`; will be clamped to an int32 +// - encoding - an optional encoding, relevant is val is a string +// - dir - true for indexOf, false for lastIndexOf +function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { + // Empty buffer means no match + if (buffer.length === 0) return -1 + + // Normalize byteOffset + if (typeof byteOffset === 'string') { + encoding = byteOffset + byteOffset = 0 + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000 + } + byteOffset = +byteOffset // Coerce to Number. + if (numberIsNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : (buffer.length - 1) + } + + // Normalize byteOffset: negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = buffer.length + byteOffset + if (byteOffset >= buffer.length) { + if (dir) return -1 + else byteOffset = buffer.length - 1 + } else if (byteOffset < 0) { + if (dir) byteOffset = 0 + else return -1 + } + + // Normalize val + if (typeof val === 'string') { + val = Buffer.from(val, encoding) + } + + // Finally, search either indexOf (if dir is true) or lastIndexOf + if (Buffer.isBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1 + } + return arrayIndexOf(buffer, val, byteOffset, encoding, dir) + } else if (typeof val === 'number') { + val = val & 0xFF // Search for a byte value [0-255] + if (typeof Uint8Array.prototype.indexOf === 'function') { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) + } + } + return arrayIndexOf(buffer, [val], byteOffset, encoding, dir) + } + + throw new TypeError('val must be string, number or Buffer') +} + +function arrayIndexOf (arr, val, byteOffset, encoding, dir) { + var indexSize = 1 + var arrLength = arr.length + var valLength = val.length + + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase() + if (encoding === 'ucs2' || encoding === 'ucs-2' || + encoding === 'utf16le' || encoding === 'utf-16le') { + if (arr.length < 2 || val.length < 2) { + return -1 + } + indexSize = 2 + arrLength /= 2 + valLength /= 2 + byteOffset /= 2 + } + } + + function read (buf, i) { + if (indexSize === 1) { + return buf[i] + } else { + return buf.readUInt16BE(i * indexSize) + } + } + + var i + if (dir) { + var foundIndex = -1 + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize + } else { + if (foundIndex !== -1) i -= i - foundIndex + foundIndex = -1 + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength + for (i = byteOffset; i >= 0; i--) { + var found = true + for (var j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false + break + } + } + if (found) return i + } + } + + return -1 +} + +Buffer.prototype.includes = function includes (val, byteOffset, encoding) { + return this.indexOf(val, byteOffset, encoding) !== -1 +} + +Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, true) +} + +Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, false) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + var strLen = string.length + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; ++i) { + var parsed = parseInt(string.substr(i * 2, 2), 16) + if (numberIsNaN(parsed)) return i + buf[offset + i] = parsed + } + return i +} + +function utf8Write (buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) +} + +function asciiWrite (buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) +} + +function base64Write (buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) +} + +function ucs2Write (buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) +} + +Buffer.prototype.write = function write (string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8' + length = this.length + offset = 0 + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset + length = this.length + offset = 0 + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset >>> 0 + if (isFinite(length)) { + length = length >>> 0 + if (encoding === undefined) encoding = 'utf8' + } else { + encoding = length + length = undefined + } + } else { + throw new Error( + 'Buffer.write(string, encoding, offset[, length]) is no longer supported' + ) + } + + var remaining = this.length - offset + if (length === undefined || length > remaining) length = remaining + + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('Attempt to write outside buffer bounds') + } + + if (!encoding) encoding = 'utf8' + + var loweredCase = false + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) + + case 'ascii': + case 'latin1': + case 'binary': + return asciiWrite(this, string, offset, length) + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.toJSON = function toJSON () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + end = Math.min(buf.length, end) + var res = [] + + var i = start + while (i < end) { + var firstByte = buf[i] + var codePoint = null + var bytesPerSequence = (firstByte > 0xEF) + ? 4 + : (firstByte > 0xDF) + ? 3 + : (firstByte > 0xBF) + ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte + } + break + case 2: + secondByte = buf[i + 1] + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint + } + } + break + case 3: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint + } + } + break + case 4: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + fourthByte = buf[i + 3] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint + } + } + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD + bytesPerSequence = 1 + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000 + res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint = 0xDC00 | codePoint & 0x3FF + } + + res.push(codePoint) + i += bytesPerSequence + } + + return decodeCodePointsArray(res) +} + +// Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety +var MAX_ARGUMENTS_LENGTH = 0x1000 + +function decodeCodePointsArray (codePoints) { + var len = codePoints.length + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + var res = '' + var i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} + +function latin1Slice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; ++i) { + out += hexSliceLookupTable[buf[i]] + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + // If bytes.length is odd, the last 8 bits must be ignored (same as node.js) + for (var i = 0; i < bytes.length - 1; i += 2) { + res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) + } + return res +} + +Buffer.prototype.slice = function slice (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len + if (start < 0) start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) end = 0 + } else if (end > len) { + end = len + } + + if (end < start) end = start + + var newBuf = this.subarray(start, end) + // Return an augmented `Uint8Array` instance + Object.setPrototypeOf(newBuf, Buffer.prototype) + + return newBuf +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUintLE = +Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val +} + +Buffer.prototype.readUintBE = +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val +} + +Buffer.prototype.readUint8 = +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUint16LE = +Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUint16BE = +Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUint32LE = +Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUint32BE = +Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var i = byteLength + var mul = 1 + var val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') + if (offset + ext > buf.length) throw new RangeError('Index out of range') +} + +Buffer.prototype.writeUintLE = +Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUintBE = +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUint8 = +Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeUint16LE = +Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 +} + +Buffer.prototype.writeUint16BE = +Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} + +Buffer.prototype.writeUint32LE = +Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = (value & 0xff) + return offset + 4 +} + +Buffer.prototype.writeUint32BE = +Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} + +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + var limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = 0 + var mul = 1 + var sub = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + var limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = byteLength - 1 + var mul = 1 + var sub = 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) + if (value < 0) value = 0xff + value + 1 + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (offset + ext > buf.length) throw new RangeError('Index out of range') + if (offset < 0) throw new RangeError('Index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + } + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function copy (target, targetStart, start, end) { + if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer') + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (targetStart >= target.length) targetStart = target.length + if (!targetStart) targetStart = 0 + if (end > 0 && end < start) end = start + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= this.length) throw new RangeError('Index out of range') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) end = this.length + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start + } + + var len = end - start + + if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { + // Use built-in when available, missing from IE11 + this.copyWithin(targetStart, start, end) + } else { + Uint8Array.prototype.set.call( + target, + this.subarray(start, end), + targetStart + ) + } + + return len +} + +// Usage: +// buffer.fill(number[, offset[, end]]) +// buffer.fill(buffer[, offset[, end]]) +// buffer.fill(string[, offset[, end]][, encoding]) +Buffer.prototype.fill = function fill (val, start, end, encoding) { + // Handle string cases: + if (typeof val === 'string') { + if (typeof start === 'string') { + encoding = start + start = 0 + end = this.length + } else if (typeof end === 'string') { + encoding = end + end = this.length + } + if (encoding !== undefined && typeof encoding !== 'string') { + throw new TypeError('encoding must be a string') + } + if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + if (val.length === 1) { + var code = val.charCodeAt(0) + if ((encoding === 'utf8' && code < 128) || + encoding === 'latin1') { + // Fast path: If `val` fits into a single byte, use that numeric value. + val = code + } + } + } else if (typeof val === 'number') { + val = val & 255 + } else if (typeof val === 'boolean') { + val = Number(val) + } + + // Invalid ranges are not set to a default, so can range check early. + if (start < 0 || this.length < start || this.length < end) { + throw new RangeError('Out of range index') + } + + if (end <= start) { + return this + } + + start = start >>> 0 + end = end === undefined ? this.length : end >>> 0 + + if (!val) val = 0 + + var i + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val + } + } else { + var bytes = Buffer.isBuffer(val) + ? val + : Buffer.from(val, encoding) + var len = bytes.length + if (len === 0) { + throw new TypeError('The value "' + val + + '" is invalid for argument "value"') + } + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len] + } + } + + return this +} + +// HELPER FUNCTIONS +// ================ + +var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g + +function base64clean (str) { + // Node takes equal signs as end of the Base64 encoding + str = str.split('=')[0] + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = str.trim().replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + + for (var i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } + + // valid lead + leadSurrogate = codePoint + + continue + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } + + // valid surrogate pair + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + } + + leadSurrogate = null + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') + } + } + + return bytes +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str, units) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break + + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(base64clean(str)) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; ++i) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i +} + +// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass +// the `instanceof` check but they should be treated as of that type. +// See: https://github.com/feross/buffer/issues/166 +function isInstance (obj, type) { + return obj instanceof type || + (obj != null && obj.constructor != null && obj.constructor.name != null && + obj.constructor.name === type.name) +} +function numberIsNaN (obj) { + // For IE11 support + return obj !== obj // eslint-disable-line no-self-compare +} + +// Create lookup table for `toString('hex')` +// See: https://github.com/feross/buffer/issues/219 +var hexSliceLookupTable = (function () { + var alphabet = '0123456789abcdef' + var table = new Array(256) + for (var i = 0; i < 16; ++i) { + var i16 = i * 16 + for (var j = 0; j < 16; ++j) { + table[i16 + j] = alphabet[i] + alphabet[j] + } + } + return table +})() diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/package.json new file mode 100644 index 000000000..3b1b4986f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/buffer/package.json @@ -0,0 +1,96 @@ +{ + "name": "buffer", + "description": "Node.js Buffer API, for the browser", + "version": "5.7.1", + "author": { + "name": "Feross Aboukhadijeh", + "email": "feross@feross.org", + "url": "https://feross.org" + }, + "bugs": { + "url": "https://github.com/feross/buffer/issues" + }, + "contributors": [ + "Romain Beauxis ", + "James Halliday " + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + }, + "devDependencies": { + "airtap": "^3.0.0", + "benchmark": "^2.1.4", + "browserify": "^17.0.0", + "concat-stream": "^2.0.0", + "hyperquest": "^2.1.3", + "is-buffer": "^2.0.4", + "is-nan": "^1.3.0", + "split": "^1.0.1", + "standard": "*", + "tape": "^5.0.1", + "through2": "^4.0.2", + "uglify-js": "^3.11.3" + }, + "homepage": "https://github.com/feross/buffer", + "jspm": { + "map": { + "./index.js": { + "node": "@node/buffer" + } + } + }, + "keywords": [ + "arraybuffer", + "browser", + "browserify", + "buffer", + "compatible", + "dataview", + "uint8array" + ], + "license": "MIT", + "main": "index.js", + "types": "index.d.ts", + "repository": { + "type": "git", + "url": "git://github.com/feross/buffer.git" + }, + "scripts": { + "perf": "browserify --debug perf/bracket-notation.js > perf/bundle.js && open perf/index.html", + "perf-node": "node perf/bracket-notation.js && node perf/concat.js && node perf/copy-big.js && node perf/copy.js && node perf/new-big.js && node perf/new.js && node perf/readDoubleBE.js && node perf/readFloatBE.js && node perf/readUInt32LE.js && node perf/slice.js && node perf/writeFloatBE.js", + "size": "browserify -r ./ | uglifyjs -c -m | gzip | wc -c", + "test": "standard && node ./bin/test.js", + "test-browser-es5": "airtap -- test/*.js", + "test-browser-es5-local": "airtap --local -- test/*.js", + "test-browser-es6": "airtap -- test/*.js test/node/*.js", + "test-browser-es6-local": "airtap --local -- test/*.js test/node/*.js", + "test-node": "tape test/*.js test/node/*.js", + "update-authors": "./bin/update-authors.sh" + }, + "standard": { + "ignore": [ + "test/node/**/*.js", + "test/common.js", + "test/_polyfill.js", + "perf/**/*.js" + ], + "globals": [ + "SharedArrayBuffer" + ] + }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/History.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/History.md new file mode 100644 index 000000000..d60ce0e6d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/History.md @@ -0,0 +1,97 @@ +3.1.2 / 2022-01-27 +================== + + * Fix return value for un-parsable strings + +3.1.1 / 2021-11-15 +================== + + * Fix "thousandsSeparator" incorrecting formatting fractional part + +3.1.0 / 2019-01-22 +================== + + * Add petabyte (`pb`) support + +3.0.0 / 2017-08-31 +================== + + * Change "kB" to "KB" in format output + * Remove support for Node.js 0.6 + * Remove support for ComponentJS + +2.5.0 / 2017-03-24 +================== + + * Add option "unit" + +2.4.0 / 2016-06-01 +================== + + * Add option "unitSeparator" + +2.3.0 / 2016-02-15 +================== + + * Drop partial bytes on all parsed units + * Fix non-finite numbers to `.format` to return `null` + * Fix parsing byte string that looks like hex + * perf: hoist regular expressions + +2.2.0 / 2015-11-13 +================== + + * add option "decimalPlaces" + * add option "fixedDecimals" + +2.1.0 / 2015-05-21 +================== + + * add `.format` export + * add `.parse` export + +2.0.2 / 2015-05-20 +================== + + * remove map recreation + * remove unnecessary object construction + +2.0.1 / 2015-05-07 +================== + + * fix browserify require + * remove node.extend dependency + +2.0.0 / 2015-04-12 +================== + + * add option "case" + * add option "thousandsSeparator" + * return "null" on invalid parse input + * support proper round-trip: bytes(bytes(num)) === num + * units no longer case sensitive when parsing + +1.0.0 / 2014-05-05 +================== + + * add negative support. fixes #6 + +0.3.0 / 2014-03-19 +================== + + * added terabyte support + +0.2.1 / 2013-04-01 +================== + + * add .component + +0.2.0 / 2012-10-28 +================== + + * bytes(200).should.eql('200b') + +0.1.0 / 2012-07-04 +================== + + * add bytes to string conversion [yields] diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/LICENSE new file mode 100644 index 000000000..63e95a963 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2012-2014 TJ Holowaychuk +Copyright (c) 2015 Jed Watson + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/Readme.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/Readme.md new file mode 100644 index 000000000..5790e23e3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/Readme.md @@ -0,0 +1,152 @@ +# Bytes utility + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Build Status][ci-image]][ci-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Utility to parse a string bytes (ex: `1TB`) to bytes (`1099511627776`) and vice-versa. + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```bash +$ npm install bytes +``` + +## Usage + +```js +var bytes = require('bytes'); +``` + +#### bytes(number|string value, [options]): number|string|null + +Default export function. Delegates to either `bytes.format` or `bytes.parse` based on the type of `value`. + +**Arguments** + +| Name | Type | Description | +|---------|----------|--------------------| +| value | `number`|`string` | Number value to format or string value to parse | +| options | `Object` | Conversion options for `format` | + +**Returns** + +| Name | Type | Description | +|---------|------------------|-------------------------------------------------| +| results | `string`|`number`|`null` | Return null upon error. Numeric value in bytes, or string value otherwise. | + +**Example** + +```js +bytes(1024); +// output: '1KB' + +bytes('1KB'); +// output: 1024 +``` + +#### bytes.format(number value, [options]): string|null + +Format the given value in bytes into a string. If the value is negative, it is kept as such. If it is a float, it is + rounded. + +**Arguments** + +| Name | Type | Description | +|---------|----------|--------------------| +| value | `number` | Value in bytes | +| options | `Object` | Conversion options | + +**Options** + +| Property | Type | Description | +|-------------------|--------|-----------------------------------------------------------------------------------------| +| decimalPlaces | `number`|`null` | Maximum number of decimal places to include in output. Default value to `2`. | +| fixedDecimals | `boolean`|`null` | Whether to always display the maximum number of decimal places. Default value to `false` | +| thousandsSeparator | `string`|`null` | Example of values: `' '`, `','` and `'.'`... Default value to `''`. | +| unit | `string`|`null` | The unit in which the result will be returned (B/KB/MB/GB/TB). Default value to `''` (which means auto detect). | +| unitSeparator | `string`|`null` | Separator to use between number and unit. Default value to `''`. | + +**Returns** + +| Name | Type | Description | +|---------|------------------|-------------------------------------------------| +| results | `string`|`null` | Return null upon error. String value otherwise. | + +**Example** + +```js +bytes.format(1024); +// output: '1KB' + +bytes.format(1000); +// output: '1000B' + +bytes.format(1000, {thousandsSeparator: ' '}); +// output: '1 000B' + +bytes.format(1024 * 1.7, {decimalPlaces: 0}); +// output: '2KB' + +bytes.format(1024, {unitSeparator: ' '}); +// output: '1 KB' +``` + +#### bytes.parse(string|number value): number|null + +Parse the string value into an integer in bytes. If no unit is given, or `value` +is a number, it is assumed the value is in bytes. + +Supported units and abbreviations are as follows and are case-insensitive: + + * `b` for bytes + * `kb` for kilobytes + * `mb` for megabytes + * `gb` for gigabytes + * `tb` for terabytes + * `pb` for petabytes + +The units are in powers of two, not ten. This means 1kb = 1024b according to this parser. + +**Arguments** + +| Name | Type | Description | +|---------------|--------|--------------------| +| value | `string`|`number` | String to parse, or number in bytes. | + +**Returns** + +| Name | Type | Description | +|---------|-------------|-------------------------| +| results | `number`|`null` | Return null upon error. Value in bytes otherwise. | + +**Example** + +```js +bytes.parse('1KB'); +// output: 1024 + +bytes.parse('1024'); +// output: 1024 + +bytes.parse(1024); +// output: 1024 +``` + +## License + +[MIT](LICENSE) + +[ci-image]: https://badgen.net/github/checks/visionmedia/bytes.js/master?label=ci +[ci-url]: https://github.com/visionmedia/bytes.js/actions?query=workflow%3Aci +[coveralls-image]: https://badgen.net/coveralls/c/github/visionmedia/bytes.js/master +[coveralls-url]: https://coveralls.io/r/visionmedia/bytes.js?branch=master +[downloads-image]: https://badgen.net/npm/dm/bytes +[downloads-url]: https://npmjs.org/package/bytes +[npm-image]: https://badgen.net/npm/v/bytes +[npm-url]: https://npmjs.org/package/bytes diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/index.js new file mode 100644 index 000000000..6f2d0f89e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/index.js @@ -0,0 +1,170 @@ +/*! + * bytes + * Copyright(c) 2012-2014 TJ Holowaychuk + * Copyright(c) 2015 Jed Watson + * MIT Licensed + */ + +'use strict'; + +/** + * Module exports. + * @public + */ + +module.exports = bytes; +module.exports.format = format; +module.exports.parse = parse; + +/** + * Module variables. + * @private + */ + +var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g; + +var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/; + +var map = { + b: 1, + kb: 1 << 10, + mb: 1 << 20, + gb: 1 << 30, + tb: Math.pow(1024, 4), + pb: Math.pow(1024, 5), +}; + +var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i; + +/** + * Convert the given value in bytes into a string or parse to string to an integer in bytes. + * + * @param {string|number} value + * @param {{ + * case: [string], + * decimalPlaces: [number] + * fixedDecimals: [boolean] + * thousandsSeparator: [string] + * unitSeparator: [string] + * }} [options] bytes options. + * + * @returns {string|number|null} + */ + +function bytes(value, options) { + if (typeof value === 'string') { + return parse(value); + } + + if (typeof value === 'number') { + return format(value, options); + } + + return null; +} + +/** + * Format the given value in bytes into a string. + * + * If the value is negative, it is kept as such. If it is a float, + * it is rounded. + * + * @param {number} value + * @param {object} [options] + * @param {number} [options.decimalPlaces=2] + * @param {number} [options.fixedDecimals=false] + * @param {string} [options.thousandsSeparator=] + * @param {string} [options.unit=] + * @param {string} [options.unitSeparator=] + * + * @returns {string|null} + * @public + */ + +function format(value, options) { + if (!Number.isFinite(value)) { + return null; + } + + var mag = Math.abs(value); + var thousandsSeparator = (options && options.thousandsSeparator) || ''; + var unitSeparator = (options && options.unitSeparator) || ''; + var decimalPlaces = (options && options.decimalPlaces !== undefined) ? options.decimalPlaces : 2; + var fixedDecimals = Boolean(options && options.fixedDecimals); + var unit = (options && options.unit) || ''; + + if (!unit || !map[unit.toLowerCase()]) { + if (mag >= map.pb) { + unit = 'PB'; + } else if (mag >= map.tb) { + unit = 'TB'; + } else if (mag >= map.gb) { + unit = 'GB'; + } else if (mag >= map.mb) { + unit = 'MB'; + } else if (mag >= map.kb) { + unit = 'KB'; + } else { + unit = 'B'; + } + } + + var val = value / map[unit.toLowerCase()]; + var str = val.toFixed(decimalPlaces); + + if (!fixedDecimals) { + str = str.replace(formatDecimalsRegExp, '$1'); + } + + if (thousandsSeparator) { + str = str.split('.').map(function (s, i) { + return i === 0 + ? s.replace(formatThousandsRegExp, thousandsSeparator) + : s + }).join('.'); + } + + return str + unitSeparator + unit; +} + +/** + * Parse the string value into an integer in bytes. + * + * If no unit is given, it is assumed the value is in bytes. + * + * @param {number|string} val + * + * @returns {number|null} + * @public + */ + +function parse(val) { + if (typeof val === 'number' && !isNaN(val)) { + return val; + } + + if (typeof val !== 'string') { + return null; + } + + // Test if the string passed is valid + var results = parseRegExp.exec(val); + var floatValue; + var unit = 'b'; + + if (!results) { + // Nothing could be extracted from the given string + floatValue = parseInt(val, 10); + unit = 'b' + } else { + // Retrieve the value and the unit + floatValue = parseFloat(results[1]); + unit = results[4].toLowerCase(); + } + + if (isNaN(floatValue)) { + return null; + } + + return Math.floor(map[unit] * floatValue); +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/package.json new file mode 100644 index 000000000..f2b6a8b0e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/bytes/package.json @@ -0,0 +1,42 @@ +{ + "name": "bytes", + "description": "Utility to parse a string bytes to bytes and vice-versa", + "version": "3.1.2", + "author": "TJ Holowaychuk (http://tjholowaychuk.com)", + "contributors": [ + "Jed Watson ", + "Théo FIDRY " + ], + "license": "MIT", + "keywords": [ + "byte", + "bytes", + "utility", + "parse", + "parser", + "convert", + "converter" + ], + "repository": "visionmedia/bytes.js", + "devDependencies": { + "eslint": "7.32.0", + "eslint-plugin-markdown": "2.2.1", + "mocha": "9.2.0", + "nyc": "15.1.0" + }, + "files": [ + "History.md", + "LICENSE", + "Readme.md", + "index.js" + ], + "engines": { + "node": ">= 0.8" + }, + "scripts": { + "lint": "eslint .", + "test": "mocha --check-leaks --reporter spec", + "test-ci": "nyc --reporter=lcov --reporter=text npm test", + "test-cov": "nyc --reporter=html --reporter=text npm test" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/LICENSE.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/LICENSE.md new file mode 100644 index 000000000..8d28acf86 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/LICENSE.md @@ -0,0 +1,16 @@ +ISC License + +Copyright (c) npm, Inc. + +Permission to use, copy, modify, and/or distribute this software for +any purpose with or without fee is hereby granted, provided that the +above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE COPYRIGHT HOLDER DISCLAIMS +ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE +USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/README.md new file mode 100644 index 000000000..6dc11babf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/README.md @@ -0,0 +1,703 @@ +# cacache [![npm version](https://img.shields.io/npm/v/cacache.svg)](https://npm.im/cacache) [![license](https://img.shields.io/npm/l/cacache.svg)](https://npm.im/cacache) [![Travis](https://img.shields.io/travis/npm/cacache.svg)](https://travis-ci.org/npm/cacache) [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/npm/cacache?svg=true)](https://ci.appveyor.com/project/npm/cacache) [![Coverage Status](https://coveralls.io/repos/github/npm/cacache/badge.svg?branch=latest)](https://coveralls.io/github/npm/cacache?branch=latest) + +[`cacache`](https://github.com/npm/cacache) is a Node.js library for managing +local key and content address caches. It's really fast, really good at +concurrency, and it will never give you corrupted data, even if cache files +get corrupted or manipulated. + +On systems that support user and group settings on files, cacache will +match the `uid` and `gid` values to the folder where the cache lives, even +when running as `root`. + +It was written to be used as [npm](https://npm.im)'s local cache, but can +just as easily be used on its own. + +## Install + +`$ npm install --save cacache` + +## Table of Contents + +* [Example](#example) +* [Features](#features) +* [Contributing](#contributing) +* [API](#api) + * [Using localized APIs](#localized-api) + * Reading + * [`ls`](#ls) + * [`ls.stream`](#ls-stream) + * [`get`](#get-data) + * [`get.stream`](#get-stream) + * [`get.info`](#get-info) + * [`get.hasContent`](#get-hasContent) + * Writing + * [`put`](#put-data) + * [`put.stream`](#put-stream) + * [`rm.all`](#rm-all) + * [`rm.entry`](#rm-entry) + * [`rm.content`](#rm-content) + * [`index.compact`](#index-compact) + * [`index.insert`](#index-insert) + * Utilities + * [`clearMemoized`](#clear-memoized) + * [`tmp.mkdir`](#tmp-mkdir) + * [`tmp.withTmp`](#with-tmp) + * Integrity + * [Subresource Integrity](#integrity) + * [`verify`](#verify) + * [`verify.lastRun`](#verify-last-run) + +### Example + +```javascript +const cacache = require('cacache') +const fs = require('fs') + +const tarball = '/path/to/mytar.tgz' +const cachePath = '/tmp/my-toy-cache' +const key = 'my-unique-key-1234' + +// Cache it! Use `cachePath` as the root of the content cache +cacache.put(cachePath, key, '10293801983029384').then(integrity => { + console.log(`Saved content to ${cachePath}.`) +}) + +const destination = '/tmp/mytar.tgz' + +// Copy the contents out of the cache and into their destination! +// But this time, use stream instead! +cacache.get.stream( + cachePath, key +).pipe( + fs.createWriteStream(destination) +).on('finish', () => { + console.log('done extracting!') +}) + +// The same thing, but skip the key index. +cacache.get.byDigest(cachePath, integrityHash).then(data => { + fs.writeFile(destination, data, err => { + console.log('tarball data fetched based on its sha512sum and written out!') + }) +}) +``` + +### Features + +* Extraction by key or by content address (shasum, etc) +* [Subresource Integrity](#integrity) web standard support +* Multi-hash support - safely host sha1, sha512, etc, in a single cache +* Automatic content deduplication +* Fault tolerance (immune to corruption, partial writes, process races, etc) +* Consistency guarantees on read and write (full data verification) +* Lockless, high-concurrency cache access +* Streaming support +* Promise support +* Fast -- sub-millisecond reads and writes including verification +* Arbitrary metadata storage +* Garbage collection and additional offline verification +* Thorough test coverage +* There's probably a bloom filter in there somewhere. Those are cool, right? 🤔 + +### Contributing + +The cacache team enthusiastically welcomes contributions and project participation! There's a bunch of things you can do if you want to contribute! The [Contributor Guide](CONTRIBUTING.md) has all the information you need for everything from reporting bugs to contributing entire new features. Please don't hesitate to jump in if you'd like to, or even ask us questions if something isn't clear. + +All participants and maintainers in this project are expected to follow [Code of Conduct](CODE_OF_CONDUCT.md), and just generally be excellent to each other. + +Please refer to the [Changelog](CHANGELOG.md) for project history details, too. + +Happy hacking! + +### API + +#### `> cacache.ls(cache) -> Promise` + +Lists info for all entries currently in the cache as a single large object. Each +entry in the object will be keyed by the unique index key, with corresponding +[`get.info`](#get-info) objects as the values. + +##### Example + +```javascript +cacache.ls(cachePath).then(console.log) +// Output +{ + 'my-thing': { + key: 'my-thing', + integrity: 'sha512-BaSe64/EnCoDED+HAsh==' + path: '.testcache/content/deadbeef', // joined with `cachePath` + time: 12345698490, + size: 4023948, + metadata: { + name: 'blah', + version: '1.2.3', + description: 'this was once a package but now it is my-thing' + } + }, + 'other-thing': { + key: 'other-thing', + integrity: 'sha1-ANothER+hasH=', + path: '.testcache/content/bada55', + time: 11992309289, + size: 111112 + } +} +``` + +#### `> cacache.ls.stream(cache) -> Readable` + +Lists info for all entries currently in the cache as a single large object. + +This works just like [`ls`](#ls), except [`get.info`](#get-info) entries are +returned as `'data'` events on the returned stream. + +##### Example + +```javascript +cacache.ls.stream(cachePath).on('data', console.log) +// Output +{ + key: 'my-thing', + integrity: 'sha512-BaSe64HaSh', + path: '.testcache/content/deadbeef', // joined with `cachePath` + time: 12345698490, + size: 13423, + metadata: { + name: 'blah', + version: '1.2.3', + description: 'this was once a package but now it is my-thing' + } +} + +{ + key: 'other-thing', + integrity: 'whirlpool-WoWSoMuchSupport', + path: '.testcache/content/bada55', + time: 11992309289, + size: 498023984029 +} + +{ + ... +} +``` + +#### `> cacache.get(cache, key, [opts]) -> Promise({data, metadata, integrity})` + +Returns an object with the cached data, digest, and metadata identified by +`key`. The `data` property of this object will be a `Buffer` instance that +presumably holds some data that means something to you. I'm sure you know what +to do with it! cacache just won't care. + +`integrity` is a [Subresource +Integrity](#integrity) +string. That is, a string that can be used to verify `data`, which looks like +`-`. + +If there is no content identified by `key`, or if the locally-stored data does +not pass the validity checksum, the promise will be rejected. + +A sub-function, `get.byDigest` may be used for identical behavior, except lookup +will happen by integrity hash, bypassing the index entirely. This version of the +function *only* returns `data` itself, without any wrapper. + +See: [options](#get-options) + +##### Note + +This function loads the entire cache entry into memory before returning it. If +you're dealing with Very Large data, consider using [`get.stream`](#get-stream) +instead. + +##### Example + +```javascript +// Look up by key +cache.get(cachePath, 'my-thing').then(console.log) +// Output: +{ + metadata: { + thingName: 'my' + }, + integrity: 'sha512-BaSe64HaSh', + data: Buffer#, + size: 9320 +} + +// Look up by digest +cache.get.byDigest(cachePath, 'sha512-BaSe64HaSh').then(console.log) +// Output: +Buffer# +``` + +#### `> cacache.get.stream(cache, key, [opts]) -> Readable` + +Returns a [Readable Stream](https://nodejs.org/api/stream.html#stream_readable_streams) of the cached data identified by `key`. + +If there is no content identified by `key`, or if the locally-stored data does +not pass the validity checksum, an error will be emitted. + +`metadata` and `integrity` events will be emitted before the stream closes, if +you need to collect that extra data about the cached entry. + +A sub-function, `get.stream.byDigest` may be used for identical behavior, +except lookup will happen by integrity hash, bypassing the index entirely. This +version does not emit the `metadata` and `integrity` events at all. + +See: [options](#get-options) + +##### Example + +```javascript +// Look up by key +cache.get.stream( + cachePath, 'my-thing' +).on('metadata', metadata => { + console.log('metadata:', metadata) +}).on('integrity', integrity => { + console.log('integrity:', integrity) +}).pipe( + fs.createWriteStream('./x.tgz') +) +// Outputs: +metadata: { ... } +integrity: 'sha512-SoMeDIGest+64==' + +// Look up by digest +cache.get.stream.byDigest( + cachePath, 'sha512-SoMeDIGest+64==' +).pipe( + fs.createWriteStream('./x.tgz') +) +``` + +#### `> cacache.get.info(cache, key) -> Promise` + +Looks up `key` in the cache index, returning information about the entry if +one exists. + +##### Fields + +* `key` - Key the entry was looked up under. Matches the `key` argument. +* `integrity` - [Subresource Integrity hash](#integrity) for the content this entry refers to. +* `path` - Filesystem path where content is stored, joined with `cache` argument. +* `time` - Timestamp the entry was first added on. +* `metadata` - User-assigned metadata associated with the entry/content. + +##### Example + +```javascript +cacache.get.info(cachePath, 'my-thing').then(console.log) + +// Output +{ + key: 'my-thing', + integrity: 'sha256-MUSTVERIFY+ALL/THINGS==' + path: '.testcache/content/deadbeef', + time: 12345698490, + size: 849234, + metadata: { + name: 'blah', + version: '1.2.3', + description: 'this was once a package but now it is my-thing' + } +} +``` + +#### `> cacache.get.hasContent(cache, integrity) -> Promise` + +Looks up a [Subresource Integrity hash](#integrity) in the cache. If content +exists for this `integrity`, it will return an object, with the specific single integrity hash +that was found in `sri` key, and the size of the found content as `size`. If no content exists for this integrity, it will return `false`. + +##### Example + +```javascript +cacache.get.hasContent(cachePath, 'sha256-MUSTVERIFY+ALL/THINGS==').then(console.log) + +// Output +{ + sri: { + source: 'sha256-MUSTVERIFY+ALL/THINGS==', + algorithm: 'sha256', + digest: 'MUSTVERIFY+ALL/THINGS==', + options: [] + }, + size: 9001 +} + +cacache.get.hasContent(cachePath, 'sha521-NOT+IN/CACHE==').then(console.log) + +// Output +false +``` + +##### Options + +##### `opts.integrity` +If present, the pre-calculated digest for the inserted content. If this option +is provided and does not match the post-insertion digest, insertion will fail +with an `EINTEGRITY` error. + +##### `opts.memoize` + +Default: null + +If explicitly truthy, cacache will read from memory and memoize data on bulk read. If `false`, cacache will read from disk data. Reader functions by default read from in-memory cache. + +##### `opts.size` +If provided, the data stream will be verified to check that enough data was +passed through. If there's more or less data than expected, insertion will fail +with an `EBADSIZE` error. + + +#### `> cacache.put(cache, key, data, [opts]) -> Promise` + +Inserts data passed to it into the cache. The returned Promise resolves with a +digest (generated according to [`opts.algorithms`](#optsalgorithms)) after the +cache entry has been successfully written. + +See: [options](#put-options) + +##### Example + +```javascript +fetch( + 'https://registry.npmjs.org/cacache/-/cacache-1.0.0.tgz' +).then(data => { + return cacache.put(cachePath, 'registry.npmjs.org|cacache@1.0.0', data) +}).then(integrity => { + console.log('integrity hash is', integrity) +}) +``` + +#### `> cacache.put.stream(cache, key, [opts]) -> Writable` + +Returns a [Writable +Stream](https://nodejs.org/api/stream.html#stream_writable_streams) that inserts +data written to it into the cache. Emits an `integrity` event with the digest of +written contents when it succeeds. + +See: [options](#put-options) + +##### Example + +```javascript +request.get( + 'https://registry.npmjs.org/cacache/-/cacache-1.0.0.tgz' +).pipe( + cacache.put.stream( + cachePath, 'registry.npmjs.org|cacache@1.0.0' + ).on('integrity', d => console.log(`integrity digest is ${d}`)) +) +``` + +##### Options + +##### `opts.metadata` + +Arbitrary metadata to be attached to the inserted key. + +##### `opts.size` + +If provided, the data stream will be verified to check that enough data was +passed through. If there's more or less data than expected, insertion will fail +with an `EBADSIZE` error. + +##### `opts.integrity` + +If present, the pre-calculated digest for the inserted content. If this option +is provided and does not match the post-insertion digest, insertion will fail +with an `EINTEGRITY` error. + +`algorithms` has no effect if this option is present. + +##### `opts.algorithms` + +Default: ['sha512'] + +Hashing algorithms to use when calculating the [subresource integrity +digest](#integrity) +for inserted data. Can use any algorithm listed in `crypto.getHashes()` or +`'omakase'`/`'お任せします'` to pick a random hash algorithm on each insertion. You +may also use any anagram of `'modnar'` to use this feature. + +Currently only supports one algorithm at a time (i.e., an array length of +exactly `1`). Has no effect if `opts.integrity` is present. + +##### `opts.memoize` + +Default: null + +If provided, cacache will memoize the given cache insertion in memory, bypassing +any filesystem checks for that key or digest in future cache fetches. Nothing +will be written to the in-memory cache unless this option is explicitly truthy. + +If `opts.memoize` is an object or a `Map`-like (that is, an object with `get` +and `set` methods), it will be written to instead of the global memoization +cache. + +Reading from disk data can be forced by explicitly passing `memoize: false` to +the reader functions, but their default will be to read from memory. + +##### `opts.tmpPrefix` +Default: null + +Prefix to append on the temporary directory name inside the cache's tmp dir. + +#### `> cacache.rm.all(cache) -> Promise` + +Clears the entire cache. Mainly by blowing away the cache directory itself. + +##### Example + +```javascript +cacache.rm.all(cachePath).then(() => { + console.log('THE APOCALYPSE IS UPON US 😱') +}) +``` + +#### `> cacache.rm.entry(cache, key, [opts]) -> Promise` + +Alias: `cacache.rm` + +Removes the index entry for `key`. Content will still be accessible if +requested directly by content address ([`get.stream.byDigest`](#get-stream)). + +By default, this appends a new entry to the index with an integrity of `null`. +If `opts.removeFully` is set to `true` then the index file itself will be +physically deleted rather than appending a `null`. + +To remove the content itself (which might still be used by other entries), use +[`rm.content`](#rm-content). Or, to safely vacuum any unused content, use +[`verify`](#verify). + +##### Example + +```javascript +cacache.rm.entry(cachePath, 'my-thing').then(() => { + console.log('I did not like it anyway') +}) +``` + +#### `> cacache.rm.content(cache, integrity) -> Promise` + +Removes the content identified by `integrity`. Any index entries referring to it +will not be usable again until the content is re-added to the cache with an +identical digest. + +##### Example + +```javascript +cacache.rm.content(cachePath, 'sha512-SoMeDIGest/IN+BaSE64==').then(() => { + console.log('data for my-thing is gone!') +}) +``` + +#### `> cacache.index.compact(cache, key, matchFn, [opts]) -> Promise` + +Uses `matchFn`, which must be a synchronous function that accepts two entries +and returns a boolean indicating whether or not the two entries match, to +deduplicate all entries in the cache for the given `key`. + +If `opts.validateEntry` is provided, it will be called as a function with the +only parameter being a single index entry. The function must return a Boolean, +if it returns `true` the entry is considered valid and will be kept in the index, +if it returns `false` the entry will be removed from the index. + +If `opts.validateEntry` is not provided, however, every entry in the index will +be deduplicated and kept until the first `null` integrity is reached, removing +all entries that were written before the `null`. + +The deduplicated list of entries is both written to the index, replacing the +existing content, and returned in the Promise. + +#### `> cacache.index.insert(cache, key, integrity, opts) -> Promise` + +Writes an index entry to the cache for the given `key` without writing content. + +It is assumed if you are using this method, you have already stored the content +some other way and you only wish to add a new index to that content. The `metadata` +and `size` properties are read from `opts` and used as part of the index entry. + +Returns a Promise resolving to the newly added entry. + +#### `> cacache.clearMemoized()` + +Completely resets the in-memory entry cache. + +#### `> tmp.mkdir(cache, opts) -> Promise` + +Returns a unique temporary directory inside the cache's `tmp` dir. This +directory will use the same safe user assignment that all the other stuff use. + +Once the directory is made, it's the user's responsibility that all files +within are given the appropriate `gid`/`uid` ownership settings to match +the rest of the cache. If not, you can ask cacache to do it for you by +calling [`tmp.fix()`](#tmp-fix), which will fix all tmp directory +permissions. + +If you want automatic cleanup of this directory, use +[`tmp.withTmp()`](#with-tpm) + +See: [options](#tmp-options) + +##### Example + +```javascript +cacache.tmp.mkdir(cache).then(dir => { + fs.writeFile(path.join(dir, 'blablabla'), Buffer#<1234>, ...) +}) +``` + +#### `> tmp.fix(cache) -> Promise` + +Sets the `uid` and `gid` properties on all files and folders within the tmp +folder to match the rest of the cache. + +Use this after manually writing files into [`tmp.mkdir`](#tmp-mkdir) or +[`tmp.withTmp`](#with-tmp). + +##### Example + +```javascript +cacache.tmp.mkdir(cache).then(dir => { + writeFile(path.join(dir, 'file'), someData).then(() => { + // make sure we didn't just put a root-owned file in the cache + cacache.tmp.fix().then(() => { + // all uids and gids match now + }) + }) +}) +``` + +#### `> tmp.withTmp(cache, opts, cb) -> Promise` + +Creates a temporary directory with [`tmp.mkdir()`](#tmp-mkdir) and calls `cb` +with it. The created temporary directory will be removed when the return value +of `cb()` resolves, the tmp directory will be automatically deleted once that +promise completes. + +The same caveats apply when it comes to managing permissions for the tmp dir's +contents. + +See: [options](#tmp-options) + +##### Example + +```javascript +cacache.tmp.withTmp(cache, dir => { + return fs.writeFileAsync(path.join(dir, 'blablabla'), Buffer#<1234>, ...) +}).then(() => { + // `dir` no longer exists +}) +``` + +##### Options + +##### `opts.tmpPrefix` +Default: null + +Prefix to append on the temporary directory name inside the cache's tmp dir. + +#### Subresource Integrity Digests + +For content verification and addressing, cacache uses strings following the +[Subresource +Integrity spec](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity). +That is, any time cacache expects an `integrity` argument or option, it +should be in the format `-`. + +One deviation from the current spec is that cacache will support any hash +algorithms supported by the underlying Node.js process. You can use +`crypto.getHashes()` to see which ones you can use. + +##### Generating Digests Yourself + +If you have an existing content shasum, they are generally formatted as a +hexadecimal string (that is, a sha1 would look like: +`5f5513f8822fdbe5145af33b64d8d970dcf95c6e`). In order to be compatible with +cacache, you'll need to convert this to an equivalent subresource integrity +string. For this example, the corresponding hash would be: +`sha1-X1UT+IIv2+UUWvM7ZNjZcNz5XG4=`. + +If you want to generate an integrity string yourself for existing data, you can +use something like this: + +```javascript +const crypto = require('crypto') +const hashAlgorithm = 'sha512' +const data = 'foobarbaz' + +const integrity = ( + hashAlgorithm + + '-' + + crypto.createHash(hashAlgorithm).update(data).digest('base64') +) +``` + +You can also use [`ssri`](https://npm.im/ssri) to have a richer set of functionality +around SRI strings, including generation, parsing, and translating from existing +hex-formatted strings. + +#### `> cacache.verify(cache, opts) -> Promise` + +Checks out and fixes up your cache: + +* Cleans up corrupted or invalid index entries. +* Custom entry filtering options. +* Garbage collects any content entries not referenced by the index. +* Checks integrity for all content entries and removes invalid content. +* Fixes cache ownership. +* Removes the `tmp` directory in the cache and all its contents. + +When it's done, it'll return an object with various stats about the verification +process, including amount of storage reclaimed, number of valid entries, number +of entries removed, etc. + +##### Options + +##### `opts.concurrency` + +Default: 20 + +Number of concurrently read files in the filesystem while doing clean up. + +##### `opts.filter` +Receives a formatted entry. Return false to remove it. +Note: might be called more than once on the same entry. + +##### `opts.log` +Custom logger function: +``` + log: { silly () {} } + log.silly('verify', 'verifying cache at', cache) +``` + +##### Example + +```sh +echo somegarbage >> $CACHEPATH/content/deadbeef +``` + +```javascript +cacache.verify(cachePath).then(stats => { + // deadbeef collected, because of invalid checksum. + console.log('cache is much nicer now! stats:', stats) +}) +``` + +#### `> cacache.verify.lastRun(cache) -> Promise` + +Returns a `Date` representing the last time `cacache.verify` was run on `cache`. + +##### Example + +```javascript +cacache.verify(cachePath).then(() => { + cacache.verify.lastRun(cachePath).then(lastTime => { + console.log('cacache.verify was last called on' + lastTime) + }) +}) +``` diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/get.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/get.js new file mode 100644 index 000000000..4e905e7cf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/get.js @@ -0,0 +1,237 @@ +'use strict' + +const Collect = require('minipass-collect') +const Minipass = require('minipass') +const Pipeline = require('minipass-pipeline') +const fs = require('fs') +const util = require('util') + +const index = require('./lib/entry-index') +const memo = require('./lib/memoization') +const read = require('./lib/content/read') + +const writeFile = util.promisify(fs.writeFile) + +function getData (cache, key, opts = {}) { + const { integrity, memoize, size } = opts + const memoized = memo.get(cache, key, opts) + if (memoized && memoize !== false) { + return Promise.resolve({ + metadata: memoized.entry.metadata, + data: memoized.data, + integrity: memoized.entry.integrity, + size: memoized.entry.size, + }) + } + + return index.find(cache, key, opts).then((entry) => { + if (!entry) + throw new index.NotFoundError(cache, key) + + return read(cache, entry.integrity, { integrity, size }).then((data) => { + if (memoize) + memo.put(cache, entry, data, opts) + + return { + data, + metadata: entry.metadata, + size: entry.size, + integrity: entry.integrity, + } + }) + }) +} +module.exports = getData + +function getDataByDigest (cache, key, opts = {}) { + const { integrity, memoize, size } = opts + const memoized = memo.get.byDigest(cache, key, opts) + if (memoized && memoize !== false) + return Promise.resolve(memoized) + + return read(cache, key, { integrity, size }).then((res) => { + if (memoize) + memo.put.byDigest(cache, key, res, opts) + return res + }) +} +module.exports.byDigest = getDataByDigest + +function getDataSync (cache, key, opts = {}) { + const { integrity, memoize, size } = opts + const memoized = memo.get(cache, key, opts) + + if (memoized && memoize !== false) { + return { + metadata: memoized.entry.metadata, + data: memoized.data, + integrity: memoized.entry.integrity, + size: memoized.entry.size, + } + } + const entry = index.find.sync(cache, key, opts) + if (!entry) + throw new index.NotFoundError(cache, key) + const data = read.sync(cache, entry.integrity, { + integrity: integrity, + size: size, + }) + const res = { + metadata: entry.metadata, + data: data, + size: entry.size, + integrity: entry.integrity, + } + if (memoize) + memo.put(cache, entry, res.data, opts) + + return res +} + +module.exports.sync = getDataSync + +function getDataByDigestSync (cache, digest, opts = {}) { + const { integrity, memoize, size } = opts + const memoized = memo.get.byDigest(cache, digest, opts) + + if (memoized && memoize !== false) + return memoized + + const res = read.sync(cache, digest, { + integrity: integrity, + size: size, + }) + if (memoize) + memo.put.byDigest(cache, digest, res, opts) + + return res +} +module.exports.sync.byDigest = getDataByDigestSync + +const getMemoizedStream = (memoized) => { + const stream = new Minipass() + stream.on('newListener', function (ev, cb) { + ev === 'metadata' && cb(memoized.entry.metadata) + ev === 'integrity' && cb(memoized.entry.integrity) + ev === 'size' && cb(memoized.entry.size) + }) + stream.end(memoized.data) + return stream +} + +function getStream (cache, key, opts = {}) { + const { memoize, size } = opts + const memoized = memo.get(cache, key, opts) + if (memoized && memoize !== false) + return getMemoizedStream(memoized) + + const stream = new Pipeline() + index + .find(cache, key) + .then((entry) => { + if (!entry) + throw new index.NotFoundError(cache, key) + + stream.emit('metadata', entry.metadata) + stream.emit('integrity', entry.integrity) + stream.emit('size', entry.size) + stream.on('newListener', function (ev, cb) { + ev === 'metadata' && cb(entry.metadata) + ev === 'integrity' && cb(entry.integrity) + ev === 'size' && cb(entry.size) + }) + + const src = read.readStream( + cache, + entry.integrity, + { ...opts, size: typeof size !== 'number' ? entry.size : size } + ) + + if (memoize) { + const memoStream = new Collect.PassThrough() + memoStream.on('collect', data => memo.put(cache, entry, data, opts)) + stream.unshift(memoStream) + } + stream.unshift(src) + }) + .catch((err) => stream.emit('error', err)) + + return stream +} + +module.exports.stream = getStream + +function getStreamDigest (cache, integrity, opts = {}) { + const { memoize } = opts + const memoized = memo.get.byDigest(cache, integrity, opts) + if (memoized && memoize !== false) { + const stream = new Minipass() + stream.end(memoized) + return stream + } else { + const stream = read.readStream(cache, integrity, opts) + if (!memoize) + return stream + + const memoStream = new Collect.PassThrough() + memoStream.on('collect', data => memo.put.byDigest( + cache, + integrity, + data, + opts + )) + return new Pipeline(stream, memoStream) + } +} + +module.exports.stream.byDigest = getStreamDigest + +function info (cache, key, opts = {}) { + const { memoize } = opts + const memoized = memo.get(cache, key, opts) + if (memoized && memoize !== false) + return Promise.resolve(memoized.entry) + else + return index.find(cache, key) +} +module.exports.info = info + +function copy (cache, key, dest, opts = {}) { + if (read.copy) { + return index.find(cache, key, opts).then((entry) => { + if (!entry) + throw new index.NotFoundError(cache, key) + return read.copy(cache, entry.integrity, dest, opts) + .then(() => { + return { + metadata: entry.metadata, + size: entry.size, + integrity: entry.integrity, + } + }) + }) + } + + return getData(cache, key, opts).then((res) => { + return writeFile(dest, res.data).then(() => { + return { + metadata: res.metadata, + size: res.size, + integrity: res.integrity, + } + }) + }) +} +module.exports.copy = copy + +function copyByDigest (cache, key, dest, opts = {}) { + if (read.copy) + return read.copy(cache, key, dest, opts).then(() => key) + + return getDataByDigest(cache, key, opts).then((res) => { + return writeFile(dest, res).then(() => key) + }) +} +module.exports.copy.byDigest = copyByDigest + +module.exports.hasContent = read.hasContent diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/index.js new file mode 100644 index 000000000..c8c52b041 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/index.js @@ -0,0 +1,46 @@ +'use strict' + +const ls = require('./ls.js') +const get = require('./get.js') +const put = require('./put.js') +const rm = require('./rm.js') +const verify = require('./verify.js') +const { clearMemoized } = require('./lib/memoization.js') +const tmp = require('./lib/util/tmp.js') +const index = require('./lib/entry-index.js') + +module.exports.index = {} +module.exports.index.compact = index.compact +module.exports.index.insert = index.insert + +module.exports.ls = ls +module.exports.ls.stream = ls.stream + +module.exports.get = get +module.exports.get.byDigest = get.byDigest +module.exports.get.sync = get.sync +module.exports.get.sync.byDigest = get.sync.byDigest +module.exports.get.stream = get.stream +module.exports.get.stream.byDigest = get.stream.byDigest +module.exports.get.copy = get.copy +module.exports.get.copy.byDigest = get.copy.byDigest +module.exports.get.info = get.info +module.exports.get.hasContent = get.hasContent +module.exports.get.hasContent.sync = get.hasContent.sync + +module.exports.put = put +module.exports.put.stream = put.stream + +module.exports.rm = rm.entry +module.exports.rm.all = rm.all +module.exports.rm.entry = module.exports.rm +module.exports.rm.content = rm.content + +module.exports.clearMemoized = clearMemoized + +module.exports.tmp = {} +module.exports.tmp.mkdir = tmp.mkdir +module.exports.tmp.withTmp = tmp.withTmp + +module.exports.verify = verify +module.exports.verify.lastRun = verify.lastRun diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/path.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/path.js new file mode 100644 index 000000000..ad5a76a4f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/path.js @@ -0,0 +1,29 @@ +'use strict' + +const contentVer = require('../../package.json')['cache-version'].content +const hashToSegments = require('../util/hash-to-segments') +const path = require('path') +const ssri = require('ssri') + +// Current format of content file path: +// +// sha512-BaSE64Hex= -> +// ~/.my-cache/content-v2/sha512/ba/da/55deadbeefc0ffee +// +module.exports = contentPath + +function contentPath (cache, integrity) { + const sri = ssri.parse(integrity, { single: true }) + // contentPath is the *strongest* algo given + return path.join( + contentDir(cache), + sri.algorithm, + ...hashToSegments(sri.hexDigest()) + ) +} + +module.exports.contentDir = contentDir + +function contentDir (cache) { + return path.join(cache, `content-v${contentVer}`) +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/read.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/read.js new file mode 100644 index 000000000..034e8eee0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/read.js @@ -0,0 +1,244 @@ +'use strict' + +const util = require('util') + +const fs = require('fs') +const fsm = require('fs-minipass') +const ssri = require('ssri') +const contentPath = require('./path') +const Pipeline = require('minipass-pipeline') + +const lstat = util.promisify(fs.lstat) +const readFile = util.promisify(fs.readFile) + +module.exports = read + +const MAX_SINGLE_READ_SIZE = 64 * 1024 * 1024 +function read (cache, integrity, opts = {}) { + const { size } = opts + return withContentSri(cache, integrity, (cpath, sri) => { + // get size + return lstat(cpath).then(stat => ({ stat, cpath, sri })) + }).then(({ stat, cpath, sri }) => { + if (typeof size === 'number' && stat.size !== size) + throw sizeError(size, stat.size) + + if (stat.size > MAX_SINGLE_READ_SIZE) + return readPipeline(cpath, stat.size, sri, new Pipeline()).concat() + + return readFile(cpath, null).then((data) => { + if (!ssri.checkData(data, sri)) + throw integrityError(sri, cpath) + + return data + }) + }) +} + +const readPipeline = (cpath, size, sri, stream) => { + stream.push( + new fsm.ReadStream(cpath, { + size, + readSize: MAX_SINGLE_READ_SIZE, + }), + ssri.integrityStream({ + integrity: sri, + size, + }) + ) + return stream +} + +module.exports.sync = readSync + +function readSync (cache, integrity, opts = {}) { + const { size } = opts + return withContentSriSync(cache, integrity, (cpath, sri) => { + const data = fs.readFileSync(cpath) + if (typeof size === 'number' && size !== data.length) + throw sizeError(size, data.length) + + if (ssri.checkData(data, sri)) + return data + + throw integrityError(sri, cpath) + }) +} + +module.exports.stream = readStream +module.exports.readStream = readStream + +function readStream (cache, integrity, opts = {}) { + const { size } = opts + const stream = new Pipeline() + withContentSri(cache, integrity, (cpath, sri) => { + // just lstat to ensure it exists + return lstat(cpath).then((stat) => ({ stat, cpath, sri })) + }).then(({ stat, cpath, sri }) => { + if (typeof size === 'number' && size !== stat.size) + return stream.emit('error', sizeError(size, stat.size)) + + readPipeline(cpath, stat.size, sri, stream) + }, er => stream.emit('error', er)) + + return stream +} + +let copyFile +if (fs.copyFile) { + module.exports.copy = copy + module.exports.copy.sync = copySync + copyFile = util.promisify(fs.copyFile) +} + +function copy (cache, integrity, dest) { + return withContentSri(cache, integrity, (cpath, sri) => { + return copyFile(cpath, dest) + }) +} + +function copySync (cache, integrity, dest) { + return withContentSriSync(cache, integrity, (cpath, sri) => { + return fs.copyFileSync(cpath, dest) + }) +} + +module.exports.hasContent = hasContent + +function hasContent (cache, integrity) { + if (!integrity) + return Promise.resolve(false) + + return withContentSri(cache, integrity, (cpath, sri) => { + return lstat(cpath).then((stat) => ({ size: stat.size, sri, stat })) + }).catch((err) => { + if (err.code === 'ENOENT') + return false + + if (err.code === 'EPERM') { + /* istanbul ignore else */ + if (process.platform !== 'win32') + throw err + else + return false + } + }) +} + +module.exports.hasContent.sync = hasContentSync + +function hasContentSync (cache, integrity) { + if (!integrity) + return false + + return withContentSriSync(cache, integrity, (cpath, sri) => { + try { + const stat = fs.lstatSync(cpath) + return { size: stat.size, sri, stat } + } catch (err) { + if (err.code === 'ENOENT') + return false + + if (err.code === 'EPERM') { + /* istanbul ignore else */ + if (process.platform !== 'win32') + throw err + else + return false + } + } + }) +} + +function withContentSri (cache, integrity, fn) { + const tryFn = () => { + const sri = ssri.parse(integrity) + // If `integrity` has multiple entries, pick the first digest + // with available local data. + const algo = sri.pickAlgorithm() + const digests = sri[algo] + + if (digests.length <= 1) { + const cpath = contentPath(cache, digests[0]) + return fn(cpath, digests[0]) + } else { + // Can't use race here because a generic error can happen before + // a ENOENT error, and can happen before a valid result + return Promise + .all(digests.map((meta) => { + return withContentSri(cache, meta, fn) + .catch((err) => { + if (err.code === 'ENOENT') { + return Object.assign( + new Error('No matching content found for ' + sri.toString()), + { code: 'ENOENT' } + ) + } + return err + }) + })) + .then((results) => { + // Return the first non error if it is found + const result = results.find((r) => !(r instanceof Error)) + if (result) + return result + + // Throw the No matching content found error + const enoentError = results.find((r) => r.code === 'ENOENT') + if (enoentError) + throw enoentError + + // Throw generic error + throw results.find((r) => r instanceof Error) + }) + } + } + + return new Promise((resolve, reject) => { + try { + tryFn() + .then(resolve) + .catch(reject) + } catch (err) { + reject(err) + } + }) +} + +function withContentSriSync (cache, integrity, fn) { + const sri = ssri.parse(integrity) + // If `integrity` has multiple entries, pick the first digest + // with available local data. + const algo = sri.pickAlgorithm() + const digests = sri[algo] + if (digests.length <= 1) { + const cpath = contentPath(cache, digests[0]) + return fn(cpath, digests[0]) + } else { + let lastErr = null + for (const meta of digests) { + try { + return withContentSriSync(cache, meta, fn) + } catch (err) { + lastErr = err + } + } + throw lastErr + } +} + +function sizeError (expected, found) { + const err = new Error(`Bad data size: expected inserted data to be ${expected} bytes, but got ${found} instead`) + err.expected = expected + err.found = found + err.code = 'EBADSIZE' + return err +} + +function integrityError (sri, path) { + const err = new Error(`Integrity verification failed for ${sri} (${path})`) + err.code = 'EINTEGRITY' + err.sri = sri + err.path = path + return err +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/rm.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/rm.js new file mode 100644 index 000000000..6a3d1a3d0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/rm.js @@ -0,0 +1,19 @@ +'use strict' + +const util = require('util') + +const contentPath = require('./path') +const { hasContent } = require('./read') +const rimraf = util.promisify(require('rimraf')) + +module.exports = rm + +function rm (cache, integrity) { + return hasContent(cache, integrity).then((content) => { + // ~pretty~ sure we can't end up with a content lacking sri, but be safe + if (content && content.sri) + return rimraf(contentPath(cache, content.sri)).then(() => true) + else + return false + }) +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/write.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/write.js new file mode 100644 index 000000000..dde1bd1dd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/content/write.js @@ -0,0 +1,189 @@ +'use strict' + +const util = require('util') + +const contentPath = require('./path') +const fixOwner = require('../util/fix-owner') +const fs = require('fs') +const moveFile = require('../util/move-file') +const Minipass = require('minipass') +const Pipeline = require('minipass-pipeline') +const Flush = require('minipass-flush') +const path = require('path') +const rimraf = util.promisify(require('rimraf')) +const ssri = require('ssri') +const uniqueFilename = require('unique-filename') +const { disposer } = require('./../util/disposer') +const fsm = require('fs-minipass') + +const writeFile = util.promisify(fs.writeFile) + +module.exports = write + +function write (cache, data, opts = {}) { + const { algorithms, size, integrity } = opts + if (algorithms && algorithms.length > 1) + throw new Error('opts.algorithms only supports a single algorithm for now') + + if (typeof size === 'number' && data.length !== size) + return Promise.reject(sizeError(size, data.length)) + + const sri = ssri.fromData(data, algorithms ? { algorithms } : {}) + if (integrity && !ssri.checkData(data, integrity, opts)) + return Promise.reject(checksumError(integrity, sri)) + + return disposer(makeTmp(cache, opts), makeTmpDisposer, + (tmp) => { + return writeFile(tmp.target, data, { flag: 'wx' }) + .then(() => moveToDestination(tmp, cache, sri, opts)) + }) + .then(() => ({ integrity: sri, size: data.length })) +} + +module.exports.stream = writeStream + +// writes proxied to the 'inputStream' that is passed to the Promise +// 'end' is deferred until content is handled. +class CacacheWriteStream extends Flush { + constructor (cache, opts) { + super() + this.opts = opts + this.cache = cache + this.inputStream = new Minipass() + this.inputStream.on('error', er => this.emit('error', er)) + this.inputStream.on('drain', () => this.emit('drain')) + this.handleContentP = null + } + + write (chunk, encoding, cb) { + if (!this.handleContentP) { + this.handleContentP = handleContent( + this.inputStream, + this.cache, + this.opts + ) + } + return this.inputStream.write(chunk, encoding, cb) + } + + flush (cb) { + this.inputStream.end(() => { + if (!this.handleContentP) { + const e = new Error('Cache input stream was empty') + e.code = 'ENODATA' + // empty streams are probably emitting end right away. + // defer this one tick by rejecting a promise on it. + return Promise.reject(e).catch(cb) + } + this.handleContentP.then( + (res) => { + res.integrity && this.emit('integrity', res.integrity) + res.size !== null && this.emit('size', res.size) + cb() + }, + (er) => cb(er) + ) + }) + } +} + +function writeStream (cache, opts = {}) { + return new CacacheWriteStream(cache, opts) +} + +function handleContent (inputStream, cache, opts) { + return disposer(makeTmp(cache, opts), makeTmpDisposer, (tmp) => { + return pipeToTmp(inputStream, cache, tmp.target, opts) + .then((res) => { + return moveToDestination( + tmp, + cache, + res.integrity, + opts + ).then(() => res) + }) + }) +} + +function pipeToTmp (inputStream, cache, tmpTarget, opts) { + let integrity + let size + const hashStream = ssri.integrityStream({ + integrity: opts.integrity, + algorithms: opts.algorithms, + size: opts.size, + }) + hashStream.on('integrity', i => { + integrity = i + }) + hashStream.on('size', s => { + size = s + }) + + const outStream = new fsm.WriteStream(tmpTarget, { + flags: 'wx', + }) + + // NB: this can throw if the hashStream has a problem with + // it, and the data is fully written. but pipeToTmp is only + // called in promisory contexts where that is handled. + const pipeline = new Pipeline( + inputStream, + hashStream, + outStream + ) + + return pipeline.promise() + .then(() => ({ integrity, size })) + .catch(er => rimraf(tmpTarget).then(() => { + throw er + })) +} + +function makeTmp (cache, opts) { + const tmpTarget = uniqueFilename(path.join(cache, 'tmp'), opts.tmpPrefix) + return fixOwner.mkdirfix(cache, path.dirname(tmpTarget)).then(() => ({ + target: tmpTarget, + moved: false, + })) +} + +function makeTmpDisposer (tmp) { + if (tmp.moved) + return Promise.resolve() + + return rimraf(tmp.target) +} + +function moveToDestination (tmp, cache, sri, opts) { + const destination = contentPath(cache, sri) + const destDir = path.dirname(destination) + + return fixOwner + .mkdirfix(cache, destDir) + .then(() => { + return moveFile(tmp.target, destination) + }) + .then(() => { + tmp.moved = true + return fixOwner.chownr(cache, destination) + }) +} + +function sizeError (expected, found) { + const err = new Error(`Bad data size: expected inserted data to be ${expected} bytes, but got ${found} instead`) + err.expected = expected + err.found = found + err.code = 'EBADSIZE' + return err +} + +function checksumError (expected, found) { + const err = new Error(`Integrity check failed: + Wanted: ${expected} + Found: ${found}`) + err.code = 'EINTEGRITY' + err.expected = expected + err.found = found + return err +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/entry-index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/entry-index.js new file mode 100644 index 000000000..71aac5ed7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/entry-index.js @@ -0,0 +1,394 @@ +'use strict' + +const util = require('util') +const crypto = require('crypto') +const fs = require('fs') +const Minipass = require('minipass') +const path = require('path') +const ssri = require('ssri') +const uniqueFilename = require('unique-filename') + +const { disposer } = require('./util/disposer') +const contentPath = require('./content/path') +const fixOwner = require('./util/fix-owner') +const hashToSegments = require('./util/hash-to-segments') +const indexV = require('../package.json')['cache-version'].index +const moveFile = require('@npmcli/move-file') +const _rimraf = require('rimraf') +const rimraf = util.promisify(_rimraf) +rimraf.sync = _rimraf.sync + +const appendFile = util.promisify(fs.appendFile) +const readFile = util.promisify(fs.readFile) +const readdir = util.promisify(fs.readdir) +const writeFile = util.promisify(fs.writeFile) + +module.exports.NotFoundError = class NotFoundError extends Error { + constructor (cache, key) { + super(`No cache entry for ${key} found in ${cache}`) + this.code = 'ENOENT' + this.cache = cache + this.key = key + } +} + +module.exports.compact = compact + +async function compact (cache, key, matchFn, opts = {}) { + const bucket = bucketPath(cache, key) + const entries = await bucketEntries(bucket) + const newEntries = [] + // we loop backwards because the bottom-most result is the newest + // since we add new entries with appendFile + for (let i = entries.length - 1; i >= 0; --i) { + const entry = entries[i] + // a null integrity could mean either a delete was appended + // or the user has simply stored an index that does not map + // to any content. we determine if the user wants to keep the + // null integrity based on the validateEntry function passed in options. + // if the integrity is null and no validateEntry is provided, we break + // as we consider the null integrity to be a deletion of everything + // that came before it. + if (entry.integrity === null && !opts.validateEntry) + break + + // if this entry is valid, and it is either the first entry or + // the newEntries array doesn't already include an entry that + // matches this one based on the provided matchFn, then we add + // it to the beginning of our list + if ((!opts.validateEntry || opts.validateEntry(entry) === true) && + (newEntries.length === 0 || + !newEntries.find((oldEntry) => matchFn(oldEntry, entry)))) + newEntries.unshift(entry) + } + + const newIndex = '\n' + newEntries.map((entry) => { + const stringified = JSON.stringify(entry) + const hash = hashEntry(stringified) + return `${hash}\t${stringified}` + }).join('\n') + + const setup = async () => { + const target = uniqueFilename(path.join(cache, 'tmp'), opts.tmpPrefix) + await fixOwner.mkdirfix(cache, path.dirname(target)) + return { + target, + moved: false, + } + } + + const teardown = async (tmp) => { + if (!tmp.moved) + return rimraf(tmp.target) + } + + const write = async (tmp) => { + await writeFile(tmp.target, newIndex, { flag: 'wx' }) + await fixOwner.mkdirfix(cache, path.dirname(bucket)) + // we use @npmcli/move-file directly here because we + // want to overwrite the existing file + await moveFile(tmp.target, bucket) + tmp.moved = true + try { + await fixOwner.chownr(cache, bucket) + } catch (err) { + if (err.code !== 'ENOENT') + throw err + } + } + + // write the file atomically + await disposer(setup(), teardown, write) + + // we reverse the list we generated such that the newest + // entries come first in order to make looping through them easier + // the true passed to formatEntry tells it to keep null + // integrity values, if they made it this far it's because + // validateEntry returned true, and as such we should return it + return newEntries.reverse().map((entry) => formatEntry(cache, entry, true)) +} + +module.exports.insert = insert + +function insert (cache, key, integrity, opts = {}) { + const { metadata, size } = opts + const bucket = bucketPath(cache, key) + const entry = { + key, + integrity: integrity && ssri.stringify(integrity), + time: Date.now(), + size, + metadata, + } + return fixOwner + .mkdirfix(cache, path.dirname(bucket)) + .then(() => { + const stringified = JSON.stringify(entry) + // NOTE - Cleverness ahoy! + // + // This works because it's tremendously unlikely for an entry to corrupt + // another while still preserving the string length of the JSON in + // question. So, we just slap the length in there and verify it on read. + // + // Thanks to @isaacs for the whiteboarding session that ended up with + // this. + return appendFile(bucket, `\n${hashEntry(stringified)}\t${stringified}`) + }) + .then(() => fixOwner.chownr(cache, bucket)) + .catch((err) => { + if (err.code === 'ENOENT') + return undefined + + throw err + // There's a class of race conditions that happen when things get deleted + // during fixOwner, or between the two mkdirfix/chownr calls. + // + // It's perfectly fine to just not bother in those cases and lie + // that the index entry was written. Because it's a cache. + }) + .then(() => { + return formatEntry(cache, entry) + }) +} + +module.exports.insert.sync = insertSync + +function insertSync (cache, key, integrity, opts = {}) { + const { metadata, size } = opts + const bucket = bucketPath(cache, key) + const entry = { + key, + integrity: integrity && ssri.stringify(integrity), + time: Date.now(), + size, + metadata, + } + fixOwner.mkdirfix.sync(cache, path.dirname(bucket)) + const stringified = JSON.stringify(entry) + fs.appendFileSync(bucket, `\n${hashEntry(stringified)}\t${stringified}`) + try { + fixOwner.chownr.sync(cache, bucket) + } catch (err) { + if (err.code !== 'ENOENT') + throw err + } + return formatEntry(cache, entry) +} + +module.exports.find = find + +function find (cache, key) { + const bucket = bucketPath(cache, key) + return bucketEntries(bucket) + .then((entries) => { + return entries.reduce((latest, next) => { + if (next && next.key === key) + return formatEntry(cache, next) + else + return latest + }, null) + }) + .catch((err) => { + if (err.code === 'ENOENT') + return null + else + throw err + }) +} + +module.exports.find.sync = findSync + +function findSync (cache, key) { + const bucket = bucketPath(cache, key) + try { + return bucketEntriesSync(bucket).reduce((latest, next) => { + if (next && next.key === key) + return formatEntry(cache, next) + else + return latest + }, null) + } catch (err) { + if (err.code === 'ENOENT') + return null + else + throw err + } +} + +module.exports.delete = del + +function del (cache, key, opts = {}) { + if (!opts.removeFully) + return insert(cache, key, null, opts) + + const bucket = bucketPath(cache, key) + return rimraf(bucket) +} + +module.exports.delete.sync = delSync + +function delSync (cache, key, opts = {}) { + if (!opts.removeFully) + return insertSync(cache, key, null, opts) + + const bucket = bucketPath(cache, key) + return rimraf.sync(bucket) +} + +module.exports.lsStream = lsStream + +function lsStream (cache) { + const indexDir = bucketDir(cache) + const stream = new Minipass({ objectMode: true }) + + readdirOrEmpty(indexDir).then(buckets => Promise.all( + buckets.map(bucket => { + const bucketPath = path.join(indexDir, bucket) + return readdirOrEmpty(bucketPath).then(subbuckets => Promise.all( + subbuckets.map(subbucket => { + const subbucketPath = path.join(bucketPath, subbucket) + + // "/cachename//./*" + return readdirOrEmpty(subbucketPath).then(entries => Promise.all( + entries.map(entry => { + const entryPath = path.join(subbucketPath, entry) + return bucketEntries(entryPath).then(entries => + // using a Map here prevents duplicate keys from + // showing up twice, I guess? + entries.reduce((acc, entry) => { + acc.set(entry.key, entry) + return acc + }, new Map()) + ).then(reduced => { + // reduced is a map of key => entry + for (const entry of reduced.values()) { + const formatted = formatEntry(cache, entry) + if (formatted) + stream.write(formatted) + } + }).catch(err => { + if (err.code === 'ENOENT') + return undefined + throw err + }) + }) + )) + }) + )) + }) + )) + .then( + () => stream.end(), + err => stream.emit('error', err) + ) + + return stream +} + +module.exports.ls = ls + +function ls (cache) { + return lsStream(cache).collect().then(entries => + entries.reduce((acc, xs) => { + acc[xs.key] = xs + return acc + }, {}) + ) +} + +module.exports.bucketEntries = bucketEntries + +function bucketEntries (bucket, filter) { + return readFile(bucket, 'utf8').then((data) => _bucketEntries(data, filter)) +} + +module.exports.bucketEntries.sync = bucketEntriesSync + +function bucketEntriesSync (bucket, filter) { + const data = fs.readFileSync(bucket, 'utf8') + return _bucketEntries(data, filter) +} + +function _bucketEntries (data, filter) { + const entries = [] + data.split('\n').forEach((entry) => { + if (!entry) + return + + const pieces = entry.split('\t') + if (!pieces[1] || hashEntry(pieces[1]) !== pieces[0]) { + // Hash is no good! Corruption or malice? Doesn't matter! + // EJECT EJECT + return + } + let obj + try { + obj = JSON.parse(pieces[1]) + } catch (e) { + // Entry is corrupted! + return + } + if (obj) + entries.push(obj) + }) + return entries +} + +module.exports.bucketDir = bucketDir + +function bucketDir (cache) { + return path.join(cache, `index-v${indexV}`) +} + +module.exports.bucketPath = bucketPath + +function bucketPath (cache, key) { + const hashed = hashKey(key) + return path.join.apply( + path, + [bucketDir(cache)].concat(hashToSegments(hashed)) + ) +} + +module.exports.hashKey = hashKey + +function hashKey (key) { + return hash(key, 'sha256') +} + +module.exports.hashEntry = hashEntry + +function hashEntry (str) { + return hash(str, 'sha1') +} + +function hash (str, digest) { + return crypto + .createHash(digest) + .update(str) + .digest('hex') +} + +function formatEntry (cache, entry, keepAll) { + // Treat null digests as deletions. They'll shadow any previous entries. + if (!entry.integrity && !keepAll) + return null + + return { + key: entry.key, + integrity: entry.integrity, + path: entry.integrity ? contentPath(cache, entry.integrity) : undefined, + size: entry.size, + time: entry.time, + metadata: entry.metadata, + } +} + +function readdirOrEmpty (dir) { + return readdir(dir).catch((err) => { + if (err.code === 'ENOENT' || err.code === 'ENOTDIR') + return [] + + throw err + }) +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/memoization.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/memoization.js new file mode 100644 index 000000000..d5465f39f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/memoization.js @@ -0,0 +1,73 @@ +'use strict' + +const LRU = require('lru-cache') + +const MAX_SIZE = 50 * 1024 * 1024 // 50MB +const MAX_AGE = 3 * 60 * 1000 + +const MEMOIZED = new LRU({ + max: MAX_SIZE, + maxAge: MAX_AGE, + length: (entry, key) => key.startsWith('key:') ? entry.data.length : entry.length, +}) + +module.exports.clearMemoized = clearMemoized + +function clearMemoized () { + const old = {} + MEMOIZED.forEach((v, k) => { + old[k] = v + }) + MEMOIZED.reset() + return old +} + +module.exports.put = put + +function put (cache, entry, data, opts) { + pickMem(opts).set(`key:${cache}:${entry.key}`, { entry, data }) + putDigest(cache, entry.integrity, data, opts) +} + +module.exports.put.byDigest = putDigest + +function putDigest (cache, integrity, data, opts) { + pickMem(opts).set(`digest:${cache}:${integrity}`, data) +} + +module.exports.get = get + +function get (cache, key, opts) { + return pickMem(opts).get(`key:${cache}:${key}`) +} + +module.exports.get.byDigest = getDigest + +function getDigest (cache, integrity, opts) { + return pickMem(opts).get(`digest:${cache}:${integrity}`) +} + +class ObjProxy { + constructor (obj) { + this.obj = obj + } + + get (key) { + return this.obj[key] + } + + set (key, val) { + this.obj[key] = val + } +} + +function pickMem (opts) { + if (!opts || !opts.memoize) + return MEMOIZED + else if (opts.memoize.get && opts.memoize.set) + return opts.memoize + else if (typeof opts.memoize === 'object') + return new ObjProxy(opts.memoize) + else + return MEMOIZED +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/disposer.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/disposer.js new file mode 100644 index 000000000..aa8aed54d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/disposer.js @@ -0,0 +1,30 @@ +'use strict' + +module.exports.disposer = disposer + +function disposer (creatorFn, disposerFn, fn) { + const runDisposer = (resource, result, shouldThrow = false) => { + return disposerFn(resource) + .then( + // disposer resolved, do something with original fn's promise + () => { + if (shouldThrow) + throw result + + return result + }, + // Disposer fn failed, crash process + (err) => { + throw err + // Or process.exit? + }) + } + + return creatorFn + .then((resource) => { + // fn(resource) can throw, so wrap in a promise here + return Promise.resolve().then(() => fn(resource)) + .then((result) => runDisposer(resource, result)) + .catch((err) => runDisposer(resource, err, true)) + }) +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/fix-owner.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/fix-owner.js new file mode 100644 index 000000000..90ffece52 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/fix-owner.js @@ -0,0 +1,142 @@ +'use strict' + +const util = require('util') + +const chownr = util.promisify(require('chownr')) +const mkdirp = require('mkdirp') +const inflight = require('promise-inflight') +const inferOwner = require('infer-owner') + +// Memoize getuid()/getgid() calls. +// patch process.setuid/setgid to invalidate cached value on change +const self = { uid: null, gid: null } +const getSelf = () => { + if (typeof self.uid !== 'number') { + self.uid = process.getuid() + const setuid = process.setuid + process.setuid = (uid) => { + self.uid = null + process.setuid = setuid + return process.setuid(uid) + } + } + if (typeof self.gid !== 'number') { + self.gid = process.getgid() + const setgid = process.setgid + process.setgid = (gid) => { + self.gid = null + process.setgid = setgid + return process.setgid(gid) + } + } +} + +module.exports.chownr = fixOwner + +function fixOwner (cache, filepath) { + if (!process.getuid) { + // This platform doesn't need ownership fixing + return Promise.resolve() + } + + getSelf() + if (self.uid !== 0) { + // almost certainly can't chown anyway + return Promise.resolve() + } + + return Promise.resolve(inferOwner(cache)).then((owner) => { + const { uid, gid } = owner + + // No need to override if it's already what we used. + if (self.uid === uid && self.gid === gid) + return + + return inflight('fixOwner: fixing ownership on ' + filepath, () => + chownr( + filepath, + typeof uid === 'number' ? uid : self.uid, + typeof gid === 'number' ? gid : self.gid + ).catch((err) => { + if (err.code === 'ENOENT') + return null + + throw err + }) + ) + }) +} + +module.exports.chownr.sync = fixOwnerSync + +function fixOwnerSync (cache, filepath) { + if (!process.getuid) { + // This platform doesn't need ownership fixing + return + } + const { uid, gid } = inferOwner.sync(cache) + getSelf() + if (self.uid !== 0) { + // almost certainly can't chown anyway + return + } + + if (self.uid === uid && self.gid === gid) { + // No need to override if it's already what we used. + return + } + try { + chownr.sync( + filepath, + typeof uid === 'number' ? uid : self.uid, + typeof gid === 'number' ? gid : self.gid + ) + } catch (err) { + // only catch ENOENT, any other error is a problem. + if (err.code === 'ENOENT') + return null + + throw err + } +} + +module.exports.mkdirfix = mkdirfix + +function mkdirfix (cache, p, cb) { + // we have to infer the owner _before_ making the directory, even though + // we aren't going to use the results, since the cache itself might not + // exist yet. If we mkdirp it, then our current uid/gid will be assumed + // to be correct if it creates the cache folder in the process. + return Promise.resolve(inferOwner(cache)).then(() => { + return mkdirp(p) + .then((made) => { + if (made) + return fixOwner(cache, made).then(() => made) + }) + .catch((err) => { + if (err.code === 'EEXIST') + return fixOwner(cache, p).then(() => null) + + throw err + }) + }) +} + +module.exports.mkdirfix.sync = mkdirfixSync + +function mkdirfixSync (cache, p) { + try { + inferOwner.sync(cache) + const made = mkdirp.sync(p) + if (made) { + fixOwnerSync(cache, made) + return made + } + } catch (err) { + if (err.code === 'EEXIST') { + fixOwnerSync(cache, p) + return null + } else + throw err + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/hash-to-segments.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/hash-to-segments.js new file mode 100644 index 000000000..445599b50 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/hash-to-segments.js @@ -0,0 +1,7 @@ +'use strict' + +module.exports = hashToSegments + +function hashToSegments (hash) { + return [hash.slice(0, 2), hash.slice(2, 4), hash.slice(4)] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/move-file.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/move-file.js new file mode 100644 index 000000000..c3f9e35eb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/move-file.js @@ -0,0 +1,67 @@ +'use strict' + +const fs = require('fs') +const util = require('util') +const chmod = util.promisify(fs.chmod) +const unlink = util.promisify(fs.unlink) +const stat = util.promisify(fs.stat) +const move = require('@npmcli/move-file') +const pinflight = require('promise-inflight') + +module.exports = moveFile + +function moveFile (src, dest) { + const isWindows = global.__CACACHE_TEST_FAKE_WINDOWS__ || + process.platform === 'win32' + + // This isn't quite an fs.rename -- the assumption is that + // if `dest` already exists, and we get certain errors while + // trying to move it, we should just not bother. + // + // In the case of cache corruption, users will receive an + // EINTEGRITY error elsewhere, and can remove the offending + // content their own way. + // + // Note that, as the name suggests, this strictly only supports file moves. + return new Promise((resolve, reject) => { + fs.link(src, dest, (err) => { + if (err) { + if (isWindows && err.code === 'EPERM') { + // XXX This is a really weird way to handle this situation, as it + // results in the src file being deleted even though the dest + // might not exist. Since we pretty much always write files to + // deterministic locations based on content hash, this is likely + // ok (or at worst, just ends in a future cache miss). But it would + // be worth investigating at some time in the future if this is + // really what we want to do here. + return resolve() + } else if (err.code === 'EEXIST' || err.code === 'EBUSY') { + // file already exists, so whatever + return resolve() + } else + return reject(err) + } else + return resolve() + }) + }) + .then(() => { + // content should never change for any reason, so make it read-only + return Promise.all([ + unlink(src), + !isWindows && chmod(dest, '0444'), + ]) + }) + .catch(() => { + return pinflight('cacache-move-file:' + dest, () => { + return stat(dest).catch((err) => { + if (err.code !== 'ENOENT') { + // Something else is wrong here. Bail bail bail + throw err + } + // file doesn't already exist! let's try a rename -> copy fallback + // only delete if it successfully copies + return move(src, dest) + }) + }) + }) +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/tmp.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/tmp.js new file mode 100644 index 000000000..0a5a50eba --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/util/tmp.js @@ -0,0 +1,35 @@ +'use strict' + +const fs = require('@npmcli/fs') + +const fixOwner = require('./fix-owner') +const path = require('path') + +module.exports.mkdir = mktmpdir + +function mktmpdir (cache, opts = {}) { + const { tmpPrefix } = opts + const tmpDir = path.join(cache, 'tmp') + return fs.mkdir(tmpDir, { recursive: true, owner: 'inherit' }) + .then(() => { + // do not use path.join(), it drops the trailing / if tmpPrefix is unset + const target = `${tmpDir}${path.sep}${tmpPrefix || ''}` + return fs.mkdtemp(target, { owner: 'inherit' }) + }) +} + +module.exports.withTmp = withTmp + +function withTmp (cache, opts, cb) { + if (!cb) { + cb = opts + opts = {} + } + return fs.withTempDir(path.join(cache, 'tmp'), cb, opts) +} + +module.exports.fix = fixtmpdir + +function fixtmpdir (cache) { + return fixOwner(cache, path.join(cache, 'tmp')) +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/verify.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/verify.js new file mode 100644 index 000000000..e9d679ece --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/lib/verify.js @@ -0,0 +1,287 @@ +'use strict' + +const util = require('util') + +const pMap = require('p-map') +const contentPath = require('./content/path') +const fixOwner = require('./util/fix-owner') +const fs = require('fs') +const fsm = require('fs-minipass') +const glob = util.promisify(require('glob')) +const index = require('./entry-index') +const path = require('path') +const rimraf = util.promisify(require('rimraf')) +const ssri = require('ssri') + +const hasOwnProperty = (obj, key) => + Object.prototype.hasOwnProperty.call(obj, key) + +const stat = util.promisify(fs.stat) +const truncate = util.promisify(fs.truncate) +const writeFile = util.promisify(fs.writeFile) +const readFile = util.promisify(fs.readFile) + +const verifyOpts = (opts) => ({ + concurrency: 20, + log: { silly () {} }, + ...opts, +}) + +module.exports = verify + +function verify (cache, opts) { + opts = verifyOpts(opts) + opts.log.silly('verify', 'verifying cache at', cache) + + const steps = [ + markStartTime, + fixPerms, + garbageCollect, + rebuildIndex, + cleanTmp, + writeVerifile, + markEndTime, + ] + + return steps + .reduce((promise, step, i) => { + const label = step.name + const start = new Date() + return promise.then((stats) => { + return step(cache, opts).then((s) => { + s && + Object.keys(s).forEach((k) => { + stats[k] = s[k] + }) + const end = new Date() + if (!stats.runTime) + stats.runTime = {} + + stats.runTime[label] = end - start + return Promise.resolve(stats) + }) + }) + }, Promise.resolve({})) + .then((stats) => { + stats.runTime.total = stats.endTime - stats.startTime + opts.log.silly( + 'verify', + 'verification finished for', + cache, + 'in', + `${stats.runTime.total}ms` + ) + return stats + }) +} + +function markStartTime (cache, opts) { + return Promise.resolve({ startTime: new Date() }) +} + +function markEndTime (cache, opts) { + return Promise.resolve({ endTime: new Date() }) +} + +function fixPerms (cache, opts) { + opts.log.silly('verify', 'fixing cache permissions') + return fixOwner + .mkdirfix(cache, cache) + .then(() => { + // TODO - fix file permissions too + return fixOwner.chownr(cache, cache) + }) + .then(() => null) +} + +// Implements a naive mark-and-sweep tracing garbage collector. +// +// The algorithm is basically as follows: +// 1. Read (and filter) all index entries ("pointers") +// 2. Mark each integrity value as "live" +// 3. Read entire filesystem tree in `content-vX/` dir +// 4. If content is live, verify its checksum and delete it if it fails +// 5. If content is not marked as live, rimraf it. +// +function garbageCollect (cache, opts) { + opts.log.silly('verify', 'garbage collecting content') + const indexStream = index.lsStream(cache) + const liveContent = new Set() + indexStream.on('data', (entry) => { + if (opts.filter && !opts.filter(entry)) + return + + liveContent.add(entry.integrity.toString()) + }) + return new Promise((resolve, reject) => { + indexStream.on('end', resolve).on('error', reject) + }).then(() => { + const contentDir = contentPath.contentDir(cache) + return glob(path.join(contentDir, '**'), { + follow: false, + nodir: true, + nosort: true, + }).then((files) => { + return Promise.resolve({ + verifiedContent: 0, + reclaimedCount: 0, + reclaimedSize: 0, + badContentCount: 0, + keptSize: 0, + }).then((stats) => + pMap( + files, + (f) => { + const split = f.split(/[/\\]/) + const digest = split.slice(split.length - 3).join('') + const algo = split[split.length - 4] + const integrity = ssri.fromHex(digest, algo) + if (liveContent.has(integrity.toString())) { + return verifyContent(f, integrity).then((info) => { + if (!info.valid) { + stats.reclaimedCount++ + stats.badContentCount++ + stats.reclaimedSize += info.size + } else { + stats.verifiedContent++ + stats.keptSize += info.size + } + return stats + }) + } else { + // No entries refer to this content. We can delete. + stats.reclaimedCount++ + return stat(f).then((s) => { + return rimraf(f).then(() => { + stats.reclaimedSize += s.size + return stats + }) + }) + } + }, + { concurrency: opts.concurrency } + ).then(() => stats) + ) + }) + }) +} + +function verifyContent (filepath, sri) { + return stat(filepath) + .then((s) => { + const contentInfo = { + size: s.size, + valid: true, + } + return ssri + .checkStream(new fsm.ReadStream(filepath), sri) + .catch((err) => { + if (err.code !== 'EINTEGRITY') + throw err + + return rimraf(filepath).then(() => { + contentInfo.valid = false + }) + }) + .then(() => contentInfo) + }) + .catch((err) => { + if (err.code === 'ENOENT') + return { size: 0, valid: false } + + throw err + }) +} + +function rebuildIndex (cache, opts) { + opts.log.silly('verify', 'rebuilding index') + return index.ls(cache).then((entries) => { + const stats = { + missingContent: 0, + rejectedEntries: 0, + totalEntries: 0, + } + const buckets = {} + for (const k in entries) { + /* istanbul ignore else */ + if (hasOwnProperty(entries, k)) { + const hashed = index.hashKey(k) + const entry = entries[k] + const excluded = opts.filter && !opts.filter(entry) + excluded && stats.rejectedEntries++ + if (buckets[hashed] && !excluded) + buckets[hashed].push(entry) + else if (buckets[hashed] && excluded) { + // skip + } else if (excluded) { + buckets[hashed] = [] + buckets[hashed]._path = index.bucketPath(cache, k) + } else { + buckets[hashed] = [entry] + buckets[hashed]._path = index.bucketPath(cache, k) + } + } + } + return pMap( + Object.keys(buckets), + (key) => { + return rebuildBucket(cache, buckets[key], stats, opts) + }, + { concurrency: opts.concurrency } + ).then(() => stats) + }) +} + +function rebuildBucket (cache, bucket, stats, opts) { + return truncate(bucket._path).then(() => { + // This needs to be serialized because cacache explicitly + // lets very racy bucket conflicts clobber each other. + return bucket.reduce((promise, entry) => { + return promise.then(() => { + const content = contentPath(cache, entry.integrity) + return stat(content) + .then(() => { + return index + .insert(cache, entry.key, entry.integrity, { + metadata: entry.metadata, + size: entry.size, + }) + .then(() => { + stats.totalEntries++ + }) + }) + .catch((err) => { + if (err.code === 'ENOENT') { + stats.rejectedEntries++ + stats.missingContent++ + return + } + throw err + }) + }) + }, Promise.resolve()) + }) +} + +function cleanTmp (cache, opts) { + opts.log.silly('verify', 'cleaning tmp directory') + return rimraf(path.join(cache, 'tmp')) +} + +function writeVerifile (cache, opts) { + const verifile = path.join(cache, '_lastverified') + opts.log.silly('verify', 'writing verifile to ' + verifile) + try { + return writeFile(verifile, '' + +new Date()) + } finally { + fixOwner.chownr.sync(cache, verifile) + } +} + +module.exports.lastRun = lastRun + +function lastRun (cache) { + return readFile(path.join(cache, '_lastverified'), 'utf8').then( + (data) => new Date(+data) + ) +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/ls.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/ls.js new file mode 100644 index 000000000..6006c99e3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/ls.js @@ -0,0 +1,6 @@ +'use strict' + +const index = require('./lib/entry-index') + +module.exports = index.ls +module.exports.stream = index.lsStream diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/package.json new file mode 100644 index 000000000..6cb414015 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/package.json @@ -0,0 +1,80 @@ +{ + "name": "cacache", + "version": "15.3.0", + "cache-version": { + "content": "2", + "index": "5" + }, + "description": "Fast, fault-tolerant, cross-platform, disk-based, data-agnostic, content-addressable cache.", + "main": "index.js", + "files": [ + "*.js", + "lib" + ], + "scripts": { + "benchmarks": "node test/benchmarks", + "preversion": "npm test", + "postversion": "npm publish", + "prepublishOnly": "git push origin --follow-tags", + "test": "tap", + "snap": "tap", + "coverage": "tap", + "test-docker": "docker run -it --rm --name pacotest -v \"$PWD\":/tmp -w /tmp node:latest npm test", + "lint": "npm run npmclilint -- \"*.*js\" \"lib/**/*.*js\" \"test/**/*.*js\"", + "npmclilint": "npmcli-lint", + "lintfix": "npm run lint -- --fix", + "postsnap": "npm run lintfix --" + }, + "repository": "https://github.com/npm/cacache", + "keywords": [ + "cache", + "caching", + "content-addressable", + "sri", + "sri hash", + "subresource integrity", + "cache", + "storage", + "store", + "file store", + "filesystem", + "disk cache", + "disk storage" + ], + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "devDependencies": { + "@npmcli/lint": "^1.0.1", + "benchmark": "^2.1.4", + "chalk": "^4.0.0", + "require-inject": "^1.4.4", + "tacks": "^1.3.0", + "tap": "^15.0.9" + }, + "tap": { + "100": true, + "test-regex": "test/[^/]*.js" + }, + "engines": { + "node": ">= 10" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/put.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/put.js new file mode 100644 index 000000000..84e9562bc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/put.js @@ -0,0 +1,83 @@ +'use strict' + +const index = require('./lib/entry-index') +const memo = require('./lib/memoization') +const write = require('./lib/content/write') +const Flush = require('minipass-flush') +const { PassThrough } = require('minipass-collect') +const Pipeline = require('minipass-pipeline') + +const putOpts = (opts) => ({ + algorithms: ['sha512'], + ...opts, +}) + +module.exports = putData + +function putData (cache, key, data, opts = {}) { + const { memoize } = opts + opts = putOpts(opts) + return write(cache, data, opts).then((res) => { + return index + .insert(cache, key, res.integrity, { ...opts, size: res.size }) + .then((entry) => { + if (memoize) + memo.put(cache, entry, data, opts) + + return res.integrity + }) + }) +} + +module.exports.stream = putStream + +function putStream (cache, key, opts = {}) { + const { memoize } = opts + opts = putOpts(opts) + let integrity + let size + + let memoData + const pipeline = new Pipeline() + // first item in the pipeline is the memoizer, because we need + // that to end first and get the collected data. + if (memoize) { + const memoizer = new PassThrough().on('collect', data => { + memoData = data + }) + pipeline.push(memoizer) + } + + // contentStream is a write-only, not a passthrough + // no data comes out of it. + const contentStream = write.stream(cache, opts) + .on('integrity', (int) => { + integrity = int + }) + .on('size', (s) => { + size = s + }) + + pipeline.push(contentStream) + + // last but not least, we write the index and emit hash and size, + // and memoize if we're doing that + pipeline.push(new Flush({ + flush () { + return index + .insert(cache, key, integrity, { ...opts, size }) + .then((entry) => { + if (memoize && memoData) + memo.put(cache, entry, memoData, opts) + + if (integrity) + pipeline.emit('integrity', integrity) + + if (size) + pipeline.emit('size', size) + }) + }, + })) + + return pipeline +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/rm.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/rm.js new file mode 100644 index 000000000..f2ef6b190 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/rm.js @@ -0,0 +1,31 @@ +'use strict' + +const util = require('util') + +const index = require('./lib/entry-index') +const memo = require('./lib/memoization') +const path = require('path') +const rimraf = util.promisify(require('rimraf')) +const rmContent = require('./lib/content/rm') + +module.exports = entry +module.exports.entry = entry + +function entry (cache, key, opts) { + memo.clearMemoized() + return index.delete(cache, key, opts) +} + +module.exports.content = content + +function content (cache, integrity) { + memo.clearMemoized() + return rmContent(cache, integrity) +} + +module.exports.all = all + +function all (cache) { + memo.clearMemoized() + return rimraf(path.join(cache, '*(content-*|index-*)')) +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/verify.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/verify.js new file mode 100644 index 000000000..db7763d7a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/cacache/verify.js @@ -0,0 +1,3 @@ +'use strict' + +module.exports = require('./lib/verify') diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/.eslintrc b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/.eslintrc new file mode 100644 index 000000000..201e859be --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/.eslintrc @@ -0,0 +1,17 @@ +{ + "root": true, + + "extends": "@ljharb", + + "rules": { + "func-name-matching": 0, + "id-length": 0, + "new-cap": [2, { + "capIsNewExceptions": [ + "GetIntrinsic", + ], + }], + "no-extra-parens": 0, + "no-magic-numbers": 0, + }, +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/.github/FUNDING.yml b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/.github/FUNDING.yml new file mode 100644 index 000000000..0011e9d65 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [ljharb] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: npm/call-bind-apply-helpers +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/.nycrc b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/.nycrc new file mode 100644 index 000000000..bdd626ce9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/.nycrc @@ -0,0 +1,9 @@ +{ + "all": true, + "check-coverage": false, + "reporter": ["text-summary", "text", "html", "json"], + "exclude": [ + "coverage", + "test" + ] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/CHANGELOG.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/CHANGELOG.md new file mode 100644 index 000000000..24849428b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/CHANGELOG.md @@ -0,0 +1,30 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [v1.0.2](https://github.com/ljharb/call-bind-apply-helpers/compare/v1.0.1...v1.0.2) - 2025-02-12 + +### Commits + +- [types] improve inferred types [`e6f9586`](https://github.com/ljharb/call-bind-apply-helpers/commit/e6f95860a3c72879cb861a858cdfb8138fbedec1) +- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `@types/tape`, `es-value-fixtures`, `for-each`, `has-strict-mode`, `object-inspect` [`e43d540`](https://github.com/ljharb/call-bind-apply-helpers/commit/e43d5409f97543bfbb11f345d47d8ce4e066d8c1) + +## [v1.0.1](https://github.com/ljharb/call-bind-apply-helpers/compare/v1.0.0...v1.0.1) - 2024-12-08 + +### Commits + +- [types] `reflectApply`: fix types [`4efc396`](https://github.com/ljharb/call-bind-apply-helpers/commit/4efc3965351a4f02cc55e836fa391d3d11ef2ef8) +- [Fix] `reflectApply`: oops, Reflect is not a function [`83cc739`](https://github.com/ljharb/call-bind-apply-helpers/commit/83cc7395de6b79b7730bdf092f1436f0b1263c75) +- [Dev Deps] update `@arethetypeswrong/cli` [`80bd5d3`](https://github.com/ljharb/call-bind-apply-helpers/commit/80bd5d3ae58b4f6b6995ce439dd5a1bcb178a940) + +## v1.0.0 - 2024-12-05 + +### Commits + +- Initial implementation, tests, readme [`7879629`](https://github.com/ljharb/call-bind-apply-helpers/commit/78796290f9b7430c9934d6f33d94ae9bc89fce04) +- Initial commit [`3f1dc16`](https://github.com/ljharb/call-bind-apply-helpers/commit/3f1dc164afc43285631b114a5f9dd9137b2b952f) +- npm init [`081df04`](https://github.com/ljharb/call-bind-apply-helpers/commit/081df048c312fcee400922026f6e97281200a603) +- Only apps should have lockfiles [`5b9ca0f`](https://github.com/ljharb/call-bind-apply-helpers/commit/5b9ca0fe8101ebfaf309c549caac4e0a017ed930) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/LICENSE new file mode 100644 index 000000000..f82f38963 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Jordan Harband + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/README.md new file mode 100644 index 000000000..8fc0dae1b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/README.md @@ -0,0 +1,62 @@ +# call-bind-apply-helpers [![Version Badge][npm-version-svg]][package-url] + +[![github actions][actions-image]][actions-url] +[![coverage][codecov-image]][codecov-url] +[![dependency status][deps-svg]][deps-url] +[![dev dependency status][dev-deps-svg]][dev-deps-url] +[![License][license-image]][license-url] +[![Downloads][downloads-image]][downloads-url] + +[![npm badge][npm-badge-png]][package-url] + +Helper functions around Function call/apply/bind, for use in `call-bind`. + +The only packages that should likely ever use this package directly are `call-bind` and `get-intrinsic`. +Please use `call-bind` unless you have a very good reason not to. + +## Getting started + +```sh +npm install --save call-bind-apply-helpers +``` + +## Usage/Examples + +```js +const assert = require('assert'); +const callBindBasic = require('call-bind-apply-helpers'); + +function f(a, b) { + assert.equal(this, 1); + assert.equal(a, 2); + assert.equal(b, 3); + assert.equal(arguments.length, 2); +} + +const fBound = callBindBasic([f, 1]); + +delete Function.prototype.call; +delete Function.prototype.bind; + +fBound(2, 3); +``` + +## Tests + +Clone the repo, `npm install`, and run `npm test` + +[package-url]: https://npmjs.org/package/call-bind-apply-helpers +[npm-version-svg]: https://versionbadg.es/ljharb/call-bind-apply-helpers.svg +[deps-svg]: https://david-dm.org/ljharb/call-bind-apply-helpers.svg +[deps-url]: https://david-dm.org/ljharb/call-bind-apply-helpers +[dev-deps-svg]: https://david-dm.org/ljharb/call-bind-apply-helpers/dev-status.svg +[dev-deps-url]: https://david-dm.org/ljharb/call-bind-apply-helpers#info=devDependencies +[npm-badge-png]: https://nodei.co/npm/call-bind-apply-helpers.png?downloads=true&stars=true +[license-image]: https://img.shields.io/npm/l/call-bind-apply-helpers.svg +[license-url]: LICENSE +[downloads-image]: https://img.shields.io/npm/dm/call-bind-apply-helpers.svg +[downloads-url]: https://npm-stat.com/charts.html?package=call-bind-apply-helpers +[codecov-image]: https://codecov.io/gh/ljharb/call-bind-apply-helpers/branch/main/graphs/badge.svg +[codecov-url]: https://app.codecov.io/gh/ljharb/call-bind-apply-helpers/ +[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/call-bind-apply-helpers +[actions-url]: https://github.com/ljharb/call-bind-apply-helpers/actions diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/actualApply.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/actualApply.d.ts new file mode 100644 index 000000000..b87286a21 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/actualApply.d.ts @@ -0,0 +1 @@ +export = Reflect.apply; \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/actualApply.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/actualApply.js new file mode 100644 index 000000000..ffa51355d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/actualApply.js @@ -0,0 +1,10 @@ +'use strict'; + +var bind = require('function-bind'); + +var $apply = require('./functionApply'); +var $call = require('./functionCall'); +var $reflectApply = require('./reflectApply'); + +/** @type {import('./actualApply')} */ +module.exports = $reflectApply || bind.call($call, $apply); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/applyBind.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/applyBind.d.ts new file mode 100644 index 000000000..d176c1ab3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/applyBind.d.ts @@ -0,0 +1,19 @@ +import actualApply from './actualApply'; + +type TupleSplitHead = T['length'] extends N + ? T + : T extends [...infer R, any] + ? TupleSplitHead + : never + +type TupleSplitTail = O['length'] extends N + ? T + : T extends [infer F, ...infer R] + ? TupleSplitTail<[...R], N, [...O, F]> + : never + +type TupleSplit = [TupleSplitHead, TupleSplitTail] + +declare function applyBind(...args: TupleSplit, 2>[1]): ReturnType; + +export = applyBind; \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/applyBind.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/applyBind.js new file mode 100644 index 000000000..d2b772314 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/applyBind.js @@ -0,0 +1,10 @@ +'use strict'; + +var bind = require('function-bind'); +var $apply = require('./functionApply'); +var actualApply = require('./actualApply'); + +/** @type {import('./applyBind')} */ +module.exports = function applyBind() { + return actualApply(bind, $apply, arguments); +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionApply.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionApply.d.ts new file mode 100644 index 000000000..1f6e11b3d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionApply.d.ts @@ -0,0 +1 @@ +export = Function.prototype.apply; \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionApply.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionApply.js new file mode 100644 index 000000000..c71df9c2b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionApply.js @@ -0,0 +1,4 @@ +'use strict'; + +/** @type {import('./functionApply')} */ +module.exports = Function.prototype.apply; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionCall.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionCall.d.ts new file mode 100644 index 000000000..15e93df35 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionCall.d.ts @@ -0,0 +1 @@ +export = Function.prototype.call; \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionCall.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionCall.js new file mode 100644 index 000000000..7a8d87357 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/functionCall.js @@ -0,0 +1,4 @@ +'use strict'; + +/** @type {import('./functionCall')} */ +module.exports = Function.prototype.call; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/index.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/index.d.ts new file mode 100644 index 000000000..541516bd0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/index.d.ts @@ -0,0 +1,64 @@ +type RemoveFromTuple< + Tuple extends readonly unknown[], + RemoveCount extends number, + Index extends 1[] = [] +> = Index["length"] extends RemoveCount + ? Tuple + : Tuple extends [infer First, ...infer Rest] + ? RemoveFromTuple + : Tuple; + +type ConcatTuples< + Prefix extends readonly unknown[], + Suffix extends readonly unknown[] +> = [...Prefix, ...Suffix]; + +type ExtractFunctionParams = T extends (this: infer TThis, ...args: infer P extends readonly unknown[]) => infer R + ? { thisArg: TThis; params: P; returnType: R } + : never; + +type BindFunction< + T extends (this: any, ...args: any[]) => any, + TThis, + TBoundArgs extends readonly unknown[], + ReceiverBound extends boolean +> = ExtractFunctionParams extends { + thisArg: infer OrigThis; + params: infer P extends readonly unknown[]; + returnType: infer R; +} + ? ReceiverBound extends true + ? (...args: RemoveFromTuple>) => R extends [OrigThis, ...infer Rest] + ? [TThis, ...Rest] // Replace `this` with `thisArg` + : R + : >>( + thisArg: U, + ...args: RemainingArgs + ) => R extends [OrigThis, ...infer Rest] + ? [U, ...ConcatTuples] // Preserve bound args in return type + : R + : never; + +declare function callBind< + const T extends (this: any, ...args: any[]) => any, + Extracted extends ExtractFunctionParams, + const TBoundArgs extends Partial & readonly unknown[], + const TThis extends Extracted["thisArg"] +>( + args: [fn: T, thisArg: TThis, ...boundArgs: TBoundArgs] +): BindFunction; + +declare function callBind< + const T extends (this: any, ...args: any[]) => any, + Extracted extends ExtractFunctionParams, + const TBoundArgs extends Partial & readonly unknown[] +>( + args: [fn: T, ...boundArgs: TBoundArgs] +): BindFunction; + +declare function callBind( + args: [fn: Exclude, ...rest: TArgs] +): never; + +// export as namespace callBind; +export = callBind; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/index.js new file mode 100644 index 000000000..2f6dab4c1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/index.js @@ -0,0 +1,15 @@ +'use strict'; + +var bind = require('function-bind'); +var $TypeError = require('es-errors/type'); + +var $call = require('./functionCall'); +var $actualApply = require('./actualApply'); + +/** @type {(args: [Function, thisArg?: unknown, ...args: unknown[]]) => Function} TODO FIXME, find a way to use import('.') */ +module.exports = function callBindBasic(args) { + if (args.length < 1 || typeof args[0] !== 'function') { + throw new $TypeError('a function is required'); + } + return $actualApply(bind, $call, args); +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/package.json new file mode 100644 index 000000000..923b8be2f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/package.json @@ -0,0 +1,85 @@ +{ + "name": "call-bind-apply-helpers", + "version": "1.0.2", + "description": "Helper functions around Function call/apply/bind, for use in `call-bind`", + "main": "index.js", + "exports": { + ".": "./index.js", + "./actualApply": "./actualApply.js", + "./applyBind": "./applyBind.js", + "./functionApply": "./functionApply.js", + "./functionCall": "./functionCall.js", + "./reflectApply": "./reflectApply.js", + "./package.json": "./package.json" + }, + "scripts": { + "prepack": "npmignore --auto --commentLines=auto", + "prepublish": "not-in-publish || npm run prepublishOnly", + "prepublishOnly": "safe-publish-latest", + "prelint": "evalmd README.md", + "lint": "eslint --ext=.js,.mjs .", + "postlint": "tsc -p . && attw -P", + "pretest": "npm run lint", + "tests-only": "nyc tape 'test/**/*.js'", + "test": "npm run tests-only", + "posttest": "npx npm@'>=10.2' audit --production", + "version": "auto-changelog && git add CHANGELOG.md", + "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ljharb/call-bind-apply-helpers.git" + }, + "author": "Jordan Harband ", + "license": "MIT", + "bugs": { + "url": "https://github.com/ljharb/call-bind-apply-helpers/issues" + }, + "homepage": "https://github.com/ljharb/call-bind-apply-helpers#readme", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "devDependencies": { + "@arethetypeswrong/cli": "^0.17.3", + "@ljharb/eslint-config": "^21.1.1", + "@ljharb/tsconfig": "^0.2.3", + "@types/for-each": "^0.3.3", + "@types/function-bind": "^1.1.10", + "@types/object-inspect": "^1.13.0", + "@types/tape": "^5.8.1", + "auto-changelog": "^2.5.0", + "encoding": "^0.1.13", + "es-value-fixtures": "^1.7.1", + "eslint": "=8.8.0", + "evalmd": "^0.0.19", + "for-each": "^0.3.5", + "has-strict-mode": "^1.1.0", + "in-publish": "^2.0.1", + "npmignore": "^0.3.1", + "nyc": "^10.3.2", + "object-inspect": "^1.13.4", + "safe-publish-latest": "^2.0.0", + "tape": "^5.9.0", + "typescript": "next" + }, + "testling": { + "files": "test/index.js" + }, + "auto-changelog": { + "output": "CHANGELOG.md", + "template": "keepachangelog", + "unreleased": false, + "commitLimit": false, + "backfillLimit": false, + "hideCredit": true + }, + "publishConfig": { + "ignore": [ + ".github/workflows" + ] + }, + "engines": { + "node": ">= 0.4" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/reflectApply.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/reflectApply.d.ts new file mode 100644 index 000000000..6b2ae764c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/reflectApply.d.ts @@ -0,0 +1,3 @@ +declare const reflectApply: false | typeof Reflect.apply; + +export = reflectApply; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/reflectApply.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/reflectApply.js new file mode 100644 index 000000000..3d03caa69 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/reflectApply.js @@ -0,0 +1,4 @@ +'use strict'; + +/** @type {import('./reflectApply')} */ +module.exports = typeof Reflect !== 'undefined' && Reflect && Reflect.apply; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/test/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/test/index.js new file mode 100644 index 000000000..1cdc89ed4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/test/index.js @@ -0,0 +1,63 @@ +'use strict'; + +var callBind = require('../'); +var hasStrictMode = require('has-strict-mode')(); +var forEach = require('for-each'); +var inspect = require('object-inspect'); +var v = require('es-value-fixtures'); + +var test = require('tape'); + +test('callBindBasic', function (t) { + forEach(v.nonFunctions, function (nonFunction) { + t['throws']( + // @ts-expect-error + function () { callBind([nonFunction]); }, + TypeError, + inspect(nonFunction) + ' is not a function' + ); + }); + + var sentinel = { sentinel: true }; + /** @type {(this: T, a: A, b: B) => [T | undefined, A, B]} */ + var func = function (a, b) { + // eslint-disable-next-line no-invalid-this + return [!hasStrictMode && this === global ? undefined : this, a, b]; + }; + t.equal(func.length, 2, 'original function length is 2'); + + /** type {(thisArg: unknown, a: number, b: number) => [unknown, number, number]} */ + var bound = callBind([func]); + /** type {((a: number, b: number) => [typeof sentinel, typeof a, typeof b])} */ + var boundR = callBind([func, sentinel]); + /** type {((b: number) => [typeof sentinel, number, typeof b])} */ + var boundArg = callBind([func, sentinel, /** @type {const} */ (1)]); + + // @ts-expect-error + t.deepEqual(bound(), [undefined, undefined, undefined], 'bound func with no args'); + + // @ts-expect-error + t.deepEqual(func(), [undefined, undefined, undefined], 'unbound func with too few args'); + // @ts-expect-error + t.deepEqual(bound(1, 2), [hasStrictMode ? 1 : Object(1), 2, undefined], 'bound func too few args'); + // @ts-expect-error + t.deepEqual(boundR(), [sentinel, undefined, undefined], 'bound func with receiver, with too few args'); + // @ts-expect-error + t.deepEqual(boundArg(), [sentinel, 1, undefined], 'bound func with receiver and arg, with too few args'); + + t.deepEqual(func(1, 2), [undefined, 1, 2], 'unbound func with right args'); + t.deepEqual(bound(1, 2, 3), [hasStrictMode ? 1 : Object(1), 2, 3], 'bound func with right args'); + t.deepEqual(boundR(1, 2), [sentinel, 1, 2], 'bound func with receiver, with right args'); + t.deepEqual(boundArg(2), [sentinel, 1, 2], 'bound func with receiver and arg, with right arg'); + + // @ts-expect-error + t.deepEqual(func(1, 2, 3), [undefined, 1, 2], 'unbound func with too many args'); + // @ts-expect-error + t.deepEqual(bound(1, 2, 3, 4), [hasStrictMode ? 1 : Object(1), 2, 3], 'bound func with too many args'); + // @ts-expect-error + t.deepEqual(boundR(1, 2, 3), [sentinel, 1, 2], 'bound func with receiver, with too many args'); + // @ts-expect-error + t.deepEqual(boundArg(2, 3), [sentinel, 1, 2], 'bound func with receiver and arg, with too many args'); + + t.end(); +}); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/tsconfig.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/tsconfig.json new file mode 100644 index 000000000..aef999308 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bind-apply-helpers/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "@ljharb/tsconfig", + "compilerOptions": { + "target": "es2021", + }, + "exclude": [ + "coverage", + ], +} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/.eslintrc b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/.eslintrc new file mode 100644 index 000000000..2612ed8fe --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/.eslintrc @@ -0,0 +1,13 @@ +{ + "root": true, + + "extends": "@ljharb", + + "rules": { + "new-cap": [2, { + "capIsNewExceptions": [ + "GetIntrinsic", + ], + }], + }, +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/.github/FUNDING.yml b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/.github/FUNDING.yml new file mode 100644 index 000000000..2a2a13571 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [ljharb] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: npm/call-bound +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/.nycrc b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/.nycrc new file mode 100644 index 000000000..bdd626ce9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/.nycrc @@ -0,0 +1,9 @@ +{ + "all": true, + "check-coverage": false, + "reporter": ["text-summary", "text", "html", "json"], + "exclude": [ + "coverage", + "test" + ] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/CHANGELOG.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/CHANGELOG.md new file mode 100644 index 000000000..8bde4e9a5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/CHANGELOG.md @@ -0,0 +1,42 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [v1.0.4](https://github.com/ljharb/call-bound/compare/v1.0.3...v1.0.4) - 2025-03-03 + +### Commits + +- [types] improve types [`e648922`](https://github.com/ljharb/call-bound/commit/e6489222a9e54f350fbf952ceabe51fd8b6027ff) +- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `@types/tape`, `es-value-fixtures`, `for-each`, `has-strict-mode`, `object-inspect` [`a42a5eb`](https://github.com/ljharb/call-bound/commit/a42a5ebe6c1b54fcdc7997c7dc64fdca9e936719) +- [Deps] update `call-bind-apply-helpers`, `get-intrinsic` [`f529eac`](https://github.com/ljharb/call-bound/commit/f529eac132404c17156bbc23ab2297a25d0f20b8) + +## [v1.0.3](https://github.com/ljharb/call-bound/compare/v1.0.2...v1.0.3) - 2024-12-15 + +### Commits + +- [Refactor] use `call-bind-apply-helpers` instead of `call-bind` [`5e0b134`](https://github.com/ljharb/call-bound/commit/5e0b13496df14fb7d05dae9412f088da8d3f75be) +- [Deps] update `get-intrinsic` [`41fc967`](https://github.com/ljharb/call-bound/commit/41fc96732a22c7b7e8f381f93ccc54bb6293be2e) +- [readme] fix example [`79a0137`](https://github.com/ljharb/call-bound/commit/79a0137723f7c6d09c9c05452bbf8d5efb5d6e49) +- [meta] add `sideEffects` flag [`08b07be`](https://github.com/ljharb/call-bound/commit/08b07be7f1c03f67dc6f3cdaf0906259771859f7) + +## [v1.0.2](https://github.com/ljharb/call-bound/compare/v1.0.1...v1.0.2) - 2024-12-10 + +### Commits + +- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `gopd` [`e6a5ffe`](https://github.com/ljharb/call-bound/commit/e6a5ffe849368fe4f74dfd6cdeca1b9baa39e8d5) +- [Deps] update `call-bind`, `get-intrinsic` [`2aeb5b5`](https://github.com/ljharb/call-bound/commit/2aeb5b521dc2b2683d1345c753ea1161de2d1c14) +- [types] improve return type [`1a0c9fe`](https://github.com/ljharb/call-bound/commit/1a0c9fe3114471e7ca1f57d104e2efe713bb4871) + +## v1.0.1 - 2024-12-05 + +### Commits + +- Initial implementation, tests, readme, types [`6d94121`](https://github.com/ljharb/call-bound/commit/6d94121a9243602e506334069f7a03189fe3363d) +- Initial commit [`0eae867`](https://github.com/ljharb/call-bound/commit/0eae867334ea025c33e6e91cdecfc9df96680cf9) +- npm init [`71b2479`](https://github.com/ljharb/call-bound/commit/71b2479c6723e0b7d91a6b663613067e98b7b275) +- Only apps should have lockfiles [`c3754a9`](https://github.com/ljharb/call-bound/commit/c3754a949b7f9132b47e2d18c1729889736741eb) +- [actions] skip `npm ls` in node < 10 [`74275a5`](https://github.com/ljharb/call-bound/commit/74275a5186b8caf6309b6b97472bdcb0df4683a8) +- [Dev Deps] add missing peer dep [`1354de8`](https://github.com/ljharb/call-bound/commit/1354de8679413e4ae9c523d85f76fa7a5e032d97) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/LICENSE new file mode 100644 index 000000000..f82f38963 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Jordan Harband + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/README.md new file mode 100644 index 000000000..a44e43e56 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/README.md @@ -0,0 +1,53 @@ +# call-bound [![Version Badge][npm-version-svg]][package-url] + +[![github actions][actions-image]][actions-url] +[![coverage][codecov-image]][codecov-url] +[![dependency status][deps-svg]][deps-url] +[![dev dependency status][dev-deps-svg]][dev-deps-url] +[![License][license-image]][license-url] +[![Downloads][downloads-image]][downloads-url] + +[![npm badge][npm-badge-png]][package-url] + +Robust call-bound JavaScript intrinsics, using `call-bind` and `get-intrinsic`. + +## Getting started + +```sh +npm install --save call-bound +``` + +## Usage/Examples + +```js +const assert = require('assert'); +const callBound = require('call-bound'); + +const slice = callBound('Array.prototype.slice'); + +delete Function.prototype.call; +delete Function.prototype.bind; +delete Array.prototype.slice; + +assert.deepEqual(slice([1, 2, 3, 4], 1, -1), [2, 3]); +``` + +## Tests + +Clone the repo, `npm install`, and run `npm test` + +[package-url]: https://npmjs.org/package/call-bound +[npm-version-svg]: https://versionbadg.es/ljharb/call-bound.svg +[deps-svg]: https://david-dm.org/ljharb/call-bound.svg +[deps-url]: https://david-dm.org/ljharb/call-bound +[dev-deps-svg]: https://david-dm.org/ljharb/call-bound/dev-status.svg +[dev-deps-url]: https://david-dm.org/ljharb/call-bound#info=devDependencies +[npm-badge-png]: https://nodei.co/npm/call-bound.png?downloads=true&stars=true +[license-image]: https://img.shields.io/npm/l/call-bound.svg +[license-url]: LICENSE +[downloads-image]: https://img.shields.io/npm/dm/call-bound.svg +[downloads-url]: https://npm-stat.com/charts.html?package=call-bound +[codecov-image]: https://codecov.io/gh/ljharb/call-bound/branch/main/graphs/badge.svg +[codecov-url]: https://app.codecov.io/gh/ljharb/call-bound/ +[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/call-bound +[actions-url]: https://github.com/ljharb/call-bound/actions diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/index.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/index.d.ts new file mode 100644 index 000000000..5562f00ed --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/index.d.ts @@ -0,0 +1,94 @@ +type Intrinsic = typeof globalThis; + +type IntrinsicName = keyof Intrinsic | `%${keyof Intrinsic}%`; + +type IntrinsicPath = IntrinsicName | `${StripPercents}.${string}` | `%${StripPercents}.${string}%`; + +type AllowMissing = boolean; + +type StripPercents = T extends `%${infer U}%` ? U : T; + +type BindMethodPrecise = + F extends (this: infer This, ...args: infer Args) => infer R + ? (obj: This, ...args: Args) => R + : F extends { + (this: infer This1, ...args: infer Args1): infer R1; + (this: infer This2, ...args: infer Args2): infer R2 + } + ? { + (obj: This1, ...args: Args1): R1; + (obj: This2, ...args: Args2): R2 + } + : never + +// Extract method type from a prototype +type GetPrototypeMethod = + (typeof globalThis)[T] extends { prototype: any } + ? M extends keyof (typeof globalThis)[T]['prototype'] + ? (typeof globalThis)[T]['prototype'][M] + : never + : never + +// Get static property/method +type GetStaticMember = + P extends keyof (typeof globalThis)[T] ? (typeof globalThis)[T][P] : never + +// Type that maps string path to actual bound function or value with better precision +type BoundIntrinsic = + S extends `${infer Obj}.prototype.${infer Method}` + ? Obj extends keyof typeof globalThis + ? BindMethodPrecise> + : unknown + : S extends `${infer Obj}.${infer Prop}` + ? Obj extends keyof typeof globalThis + ? GetStaticMember + : unknown + : unknown + +declare function arraySlice(array: readonly T[], start?: number, end?: number): T[]; +declare function arraySlice(array: ArrayLike, start?: number, end?: number): T[]; +declare function arraySlice(array: IArguments, start?: number, end?: number): T[]; + +// Special cases for methods that need explicit typing +interface SpecialCases { + '%Object.prototype.isPrototypeOf%': (thisArg: {}, obj: unknown) => boolean; + '%String.prototype.replace%': { + (str: string, searchValue: string | RegExp, replaceValue: string): string; + (str: string, searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string + }; + '%Object.prototype.toString%': (obj: {}) => string; + '%Object.prototype.hasOwnProperty%': (obj: {}, v: PropertyKey) => boolean; + '%Array.prototype.slice%': typeof arraySlice; + '%Array.prototype.map%': (array: readonly T[], callbackfn: (value: T, index: number, array: readonly T[]) => U, thisArg?: any) => U[]; + '%Array.prototype.filter%': (array: readonly T[], predicate: (value: T, index: number, array: readonly T[]) => unknown, thisArg?: any) => T[]; + '%Array.prototype.indexOf%': (array: readonly T[], searchElement: T, fromIndex?: number) => number; + '%Function.prototype.apply%': (fn: (...args: A) => R, thisArg: any, args: A) => R; + '%Function.prototype.call%': (fn: (...args: A) => R, thisArg: any, ...args: A) => R; + '%Function.prototype.bind%': (fn: (...args: A) => R, thisArg: any, ...args: A) => (...remainingArgs: A) => R; + '%Promise.prototype.then%': { + (promise: Promise, onfulfilled: (value: T) => R | PromiseLike): Promise; + (promise: Promise, onfulfilled: ((value: T) => R | PromiseLike) | undefined | null, onrejected: (reason: any) => R | PromiseLike): Promise; + }; + '%RegExp.prototype.test%': (regexp: RegExp, str: string) => boolean; + '%RegExp.prototype.exec%': (regexp: RegExp, str: string) => RegExpExecArray | null; + '%Error.prototype.toString%': (error: Error) => string; + '%TypeError.prototype.toString%': (error: TypeError) => string; + '%String.prototype.split%': ( + obj: unknown, + splitter: string | RegExp | { + [Symbol.split](string: string, limit?: number): string[]; + }, + limit?: number | undefined + ) => string[]; +} + +/** + * Returns a bound function for a prototype method, or a value for a static property. + * + * @param name - The name of the intrinsic (e.g. 'Array.prototype.slice') + * @param {AllowMissing} [allowMissing] - Whether to allow missing intrinsics (default: false) + */ +declare function callBound, S extends IntrinsicPath>(name: K, allowMissing?: AllowMissing): SpecialCases[`%${StripPercents}%`]; +declare function callBound, S extends IntrinsicPath>(name: S, allowMissing?: AllowMissing): BoundIntrinsic; + +export = callBound; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/index.js new file mode 100644 index 000000000..e9ade749d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/index.js @@ -0,0 +1,19 @@ +'use strict'; + +var GetIntrinsic = require('get-intrinsic'); + +var callBindBasic = require('call-bind-apply-helpers'); + +/** @type {(thisArg: string, searchString: string, position?: number) => number} */ +var $indexOf = callBindBasic([GetIntrinsic('%String.prototype.indexOf%')]); + +/** @type {import('.')} */ +module.exports = function callBoundIntrinsic(name, allowMissing) { + /* eslint no-extra-parens: 0 */ + + var intrinsic = /** @type {(this: unknown, ...args: unknown[]) => unknown} */ (GetIntrinsic(name, !!allowMissing)); + if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) { + return callBindBasic(/** @type {const} */ ([intrinsic])); + } + return intrinsic; +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/package.json new file mode 100644 index 000000000..d542db430 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/package.json @@ -0,0 +1,99 @@ +{ + "name": "call-bound", + "version": "1.0.4", + "description": "Robust call-bound JavaScript intrinsics, using `call-bind` and `get-intrinsic`.", + "main": "index.js", + "exports": { + ".": "./index.js", + "./package.json": "./package.json" + }, + "sideEffects": false, + "scripts": { + "prepack": "npmignore --auto --commentLines=auto", + "prepublish": "not-in-publish || npm run prepublishOnly", + "prepublishOnly": "safe-publish-latest", + "prelint": "evalmd README.md", + "lint": "eslint --ext=.js,.mjs .", + "postlint": "tsc -p . && attw -P", + "pretest": "npm run lint", + "tests-only": "nyc tape 'test/**/*.js'", + "test": "npm run tests-only", + "posttest": "npx npm@'>=10.2' audit --production", + "version": "auto-changelog && git add CHANGELOG.md", + "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ljharb/call-bound.git" + }, + "keywords": [ + "javascript", + "ecmascript", + "es", + "js", + "callbind", + "callbound", + "call", + "bind", + "bound", + "call-bind", + "call-bound", + "function", + "es-abstract" + ], + "author": "Jordan Harband ", + "funding": { + "url": "https://github.com/sponsors/ljharb" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/ljharb/call-bound/issues" + }, + "homepage": "https://github.com/ljharb/call-bound#readme", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "devDependencies": { + "@arethetypeswrong/cli": "^0.17.4", + "@ljharb/eslint-config": "^21.1.1", + "@ljharb/tsconfig": "^0.3.0", + "@types/call-bind": "^1.0.5", + "@types/get-intrinsic": "^1.2.3", + "@types/tape": "^5.8.1", + "auto-changelog": "^2.5.0", + "encoding": "^0.1.13", + "es-value-fixtures": "^1.7.1", + "eslint": "=8.8.0", + "evalmd": "^0.0.19", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "has-strict-mode": "^1.1.0", + "in-publish": "^2.0.1", + "npmignore": "^0.3.1", + "nyc": "^10.3.2", + "object-inspect": "^1.13.4", + "safe-publish-latest": "^2.0.0", + "tape": "^5.9.0", + "typescript": "next" + }, + "testling": { + "files": "test/index.js" + }, + "auto-changelog": { + "output": "CHANGELOG.md", + "template": "keepachangelog", + "unreleased": false, + "commitLimit": false, + "backfillLimit": false, + "hideCredit": true + }, + "publishConfig": { + "ignore": [ + ".github/workflows" + ] + }, + "engines": { + "node": ">= 0.4" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/test/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/test/index.js new file mode 100644 index 000000000..a2fc9f0f2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/test/index.js @@ -0,0 +1,61 @@ +'use strict'; + +var test = require('tape'); + +var callBound = require('../'); + +/** @template {true} T @template U @typedef {T extends U ? T : never} AssertType */ + +test('callBound', function (t) { + // static primitive + t.equal(callBound('Array.length'), Array.length, 'Array.length yields itself'); + t.equal(callBound('%Array.length%'), Array.length, '%Array.length% yields itself'); + + // static non-function object + t.equal(callBound('Array.prototype'), Array.prototype, 'Array.prototype yields itself'); + t.equal(callBound('%Array.prototype%'), Array.prototype, '%Array.prototype% yields itself'); + t.equal(callBound('Array.constructor'), Array.constructor, 'Array.constructor yields itself'); + t.equal(callBound('%Array.constructor%'), Array.constructor, '%Array.constructor% yields itself'); + + // static function + t.equal(callBound('Date.parse'), Date.parse, 'Date.parse yields itself'); + t.equal(callBound('%Date.parse%'), Date.parse, '%Date.parse% yields itself'); + + // prototype primitive + t.equal(callBound('Error.prototype.message'), Error.prototype.message, 'Error.prototype.message yields itself'); + t.equal(callBound('%Error.prototype.message%'), Error.prototype.message, '%Error.prototype.message% yields itself'); + + var x = callBound('Object.prototype.toString'); + var y = callBound('%Object.prototype.toString%'); + + // prototype function + t.notEqual(x, Object.prototype.toString, 'Object.prototype.toString does not yield itself'); + t.notEqual(y, Object.prototype.toString, '%Object.prototype.toString% does not yield itself'); + t.equal(x(true), Object.prototype.toString.call(true), 'call-bound Object.prototype.toString calls into the original'); + t.equal(y(true), Object.prototype.toString.call(true), 'call-bound %Object.prototype.toString% calls into the original'); + + t['throws']( + // @ts-expect-error + function () { callBound('does not exist'); }, + SyntaxError, + 'nonexistent intrinsic throws' + ); + t['throws']( + // @ts-expect-error + function () { callBound('does not exist', true); }, + SyntaxError, + 'allowMissing arg still throws for unknown intrinsic' + ); + + t.test('real but absent intrinsic', { skip: typeof WeakRef !== 'undefined' }, function (st) { + st['throws']( + function () { callBound('WeakRef'); }, + TypeError, + 'real but absent intrinsic throws' + ); + st.equal(callBound('WeakRef', true), undefined, 'allowMissing arg avoids exception'); + st.end(); + }); + + t.end(); +}); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/tsconfig.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/tsconfig.json new file mode 100644 index 000000000..8976d98b8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/call-bound/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@ljharb/tsconfig", + "compilerOptions": { + "target": "ESNext", + "lib": ["es2024"], + }, + "exclude": [ + "coverage", + ], +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/LICENSE new file mode 100644 index 000000000..19129e315 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/README.md new file mode 100644 index 000000000..70e9a54a3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/README.md @@ -0,0 +1,3 @@ +Like `chown -R`. + +Takes the same arguments as `fs.chown()` diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/chownr.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/chownr.js new file mode 100644 index 000000000..0d4093216 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/chownr.js @@ -0,0 +1,167 @@ +'use strict' +const fs = require('fs') +const path = require('path') + +/* istanbul ignore next */ +const LCHOWN = fs.lchown ? 'lchown' : 'chown' +/* istanbul ignore next */ +const LCHOWNSYNC = fs.lchownSync ? 'lchownSync' : 'chownSync' + +/* istanbul ignore next */ +const needEISDIRHandled = fs.lchown && + !process.version.match(/v1[1-9]+\./) && + !process.version.match(/v10\.[6-9]/) + +const lchownSync = (path, uid, gid) => { + try { + return fs[LCHOWNSYNC](path, uid, gid) + } catch (er) { + if (er.code !== 'ENOENT') + throw er + } +} + +/* istanbul ignore next */ +const chownSync = (path, uid, gid) => { + try { + return fs.chownSync(path, uid, gid) + } catch (er) { + if (er.code !== 'ENOENT') + throw er + } +} + +/* istanbul ignore next */ +const handleEISDIR = + needEISDIRHandled ? (path, uid, gid, cb) => er => { + // Node prior to v10 had a very questionable implementation of + // fs.lchown, which would always try to call fs.open on a directory + // Fall back to fs.chown in those cases. + if (!er || er.code !== 'EISDIR') + cb(er) + else + fs.chown(path, uid, gid, cb) + } + : (_, __, ___, cb) => cb + +/* istanbul ignore next */ +const handleEISDirSync = + needEISDIRHandled ? (path, uid, gid) => { + try { + return lchownSync(path, uid, gid) + } catch (er) { + if (er.code !== 'EISDIR') + throw er + chownSync(path, uid, gid) + } + } + : (path, uid, gid) => lchownSync(path, uid, gid) + +// fs.readdir could only accept an options object as of node v6 +const nodeVersion = process.version +let readdir = (path, options, cb) => fs.readdir(path, options, cb) +let readdirSync = (path, options) => fs.readdirSync(path, options) +/* istanbul ignore next */ +if (/^v4\./.test(nodeVersion)) + readdir = (path, options, cb) => fs.readdir(path, cb) + +const chown = (cpath, uid, gid, cb) => { + fs[LCHOWN](cpath, uid, gid, handleEISDIR(cpath, uid, gid, er => { + // Skip ENOENT error + cb(er && er.code !== 'ENOENT' ? er : null) + })) +} + +const chownrKid = (p, child, uid, gid, cb) => { + if (typeof child === 'string') + return fs.lstat(path.resolve(p, child), (er, stats) => { + // Skip ENOENT error + if (er) + return cb(er.code !== 'ENOENT' ? er : null) + stats.name = child + chownrKid(p, stats, uid, gid, cb) + }) + + if (child.isDirectory()) { + chownr(path.resolve(p, child.name), uid, gid, er => { + if (er) + return cb(er) + const cpath = path.resolve(p, child.name) + chown(cpath, uid, gid, cb) + }) + } else { + const cpath = path.resolve(p, child.name) + chown(cpath, uid, gid, cb) + } +} + + +const chownr = (p, uid, gid, cb) => { + readdir(p, { withFileTypes: true }, (er, children) => { + // any error other than ENOTDIR or ENOTSUP means it's not readable, + // or doesn't exist. give up. + if (er) { + if (er.code === 'ENOENT') + return cb() + else if (er.code !== 'ENOTDIR' && er.code !== 'ENOTSUP') + return cb(er) + } + if (er || !children.length) + return chown(p, uid, gid, cb) + + let len = children.length + let errState = null + const then = er => { + if (errState) + return + if (er) + return cb(errState = er) + if (-- len === 0) + return chown(p, uid, gid, cb) + } + + children.forEach(child => chownrKid(p, child, uid, gid, then)) + }) +} + +const chownrKidSync = (p, child, uid, gid) => { + if (typeof child === 'string') { + try { + const stats = fs.lstatSync(path.resolve(p, child)) + stats.name = child + child = stats + } catch (er) { + if (er.code === 'ENOENT') + return + else + throw er + } + } + + if (child.isDirectory()) + chownrSync(path.resolve(p, child.name), uid, gid) + + handleEISDirSync(path.resolve(p, child.name), uid, gid) +} + +const chownrSync = (p, uid, gid) => { + let children + try { + children = readdirSync(p, { withFileTypes: true }) + } catch (er) { + if (er.code === 'ENOENT') + return + else if (er.code === 'ENOTDIR' || er.code === 'ENOTSUP') + return handleEISDirSync(p, uid, gid) + else + throw er + } + + if (children && children.length) + children.forEach(child => chownrKidSync(p, child, uid, gid)) + + return handleEISDirSync(p, uid, gid) +} + +module.exports = chownr +chownr.sync = chownrSync diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/package.json new file mode 100644 index 000000000..5b0214ca1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/chownr/package.json @@ -0,0 +1,32 @@ +{ + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "name": "chownr", + "description": "like `chown -R`", + "version": "2.0.0", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/chownr.git" + }, + "main": "chownr.js", + "files": [ + "chownr.js" + ], + "devDependencies": { + "mkdirp": "0.3", + "rimraf": "^2.7.1", + "tap": "^14.10.6" + }, + "tap": { + "check-coverage": true + }, + "scripts": { + "test": "tap", + "preversion": "npm test", + "postversion": "npm publish", + "prepublishOnly": "git push origin --follow-tags" + }, + "license": "ISC", + "engines": { + "node": ">=10" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/index.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/index.d.ts new file mode 100644 index 000000000..ed5899509 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/index.d.ts @@ -0,0 +1,47 @@ +declare namespace cleanStack { + interface Options { + /** + Prettify the file paths in the stack: + + `/Users/sindresorhus/dev/clean-stack/unicorn.js:2:15` → `~/dev/clean-stack/unicorn.js:2:15` + + @default false + */ + readonly pretty?: boolean; + } +} + +/** +Clean up error stack traces. Removes the mostly unhelpful internal Node.js entries. + +@param stack - The `stack` property of an `Error`. + +@example +``` +import cleanStack = require('clean-stack'); + +const error = new Error('Missing unicorn'); + +console.log(error.stack); + +// Error: Missing unicorn +// at Object. (/Users/sindresorhus/dev/clean-stack/unicorn.js:2:15) +// at Module._compile (module.js:409:26) +// at Object.Module._extensions..js (module.js:416:10) +// at Module.load (module.js:343:32) +// at Function.Module._load (module.js:300:12) +// at Function.Module.runMain (module.js:441:10) +// at startup (node.js:139:18) + +console.log(cleanStack(error.stack)); + +// Error: Missing unicorn +// at Object. (/Users/sindresorhus/dev/clean-stack/unicorn.js:2:15) +``` +*/ +declare function cleanStack( + stack: string, + options?: cleanStack.Options +): string; + +export = cleanStack; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/index.js new file mode 100644 index 000000000..8c1dcc4cd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/index.js @@ -0,0 +1,40 @@ +'use strict'; +const os = require('os'); + +const extractPathRegex = /\s+at.*(?:\(|\s)(.*)\)?/; +const pathRegex = /^(?:(?:(?:node|(?:internal\/[\w/]*|.*node_modules\/(?:babel-polyfill|pirates)\/.*)?\w+)\.js:\d+:\d+)|native)/; +const homeDir = typeof os.homedir === 'undefined' ? '' : os.homedir(); + +module.exports = (stack, options) => { + options = Object.assign({pretty: false}, options); + + return stack.replace(/\\/g, '/') + .split('\n') + .filter(line => { + const pathMatches = line.match(extractPathRegex); + if (pathMatches === null || !pathMatches[1]) { + return true; + } + + const match = pathMatches[1]; + + // Electron + if ( + match.includes('.app/Contents/Resources/electron.asar') || + match.includes('.app/Contents/Resources/default_app.asar') + ) { + return false; + } + + return !pathRegex.test(match); + }) + .filter(line => line.trim() !== '') + .map(line => { + if (options.pretty) { + return line.replace(extractPathRegex, (m, p1) => m.replace(p1, p1.replace(homeDir, '~'))); + } + + return line; + }) + .join('\n'); +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/license b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/license new file mode 100644 index 000000000..e7af2f771 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/package.json new file mode 100644 index 000000000..719fdff55 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/package.json @@ -0,0 +1,39 @@ +{ + "name": "clean-stack", + "version": "2.2.0", + "description": "Clean up error stack traces", + "license": "MIT", + "repository": "sindresorhus/clean-stack", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=6" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "clean", + "stack", + "trace", + "traces", + "error", + "err", + "electron" + ], + "devDependencies": { + "ava": "^1.4.1", + "tsd": "^0.7.2", + "xo": "^0.24.0" + }, + "browser": { + "os": false + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/readme.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/readme.md new file mode 100644 index 000000000..8d4416046 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/clean-stack/readme.md @@ -0,0 +1,76 @@ +# clean-stack [![Build Status](https://travis-ci.org/sindresorhus/clean-stack.svg?branch=master)](https://travis-ci.org/sindresorhus/clean-stack) + +> Clean up error stack traces + +Removes the mostly unhelpful internal Node.js entries. + +Also works in Electron. + + +## Install + +``` +$ npm install clean-stack +``` + + +## Usage + +```js +const cleanStack = require('clean-stack'); + +const error = new Error('Missing unicorn'); + +console.log(error.stack); +/* +Error: Missing unicorn + at Object. (/Users/sindresorhus/dev/clean-stack/unicorn.js:2:15) + at Module._compile (module.js:409:26) + at Object.Module._extensions..js (module.js:416:10) + at Module.load (module.js:343:32) + at Function.Module._load (module.js:300:12) + at Function.Module.runMain (module.js:441:10) + at startup (node.js:139:18) +*/ + +console.log(cleanStack(error.stack)); +/* +Error: Missing unicorn + at Object. (/Users/sindresorhus/dev/clean-stack/unicorn.js:2:15) +*/ +``` + + +## API + +### cleanStack(stack, [options]) + +#### stack + +Type: `string` + +The `stack` property of an `Error`. + +#### options + +Type: `Object` + +##### pretty + +Type: `boolean`
    +Default: `false` + +Prettify the file paths in the stack: + +`/Users/sindresorhus/dev/clean-stack/unicorn.js:2:15` → `~/dev/clean-stack/unicorn.js:2:15` + + +## Related + +- [extrack-stack](https://github.com/sindresorhus/extract-stack) - Extract the actual stack of an error +- [stack-utils](https://github.com/tapjs/stack-utils) - Captures and cleans stack traces + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/LICENSE new file mode 100644 index 000000000..19129e315 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/README.md new file mode 100644 index 000000000..f89aa17d3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/README.md @@ -0,0 +1,129 @@ +# color-support + +A module which will endeavor to guess your terminal's level of color +support. + +[![Build Status](https://travis-ci.org/isaacs/color-support.svg?branch=master)](https://travis-ci.org/isaacs/color-support) [![Coverage Status](https://coveralls.io/repos/github/isaacs/color-support/badge.svg?branch=master)](https://coveralls.io/github/isaacs/color-support?branch=master) + +This is similar to `supports-color`, but it does not read +`process.argv`. + +1. If not in a node environment, not supported. + +2. If stdout is not a TTY, not supported, unless the `ignoreTTY` + option is set. + +3. If the `TERM` environ is `dumb`, not supported, unless the + `ignoreDumb` option is set. + +4. If on Windows, then support 16 colors. + +5. If using Tmux, then support 256 colors. + +7. Handle continuous-integration servers. If `CI` or + `TEAMCITY_VERSION` are set in the environment, and `TRAVIS` is not + set, then color is not supported, unless `ignoreCI` option is set. + +6. Guess based on the `TERM_PROGRAM` environ. These terminals support + 16m colors: + + - `iTerm.app` version 3.x supports 16m colors, below support 256 + - `MacTerm` supports 16m colors + - `Apple_Terminal` supports 256 colors + - Have more things that belong on this list? Send a PR! + +8. Make a guess based on the `TERM` environment variable. Any + `xterm-256color` will get 256 colors. Any screen, xterm, vt100, + color, ansi, cygwin, or linux `TERM` will get 16 colors. + +9. If `COLORTERM` environment variable is set, then support 16 colors. + +10. At this point, we assume that color is not supported. + +## USAGE + +```javascript +var testColorSupport = require('color-support') +var colorSupport = testColorSupport(/* options object */) + +if (!colorSupport) { + console.log('color is not supported') +} else if (colorSupport.has16m) { + console.log('\x1b[38;2;102;194;255m16m colors\x1b[0m') +} else if (colorSupport.has256) { + console.log('\x1b[38;5;119m256 colors\x1b[0m') +} else if (colorSupport.hasBasic) { + console.log('\x1b[31mbasic colors\x1b[0m') +} else { + console.log('this is impossible, but colors are not supported') +} +``` + +If you don't have any options to set, you can also just look at the +flags which will all be set on the test function itself. (Of course, +this doesn't return a falsey value when colors aren't supported, and +doesn't allow you to set options.) + +```javascript +var colorSupport = require('color-support') + +if (colorSupport.has16m) { + console.log('\x1b[38;2;102;194;255m16m colors\x1b[0m') +} else if (colorSupport.has256) { + console.log('\x1b[38;5;119m256 colors\x1b[0m') +} else if (colorSupport.hasBasic) { + console.log('\x1b[31mbasic colors\x1b[0m') +} else { + console.log('colors are not supported') +} +``` + +## Options + +You can pass in the following options. + +* ignoreTTY - default false. Ignore the `isTTY` check. +* ignoreDumb - default false. Ignore `TERM=dumb` environ check. +* ignoreCI - default false. Ignore `CI` environ check. +* env - Object for environment vars. Defaults to `process.env`. +* stream - Stream for `isTTY` check. Defaults to `process.stdout`. +* term - String for `TERM` checking. Defaults to `env.TERM`. +* alwaysReturn - default false. Return an object when colors aren't + supported (instead of returning `false`). +* level - A number from 0 to 3. This will return a result for the + specified level. This is useful if you want to be able to set the + color support level explicitly as a number in an environment + variable or config, but then use the object flags in your program. + Except for `alwaysReturn` to return an object for level 0, all other + options are ignored, since no checking is done if a level is + explicitly set. + +## Return Value + +If no color support is available, then `false` is returned by default, +unless the `alwaysReturn` flag is set to `true`. This is so that the +simple question of "can I use colors or not" can treat any truthy +return as "yes". + +Otherwise, the return object has the following fields: + +* `level` - A number from 0 to 3 + * `0` - No color support + * `1` - Basic (16) color support + * `2` - 256 color support + * `3` - 16 million (true) color support +* `hasBasic` - Boolean +* `has256` - Boolean +* `has16m` - Boolean + +## CLI + +You can run the `color-support` bin from the command line which will +just dump the values as this module calculates them in whatever env +it's run. It takes no command line arguments. + +## Credits + +This is a spiritual, if not actual, fork of +[supports-color](http://npm.im/supports-color) by the ever prolific +[Sindre Sorhus](http://npm.im/~sindresorhus). diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/bin.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/bin.js new file mode 100644 index 000000000..3c0a96721 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/bin.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node +var colorSupport = require('./')({alwaysReturn: true }) +console.log(JSON.stringify(colorSupport, null, 2)) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/browser.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/browser.js new file mode 100644 index 000000000..ab5c6631a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/browser.js @@ -0,0 +1,14 @@ +module.exports = colorSupport({ alwaysReturn: true }, colorSupport) + +function colorSupport(options, obj) { + obj = obj || {} + options = options || {} + obj.level = 0 + obj.hasBasic = false + obj.has256 = false + obj.has16m = false + if (!options.alwaysReturn) { + return false + } + return obj +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/index.js new file mode 100644 index 000000000..6b6f3b281 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/index.js @@ -0,0 +1,134 @@ +// call it on itself so we can test the export val for basic stuff +module.exports = colorSupport({ alwaysReturn: true }, colorSupport) + +function hasNone (obj, options) { + obj.level = 0 + obj.hasBasic = false + obj.has256 = false + obj.has16m = false + if (!options.alwaysReturn) { + return false + } + return obj +} + +function hasBasic (obj) { + obj.hasBasic = true + obj.has256 = false + obj.has16m = false + obj.level = 1 + return obj +} + +function has256 (obj) { + obj.hasBasic = true + obj.has256 = true + obj.has16m = false + obj.level = 2 + return obj +} + +function has16m (obj) { + obj.hasBasic = true + obj.has256 = true + obj.has16m = true + obj.level = 3 + return obj +} + +function colorSupport (options, obj) { + options = options || {} + + obj = obj || {} + + // if just requesting a specific level, then return that. + if (typeof options.level === 'number') { + switch (options.level) { + case 0: + return hasNone(obj, options) + case 1: + return hasBasic(obj) + case 2: + return has256(obj) + case 3: + return has16m(obj) + } + } + + obj.level = 0 + obj.hasBasic = false + obj.has256 = false + obj.has16m = false + + if (typeof process === 'undefined' || + !process || + !process.stdout || + !process.env || + !process.platform) { + return hasNone(obj, options) + } + + var env = options.env || process.env + var stream = options.stream || process.stdout + var term = options.term || env.TERM || '' + var platform = options.platform || process.platform + + if (!options.ignoreTTY && !stream.isTTY) { + return hasNone(obj, options) + } + + if (!options.ignoreDumb && term === 'dumb' && !env.COLORTERM) { + return hasNone(obj, options) + } + + if (platform === 'win32') { + return hasBasic(obj) + } + + if (env.TMUX) { + return has256(obj) + } + + if (!options.ignoreCI && (env.CI || env.TEAMCITY_VERSION)) { + if (env.TRAVIS) { + return has256(obj) + } else { + return hasNone(obj, options) + } + } + + // TODO: add more term programs + switch (env.TERM_PROGRAM) { + case 'iTerm.app': + var ver = env.TERM_PROGRAM_VERSION || '0.' + if (/^[0-2]\./.test(ver)) { + return has256(obj) + } else { + return has16m(obj) + } + + case 'HyperTerm': + case 'Hyper': + return has16m(obj) + + case 'MacTerm': + return has16m(obj) + + case 'Apple_Terminal': + return has256(obj) + } + + if (/^xterm-256/.test(term)) { + return has256(obj) + } + + if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(term)) { + return hasBasic(obj) + } + + if (env.COLORTERM) { + return hasBasic(obj) + } + + return hasNone(obj, options) +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/package.json new file mode 100644 index 000000000..f3e3b7714 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/color-support/package.json @@ -0,0 +1,36 @@ +{ + "name": "color-support", + "version": "1.1.3", + "description": "A module which will endeavor to guess your terminal's level of color support.", + "main": "index.js", + "browser": "browser.js", + "bin": "bin.js", + "devDependencies": { + "tap": "^10.3.3" + }, + "scripts": { + "test": "tap test/*.js --100 -J", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --all; git push origin --tags" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/isaacs/color-support.git" + }, + "keywords": [ + "terminal", + "color", + "support", + "xterm", + "truecolor", + "256" + ], + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "license": "ISC", + "files": [ + "browser.js", + "index.js", + "bin.js" + ] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/LICENSE.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/LICENSE.md new file mode 100644 index 000000000..6ba7a0fbb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/LICENSE.md @@ -0,0 +1,7 @@ +Copyright © Jorge Bucaran <> + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/README.md new file mode 100644 index 000000000..693ae44d1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/README.md @@ -0,0 +1,134 @@ +# 🌈Colorette + +> Easily set your terminal text color & styles. + +- No dependecies +- Automatic color support detection +- Up to [2x faster](#benchmarks) than alternatives +- TypeScript support +- [`NO_COLOR`](https://no-color.org) friendly +- Node >= `10` + +> [**Upgrading from Colorette `1.x`?**](https://github.com/jorgebucaran/colorette/issues/70) + +## Quickstart + +```js +import { blue, bold, underline } from "colorette" + +console.log( + blue("I'm blue"), + bold(blue("da ba dee")), + underline(bold(blue("da ba daa"))) +) +``` + +Here's an example using [template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals). + +```js +console.log(` + There's a ${underline(blue("house"))}, + With a ${bold(blue("window"))}, + And a ${blue("corvette")} + And everything is blue +`) +``` + +You can also nest styles without breaking existing color sequences. + +```js +console.log(bold(`I'm ${blue(`da ba ${underline("dee")} da ba`)} daa`)) +``` + +Need to override terminal color detection? You can do that too. + +```js +import { createColors } from "colorette" + +const { blue } = createColors({ useColor: false }) + +console.log(blue("Blue? Nope, nah")) +``` + +## Installation + +```console +npm install colorette +``` + +## API + +### \() + +> See all [supported colors](#supported-colors). + +```js +import { blue } from "colorette" + +blue("I'm blue") //=> \x1b[34mI'm blue\x1b[39m +``` + +### createColors() + +Override terminal color detection via `createColors({ useColor })`. + +```js +import { createColors } from "colorette" + +const { blue } = createColors({ useColor: false }) +``` + +### isColorSupported + +`true` if your terminal supports color, `false` otherwise. Used internally, but exposed for convenience. + +## Environment + +You can override color detection from the CLI by setting the `--no-color` or `--color` flags. + +```console +$ ./example.js --no-color | ./consumer.js +``` + +Or if you can't use CLI flags, by setting the `NO_COLOR=` or `FORCE_COLOR=` environment variables. + +```console +$ NO_COLOR= ./example.js | ./consumer.js +``` + +## Supported colors + +| Colors | Background Colors | Bright Colors | Bright Background Colors | Modifiers | +| ------- | ----------------- | ------------- | ------------------------ | ----------------- | +| black | bgBlack | blackBright | bgBlackBright | dim | +| red | bgRed | redBright | bgRedBright | **bold** | +| green | bgGreen | greenBright | bgGreenBright | hidden | +| yellow | bgYellow | yellowBright | bgYellowBright | _italic_ | +| blue | bgBlue | blueBright | bgBlueBright | underline | +| magenta | bgMagenta | magentaBright | bgMagentaBright | ~~strikethrough~~ | +| cyan | bgCyan | cyanBright | bgCyanBright | reset | +| white | bgWhite | whiteBright | bgWhiteBright | | +| gray | | | | | + +## [Benchmarks](https://github.com/jorgebucaran/colorette/actions/workflows/bench.yml) + +```console +npm --prefix bench start +``` + +```diff + chalk 1,786,703 ops/sec + kleur 1,618,960 ops/sec + colors 646,823 ops/sec + ansi-colors 786,149 ops/sec + picocolors 2,871,758 ops/sec ++ colorette 3,002,751 ops/sec +``` + +## Acknowledgments + +Colorette started out in 2015 by [@jorgebucaran](https://github.com/jorgebucaran) as a lightweight alternative to [Chalk](https://github.com/chalk/chalk) and was introduced originally as [Clor](https://github.com/jorgebucaran/colorette/commit/b01b5b9961ceb7df878583a3002e836fae9e37ce). Our terminal color detection logic borrows heavily from [@sindresorhus](https://github.com/sindresorhus) and [@Qix-](https://github.com/Qix-) work on Chalk. The idea of slicing strings to clear bleeding sequences was adapted from a similar technique used by [@alexeyraspopov](https://github.com/alexeyraspopov) in [picocolors](https://github.com/alexeyraspopov/picocolors). Thank you to all our contributors! <3 + +## License + +[MIT](LICENSE.md) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/index.cjs b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/index.cjs new file mode 100644 index 000000000..baf0e6434 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/index.cjs @@ -0,0 +1,218 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +var tty = require('tty'); + +function _interopNamespace(e) { + if (e && e.__esModule) return e; + var n = Object.create(null); + if (e) { + Object.keys(e).forEach(function (k) { + if (k !== 'default') { + var d = Object.getOwnPropertyDescriptor(e, k); + Object.defineProperty(n, k, d.get ? d : { + enumerable: true, + get: function () { return e[k]; } + }); + } + }); + } + n["default"] = e; + return Object.freeze(n); +} + +var tty__namespace = /*#__PURE__*/_interopNamespace(tty); + +const { + env = {}, + argv = [], + platform = "", +} = typeof process === "undefined" ? {} : process; + +const isDisabled = "NO_COLOR" in env || argv.includes("--no-color"); +const isForced = "FORCE_COLOR" in env || argv.includes("--color"); +const isWindows = platform === "win32"; +const isDumbTerminal = env.TERM === "dumb"; + +const isCompatibleTerminal = + tty__namespace && tty__namespace.isatty && tty__namespace.isatty(1) && env.TERM && !isDumbTerminal; + +const isCI = + "CI" in env && + ("GITHUB_ACTIONS" in env || "GITLAB_CI" in env || "CIRCLECI" in env); + +const isColorSupported = + !isDisabled && + (isForced || (isWindows && !isDumbTerminal) || isCompatibleTerminal || isCI); + +const replaceClose = ( + index, + string, + close, + replace, + head = string.substring(0, index) + replace, + tail = string.substring(index + close.length), + next = tail.indexOf(close) +) => head + (next < 0 ? tail : replaceClose(next, tail, close, replace)); + +const clearBleed = (index, string, open, close, replace) => + index < 0 + ? open + string + close + : open + replaceClose(index, string, close, replace) + close; + +const filterEmpty = + (open, close, replace = open, at = open.length + 1) => + (string) => + string || !(string === "" || string === undefined) + ? clearBleed( + ("" + string).indexOf(close, at), + string, + open, + close, + replace + ) + : ""; + +const init = (open, close, replace) => + filterEmpty(`\x1b[${open}m`, `\x1b[${close}m`, replace); + +const colors = { + reset: init(0, 0), + bold: init(1, 22, "\x1b[22m\x1b[1m"), + dim: init(2, 22, "\x1b[22m\x1b[2m"), + italic: init(3, 23), + underline: init(4, 24), + inverse: init(7, 27), + hidden: init(8, 28), + strikethrough: init(9, 29), + black: init(30, 39), + red: init(31, 39), + green: init(32, 39), + yellow: init(33, 39), + blue: init(34, 39), + magenta: init(35, 39), + cyan: init(36, 39), + white: init(37, 39), + gray: init(90, 39), + bgBlack: init(40, 49), + bgRed: init(41, 49), + bgGreen: init(42, 49), + bgYellow: init(43, 49), + bgBlue: init(44, 49), + bgMagenta: init(45, 49), + bgCyan: init(46, 49), + bgWhite: init(47, 49), + blackBright: init(90, 39), + redBright: init(91, 39), + greenBright: init(92, 39), + yellowBright: init(93, 39), + blueBright: init(94, 39), + magentaBright: init(95, 39), + cyanBright: init(96, 39), + whiteBright: init(97, 39), + bgBlackBright: init(100, 49), + bgRedBright: init(101, 49), + bgGreenBright: init(102, 49), + bgYellowBright: init(103, 49), + bgBlueBright: init(104, 49), + bgMagentaBright: init(105, 49), + bgCyanBright: init(106, 49), + bgWhiteBright: init(107, 49), +}; + +const createColors = ({ useColor = isColorSupported } = {}) => + useColor + ? colors + : Object.keys(colors).reduce( + (colors, key) => ({ ...colors, [key]: String }), + {} + ); + +const { + reset, + bold, + dim, + italic, + underline, + inverse, + hidden, + strikethrough, + black, + red, + green, + yellow, + blue, + magenta, + cyan, + white, + gray, + bgBlack, + bgRed, + bgGreen, + bgYellow, + bgBlue, + bgMagenta, + bgCyan, + bgWhite, + blackBright, + redBright, + greenBright, + yellowBright, + blueBright, + magentaBright, + cyanBright, + whiteBright, + bgBlackBright, + bgRedBright, + bgGreenBright, + bgYellowBright, + bgBlueBright, + bgMagentaBright, + bgCyanBright, + bgWhiteBright, +} = createColors(); + +exports.bgBlack = bgBlack; +exports.bgBlackBright = bgBlackBright; +exports.bgBlue = bgBlue; +exports.bgBlueBright = bgBlueBright; +exports.bgCyan = bgCyan; +exports.bgCyanBright = bgCyanBright; +exports.bgGreen = bgGreen; +exports.bgGreenBright = bgGreenBright; +exports.bgMagenta = bgMagenta; +exports.bgMagentaBright = bgMagentaBright; +exports.bgRed = bgRed; +exports.bgRedBright = bgRedBright; +exports.bgWhite = bgWhite; +exports.bgWhiteBright = bgWhiteBright; +exports.bgYellow = bgYellow; +exports.bgYellowBright = bgYellowBright; +exports.black = black; +exports.blackBright = blackBright; +exports.blue = blue; +exports.blueBright = blueBright; +exports.bold = bold; +exports.createColors = createColors; +exports.cyan = cyan; +exports.cyanBright = cyanBright; +exports.dim = dim; +exports.gray = gray; +exports.green = green; +exports.greenBright = greenBright; +exports.hidden = hidden; +exports.inverse = inverse; +exports.isColorSupported = isColorSupported; +exports.italic = italic; +exports.magenta = magenta; +exports.magentaBright = magentaBright; +exports.red = red; +exports.redBright = redBright; +exports.reset = reset; +exports.strikethrough = strikethrough; +exports.underline = underline; +exports.white = white; +exports.whiteBright = whiteBright; +exports.yellow = yellow; +exports.yellowBright = yellowBright; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/index.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/index.d.ts new file mode 100644 index 000000000..ba32c9f34 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/index.d.ts @@ -0,0 +1,93 @@ +declare module "colorette" { + type Color = (text: string | number) => string + + interface Colorette { + reset: Color + bold: Color + dim: Color + italic: Color + underline: Color + inverse: Color + hidden: Color + strikethrough: Color + black: Color + red: Color + green: Color + yellow: Color + blue: Color + magenta: Color + cyan: Color + white: Color + gray: Color + bgBlack: Color + bgRed: Color + bgGreen: Color + bgYellow: Color + bgBlue: Color + bgMagenta: Color + bgCyan: Color + bgWhite: Color + blackBright: Color + redBright: Color + greenBright: Color + yellowBright: Color + blueBright: Color + magentaBright: Color + cyanBright: Color + whiteBright: Color + bgBlackBright: Color + bgRedBright: Color + bgGreenBright: Color + bgYellowBright: Color + bgBlueBright: Color + bgMagentaBright: Color + bgCyanBright: Color + bgWhiteBright: Color + } + + const reset: Color + const bold: Color + const dim: Color + const italic: Color + const underline: Color + const inverse: Color + const hidden: Color + const strikethrough: Color + const black: Color + const red: Color + const green: Color + const yellow: Color + const blue: Color + const magenta: Color + const cyan: Color + const white: Color + const gray: Color + const bgBlack: Color + const bgRed: Color + const bgGreen: Color + const bgYellow: Color + const bgBlue: Color + const bgMagenta: Color + const bgCyan: Color + const bgWhite: Color + const blackBright: Color + const redBright: Color + const greenBright: Color + const yellowBright: Color + const blueBright: Color + const magentaBright: Color + const cyanBright: Color + const whiteBright: Color + const bgBlackBright: Color + const bgRedBright: Color + const bgGreenBright: Color + const bgYellowBright: Color + const bgBlueBright: Color + const bgMagentaBright: Color + const bgCyanBright: Color + const bgWhiteBright: Color + + const isColorSupported: boolean + + function createColors(options?: { useColor: boolean }): Colorette +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/index.js new file mode 100644 index 000000000..0d64e6b3c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/index.js @@ -0,0 +1,150 @@ +import * as tty from "tty" + +const { + env = {}, + argv = [], + platform = "", +} = typeof process === "undefined" ? {} : process + +const isDisabled = "NO_COLOR" in env || argv.includes("--no-color") +const isForced = "FORCE_COLOR" in env || argv.includes("--color") +const isWindows = platform === "win32" +const isDumbTerminal = env.TERM === "dumb" + +const isCompatibleTerminal = + tty && tty.isatty && tty.isatty(1) && env.TERM && !isDumbTerminal + +const isCI = + "CI" in env && + ("GITHUB_ACTIONS" in env || "GITLAB_CI" in env || "CIRCLECI" in env) + +export const isColorSupported = + !isDisabled && + (isForced || (isWindows && !isDumbTerminal) || isCompatibleTerminal || isCI) + +const replaceClose = ( + index, + string, + close, + replace, + head = string.substring(0, index) + replace, + tail = string.substring(index + close.length), + next = tail.indexOf(close) +) => head + (next < 0 ? tail : replaceClose(next, tail, close, replace)) + +const clearBleed = (index, string, open, close, replace) => + index < 0 + ? open + string + close + : open + replaceClose(index, string, close, replace) + close + +const filterEmpty = + (open, close, replace = open, at = open.length + 1) => + (string) => + string || !(string === "" || string === undefined) + ? clearBleed( + ("" + string).indexOf(close, at), + string, + open, + close, + replace + ) + : "" + +const init = (open, close, replace) => + filterEmpty(`\x1b[${open}m`, `\x1b[${close}m`, replace) + +const colors = { + reset: init(0, 0), + bold: init(1, 22, "\x1b[22m\x1b[1m"), + dim: init(2, 22, "\x1b[22m\x1b[2m"), + italic: init(3, 23), + underline: init(4, 24), + inverse: init(7, 27), + hidden: init(8, 28), + strikethrough: init(9, 29), + black: init(30, 39), + red: init(31, 39), + green: init(32, 39), + yellow: init(33, 39), + blue: init(34, 39), + magenta: init(35, 39), + cyan: init(36, 39), + white: init(37, 39), + gray: init(90, 39), + bgBlack: init(40, 49), + bgRed: init(41, 49), + bgGreen: init(42, 49), + bgYellow: init(43, 49), + bgBlue: init(44, 49), + bgMagenta: init(45, 49), + bgCyan: init(46, 49), + bgWhite: init(47, 49), + blackBright: init(90, 39), + redBright: init(91, 39), + greenBright: init(92, 39), + yellowBright: init(93, 39), + blueBright: init(94, 39), + magentaBright: init(95, 39), + cyanBright: init(96, 39), + whiteBright: init(97, 39), + bgBlackBright: init(100, 49), + bgRedBright: init(101, 49), + bgGreenBright: init(102, 49), + bgYellowBright: init(103, 49), + bgBlueBright: init(104, 49), + bgMagentaBright: init(105, 49), + bgCyanBright: init(106, 49), + bgWhiteBright: init(107, 49), +} + +export const createColors = ({ useColor = isColorSupported } = {}) => + useColor + ? colors + : Object.keys(colors).reduce( + (colors, key) => ({ ...colors, [key]: String }), + {} + ) + +export const { + reset, + bold, + dim, + italic, + underline, + inverse, + hidden, + strikethrough, + black, + red, + green, + yellow, + blue, + magenta, + cyan, + white, + gray, + bgBlack, + bgRed, + bgGreen, + bgYellow, + bgBlue, + bgMagenta, + bgCyan, + bgWhite, + blackBright, + redBright, + greenBright, + yellowBright, + blueBright, + magentaBright, + cyanBright, + whiteBright, + bgBlackBright, + bgRedBright, + bgGreenBright, + bgYellowBright, + bgBlueBright, + bgMagentaBright, + bgCyanBright, + bgWhiteBright, +} = createColors() diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/package.json new file mode 100644 index 000000000..ab90f9d4e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/colorette/package.json @@ -0,0 +1,39 @@ +{ + "name": "colorette", + "version": "2.0.19", + "type": "module", + "main": "index.cjs", + "module": "index.js", + "types": "index.d.ts", + "description": "🌈Easily set your terminal text color & styles.", + "repository": "jorgebucaran/colorette", + "license": "MIT", + "exports": { + "./package.json": "./package.json", + ".": { + "require": "./index.cjs", + "import": "./index.js" + } + }, + "files": [ + "*.*(c)[tj]s*" + ], + "author": "Jorge Bucaran", + "keywords": [ + "terminal", + "styles", + "color", + "ansi" + ], + "scripts": { + "test": "c8 twist tests/*.js", + "build": "npx rollup --format cjs --input index.js --file index.cjs", + "deploy": "npm test && git commit --all --message $tag && git tag --sign $tag --message $tag && git push && git push --tags", + "release": "tag=$npm_package_version npm run deploy && npm publish --access public", + "prepare": "npm run build" + }, + "devDependencies": { + "c8": "*", + "twist": "*" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/LICENSE new file mode 100644 index 000000000..10f997ab1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2011 TJ Holowaychuk + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/Readme.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/Readme.md new file mode 100644 index 000000000..095e2aefb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/commander/Readme.md @@ -0,0 +1,1134 @@ +# Commander.js + +[![Build Status](https://github.com/tj/commander.js/workflows/build/badge.svg)](https://github.com/tj/commander.js/actions?query=workflow%3A%22build%22) +[![NPM Version](http://img.shields.io/npm/v/commander.svg?style=flat)](https://www.npmjs.org/package/commander) +[![NPM Downloads](https://img.shields.io/npm/dm/commander.svg?style=flat)](https://npmcharts.com/compare/commander?minimal=true) +[![Install Size](https://packagephobia.now.sh/badge?p=commander)](https://packagephobia.now.sh/result?p=commander) + +The complete solution for [node.js](http://nodejs.org) command-line interfaces. + +Read this in other languages: English | [简体中文](./Readme_zh-CN.md) + +- [Commander.js](#commanderjs) + - [Installation](#installation) + - [Quick Start](#quick-start) + - [Declaring _program_ variable](#declaring-program-variable) + - [Options](#options) + - [Common option types, boolean and value](#common-option-types-boolean-and-value) + - [Default option value](#default-option-value) + - [Other option types, negatable boolean and boolean|value](#other-option-types-negatable-boolean-and-booleanvalue) + - [Required option](#required-option) + - [Variadic option](#variadic-option) + - [Version option](#version-option) + - [More configuration](#more-configuration) + - [Custom option processing](#custom-option-processing) + - [Commands](#commands) + - [Command-arguments](#command-arguments) + - [More configuration](#more-configuration-1) + - [Custom argument processing](#custom-argument-processing) + - [Action handler](#action-handler) + - [Stand-alone executable (sub)commands](#stand-alone-executable-subcommands) + - [Life cycle hooks](#life-cycle-hooks) + - [Automated help](#automated-help) + - [Custom help](#custom-help) + - [Display help after errors](#display-help-after-errors) + - [Display help from code](#display-help-from-code) + - [.name](#name) + - [.usage](#usage) + - [.description and .summary](#description-and-summary) + - [.helpOption(flags, description)](#helpoptionflags-description) + - [.addHelpCommand()](#addhelpcommand) + - [More configuration](#more-configuration-2) + - [Custom event listeners](#custom-event-listeners) + - [Bits and pieces](#bits-and-pieces) + - [.parse() and .parseAsync()](#parse-and-parseasync) + - [Parsing Configuration](#parsing-configuration) + - [Legacy options as properties](#legacy-options-as-properties) + - [TypeScript](#typescript) + - [createCommand()](#createcommand) + - [Node options such as `--harmony`](#node-options-such-as---harmony) + - [Debugging stand-alone executable subcommands](#debugging-stand-alone-executable-subcommands) + - [Display error](#display-error) + - [Override exit and output handling](#override-exit-and-output-handling) + - [Additional documentation](#additional-documentation) + - [Support](#support) + - [Commander for enterprise](#commander-for-enterprise) + +For information about terms used in this document see: [terminology](./docs/terminology.md) + +## Installation + +```sh +npm install commander +``` + +## Quick Start + +You write code to describe your command line interface. +Commander looks after parsing the arguments into options and command-arguments, +displays usage errors for problems, and implements a help system. + +Commander is strict and displays an error for unrecognised options. +The two most used option types are a boolean option, and an option which takes its value from the following argument. + +Example file: [split.js](./examples/split.js) + +```js +const { program } = require('commander'); + +program + .option('--first') + .option('-s, --separator '); + +program.parse(); + +const options = program.opts(); +const limit = options.first ? 1 : undefined; +console.log(program.args[0].split(options.separator, limit)); +``` + +```console +$ node split.js -s / --fits a/b/c +error: unknown option '--fits' +(Did you mean --first?) +$ node split.js -s / --first a/b/c +[ 'a' ] +``` + +Here is a more complete program using a subcommand and with descriptions for the help. In a multi-command program, you have an action handler for each command (or stand-alone executables for the commands). + +Example file: [string-util.js](./examples/string-util.js) + +```js +const { Command } = require('commander'); +const program = new Command(); + +program + .name('string-util') + .description('CLI to some JavaScript string utilities') + .version('0.8.0'); + +program.command('split') + .description('Split a string into substrings and display as an array') + .argument('', 'string to split') + .option('--first', 'display just the first substring') + .option('-s, --separator ', 'separator character', ',') + .action((str, options) => { + const limit = options.first ? 1 : undefined; + console.log(str.split(options.separator, limit)); + }); + +program.parse(); +``` + +```console +$ node string-util.js help split +Usage: string-util split [options] + +Split a string into substrings and display as an array. + +Arguments: + string string to split + +Options: + --first display just the first substring + -s, --separator separator character (default: ",") + -h, --help display help for command + +$ node string-util.js split --separator=/ a/b/c +[ 'a', 'b', 'c' ] +``` + +More samples can be found in the [examples](https://github.com/tj/commander.js/tree/master/examples) directory. + +## Declaring _program_ variable + +Commander exports a global object which is convenient for quick programs. +This is used in the examples in this README for brevity. + +```js +// CommonJS (.cjs) +const { program } = require('commander'); +``` + +For larger programs which may use commander in multiple ways, including unit testing, it is better to create a local Command object to use. + +```js +// CommonJS (.cjs) +const { Command } = require('commander'); +const program = new Command(); +``` + +```js +// ECMAScript (.mjs) +import { Command } from 'commander'; +const program = new Command(); +``` + +```ts +// TypeScript (.ts) +import { Command } from 'commander'; +const program = new Command(); +``` + +## Options + +Options are defined with the `.option()` method, also serving as documentation for the options. Each option can have a short flag (single character) and a long name, separated by a comma or space or vertical bar ('|'). + +The parsed options can be accessed by calling `.opts()` on a `Command` object, and are passed to the action handler. + +Multi-word options such as "--template-engine" are camel-cased, becoming `program.opts().templateEngine` etc. + +An option and its option-argument can be separated by a space, or combined into the same argument. The option-argument can follow the short option directly or follow an `=` for a long option. + +```sh +serve -p 80 +serve -p80 +serve --port 80 +serve --port=80 +``` + +You can use `--` to indicate the end of the options, and any remaining arguments will be used without being interpreted. + +By default options on the command line are not positional, and can be specified before or after other arguments. + +There are additional related routines for when `.opts()` is not enough: + +- `.optsWithGlobals()` returns merged local and global option values +- `.getOptionValue()` and `.setOptionValue()` work with a single option value +- `.getOptionValueSource()` and `.setOptionValueWithSource()` include where the option value came from + +### Common option types, boolean and value + +The two most used option types are a boolean option, and an option which takes its value +from the following argument (declared with angle brackets like `--expect `). Both are `undefined` unless specified on command line. + +Example file: [options-common.js](./examples/options-common.js) + +```js +program + .option('-d, --debug', 'output extra debugging') + .option('-s, --small', 'small pizza size') + .option('-p, --pizza-type ', 'flavour of pizza'); + +program.parse(process.argv); + +const options = program.opts(); +if (options.debug) console.log(options); +console.log('pizza details:'); +if (options.small) console.log('- small pizza size'); +if (options.pizzaType) console.log(`- ${options.pizzaType}`); +``` + +```console +$ pizza-options -p +error: option '-p, --pizza-type ' argument missing +$ pizza-options -d -s -p vegetarian +{ debug: true, small: true, pizzaType: 'vegetarian' } +pizza details: +- small pizza size +- vegetarian +$ pizza-options --pizza-type=cheese +pizza details: +- cheese +``` + +Multiple boolean short options may be combined together following the dash, and may be followed by a single short option taking a value. +For example `-d -s -p cheese` may be written as `-ds -p cheese` or even `-dsp cheese`. + +Options with an expected option-argument are greedy and will consume the following argument whatever the value. +So `--id -xyz` reads `-xyz` as the option-argument. + +`program.parse(arguments)` processes the arguments, leaving any args not consumed by the program options in the `program.args` array. The parameter is optional and defaults to `process.argv`. + +### Default option value + +You can specify a default value for an option. + +Example file: [options-defaults.js](./examples/options-defaults.js) + +```js +program + .option('-c, --cheese ', 'add the specified type of cheese', 'blue'); + +program.parse(); + +console.log(`cheese: ${program.opts().cheese}`); +``` + +```console +$ pizza-options +cheese: blue +$ pizza-options --cheese stilton +cheese: stilton +``` + +### Other option types, negatable boolean and boolean|value + +You can define a boolean option long name with a leading `no-` to set the option value to false when used. +Defined alone this also makes the option true by default. + +If you define `--foo` first, adding `--no-foo` does not change the default value from what it would +otherwise be. + +Example file: [options-negatable.js](./examples/options-negatable.js) + +```js +program + .option('--no-sauce', 'Remove sauce') + .option('--cheese ', 'cheese flavour', 'mozzarella') + .option('--no-cheese', 'plain with no cheese') + .parse(); + +const options = program.opts(); +const sauceStr = options.sauce ? 'sauce' : 'no sauce'; +const cheeseStr = (options.cheese === false) ? 'no cheese' : `${options.cheese} cheese`; +console.log(`You ordered a pizza with ${sauceStr} and ${cheeseStr}`); +``` + +```console +$ pizza-options +You ordered a pizza with sauce and mozzarella cheese +$ pizza-options --sauce +error: unknown option '--sauce' +$ pizza-options --cheese=blue +You ordered a pizza with sauce and blue cheese +$ pizza-options --no-sauce --no-cheese +You ordered a pizza with no sauce and no cheese +``` + +You can specify an option which may be used as a boolean option but may optionally take an option-argument +(declared with square brackets like `--optional [value]`). + +Example file: [options-boolean-or-value.js](./examples/options-boolean-or-value.js) + +```js +program + .option('-c, --cheese [type]', 'Add cheese with optional type'); + +program.parse(process.argv); + +const options = program.opts(); +if (options.cheese === undefined) console.log('no cheese'); +else if (options.cheese === true) console.log('add cheese'); +else console.log(`add cheese type ${options.cheese}`); +``` + +```console +$ pizza-options +no cheese +$ pizza-options --cheese +add cheese +$ pizza-options --cheese mozzarella +add cheese type mozzarella +``` + +Options with an optional option-argument are not greedy and will ignore arguments starting with a dash. +So `id` behaves as a boolean option for `--id -5`, but you can use a combined form if needed like `--id=-5`. + +For information about possible ambiguous cases, see [options taking varying arguments](./docs/options-taking-varying-arguments.md). + +### Required option + +You may specify a required (mandatory) option using `.requiredOption()`. The option must have a value after parsing, usually specified on the command line, or perhaps from a default value (say from environment). The method is otherwise the same as `.option()` in format, taking flags and description, and optional default value or custom processing. + +Example file: [options-required.js](./examples/options-required.js) + +```js +program + .requiredOption('-c, --cheese ', 'pizza must have cheese'); + +program.parse(); +``` + +```console +$ pizza +error: required option '-c, --cheese ' not specified +``` + +### Variadic option + +You may make an option variadic by appending `...` to the value placeholder when declaring the option. On the command line you +can then specify multiple option-arguments, and the parsed option value will be an array. The extra arguments +are read until the first argument starting with a dash. The special argument `--` stops option processing entirely. If a value +is specified in the same argument as the option then no further values are read. + +Example file: [options-variadic.js](./examples/options-variadic.js) + +```js +program + .option('-n, --number ', 'specify numbers') + .option('-l, --letter [letters...]', 'specify letters'); + +program.parse(); + +console.log('Options: ', program.opts()); +console.log('Remaining arguments: ', program.args); +``` + +```console +$ collect -n 1 2 3 --letter a b c +Options: { number: [ '1', '2', '3' ], letter: [ 'a', 'b', 'c' ] } +Remaining arguments: [] +$ collect --letter=A -n80 operand +Options: { number: [ '80' ], letter: [ 'A' ] } +Remaining arguments: [ 'operand' ] +$ collect --letter -n 1 -n 2 3 -- operand +Options: { number: [ '1', '2', '3' ], letter: true } +Remaining arguments: [ 'operand' ] +``` + +For information about possible ambiguous cases, see [options taking varying arguments](./docs/options-taking-varying-arguments.md). + +### Version option + +The optional `version` method adds handling for displaying the command version. The default option flags are `-V` and `--version`, and when present the command prints the version number and exits. + +```js +program.version('0.0.1'); +``` + +```console +$ ./examples/pizza -V +0.0.1 +``` + +You may change the flags and description by passing additional parameters to the `version` method, using +the same syntax for flags as the `option` method. + +```js +program.version('0.0.1', '-v, --vers', 'output the current version'); +``` + +### More configuration + +You can add most options using the `.option()` method, but there are some additional features available +by constructing an `Option` explicitly for less common cases. + +Example files: [options-extra.js](./examples/options-extra.js), [options-env.js](./examples/options-env.js), [options-conflicts.js](./examples/options-conflicts.js), [options-implies.js](./examples/options-implies.js) + +```js +program + .addOption(new Option('-s, --secret').hideHelp()) + .addOption(new Option('-t, --timeout ', 'timeout in seconds').default(60, 'one minute')) + .addOption(new Option('-d, --drink ', 'drink size').choices(['small', 'medium', 'large'])) + .addOption(new Option('-p, --port ', 'port number').env('PORT')) + .addOption(new Option('--donate [amount]', 'optional donation in dollars').preset('20').argParser(parseFloat)) + .addOption(new Option('--disable-server', 'disables the server').conflicts('port')) + .addOption(new Option('--free-drink', 'small drink included free ').implies({ drink: 'small' })); +``` + +```console +$ extra --help +Usage: help [options] + +Options: + -t, --timeout timeout in seconds (default: one minute) + -d, --drink drink cup size (choices: "small", "medium", "large") + -p, --port port number (env: PORT) + --donate [amount] optional donation in dollars (preset: "20") + --disable-server disables the server + --free-drink small drink included free + -h, --help display help for command + +$ extra --drink huge +error: option '-d, --drink ' argument 'huge' is invalid. Allowed choices are small, medium, large. + +$ PORT=80 extra --donate --free-drink +Options: { timeout: 60, donate: 20, port: '80', freeDrink: true, drink: 'small' } + +$ extra --disable-server --port 8000 +error: option '--disable-server' cannot be used with option '-p, --port ' +``` + +Specify a required (mandatory) option using the `Option` method `.makeOptionMandatory()`. This matches the `Command` method [.requiredOption()](#required-option). + +### Custom option processing + +You may specify a function to do custom processing of option-arguments. The callback function receives two parameters, +the user specified option-argument and the previous value for the option. It returns the new value for the option. + +This allows you to coerce the option-argument to the desired type, or accumulate values, or do entirely custom processing. + +You can optionally specify the default/starting value for the option after the function parameter. + +Example file: [options-custom-processing.js](./examples/options-custom-processing.js) + +```js +function myParseInt(value, dummyPrevious) { + // parseInt takes a string and a radix + const parsedValue = parseInt(value, 10); + if (isNaN(parsedValue)) { + throw new commander.InvalidArgumentError('Not a number.'); + } + return parsedValue; +} + +function increaseVerbosity(dummyValue, previous) { + return previous + 1; +} + +function collect(value, previous) { + return previous.concat([value]); +} + +function commaSeparatedList(value, dummyPrevious) { + return value.split(','); +} + +program + .option('-f, --float ', 'float argument', parseFloat) + .option('-i, --integer ', 'integer argument', myParseInt) + .option('-v, --verbose', 'verbosity that can be increased', increaseVerbosity, 0) + .option('-c, --collect ', 'repeatable value', collect, []) + .option('-l, --list ', 'comma separated list', commaSeparatedList) +; + +program.parse(); + +const options = program.opts(); +if (options.float !== undefined) console.log(`float: ${options.float}`); +if (options.integer !== undefined) console.log(`integer: ${options.integer}`); +if (options.verbose > 0) console.log(`verbosity: ${options.verbose}`); +if (options.collect.length > 0) console.log(options.collect); +if (options.list !== undefined) console.log(options.list); +``` + +```console +$ custom -f 1e2 +float: 100 +$ custom --integer 2 +integer: 2 +$ custom -v -v -v +verbose: 3 +$ custom -c a -c b -c c +[ 'a', 'b', 'c' ] +$ custom --list x,y,z +[ 'x', 'y', 'z' ] +``` + +## Commands + +You can specify (sub)commands using `.command()` or `.addCommand()`. There are two ways these can be implemented: using an action handler attached to the command, or as a stand-alone executable file (described in more detail later). The subcommands may be nested ([example](./examples/nestedCommands.js)). + +In the first parameter to `.command()` you specify the command name. You may append the command-arguments after the command name, or specify them separately using `.argument()`. The arguments may be `` or `[optional]`, and the last argument may also be `variadic...`. + +You can use `.addCommand()` to add an already configured subcommand to the program. + +For example: + +```js +// Command implemented using action handler (description is supplied separately to `.command`) +// Returns new command for configuring. +program + .command('clone [destination]') + .description('clone a repository into a newly created directory') + .action((source, destination) => { + console.log('clone command called'); + }); + +// Command implemented using stand-alone executable file, indicated by adding description as second parameter to `.command`. +// Returns `this` for adding more commands. +program + .command('start ', 'start named service') + .command('stop [service]', 'stop named service, or all if no name supplied'); + +// Command prepared separately. +// Returns `this` for adding more commands. +program + .addCommand(build.makeBuildCommand()); +``` + +Configuration options can be passed with the call to `.command()` and `.addCommand()`. Specifying `hidden: true` will +remove the command from the generated help output. Specifying `isDefault: true` will run the subcommand if no other +subcommand is specified ([example](./examples/defaultCommand.js)). + +You can add alternative names for a command with `.alias()`. ([example](./examples/alias.js)) + +For safety, `.addCommand()` does not automatically copy the inherited settings from the parent command. There is a helper routine `.copyInheritedSettings()` for copying the settings when they are wanted. + +### Command-arguments + +For subcommands, you can specify the argument syntax in the call to `.command()` (as shown above). This +is the only method usable for subcommands implemented using a stand-alone executable, but for other subcommands +you can instead use the following method. + +To configure a command, you can use `.argument()` to specify each expected command-argument. +You supply the argument name and an optional description. The argument may be `` or `[optional]`. +You can specify a default value for an optional command-argument. + +Example file: [argument.js](./examples/argument.js) + +```js +program + .version('0.1.0') + .argument('', 'user to login') + .argument('[password]', 'password for user, if required', 'no password given') + .action((username, password) => { + console.log('username:', username); + console.log('password:', password); + }); +``` + + The last argument of a command can be variadic, and only the last argument. To make an argument variadic you + append `...` to the argument name. A variadic argument is passed to the action handler as an array. For example: + +```js +program + .version('0.1.0') + .command('rmdir') + .argument('') + .action(function (dirs) { + dirs.forEach((dir) => { + console.log('rmdir %s', dir); + }); + }); +``` + +There is a convenience method to add multiple arguments at once, but without descriptions: + +```js +program + .arguments(' '); +``` + +#### More configuration + +There are some additional features available by constructing an `Argument` explicitly for less common cases. + +Example file: [arguments-extra.js](./examples/arguments-extra.js) + +```js +program + .addArgument(new commander.Argument('', 'drink cup size').choices(['small', 'medium', 'large'])) + .addArgument(new commander.Argument('[timeout]', 'timeout in seconds').default(60, 'one minute')) +``` + +#### Custom argument processing + +You may specify a function to do custom processing of command-arguments (like for option-arguments). +The callback function receives two parameters, the user specified command-argument and the previous value for the argument. +It returns the new value for the argument. + +The processed argument values are passed to the action handler, and saved as `.processedArgs`. + +You can optionally specify the default/starting value for the argument after the function parameter. + +Example file: [arguments-custom-processing.js](./examples/arguments-custom-processing.js) + +```js +program + .command('add') + .argument('', 'integer argument', myParseInt) + .argument('[second]', 'integer argument', myParseInt, 1000) + .action((first, second) => { + console.log(`${first} + ${second} = ${first + second}`); + }) +; +``` + +### Action handler + +The action handler gets passed a parameter for each command-argument you declared, and two additional parameters +which are the parsed options and the command object itself. + +Example file: [thank.js](./examples/thank.js) + +```js +program + .argument('') + .option('-t, --title ', 'title to use before name') + .option('-d, --debug', 'display some debugging') + .action((name, options, command) => { + if (options.debug) { + console.error('Called %s with options %o', command.name(), options); + } + const title = options.title ? `${options.title} ` : ''; + console.log(`Thank-you ${title}${name}`); + }); +``` + +If you prefer, you can work with the command directly and skip declaring the parameters for the action handler. The `this` keyword is set to the running command and can be used from a function expression (but not from an arrow function). + +Example file: [action-this.js](./examples/action-this.js) + +```js +program + .command('serve') + .argument(' + +``` + +--- + +To use iMurmurHash in Node.js, install the module using NPM: + +```bash +npm install imurmurhash +``` + +Then simply include it in your scripts: + +```javascript +MurmurHash3 = require('imurmurhash'); +``` + +Quick Example +------------- + +```javascript +// Create the initial hash +var hashState = MurmurHash3('string'); + +// Incrementally add text +hashState.hash('more strings'); +hashState.hash('even more strings'); + +// All calls can be chained if desired +hashState.hash('and').hash('some').hash('more'); + +// Get a result +hashState.result(); +// returns 0xe4ccfe6b +``` + +Functions +--------- + +### MurmurHash3 ([string], [seed]) +Get a hash state object, optionally initialized with the given _string_ and _seed_. _Seed_ must be a positive integer if provided. Calling this function without the `new` keyword will return a cached state object that has been reset. This is safe to use as long as the object is only used from a single thread and no other hashes are created while operating on this one. If this constraint cannot be met, you can use `new` to create a new state object. For example: + +```javascript +// Use the cached object, calling the function again will return the same +// object (but reset, so the current state would be lost) +hashState = MurmurHash3(); +... + +// Create a new object that can be safely used however you wish. Calling the +// function again will simply return a new state object, and no state loss +// will occur, at the cost of creating more objects. +hashState = new MurmurHash3(); +``` + +Both methods can be mixed however you like if you have different use cases. + +--- + +### MurmurHash3.prototype.hash (string) +Incrementally add _string_ to the hash. This can be called as many times as you want for the hash state object, including after a call to `result()`. Returns `this` so calls can be chained. + +--- + +### MurmurHash3.prototype.result () +Get the result of the hash as a 32-bit positive integer. This performs the tail and finalizer portions of the algorithm, but does not store the result in the state object. This means that it is perfectly safe to get results and then continue adding strings via `hash`. + +```javascript +// Do the whole string at once +MurmurHash3('this is a test string').result(); +// 0x70529328 + +// Do part of the string, get a result, then the other part +var m = MurmurHash3('this is a'); +m.result(); +// 0xbfc4f834 +m.hash(' test string').result(); +// 0x70529328 (same as above) +``` + +--- + +### MurmurHash3.prototype.reset ([seed]) +Reset the state object for reuse, optionally using the given _seed_ (defaults to 0 like the constructor). Returns `this` so calls can be chained. + +--- + +License (MIT) +------------- +Copyright (c) 2013 Gary Court, Jens Taylor + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/imurmurhash/imurmurhash.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/imurmurhash/imurmurhash.js new file mode 100644 index 000000000..e63146a2b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/imurmurhash/imurmurhash.js @@ -0,0 +1,138 @@ +/** + * @preserve + * JS Implementation of incremental MurmurHash3 (r150) (as of May 10, 2013) + * + * @author Jens Taylor + * @see http://github.com/homebrewing/brauhaus-diff + * @author Gary Court + * @see http://github.com/garycourt/murmurhash-js + * @author Austin Appleby + * @see http://sites.google.com/site/murmurhash/ + */ +(function(){ + var cache; + + // Call this function without `new` to use the cached object (good for + // single-threaded environments), or with `new` to create a new object. + // + // @param {string} key A UTF-16 or ASCII string + // @param {number} seed An optional positive integer + // @return {object} A MurmurHash3 object for incremental hashing + function MurmurHash3(key, seed) { + var m = this instanceof MurmurHash3 ? this : cache; + m.reset(seed) + if (typeof key === 'string' && key.length > 0) { + m.hash(key); + } + + if (m !== this) { + return m; + } + }; + + // Incrementally add a string to this hash + // + // @param {string} key A UTF-16 or ASCII string + // @return {object} this + MurmurHash3.prototype.hash = function(key) { + var h1, k1, i, top, len; + + len = key.length; + this.len += len; + + k1 = this.k1; + i = 0; + switch (this.rem) { + case 0: k1 ^= len > i ? (key.charCodeAt(i++) & 0xffff) : 0; + case 1: k1 ^= len > i ? (key.charCodeAt(i++) & 0xffff) << 8 : 0; + case 2: k1 ^= len > i ? (key.charCodeAt(i++) & 0xffff) << 16 : 0; + case 3: + k1 ^= len > i ? (key.charCodeAt(i) & 0xff) << 24 : 0; + k1 ^= len > i ? (key.charCodeAt(i++) & 0xff00) >> 8 : 0; + } + + this.rem = (len + this.rem) & 3; // & 3 is same as % 4 + len -= this.rem; + if (len > 0) { + h1 = this.h1; + while (1) { + k1 = (k1 * 0x2d51 + (k1 & 0xffff) * 0xcc9e0000) & 0xffffffff; + k1 = (k1 << 15) | (k1 >>> 17); + k1 = (k1 * 0x3593 + (k1 & 0xffff) * 0x1b870000) & 0xffffffff; + + h1 ^= k1; + h1 = (h1 << 13) | (h1 >>> 19); + h1 = (h1 * 5 + 0xe6546b64) & 0xffffffff; + + if (i >= len) { + break; + } + + k1 = ((key.charCodeAt(i++) & 0xffff)) ^ + ((key.charCodeAt(i++) & 0xffff) << 8) ^ + ((key.charCodeAt(i++) & 0xffff) << 16); + top = key.charCodeAt(i++); + k1 ^= ((top & 0xff) << 24) ^ + ((top & 0xff00) >> 8); + } + + k1 = 0; + switch (this.rem) { + case 3: k1 ^= (key.charCodeAt(i + 2) & 0xffff) << 16; + case 2: k1 ^= (key.charCodeAt(i + 1) & 0xffff) << 8; + case 1: k1 ^= (key.charCodeAt(i) & 0xffff); + } + + this.h1 = h1; + } + + this.k1 = k1; + return this; + }; + + // Get the result of this hash + // + // @return {number} The 32-bit hash + MurmurHash3.prototype.result = function() { + var k1, h1; + + k1 = this.k1; + h1 = this.h1; + + if (k1 > 0) { + k1 = (k1 * 0x2d51 + (k1 & 0xffff) * 0xcc9e0000) & 0xffffffff; + k1 = (k1 << 15) | (k1 >>> 17); + k1 = (k1 * 0x3593 + (k1 & 0xffff) * 0x1b870000) & 0xffffffff; + h1 ^= k1; + } + + h1 ^= this.len; + + h1 ^= h1 >>> 16; + h1 = (h1 * 0xca6b + (h1 & 0xffff) * 0x85eb0000) & 0xffffffff; + h1 ^= h1 >>> 13; + h1 = (h1 * 0xae35 + (h1 & 0xffff) * 0xc2b20000) & 0xffffffff; + h1 ^= h1 >>> 16; + + return h1 >>> 0; + }; + + // Reset the hash object for reuse + // + // @param {number} seed An optional positive integer + MurmurHash3.prototype.reset = function(seed) { + this.h1 = typeof seed === 'number' ? seed : 0; + this.rem = this.k1 = this.len = 0; + return this; + }; + + // A cached object to use. This can be safely used if you're in a single- + // threaded environment, otherwise you need to create new hashes to use. + cache = new MurmurHash3(); + + if (typeof(module) != 'undefined') { + module.exports = MurmurHash3; + } else { + this.MurmurHash3 = MurmurHash3; + } +}()); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/imurmurhash/imurmurhash.min.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/imurmurhash/imurmurhash.min.js new file mode 100644 index 000000000..dc0ee88d6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/imurmurhash/imurmurhash.min.js @@ -0,0 +1,12 @@ +/** + * @preserve + * JS Implementation of incremental MurmurHash3 (r150) (as of May 10, 2013) + * + * @author Jens Taylor + * @see http://github.com/homebrewing/brauhaus-diff + * @author Gary Court + * @see http://github.com/garycourt/murmurhash-js + * @author Austin Appleby + * @see http://sites.google.com/site/murmurhash/ + */ +!function(){function t(h,r){var s=this instanceof t?this:e;return s.reset(r),"string"==typeof h&&h.length>0&&s.hash(h),s!==this?s:void 0}var e;t.prototype.hash=function(t){var e,h,r,s,i;switch(i=t.length,this.len+=i,h=this.k1,r=0,this.rem){case 0:h^=i>r?65535&t.charCodeAt(r++):0;case 1:h^=i>r?(65535&t.charCodeAt(r++))<<8:0;case 2:h^=i>r?(65535&t.charCodeAt(r++))<<16:0;case 3:h^=i>r?(255&t.charCodeAt(r))<<24:0,h^=i>r?(65280&t.charCodeAt(r++))>>8:0}if(this.rem=3&i+this.rem,i-=this.rem,i>0){for(e=this.h1;;){if(h=4294967295&11601*h+3432906752*(65535&h),h=h<<15|h>>>17,h=4294967295&13715*h+461832192*(65535&h),e^=h,e=e<<13|e>>>19,e=4294967295&5*e+3864292196,r>=i)break;h=65535&t.charCodeAt(r++)^(65535&t.charCodeAt(r++))<<8^(65535&t.charCodeAt(r++))<<16,s=t.charCodeAt(r++),h^=(255&s)<<24^(65280&s)>>8}switch(h=0,this.rem){case 3:h^=(65535&t.charCodeAt(r+2))<<16;case 2:h^=(65535&t.charCodeAt(r+1))<<8;case 1:h^=65535&t.charCodeAt(r)}this.h1=e}return this.k1=h,this},t.prototype.result=function(){var t,e;return t=this.k1,e=this.h1,t>0&&(t=4294967295&11601*t+3432906752*(65535&t),t=t<<15|t>>>17,t=4294967295&13715*t+461832192*(65535&t),e^=t),e^=this.len,e^=e>>>16,e=4294967295&51819*e+2246770688*(65535&e),e^=e>>>13,e=4294967295&44597*e+3266445312*(65535&e),e^=e>>>16,e>>>0},t.prototype.reset=function(t){return this.h1="number"==typeof t?t:0,this.rem=this.k1=this.len=0,this},e=new t,"undefined"!=typeof module?module.exports=t:this.MurmurHash3=t}(); \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/imurmurhash/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/imurmurhash/package.json new file mode 100644 index 000000000..8a93edb55 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/imurmurhash/package.json @@ -0,0 +1,40 @@ +{ + "name": "imurmurhash", + "version": "0.1.4", + "description": "An incremental implementation of MurmurHash3", + "homepage": "https://github.com/jensyt/imurmurhash-js", + "main": "imurmurhash.js", + "files": [ + "imurmurhash.js", + "imurmurhash.min.js", + "package.json", + "README.md" + ], + "repository": { + "type": "git", + "url": "https://github.com/jensyt/imurmurhash-js" + }, + "bugs": { + "url": "https://github.com/jensyt/imurmurhash-js/issues" + }, + "keywords": [ + "murmur", + "murmurhash", + "murmurhash3", + "hash", + "incremental" + ], + "author": { + "name": "Jens Taylor", + "email": "jensyt@gmail.com", + "url": "https://github.com/homebrewing" + }, + "license": "MIT", + "dependencies": { + }, + "devDependencies": { + }, + "engines": { + "node": ">=0.8.19" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/index.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/index.d.ts new file mode 100644 index 000000000..118523115 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/index.d.ts @@ -0,0 +1,42 @@ +declare namespace indentString { + interface Options { + /** + The string to use for the indent. + + @default ' ' + */ + readonly indent?: string; + + /** + Also indent empty lines. + + @default false + */ + readonly includeEmptyLines?: boolean; + } +} + +/** +Indent each line in a string. + +@param string - The string to indent. +@param count - How many times you want `options.indent` repeated. Default: `1`. + +@example +``` +import indentString = require('indent-string'); + +indentString('Unicorns\nRainbows', 4); +//=> ' Unicorns\n Rainbows' + +indentString('Unicorns\nRainbows', 4, {indent: '♥'}); +//=> '♥♥♥♥Unicorns\n♥♥♥♥Rainbows' +``` +*/ +declare function indentString( + string: string, + count?: number, + options?: indentString.Options +): string; + +export = indentString; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/index.js new file mode 100644 index 000000000..e1ab804f2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/index.js @@ -0,0 +1,35 @@ +'use strict'; + +module.exports = (string, count = 1, options) => { + options = { + indent: ' ', + includeEmptyLines: false, + ...options + }; + + if (typeof string !== 'string') { + throw new TypeError( + `Expected \`input\` to be a \`string\`, got \`${typeof string}\`` + ); + } + + if (typeof count !== 'number') { + throw new TypeError( + `Expected \`count\` to be a \`number\`, got \`${typeof count}\`` + ); + } + + if (typeof options.indent !== 'string') { + throw new TypeError( + `Expected \`options.indent\` to be a \`string\`, got \`${typeof options.indent}\`` + ); + } + + if (count === 0) { + return string; + } + + const regex = options.includeEmptyLines ? /^/gm : /^(?!\s*$)/gm; + + return string.replace(regex, options.indent.repeat(count)); +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/license b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/license new file mode 100644 index 000000000..e7af2f771 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/package.json new file mode 100644 index 000000000..497bb83bb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/package.json @@ -0,0 +1,37 @@ +{ + "name": "indent-string", + "version": "4.0.0", + "description": "Indent each line in a string", + "license": "MIT", + "repository": "sindresorhus/indent-string", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "indent", + "string", + "pad", + "align", + "line", + "text", + "each", + "every" + ], + "devDependencies": { + "ava": "^1.4.1", + "tsd": "^0.7.2", + "xo": "^0.24.0" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/readme.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/readme.md new file mode 100644 index 000000000..49967de07 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/indent-string/readme.md @@ -0,0 +1,70 @@ +# indent-string [![Build Status](https://travis-ci.org/sindresorhus/indent-string.svg?branch=master)](https://travis-ci.org/sindresorhus/indent-string) + +> Indent each line in a string + + +## Install + +``` +$ npm install indent-string +``` + + +## Usage + +```js +const indentString = require('indent-string'); + +indentString('Unicorns\nRainbows', 4); +//=> ' Unicorns\n Rainbows' + +indentString('Unicorns\nRainbows', 4, {indent: '♥'}); +//=> '♥♥♥♥Unicorns\n♥♥♥♥Rainbows' +``` + + +## API + +### indentString(string, [count], [options]) + +#### string + +Type: `string` + +The string to indent. + +#### count + +Type: `number`
    +Default: `1` + +How many times you want `options.indent` repeated. + +#### options + +Type: `object` + +##### indent + +Type: `string`
    +Default: `' '` + +The string to use for the indent. + +##### includeEmptyLines + +Type: `boolean`
    +Default: `false` + +Also indent empty lines. + + +## Related + +- [indent-string-cli](https://github.com/sindresorhus/indent-string-cli) - CLI for this module +- [strip-indent](https://github.com/sindresorhus/strip-indent) - Strip leading whitespace from every line in a string + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/LICENSE new file mode 100644 index 000000000..20a476254 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) npm, Inc. and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/README.md new file mode 100644 index 000000000..146caf7b8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/README.md @@ -0,0 +1,41 @@ +# infer-owner + +Infer the owner of a path based on the owner of its nearest existing parent + +## USAGE + +```js +const inferOwner = require('infer-owner') + +inferOwner('/some/cache/folder/file').then(owner => { + // owner is {uid, gid} that should be attached to + // the /some/cache/folder/file, based on ownership + // of /some/cache/folder, /some/cache, /some, or /, + // whichever is the first to exist +}) + +// same, but not async +const owner = inferOwner.sync('/some/cache/folder/file') + +// results are cached! to reset the cache (eg, to change +// permissions for whatever reason), do this: +inferOwner.clearCache() +``` + +This module endeavors to be as performant as possible. Parallel requests +for ownership of the same path will only stat the directories one time. + +## API + +* `inferOwner(path) -> Promise<{ uid, gid }>` + + If the path exists, return its uid and gid. If it does not, look to + its parent, then its grandparent, and so on. + +* `inferOwner(path) -> { uid, gid }` + + Sync form of `inferOwner(path)`. + +* `inferOwner.clearCache()` + + Delete all cached ownership information and in-flight tracking. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/index.js new file mode 100644 index 000000000..a7bddcbd2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/index.js @@ -0,0 +1,71 @@ +const cache = new Map() +const fs = require('fs') +const { dirname, resolve } = require('path') + + +const lstat = path => new Promise((res, rej) => + fs.lstat(path, (er, st) => er ? rej(er) : res(st))) + +const inferOwner = path => { + path = resolve(path) + if (cache.has(path)) + return Promise.resolve(cache.get(path)) + + const statThen = st => { + const { uid, gid } = st + cache.set(path, { uid, gid }) + return { uid, gid } + } + const parent = dirname(path) + const parentTrap = parent === path ? null : er => { + return inferOwner(parent).then((owner) => { + cache.set(path, owner) + return owner + }) + } + return lstat(path).then(statThen, parentTrap) +} + +const inferOwnerSync = path => { + path = resolve(path) + if (cache.has(path)) + return cache.get(path) + + const parent = dirname(path) + + // avoid obscuring call site by re-throwing + // "catch" the error by returning from a finally, + // only if we're not at the root, and the parent call works. + let threw = true + try { + const st = fs.lstatSync(path) + threw = false + const { uid, gid } = st + cache.set(path, { uid, gid }) + return { uid, gid } + } finally { + if (threw && parent !== path) { + const owner = inferOwnerSync(parent) + cache.set(path, owner) + return owner // eslint-disable-line no-unsafe-finally + } + } +} + +const inflight = new Map() +module.exports = path => { + path = resolve(path) + if (inflight.has(path)) + return Promise.resolve(inflight.get(path)) + const p = inferOwner(path).then(owner => { + inflight.delete(path) + return owner + }) + inflight.set(path, p) + return p +} +module.exports.sync = inferOwnerSync +module.exports.clearCache = () => { + cache.clear() + inflight.clear() +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/package.json new file mode 100644 index 000000000..c4b2b6e6d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/infer-owner/package.json @@ -0,0 +1,26 @@ +{ + "name": "infer-owner", + "version": "1.0.4", + "description": "Infer the owner of a path based on the owner of its nearest existing parent", + "author": "Isaac Z. Schlueter (https://izs.me)", + "license": "ISC", + "scripts": { + "test": "tap -J test/*.js --100", + "snap": "TAP_SNAPSHOT=1 tap -J test/*.js --100", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --follow-tags" + }, + "devDependencies": { + "mutate-fs": "^2.1.1", + "tap": "^12.4.2" + }, + "main": "index.js", + "repository": "https://github.com/npm/infer-owner", + "publishConfig": { + "access": "public" + }, + "files": [ + "index.js" + ] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/LICENSE new file mode 100644 index 000000000..05eeeb88c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/README.md new file mode 100644 index 000000000..6dc892917 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/README.md @@ -0,0 +1,37 @@ +# inflight + +Add callbacks to requests in flight to avoid async duplication + +## USAGE + +```javascript +var inflight = require('inflight') + +// some request that does some stuff +function req(key, callback) { + // key is any random string. like a url or filename or whatever. + // + // will return either a falsey value, indicating that the + // request for this key is already in flight, or a new callback + // which when called will call all callbacks passed to inflightk + // with the same key + callback = inflight(key, callback) + + // If we got a falsey value back, then there's already a req going + if (!callback) return + + // this is where you'd fetch the url or whatever + // callback is also once()-ified, so it can safely be assigned + // to multiple events etc. First call wins. + setTimeout(function() { + callback(null, key) + }, 100) +} + +// only assigns a single setTimeout +// when it dings, all cbs get called +req('foo', cb1) +req('foo', cb2) +req('foo', cb3) +req('foo', cb4) +``` diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/inflight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/inflight.js new file mode 100644 index 000000000..48202b3ca --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/inflight.js @@ -0,0 +1,54 @@ +var wrappy = require('wrappy') +var reqs = Object.create(null) +var once = require('once') + +module.exports = wrappy(inflight) + +function inflight (key, cb) { + if (reqs[key]) { + reqs[key].push(cb) + return null + } else { + reqs[key] = [cb] + return makeres(key) + } +} + +function makeres (key) { + return once(function RES () { + var cbs = reqs[key] + var len = cbs.length + var args = slice(arguments) + + // XXX It's somewhat ambiguous whether a new callback added in this + // pass should be queued for later execution if something in the + // list of callbacks throws, or if it should just be discarded. + // However, it's such an edge case that it hardly matters, and either + // choice is likely as surprising as the other. + // As it happens, we do go ahead and schedule it for later execution. + try { + for (var i = 0; i < len; i++) { + cbs[i].apply(null, args) + } + } finally { + if (cbs.length > len) { + // added more in the interim. + // de-zalgo, just in case, but don't call again. + cbs.splice(0, len) + process.nextTick(function () { + RES.apply(null, args) + }) + } else { + delete reqs[key] + } + } + }) +} + +function slice (args) { + var length = args.length + var array = [] + + for (var i = 0; i < length; i++) array[i] = args[i] + return array +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/package.json new file mode 100644 index 000000000..6084d3509 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inflight/package.json @@ -0,0 +1,29 @@ +{ + "name": "inflight", + "version": "1.0.6", + "description": "Add callbacks to requests in flight to avoid async duplication", + "main": "inflight.js", + "files": [ + "inflight.js" + ], + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + }, + "devDependencies": { + "tap": "^7.1.2" + }, + "scripts": { + "test": "tap test.js --100" + }, + "repository": { + "type": "git", + "url": "https://github.com/npm/inflight.git" + }, + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "bugs": { + "url": "https://github.com/isaacs/inflight/issues" + }, + "homepage": "https://github.com/isaacs/inflight", + "license": "ISC" +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/LICENSE new file mode 100644 index 000000000..dea3013d6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/LICENSE @@ -0,0 +1,16 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/README.md new file mode 100644 index 000000000..b1c566585 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/README.md @@ -0,0 +1,42 @@ +Browser-friendly inheritance fully compatible with standard node.js +[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor). + +This package exports standard `inherits` from node.js `util` module in +node environment, but also provides alternative browser-friendly +implementation through [browser +field](https://gist.github.com/shtylman/4339901). Alternative +implementation is a literal copy of standard one located in standalone +module to avoid requiring of `util`. It also has a shim for old +browsers with no `Object.create` support. + +While keeping you sure you are using standard `inherits` +implementation in node.js environment, it allows bundlers such as +[browserify](https://github.com/substack/node-browserify) to not +include full `util` package to your client code if all you need is +just `inherits` function. It worth, because browser shim for `util` +package is large and `inherits` is often the single function you need +from it. + +It's recommended to use this package instead of +`require('util').inherits` for any code that has chances to be used +not only in node.js but in browser too. + +## usage + +```js +var inherits = require('inherits'); +// then use exactly as the standard one +``` + +## note on version ~1.0 + +Version ~1.0 had completely different motivation and is not compatible +neither with 2.0 nor with standard node.js `inherits`. + +If you are using version ~1.0 and planning to switch to ~2.0, be +careful: + +* new version uses `super_` instead of `super` for referencing + superclass +* new version overwrites current prototype while old one preserves any + existing fields on it diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/inherits.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/inherits.js new file mode 100644 index 000000000..f71f2d932 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/inherits.js @@ -0,0 +1,9 @@ +try { + var util = require('util'); + /* istanbul ignore next */ + if (typeof util.inherits !== 'function') throw ''; + module.exports = util.inherits; +} catch (e) { + /* istanbul ignore next */ + module.exports = require('./inherits_browser.js'); +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/inherits_browser.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/inherits_browser.js new file mode 100644 index 000000000..86bbb3dc2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/inherits_browser.js @@ -0,0 +1,27 @@ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }) + } + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/package.json new file mode 100644 index 000000000..37b4366b8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/inherits/package.json @@ -0,0 +1,29 @@ +{ + "name": "inherits", + "description": "Browser-friendly inheritance fully compatible with standard node.js inherits()", + "version": "2.0.4", + "keywords": [ + "inheritance", + "class", + "klass", + "oop", + "object-oriented", + "inherits", + "browser", + "browserify" + ], + "main": "./inherits.js", + "browser": "./inherits_browser.js", + "repository": "git://github.com/isaacs/inherits", + "license": "ISC", + "scripts": { + "test": "tap" + }, + "devDependencies": { + "tap": "^14.2.4" + }, + "files": [ + "inherits.js", + "inherits_browser.js" + ] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/LICENSE new file mode 100644 index 000000000..19129e315 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/README.md new file mode 100644 index 000000000..33df25829 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/README.md @@ -0,0 +1,102 @@ +An ini format parser and serializer for node. + +Sections are treated as nested objects. Items before the first +heading are saved on the object directly. + +## Usage + +Consider an ini-file `config.ini` that looks like this: + + ; this comment is being ignored + scope = global + + [database] + user = dbuser + password = dbpassword + database = use_this_database + + [paths.default] + datadir = /var/lib/data + array[] = first value + array[] = second value + array[] = third value + +You can read, manipulate and write the ini-file like so: + + var fs = require('fs') + , ini = require('ini') + + var config = ini.parse(fs.readFileSync('./config.ini', 'utf-8')) + + config.scope = 'local' + config.database.database = 'use_another_database' + config.paths.default.tmpdir = '/tmp' + delete config.paths.default.datadir + config.paths.default.array.push('fourth value') + + fs.writeFileSync('./config_modified.ini', ini.stringify(config, { section: 'section' })) + +This will result in a file called `config_modified.ini` being written +to the filesystem with the following content: + + [section] + scope=local + [section.database] + user=dbuser + password=dbpassword + database=use_another_database + [section.paths.default] + tmpdir=/tmp + array[]=first value + array[]=second value + array[]=third value + array[]=fourth value + + +## API + +### decode(inistring) + +Decode the ini-style formatted `inistring` into a nested object. + +### parse(inistring) + +Alias for `decode(inistring)` + +### encode(object, [options]) + +Encode the object `object` into an ini-style formatted string. If the +optional parameter `section` is given, then all top-level properties +of the object are put into this section and the `section`-string is +prepended to all sub-sections, see the usage example above. + +The `options` object may contain the following: + +* `section` A string which will be the first `section` in the encoded + ini data. Defaults to none. +* `whitespace` Boolean to specify whether to put whitespace around the + `=` character. By default, whitespace is omitted, to be friendly to + some persnickety old parsers that don't tolerate it well. But some + find that it's more human-readable and pretty with the whitespace. + +For backwards compatibility reasons, if a `string` options is passed +in, then it is assumed to be the `section` value. + +### stringify(object, [options]) + +Alias for `encode(object, [options])` + +### safe(val) + +Escapes the string `val` such that it is safe to be used as a key or +value in an ini-file. Basically escapes quotes. For example + + ini.safe('"unsafe string"') + +would result in + + "\"unsafe string\"" + +### unsafe(val) + +Unescapes the string `val` diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/ini.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/ini.js new file mode 100644 index 000000000..b576f08d7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/ini.js @@ -0,0 +1,206 @@ +exports.parse = exports.decode = decode + +exports.stringify = exports.encode = encode + +exports.safe = safe +exports.unsafe = unsafe + +var eol = typeof process !== 'undefined' && + process.platform === 'win32' ? '\r\n' : '\n' + +function encode (obj, opt) { + var children = [] + var out = '' + + if (typeof opt === 'string') { + opt = { + section: opt, + whitespace: false, + } + } else { + opt = opt || {} + opt.whitespace = opt.whitespace === true + } + + var separator = opt.whitespace ? ' = ' : '=' + + Object.keys(obj).forEach(function (k, _, __) { + var val = obj[k] + if (val && Array.isArray(val)) { + val.forEach(function (item) { + out += safe(k + '[]') + separator + safe(item) + '\n' + }) + } else if (val && typeof val === 'object') + children.push(k) + else + out += safe(k) + separator + safe(val) + eol + }) + + if (opt.section && out.length) + out = '[' + safe(opt.section) + ']' + eol + out + + children.forEach(function (k, _, __) { + var nk = dotSplit(k).join('\\.') + var section = (opt.section ? opt.section + '.' : '') + nk + var child = encode(obj[k], { + section: section, + whitespace: opt.whitespace, + }) + if (out.length && child.length) + out += eol + + out += child + }) + + return out +} + +function dotSplit (str) { + return str.replace(/\1/g, '\u0002LITERAL\\1LITERAL\u0002') + .replace(/\\\./g, '\u0001') + .split(/\./).map(function (part) { + return part.replace(/\1/g, '\\.') + .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001') + }) +} + +function decode (str) { + var out = {} + var p = out + var section = null + // section |key = value + var re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i + var lines = str.split(/[\r\n]+/g) + + lines.forEach(function (line, _, __) { + if (!line || line.match(/^\s*[;#]/)) + return + var match = line.match(re) + if (!match) + return + if (match[1] !== undefined) { + section = unsafe(match[1]) + if (section === '__proto__') { + // not allowed + // keep parsing the section, but don't attach it. + p = {} + return + } + p = out[section] = out[section] || {} + return + } + var key = unsafe(match[2]) + if (key === '__proto__') + return + var value = match[3] ? unsafe(match[4]) : true + switch (value) { + case 'true': + case 'false': + case 'null': value = JSON.parse(value) + } + + // Convert keys with '[]' suffix to an array + if (key.length > 2 && key.slice(-2) === '[]') { + key = key.substring(0, key.length - 2) + if (key === '__proto__') + return + if (!p[key]) + p[key] = [] + else if (!Array.isArray(p[key])) + p[key] = [p[key]] + } + + // safeguard against resetting a previously defined + // array by accidentally forgetting the brackets + if (Array.isArray(p[key])) + p[key].push(value) + else + p[key] = value + }) + + // {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}} + // use a filter to return the keys that have to be deleted. + Object.keys(out).filter(function (k, _, __) { + if (!out[k] || + typeof out[k] !== 'object' || + Array.isArray(out[k])) + return false + + // see if the parent section is also an object. + // if so, add it to that, and mark this one for deletion + var parts = dotSplit(k) + var p = out + var l = parts.pop() + var nl = l.replace(/\\\./g, '.') + parts.forEach(function (part, _, __) { + if (part === '__proto__') + return + if (!p[part] || typeof p[part] !== 'object') + p[part] = {} + p = p[part] + }) + if (p === out && nl === l) + return false + + p[nl] = out[k] + return true + }).forEach(function (del, _, __) { + delete out[del] + }) + + return out +} + +function isQuoted (val) { + return (val.charAt(0) === '"' && val.slice(-1) === '"') || + (val.charAt(0) === "'" && val.slice(-1) === "'") +} + +function safe (val) { + return (typeof val !== 'string' || + val.match(/[=\r\n]/) || + val.match(/^\[/) || + (val.length > 1 && + isQuoted(val)) || + val !== val.trim()) + ? JSON.stringify(val) + : val.replace(/;/g, '\\;').replace(/#/g, '\\#') +} + +function unsafe (val, doUnesc) { + val = (val || '').trim() + if (isQuoted(val)) { + // remove the single quotes before calling JSON.parse + if (val.charAt(0) === "'") + val = val.substr(1, val.length - 2) + + try { + val = JSON.parse(val) + } catch (_) {} + } else { + // walk the val to find the first not-escaped ; character + var esc = false + var unesc = '' + for (var i = 0, l = val.length; i < l; i++) { + var c = val.charAt(i) + if (esc) { + if ('\\;#'.indexOf(c) !== -1) + unesc += c + else + unesc += '\\' + c + + esc = false + } else if (';#'.indexOf(c) !== -1) + break + else if (c === '\\') + esc = true + else + unesc += c + } + if (esc) + unesc += '\\' + + return unesc.trim() + } + return val +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/package.json new file mode 100644 index 000000000..c830a3556 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ini/package.json @@ -0,0 +1,33 @@ +{ + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "name": "ini", + "description": "An ini encoder/decoder for node", + "version": "1.3.8", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/ini.git" + }, + "main": "ini.js", + "scripts": { + "eslint": "eslint", + "lint": "npm run eslint -- ini.js test/*.js", + "lintfix": "npm run lint -- --fix", + "test": "tap", + "posttest": "npm run lint", + "preversion": "npm test", + "postversion": "npm publish", + "prepublishOnly": "git push origin --follow-tags" + }, + "devDependencies": { + "eslint": "^7.9.0", + "eslint-plugin-import": "^2.22.0", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-standard": "^4.0.1", + "tap": "14" + }, + "license": "ISC", + "files": [ + "ini.js" + ] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/CHANGELOG b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/CHANGELOG new file mode 100644 index 000000000..cbc8a8afd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/CHANGELOG @@ -0,0 +1,115 @@ +v1.0.3: + date: 2017-04-18 + changes: + - fix buble support +v1.0.2: + date: 2017-03-29 + changes: + - add support for coffeescript (now with no hyphen) +v1.0.1: + date: 2016-05-01 + changes: + - add support for buble +v1.0.0: + date: 2015-11-18 + changes: + - add support for babel-register + - go stable! +v0.6.6: + date: 2015-09-21 + changes: + - add support for ts-node (formerly typescript-node) +v0.6.5: + date: 2015-07-22 + changes: + - add support for typescript 1.5 via typescript-node +v0.6.4: + date: 2015-07-07 + changes: + - add support for earlgrey +v0.6.3: + date: 2015-07-03 + changes: + - prefer babel/core to babel +v0.6.2: + date: 2015-05-20 + changes: + - update module list for iced coffee-script +v0.6.1: + date: 2015-05-20 + changes: + - Fix toml loader. +v0.6.0: + date: 2015-05-19 + changes: + - Combine fallbacks and loaders into `extensions`. + - Provide implementation guidance. +v0.5.1: + date: 2015-03-01 + changes: + - Add support for CirruScript. +v0.5.0: + date: 2015-02-27 + changes: + - Refactor es6 support via Babel (formerly 6to5) +v0.4.3: + date: 2015-02-09 + changes: + - Switch support from typescript-require to typescript-register. +v0.4.2: + date: 2015-01-16 + changes: + - Add support for wisp. +v0.4.1: + date: 2015-01-10 + changes: + - Add support for 6to5 (es6) +v0.4.0: + date: 2014-01-09 + changes: + - Add support for fallback (legacy) modules + - Add support for module configurations +v0.3.10: + date: 2014-12-17 + changes: + - Add support for json5. +v0.3.9: + date: 2014-12-08 + changes: + - Add support for literate iced coffee. +v0.3.8: + date: 2014-11-20 + changes: + - Add support for [cjsx](https://github.com/jsdf/coffee-react). +v0.3.7: + date: 2014-09-08 + changes: + - Add support for [TypeScript](http://www.typescriptlang.org/). +v0.3.6: + date: 2014-08-25 + changes: + - Add support for coffee.md. +v0.3.5: + date: 2014-07-03 + changes: + - Add support for jsx. +v0.3.4: + date: 2014-06-27 + changes: + - Make .js first jsVariant entry. +v0.3.3: + date: 2014-06-02 + changes: + - Fix casing on livescript dependency. +v0.3.0: + date: 2014-04-20 + changes: + - Simplify loading of coffee-script and iced-coffee-script. +v0.2.0: + date: 2014-04-20 + changes: + - Move module loading into rechoir. +v0.1.0: + date: 2014-04-20 + changes: + - Initial public release. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/LICENSE new file mode 100644 index 000000000..7d7525daa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2014-2018 Tyler Kellen , Blaine Bublitz , and Eric Schoffstall + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/README.md new file mode 100644 index 000000000..f56410c09 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/README.md @@ -0,0 +1,229 @@ +

    + + + +

    + +# interpret + +[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Travis Build Status][travis-image]][travis-url] [![AppVeyor Build Status][appveyor-image]][appveyor-url] [![Coveralls Status][coveralls-image]][coveralls-url] [![Gitter chat][gitter-image]][gitter-url] + +A dictionary of file extensions and associated module loaders. + +## What is it +This is used by [Liftoff](http://github.com/tkellen/node-liftoff) to automatically require dependencies for configuration files, and by [rechoir](http://github.com/tkellen/node-rechoir) for registering module loaders. + +## interpret for enterprise + +Available as part of the Tidelift Subscription + +The maintainers of interpret and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-interpret?utm_source=npm-interpret&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) + +## API + +### extensions +Map file types to modules which provide a [require.extensions] loader. + +```js +{ + '.babel.js': [ + { + module: '@babel/register', + register: function(hook) { + hook({ + extensions: '.js', + rootMode: 'upward-optional', + ignore: [ignoreNonBabelAndNodeModules], + }); + }, + }, + { + module: 'babel-register', + register: function(hook) { + hook({ + extensions: '.js', + ignore: ignoreNonBabelAndNodeModules, + }); + }, + }, + { + module: 'babel-core/register', + register: function(hook) { + hook({ + extensions: '.js', + ignore: ignoreNonBabelAndNodeModules, + }); + }, + }, + { + module: 'babel/register', + register: function(hook) { + hook({ + extensions: '.js', + ignore: ignoreNonBabelAndNodeModules, + }); + }, + }, + ], + '.babel.ts': [ + { + module: '@babel/register', + register: function(hook) { + hook({ + extensions: '.ts', + rootMode: 'upward-optional', + ignore: [ignoreNonBabelAndNodeModules], + }); + }, + }, + ], + '.buble.js': 'buble/register', + '.cirru': 'cirru-script/lib/register', + '.cjsx': 'node-cjsx/register', + '.co': 'coco', + '.coffee': ['coffeescript/register', 'coffee-script/register', 'coffeescript', 'coffee-script'], + '.coffee.md': ['coffeescript/register', 'coffee-script/register', 'coffeescript', 'coffee-script'], + '.csv': 'require-csv', + '.eg': 'earlgrey/register', + '.esm.js': { + module: 'esm', + register: function(hook) { + // register on .js extension due to https://github.com/joyent/node/blob/v0.12.0/lib/module.js#L353 + // which only captures the final extension (.babel.js -> .js) + var esmLoader = hook(module); + require.extensions['.js'] = esmLoader('module')._extensions['.js']; + }, + }, + '.iced': ['iced-coffee-script/register', 'iced-coffee-script'], + '.iced.md': 'iced-coffee-script/register', + '.ini': 'require-ini', + '.js': null, + '.json': null, + '.json5': ['json5/lib/register', 'json5/lib/require'], + '.jsx': [ + { + module: '@babel/register', + register: function(hook) { + hook({ + extensions: '.jsx', + rootMode: 'upward-optional', + ignore: [ignoreNonBabelAndNodeModules], + }); + }, + }, + { + module: 'babel-register', + register: function(hook) { + hook({ + extensions: '.jsx', + ignore: ignoreNonBabelAndNodeModules, + }); + }, + }, + { + module: 'babel-core/register', + register: function(hook) { + hook({ + extensions: '.jsx', + ignore: ignoreNonBabelAndNodeModules, + }); + }, + }, + { + module: 'babel/register', + register: function(hook) { + hook({ + extensions: '.jsx', + ignore: ignoreNonBabelAndNodeModules, + }); + }, + }, + { + module: 'node-jsx', + register: function(hook) { + hook.install({ extension: '.jsx', harmony: true }); + }, + }, + ], + '.litcoffee': ['coffeescript/register', 'coffee-script/register', 'coffeescript', 'coffee-script'], + '.liticed': 'iced-coffee-script/register', + '.ls': ['livescript', 'LiveScript'], + '.mjs': '/absolute/path/to/interpret/mjs-stub.js', + '.node': null, + '.toml': { + module: 'toml-require', + register: function(hook) { + hook.install(); + }, + }, + '.ts': [ + 'ts-node/register', + 'typescript-node/register', + 'typescript-register', + 'typescript-require', + 'sucrase/register/ts', + { + module: '@babel/register', + register: function(hook) { + hook({ + extensions: '.ts', + rootMode: 'upward-optional', + ignore: [ignoreNonBabelAndNodeModules], + }); + }, + }, + ], + '.tsx': [ + 'ts-node/register', + 'typescript-node/register', + 'sucrase/register', + { + module: '@babel/register', + register: function(hook) { + hook({ + extensions: '.tsx', + rootMode: 'upward-optional', + ignore: [ignoreNonBabelAndNodeModules], + }); + }, + }, + ], + '.wisp': 'wisp/engine/node', + '.xml': 'require-xml', + '.yaml': 'require-yaml', + '.yml': 'require-yaml', +} +``` + +### jsVariants +Same as above, but only include the extensions which are javascript variants. + +## How to use it + +Consumers should use the exported `extensions` or `jsVariants` object to determine which module should be loaded for a given extension. If a matching extension is found, consumers should do the following: + +1. If the value is null, do nothing. + +2. If the value is a string, try to require it. + +3. If the value is an object, try to require the `module` property. If successful, the `register` property (a function) should be called with the module passed as the first argument. + +4. If the value is an array, iterate over it, attempting step #2 or #3 until one of the attempts does not throw. + +[require.extensions]: http://nodejs.org/api/globals.html#globals_require_extensions + +[downloads-image]: http://img.shields.io/npm/dm/interpret.svg +[npm-url]: https://www.npmjs.com/package/interpret +[npm-image]: http://img.shields.io/npm/v/interpret.svg + +[travis-url]: https://travis-ci.org/gulpjs/interpret +[travis-image]: http://img.shields.io/travis/gulpjs/interpret.svg?label=travis-ci + +[appveyor-url]: https://ci.appveyor.com/project/gulpjs/interpret +[appveyor-image]: https://img.shields.io/appveyor/ci/gulpjs/interpret.svg?label=appveyor + +[coveralls-url]: https://coveralls.io/r/gulpjs/interpret +[coveralls-image]: http://img.shields.io/coveralls/gulpjs/interpret/master.svg + +[gitter-url]: https://gitter.im/gulpjs/gulp +[gitter-image]: https://badges.gitter.im/gulpjs/gulp.svg diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/index.js new file mode 100644 index 000000000..2a2b82975 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/index.js @@ -0,0 +1,211 @@ +var path = require('path'); + +var endsInBabelJs = /\.babel\.[jt]s(x)$/; + +var mjsStub = path.join(__dirname, 'mjs-stub'); + +function ignoreNonBabelAndNodeModules(file) { + return !endsInBabelJs.test(file) && + path.relative(process.cwd(), file).split(path.sep).indexOf('node_modules') >= 0; +} + +var extensions = { + '.babel.js': [ + { + module: '@babel/register', + register: function(hook) { + hook({ + extensions: '.js', + rootMode: 'upward-optional', + ignore: [ignoreNonBabelAndNodeModules], + }); + }, + }, + { + module: 'babel-register', + register: function(hook) { + hook({ + extensions: '.js', + ignore: ignoreNonBabelAndNodeModules, + }); + }, + }, + { + module: 'babel-core/register', + register: function(hook) { + hook({ + extensions: '.js', + ignore: ignoreNonBabelAndNodeModules, + }); + }, + }, + { + module: 'babel/register', + register: function(hook) { + hook({ + extensions: '.js', + ignore: ignoreNonBabelAndNodeModules, + }); + }, + }, + ], + '.babel.ts': [ + { + module: '@babel/register', + register: function(hook) { + hook({ + extensions: '.ts', + rootMode: 'upward-optional', + ignore: [ignoreNonBabelAndNodeModules], + }); + }, + }, + ], + '.buble.js': 'buble/register', + '.cirru': 'cirru-script/lib/register', + '.cjsx': 'node-cjsx/register', + '.co': 'coco', + '.coffee': ['coffeescript/register', 'coffee-script/register', 'coffeescript', 'coffee-script'], + '.coffee.md': ['coffeescript/register', 'coffee-script/register', 'coffeescript', 'coffee-script'], + '.csv': 'require-csv', + '.eg': 'earlgrey/register', + '.esm.js': { + module: 'esm', + register: function(hook) { + // register on .js extension due to https://github.com/joyent/node/blob/v0.12.0/lib/module.js#L353 + // which only captures the final extension (.babel.js -> .js) + var esmLoader = hook(module); + require.extensions['.js'] = esmLoader('module')._extensions['.js']; + }, + }, + '.iced': ['iced-coffee-script/register', 'iced-coffee-script'], + '.iced.md': 'iced-coffee-script/register', + '.ini': 'require-ini', + '.js': null, + '.json': null, + '.json5': ['json5/lib/register', 'json5/lib/require'], + '.jsx': [ + { + module: '@babel/register', + register: function(hook) { + hook({ + extensions: '.jsx', + rootMode: 'upward-optional', + ignore: [ignoreNonBabelAndNodeModules], + }); + }, + }, + { + module: 'babel-register', + register: function(hook) { + hook({ + extensions: '.jsx', + ignore: ignoreNonBabelAndNodeModules, + }); + }, + }, + { + module: 'babel-core/register', + register: function(hook) { + hook({ + extensions: '.jsx', + ignore: ignoreNonBabelAndNodeModules, + }); + }, + }, + { + module: 'babel/register', + register: function(hook) { + hook({ + extensions: '.jsx', + ignore: ignoreNonBabelAndNodeModules, + }); + }, + }, + { + module: 'node-jsx', + register: function(hook) { + hook.install({ extension: '.jsx', harmony: true }); + }, + }, + ], + '.litcoffee': ['coffeescript/register', 'coffee-script/register', 'coffeescript', 'coffee-script'], + '.liticed': 'iced-coffee-script/register', + '.ls': ['livescript', 'LiveScript'], + '.mjs': mjsStub, + '.node': null, + '.toml': { + module: 'toml-require', + register: function(hook) { + hook.install(); + }, + }, + '.ts': [ + 'ts-node/register', + 'typescript-node/register', + 'typescript-register', + 'typescript-require', + 'sucrase/register/ts', + { + module: '@babel/register', + register: function(hook) { + hook({ + extensions: '.ts', + rootMode: 'upward-optional', + ignore: [ignoreNonBabelAndNodeModules], + }); + }, + }, + ], + '.tsx': [ + 'ts-node/register', + 'typescript-node/register', + 'sucrase/register', + { + module: '@babel/register', + register: function(hook) { + hook({ + extensions: '.tsx', + rootMode: 'upward-optional', + ignore: [ignoreNonBabelAndNodeModules], + }); + }, + }, + ], + '.wisp': 'wisp/engine/node', + '.xml': 'require-xml', + '.yaml': 'require-yaml', + '.yml': 'require-yaml', +}; + +var jsVariantExtensions = [ + '.js', + '.babel.js', + '.babel.ts', + '.buble.js', + '.cirru', + '.cjsx', + '.co', + '.coffee', + '.coffee.md', + '.eg', + '.esm.js', + '.iced', + '.iced.md', + '.jsx', + '.litcoffee', + '.liticed', + '.ls', + '.mjs', + '.ts', + '.tsx', + '.wisp', +]; + +module.exports = { + extensions: extensions, + jsVariants: jsVariantExtensions.reduce(function(result, ext) { + result[ext] = extensions[ext]; + return result; + }, {}), +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/mjs-stub.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/mjs-stub.js new file mode 100644 index 000000000..6a1af9568 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/mjs-stub.js @@ -0,0 +1 @@ +require.extensions['.mjs'] = null; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/package.json new file mode 100644 index 000000000..cc05601f4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/interpret/package.json @@ -0,0 +1,75 @@ +{ + "name": "interpret", + "version": "2.2.0", + "description": "A dictionary of file extensions and associated module loaders.", + "author": "Gulp Team (http://gulpjs.com/)", + "contributors": [ + "Blaine Bublitz ", + "Tyler Kellen (http://goingslowly.com/)" + ], + "repository": "gulpjs/interpret", + "license": "MIT", + "engines": { + "node": ">= 0.10" + }, + "main": "index.js", + "files": [ + "LICENSE", + "index.js", + "mjs-stub.js" + ], + "scripts": { + "lint": "eslint .", + "pretest": "rm -rf tmp/ && npm run lint", + "test": "mocha --async-only", + "cover": "nyc --reporter=lcov --reporter=text-summary npm test", + "coveralls": "nyc --reporter=text-lcov npm test | coveralls" + }, + "dependencies": {}, + "devDependencies": { + "coveralls": "github:phated/node-coveralls#2.x", + "eslint": "^2.13.0", + "eslint-config-gulp": "^3.0.1", + "expect": "^1.20.2", + "mocha": "^3.5.3", + "nyc": "^10.3.2", + "parse-node-version": "^1.0.0", + "rechoir": "^0.7.0", + "shelljs": "0.7.5", + "trash-cli": "^3.0.0" + }, + "keywords": [ + "cirru-script", + "cjsx", + "co", + "coco", + "coffee", + "coffee-script", + "coffee.md", + "coffeescript", + "csv", + "earlgrey", + "es", + "es6", + "iced", + "iced.md", + "iced-coffee-script", + "ini", + "js", + "json", + "json5", + "jsx", + "react", + "litcoffee", + "liticed", + "ls", + "livescript", + "toml", + "ts", + "typescript", + "wisp", + "xml", + "yaml", + "yml" + ] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/LICENSE new file mode 100644 index 000000000..ec79adb0c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2011 by Beau Gunderson + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/README.md new file mode 100644 index 000000000..93ccb412d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/README.md @@ -0,0 +1,105 @@ +[![CircleCI](https://dl.circleci.com/status-badge/img/circleci/9fJmTZfn8d8p7GtVt688PY/JjriGjhcxBD6zYKygMZaet/tree/master.svg?style=svg&circle-token=7baede7efd3db5f1f25fb439e97d5f695ff76318)](https://dl.circleci.com/status-badge/redirect/circleci/9fJmTZfn8d8p7GtVt688PY/JjriGjhcxBD6zYKygMZaet/tree/master) +[![codecov]](https://codecov.io/github/beaugunderson/ip-address?branch=master) +[![downloads]](https://www.npmjs.com/package/ip-address) +[![npm]](https://www.npmjs.com/package/ip-address) +[![snyk]](https://snyk.io/test/github/beaugunderson/ip-address) + +[codecov]: https://codecov.io/github/beaugunderson/ip-address/coverage.svg?branch=master +[downloads]: https://img.shields.io/npm/dm/ip-address.svg +[npm]: https://img.shields.io/npm/v/ip-address.svg +[snyk]: https://snyk.io/test/github/beaugunderson/ip-address/badge.svg + +## ip-address + +`ip-address` is a library for validating and manipulating IPv4 and IPv6 +addresses in JavaScript. + +### Upgrading from 9.x to 10.x + +The dependency on `jsbn` was removed thanks to +[michal-kocarek](https://github.com/michal-kocarek). Thanks Michal! For +clarity, all methods with BigInteger in the name were renamed to BigInt. + +#### Breaking changes + +- `#fromBigInteger()` → `#fromBigInt()`; now returns a native BigInt +- `#bigInteger()` → `#bigInt()`; now returns a native BigInt + +### Documentation + +Documentation is available at [ip-address.js.org](http://ip-address.js.org/). + +### Examples + +```js +var Address6 = require('ip-address').Address6; + +var address = new Address6('2001:0:ce49:7601:e866:efff:62c3:fffe'); + +var teredo = address.inspectTeredo(); + +teredo.client4; // '157.60.0.1' +``` + +### Features + +- Usable via CommonJS or ESM +- Parsing of all IPv6 notations +- Parsing of IPv6 addresses and ports from URLs with `Address6.fromURL(url)` +- Validity checking +- Decoding of the [Teredo + information](http://en.wikipedia.org/wiki/Teredo_tunneling#IPv6_addressing) + in an address +- Whether one address is a valid subnet of another +- What special properties a given address has (multicast prefix, unique + local address prefix, etc.) +- Number of subnets of a certain size in a given address +- Display methods + - Hex, binary, and decimal + - Canonical form + - Correct form + - IPv4-compatible (i.e. `::ffff:192.168.0.1`) +- Works in [node](http://nodejs.org/) and the browser (with browserify) +- ~1,600 test cases + +### Used by + +- [anon](https://github.com/edsu/anon) which powers + [@congressedits](https://twitter.com/congressedits), among + [many others](https://github.com/edsu/anon#community) +- [base85](https://github.com/noseglid/base85): base85 encoding/decoding +- [contrail-web-core](https://github.com/Juniper/contrail-web-core): part of + Contrail, a network virtualization solution made by Juniper Networks +- [dhcpjs](https://github.com/apaprocki/node-dhcpjs): a DHCP client and server +- [epochtalk](https://github.com/epochtalk/epochtalk): next generation forum + software +- [geoip-web](https://github.com/tfrce/node-geoip-web): a server for + quickly geolocating IP addresses +- [hexabus](https://github.com/mysmartgrid/hexabus): an IPv6-based home + automation bus +- [hubot-deploy](https://github.com/atmos/hubot-deploy): GitHub Flow via hubot +- [heroku-portscanner](https://github.com/robison/heroku-portscanner): nmap + hosted on Heroku +- [ipfs-swarm](https://github.com/diasdavid/node-ipfs-swarm): a swarm + implementation based on IPFS +- [javascript-x-server](https://github.com/GothAck/javascript-x-server): an X + server written in JavaScript +- [libnmap](https://github.com/jas-/node-libnmap): a node API for nmap +- [mail-io](https://github.com/mofux/mail-io): a lightweight SMTP server +- [maxmind-db-reader](https://github.com/PaddeK/node-maxmind-db): a library for + reading MaxMind database files +- [proxy-protocol-v2](https://github.com/ably/proxy-protocol-v2): a proxy + protocol encoder/decoder built by [Ably](https://www.ably.io/) +- [Samsara](https://github.com/mariusGundersen/Samsara): a Docker web interface +- [sis-api](https://github.com/sis-cmdb/sis-api): a configuration management + database API +- [socks5-client](https://github.com/mattcg/socks5-client): a SOCKS v5 client +- [socksified](https://github.com/vially/node-socksified): a SOCKS v5 client +- [socksv5](https://github.com/mscdex/socksv5): a SOCKS v5 server/client +- [ssdapi](https://github.com/rsolomou/ssdapi): an API created by the + University of Portsmouth +- [SwitchyOmega](https://github.com/FelisCatus/SwitchyOmega): a [Chrome + extension](https://chrome.google.com/webstore/detail/padekgcemlokbadohgkifijomclgjgif) + for switching between multiple proxies with ~311k users! +- [swiz](https://github.com/racker/node-swiz): a serialization framework built + and used by [Rackspace](http://www.rackspace.com/) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.d.ts new file mode 100644 index 000000000..59b216516 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.d.ts @@ -0,0 +1,5 @@ +export declare class AddressError extends Error { + parseMessage?: string; + constructor(message: string, parseMessage?: string); +} +//# sourceMappingURL=address-error.d.ts.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.d.ts.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.d.ts.map new file mode 100644 index 000000000..0ef7fa696 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"address-error.d.ts","sourceRoot":"","sources":["../src/address-error.ts"],"names":[],"mappings":"AAAA,qBAAa,YAAa,SAAQ,KAAK;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;gBAEV,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM;CAOnD"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.js new file mode 100644 index 000000000..c178ae482 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.AddressError = void 0; +class AddressError extends Error { + constructor(message, parseMessage) { + super(message); + this.name = 'AddressError'; + this.parseMessage = parseMessage; + } +} +exports.AddressError = AddressError; +//# sourceMappingURL=address-error.js.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.js.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.js.map new file mode 100644 index 000000000..5d71d1343 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/address-error.js.map @@ -0,0 +1 @@ +{"version":3,"file":"address-error.js","sourceRoot":"","sources":["../src/address-error.ts"],"names":[],"mappings":";;;AAAA,MAAa,YAAa,SAAQ,KAAK;IAGrC,YAAY,OAAe,EAAE,YAAqB;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAE3B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;CACF;AAVD,oCAUC"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.d.ts new file mode 100644 index 000000000..a4250d881 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.d.ts @@ -0,0 +1,15 @@ +import { Address4 } from './ipv4'; +import { Address6 } from './ipv6'; +export interface ReverseFormOptions { + omitSuffix?: boolean; +} +export declare function isInSubnet(this: Address4 | Address6, address: Address4 | Address6): boolean; +export declare function isCorrect(defaultBits: number): (this: Address4 | Address6) => boolean; +export declare function numberToPaddedHex(number: number): string; +export declare function stringToPaddedHex(numberString: string): string; +/** + * @param binaryValue Binary representation of a value (e.g. `10`) + * @param position Byte position, where 0 is the least significant bit + */ +export declare function testBit(binaryValue: string, position: number): boolean; +//# sourceMappingURL=common.d.ts.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.d.ts.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.d.ts.map new file mode 100644 index 000000000..d13705ad6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,EAAE,OAAO,EAAE,QAAQ,GAAG,QAAQ,WAUjF;AAED,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,UACpB,QAAQ,GAAG,QAAQ,aAW3C;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,UAE/C;AAED,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,UAErD;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAStE"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.js new file mode 100644 index 000000000..273a01e28 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.js @@ -0,0 +1,46 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isInSubnet = isInSubnet; +exports.isCorrect = isCorrect; +exports.numberToPaddedHex = numberToPaddedHex; +exports.stringToPaddedHex = stringToPaddedHex; +exports.testBit = testBit; +function isInSubnet(address) { + if (this.subnetMask < address.subnetMask) { + return false; + } + if (this.mask(address.subnetMask) === address.mask()) { + return true; + } + return false; +} +function isCorrect(defaultBits) { + return function () { + if (this.addressMinusSuffix !== this.correctForm()) { + return false; + } + if (this.subnetMask === defaultBits && !this.parsedSubnet) { + return true; + } + return this.parsedSubnet === String(this.subnetMask); + }; +} +function numberToPaddedHex(number) { + return number.toString(16).padStart(2, '0'); +} +function stringToPaddedHex(numberString) { + return numberToPaddedHex(parseInt(numberString, 10)); +} +/** + * @param binaryValue Binary representation of a value (e.g. `10`) + * @param position Byte position, where 0 is the least significant bit + */ +function testBit(binaryValue, position) { + const { length } = binaryValue; + if (position > length) { + return false; + } + const positionInString = length - position; + return binaryValue.substring(positionInString, positionInString + 1) === '1'; +} +//# sourceMappingURL=common.js.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.js.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.js.map new file mode 100644 index 000000000..036ce661d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/common.js.map @@ -0,0 +1 @@ +{"version":3,"file":"common.js","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":";;AAOA,gCAUC;AAED,8BAYC;AAED,8CAEC;AAED,8CAEC;AAMD,0BASC;AA/CD,SAAgB,UAAU,CAA4B,OAA4B;IAChF,IAAI,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;QACzC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAgB,SAAS,CAAC,WAAmB;IAC3C,OAAO;QACL,IAAI,IAAI,CAAC,kBAAkB,KAAK,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACnD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,KAAK,WAAW,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YAC1D,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,YAAY,KAAK,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvD,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,iBAAiB,CAAC,MAAc;IAC9C,OAAO,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED,SAAgB,iBAAiB,CAAC,YAAoB;IACpD,OAAO,iBAAiB,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,CAAC;AACvD,CAAC;AAED;;;GAGG;AACH,SAAgB,OAAO,CAAC,WAAmB,EAAE,QAAgB;IAC3D,MAAM,EAAE,MAAM,EAAE,GAAG,WAAW,CAAC;IAE/B,IAAI,QAAQ,GAAG,MAAM,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC3C,OAAO,WAAW,CAAC,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC;AAC/E,CAAC"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.d.ts new file mode 100644 index 000000000..14f8fe002 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.d.ts @@ -0,0 +1,8 @@ +export { Address4 } from './ipv4'; +export { Address6 } from './ipv6'; +export { AddressError } from './address-error'; +import * as helpers from './v6/helpers'; +export declare const v6: { + helpers: typeof helpers; +}; +//# sourceMappingURL=ip-address.d.ts.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.d.ts.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.d.ts.map new file mode 100644 index 000000000..7bcb98aba --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ip-address.d.ts","sourceRoot":"","sources":["../src/ip-address.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAExC,eAAO,MAAM,EAAE;;CAAc,CAAC"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.js new file mode 100644 index 000000000..84f348709 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.js @@ -0,0 +1,35 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.v6 = exports.AddressError = exports.Address6 = exports.Address4 = void 0; +var ipv4_1 = require("./ipv4"); +Object.defineProperty(exports, "Address4", { enumerable: true, get: function () { return ipv4_1.Address4; } }); +var ipv6_1 = require("./ipv6"); +Object.defineProperty(exports, "Address6", { enumerable: true, get: function () { return ipv6_1.Address6; } }); +var address_error_1 = require("./address-error"); +Object.defineProperty(exports, "AddressError", { enumerable: true, get: function () { return address_error_1.AddressError; } }); +const helpers = __importStar(require("./v6/helpers")); +exports.v6 = { helpers }; +//# sourceMappingURL=ip-address.js.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.js.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.js.map new file mode 100644 index 000000000..cb89ed368 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ip-address.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ip-address.js","sourceRoot":"","sources":["../src/ip-address.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+BAAkC;AAAzB,gGAAA,QAAQ,OAAA;AACjB,+BAAkC;AAAzB,gGAAA,QAAQ,OAAA;AACjB,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AAErB,sDAAwC;AAE3B,QAAA,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.d.ts new file mode 100644 index 000000000..28edbaa5b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.d.ts @@ -0,0 +1,209 @@ +import * as common from './common'; +/** + * Represents an IPv4 address + * @class Address4 + * @param {string} address - An IPv4 address string + */ +export declare class Address4 { + address: string; + addressMinusSuffix?: string; + groups: number; + parsedAddress: string[]; + parsedSubnet: string; + subnet: string; + subnetMask: number; + v4: boolean; + constructor(address: string); + static isValid(address: string): boolean; + parse(address: string): string[]; + /** + * Returns the correct form of an address + * @memberof Address4 + * @instance + * @returns {String} + */ + correctForm(): string; + /** + * Returns true if the address is correct, false otherwise + * @memberof Address4 + * @instance + * @returns {Boolean} + */ + isCorrect: (this: Address4 | import("./ipv6").Address6) => boolean; + /** + * Converts a hex string to an IPv4 address object + * @memberof Address4 + * @static + * @param {string} hex - a hex string to convert + * @returns {Address4} + */ + static fromHex(hex: string): Address4; + /** + * Converts an integer into a IPv4 address object + * @memberof Address4 + * @static + * @param {integer} integer - a number to convert + * @returns {Address4} + */ + static fromInteger(integer: number): Address4; + /** + * Return an address from in-addr.arpa form + * @memberof Address4 + * @static + * @param {string} arpaFormAddress - an 'in-addr.arpa' form ipv4 address + * @returns {Adress4} + * @example + * var address = Address4.fromArpa(42.2.0.192.in-addr.arpa.) + * address.correctForm(); // '192.0.2.42' + */ + static fromArpa(arpaFormAddress: string): Address4; + /** + * Converts an IPv4 address object to a hex string + * @memberof Address4 + * @instance + * @returns {String} + */ + toHex(): string; + /** + * Converts an IPv4 address object to an array of bytes + * @memberof Address4 + * @instance + * @returns {Array} + */ + toArray(): number[]; + /** + * Converts an IPv4 address object to an IPv6 address group + * @memberof Address4 + * @instance + * @returns {String} + */ + toGroup6(): string; + /** + * Returns the address as a `bigint` + * @memberof Address4 + * @instance + * @returns {bigint} + */ + bigInt(): bigint; + /** + * Helper function getting start address. + * @memberof Address4 + * @instance + * @returns {bigint} + */ + _startAddress(): bigint; + /** + * The first address in the range given by this address' subnet. + * Often referred to as the Network Address. + * @memberof Address4 + * @instance + * @returns {Address4} + */ + startAddress(): Address4; + /** + * The first host address in the range given by this address's subnet ie + * the first address after the Network Address + * @memberof Address4 + * @instance + * @returns {Address4} + */ + startAddressExclusive(): Address4; + /** + * Helper function getting end address. + * @memberof Address4 + * @instance + * @returns {bigint} + */ + _endAddress(): bigint; + /** + * The last address in the range given by this address' subnet + * Often referred to as the Broadcast + * @memberof Address4 + * @instance + * @returns {Address4} + */ + endAddress(): Address4; + /** + * The last host address in the range given by this address's subnet ie + * the last address prior to the Broadcast Address + * @memberof Address4 + * @instance + * @returns {Address4} + */ + endAddressExclusive(): Address4; + /** + * Converts a BigInt to a v4 address object + * @memberof Address4 + * @static + * @param {bigint} bigInt - a BigInt to convert + * @returns {Address4} + */ + static fromBigInt(bigInt: bigint): Address4; + /** + * Convert a byte array to an Address4 object + * @memberof Address4 + * @static + * @param {Array} bytes - an array of 4 bytes (0-255) + * @returns {Address4} + */ + static fromByteArray(bytes: Array): Address4; + /** + * Convert an unsigned byte array to an Address4 object + * @memberof Address4 + * @static + * @param {Array} bytes - an array of 4 unsigned bytes (0-255) + * @returns {Address4} + */ + static fromUnsignedByteArray(bytes: Array): Address4; + /** + * Returns the first n bits of the address, defaulting to the + * subnet mask + * @memberof Address4 + * @instance + * @returns {String} + */ + mask(mask?: number): string; + /** + * Returns the bits in the given range as a base-2 string + * @memberof Address4 + * @instance + * @returns {string} + */ + getBitsBase2(start: number, end: number): string; + /** + * Return the reversed ip6.arpa form of the address + * @memberof Address4 + * @param {Object} options + * @param {boolean} options.omitSuffix - omit the "in-addr.arpa" suffix + * @instance + * @returns {String} + */ + reverseForm(options?: common.ReverseFormOptions): string; + /** + * Returns true if the given address is in the subnet of the current address + * @memberof Address4 + * @instance + * @returns {boolean} + */ + isInSubnet: typeof common.isInSubnet; + /** + * Returns true if the given address is a multicast address + * @memberof Address4 + * @instance + * @returns {boolean} + */ + isMulticast(): boolean; + /** + * Returns a zero-padded base-2 string representation of the address + * @memberof Address4 + * @instance + * @returns {string} + */ + binaryZeroPad(): string; + /** + * Groups an IPv4 address for inclusion at the end of an IPv6 address + * @returns {String} + */ + groupForV6(): string; +} +//# sourceMappingURL=ipv4.d.ts.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.d.ts.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.d.ts.map new file mode 100644 index 000000000..165d45912 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ipv4.d.ts","sourceRoot":"","sources":["../src/ipv4.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AAInC;;;;GAIG;AACH,qBAAa,QAAQ;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAoB;IAClC,aAAa,EAAE,MAAM,EAAE,CAAM;IAC7B,YAAY,EAAE,MAAM,CAAM;IAC1B,MAAM,EAAE,MAAM,CAAS;IACvB,UAAU,EAAE,MAAM,CAAM;IACxB,EAAE,EAAE,OAAO,CAAQ;gBAEP,OAAO,EAAE,MAAM;IAsB3B,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAcxC,KAAK,CAAC,OAAO,EAAE,MAAM;IAUrB;;;;;OAKG;IACH,WAAW,IAAI,MAAM;IAIrB;;;;;OAKG;IACH,SAAS,0DAAoC;IAE7C;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ;IAcrC;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ;IAI7C;;;;;;;;;OASG;IACH,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,QAAQ;IASlD;;;;;OAKG;IACH,KAAK,IAAI,MAAM;IAIf;;;;;OAKG;IACH,OAAO,IAAI,MAAM,EAAE;IAInB;;;;;OAKG;IACH,QAAQ,IAAI,MAAM;IAelB;;;;;OAKG;IACH,MAAM,IAAI,MAAM;IAIhB;;;;;OAKG;IACH,aAAa,IAAI,MAAM;IAIvB;;;;;;OAMG;IACH,YAAY,IAAI,QAAQ;IAIxB;;;;;;OAMG;IACH,qBAAqB,IAAI,QAAQ;IAKjC;;;;;OAKG;IACH,WAAW,IAAI,MAAM;IAIrB;;;;;;OAMG;IACH,UAAU,IAAI,QAAQ;IAItB;;;;;;OAMG;IACH,mBAAmB,IAAI,QAAQ;IAK/B;;;;;;OAMG;IACH,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAI3C;;;;;;OAMG;IACH,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,QAAQ;IAepD;;;;;;OAMG;IACH,MAAM,CAAC,qBAAqB,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,QAAQ;IAS5D;;;;;;OAMG;IACH,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM;IAQ3B;;;;;OAKG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;IAIhD;;;;;;;OAOG;IACH,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,kBAAkB,GAAG,MAAM;IAcxD;;;;;OAKG;IACH,UAAU,2BAAqB;IAE/B;;;;;OAKG;IACH,WAAW,IAAI,OAAO;IAItB;;;;;OAKG;IACH,aAAa,IAAI,MAAM;IAIvB;;;OAGG;IACH,UAAU,IAAI,MAAM;CAYrB"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.js new file mode 100644 index 000000000..311c89c69 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.js @@ -0,0 +1,360 @@ +"use strict"; +/* eslint-disable no-param-reassign */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Address4 = void 0; +const common = __importStar(require("./common")); +const constants = __importStar(require("./v4/constants")); +const address_error_1 = require("./address-error"); +/** + * Represents an IPv4 address + * @class Address4 + * @param {string} address - An IPv4 address string + */ +class Address4 { + constructor(address) { + this.groups = constants.GROUPS; + this.parsedAddress = []; + this.parsedSubnet = ''; + this.subnet = '/32'; + this.subnetMask = 32; + this.v4 = true; + /** + * Returns true if the address is correct, false otherwise + * @memberof Address4 + * @instance + * @returns {Boolean} + */ + this.isCorrect = common.isCorrect(constants.BITS); + /** + * Returns true if the given address is in the subnet of the current address + * @memberof Address4 + * @instance + * @returns {boolean} + */ + this.isInSubnet = common.isInSubnet; + this.address = address; + const subnet = constants.RE_SUBNET_STRING.exec(address); + if (subnet) { + this.parsedSubnet = subnet[0].replace('/', ''); + this.subnetMask = parseInt(this.parsedSubnet, 10); + this.subnet = `/${this.subnetMask}`; + if (this.subnetMask < 0 || this.subnetMask > constants.BITS) { + throw new address_error_1.AddressError('Invalid subnet mask.'); + } + address = address.replace(constants.RE_SUBNET_STRING, ''); + } + this.addressMinusSuffix = address; + this.parsedAddress = this.parse(address); + } + static isValid(address) { + try { + // eslint-disable-next-line no-new + new Address4(address); + return true; + } + catch (e) { + return false; + } + } + /* + * Parses a v4 address + */ + parse(address) { + const groups = address.split('.'); + if (!address.match(constants.RE_ADDRESS)) { + throw new address_error_1.AddressError('Invalid IPv4 address.'); + } + return groups; + } + /** + * Returns the correct form of an address + * @memberof Address4 + * @instance + * @returns {String} + */ + correctForm() { + return this.parsedAddress.map((part) => parseInt(part, 10)).join('.'); + } + /** + * Converts a hex string to an IPv4 address object + * @memberof Address4 + * @static + * @param {string} hex - a hex string to convert + * @returns {Address4} + */ + static fromHex(hex) { + const padded = hex.replace(/:/g, '').padStart(8, '0'); + const groups = []; + let i; + for (i = 0; i < 8; i += 2) { + const h = padded.slice(i, i + 2); + groups.push(parseInt(h, 16)); + } + return new Address4(groups.join('.')); + } + /** + * Converts an integer into a IPv4 address object + * @memberof Address4 + * @static + * @param {integer} integer - a number to convert + * @returns {Address4} + */ + static fromInteger(integer) { + return Address4.fromHex(integer.toString(16)); + } + /** + * Return an address from in-addr.arpa form + * @memberof Address4 + * @static + * @param {string} arpaFormAddress - an 'in-addr.arpa' form ipv4 address + * @returns {Adress4} + * @example + * var address = Address4.fromArpa(42.2.0.192.in-addr.arpa.) + * address.correctForm(); // '192.0.2.42' + */ + static fromArpa(arpaFormAddress) { + // remove ending ".in-addr.arpa." or just "." + const leader = arpaFormAddress.replace(/(\.in-addr\.arpa)?\.$/, ''); + const address = leader.split('.').reverse().join('.'); + return new Address4(address); + } + /** + * Converts an IPv4 address object to a hex string + * @memberof Address4 + * @instance + * @returns {String} + */ + toHex() { + return this.parsedAddress.map((part) => common.stringToPaddedHex(part)).join(':'); + } + /** + * Converts an IPv4 address object to an array of bytes + * @memberof Address4 + * @instance + * @returns {Array} + */ + toArray() { + return this.parsedAddress.map((part) => parseInt(part, 10)); + } + /** + * Converts an IPv4 address object to an IPv6 address group + * @memberof Address4 + * @instance + * @returns {String} + */ + toGroup6() { + const output = []; + let i; + for (i = 0; i < constants.GROUPS; i += 2) { + output.push(`${common.stringToPaddedHex(this.parsedAddress[i])}${common.stringToPaddedHex(this.parsedAddress[i + 1])}`); + } + return output.join(':'); + } + /** + * Returns the address as a `bigint` + * @memberof Address4 + * @instance + * @returns {bigint} + */ + bigInt() { + return BigInt(`0x${this.parsedAddress.map((n) => common.stringToPaddedHex(n)).join('')}`); + } + /** + * Helper function getting start address. + * @memberof Address4 + * @instance + * @returns {bigint} + */ + _startAddress() { + return BigInt(`0b${this.mask() + '0'.repeat(constants.BITS - this.subnetMask)}`); + } + /** + * The first address in the range given by this address' subnet. + * Often referred to as the Network Address. + * @memberof Address4 + * @instance + * @returns {Address4} + */ + startAddress() { + return Address4.fromBigInt(this._startAddress()); + } + /** + * The first host address in the range given by this address's subnet ie + * the first address after the Network Address + * @memberof Address4 + * @instance + * @returns {Address4} + */ + startAddressExclusive() { + const adjust = BigInt('1'); + return Address4.fromBigInt(this._startAddress() + adjust); + } + /** + * Helper function getting end address. + * @memberof Address4 + * @instance + * @returns {bigint} + */ + _endAddress() { + return BigInt(`0b${this.mask() + '1'.repeat(constants.BITS - this.subnetMask)}`); + } + /** + * The last address in the range given by this address' subnet + * Often referred to as the Broadcast + * @memberof Address4 + * @instance + * @returns {Address4} + */ + endAddress() { + return Address4.fromBigInt(this._endAddress()); + } + /** + * The last host address in the range given by this address's subnet ie + * the last address prior to the Broadcast Address + * @memberof Address4 + * @instance + * @returns {Address4} + */ + endAddressExclusive() { + const adjust = BigInt('1'); + return Address4.fromBigInt(this._endAddress() - adjust); + } + /** + * Converts a BigInt to a v4 address object + * @memberof Address4 + * @static + * @param {bigint} bigInt - a BigInt to convert + * @returns {Address4} + */ + static fromBigInt(bigInt) { + return Address4.fromHex(bigInt.toString(16)); + } + /** + * Convert a byte array to an Address4 object + * @memberof Address4 + * @static + * @param {Array} bytes - an array of 4 bytes (0-255) + * @returns {Address4} + */ + static fromByteArray(bytes) { + if (bytes.length !== 4) { + throw new address_error_1.AddressError('IPv4 addresses require exactly 4 bytes'); + } + // Validate that all bytes are within valid range (0-255) + for (let i = 0; i < bytes.length; i++) { + if (!Number.isInteger(bytes[i]) || bytes[i] < 0 || bytes[i] > 255) { + throw new address_error_1.AddressError('All bytes must be integers between 0 and 255'); + } + } + return this.fromUnsignedByteArray(bytes); + } + /** + * Convert an unsigned byte array to an Address4 object + * @memberof Address4 + * @static + * @param {Array} bytes - an array of 4 unsigned bytes (0-255) + * @returns {Address4} + */ + static fromUnsignedByteArray(bytes) { + if (bytes.length !== 4) { + throw new address_error_1.AddressError('IPv4 addresses require exactly 4 bytes'); + } + const address = bytes.join('.'); + return new Address4(address); + } + /** + * Returns the first n bits of the address, defaulting to the + * subnet mask + * @memberof Address4 + * @instance + * @returns {String} + */ + mask(mask) { + if (mask === undefined) { + mask = this.subnetMask; + } + return this.getBitsBase2(0, mask); + } + /** + * Returns the bits in the given range as a base-2 string + * @memberof Address4 + * @instance + * @returns {string} + */ + getBitsBase2(start, end) { + return this.binaryZeroPad().slice(start, end); + } + /** + * Return the reversed ip6.arpa form of the address + * @memberof Address4 + * @param {Object} options + * @param {boolean} options.omitSuffix - omit the "in-addr.arpa" suffix + * @instance + * @returns {String} + */ + reverseForm(options) { + if (!options) { + options = {}; + } + const reversed = this.correctForm().split('.').reverse().join('.'); + if (options.omitSuffix) { + return reversed; + } + return `${reversed}.in-addr.arpa.`; + } + /** + * Returns true if the given address is a multicast address + * @memberof Address4 + * @instance + * @returns {boolean} + */ + isMulticast() { + return this.isInSubnet(new Address4('224.0.0.0/4')); + } + /** + * Returns a zero-padded base-2 string representation of the address + * @memberof Address4 + * @instance + * @returns {string} + */ + binaryZeroPad() { + return this.bigInt().toString(2).padStart(constants.BITS, '0'); + } + /** + * Groups an IPv4 address for inclusion at the end of an IPv6 address + * @returns {String} + */ + groupForV6() { + const segments = this.parsedAddress; + return this.address.replace(constants.RE_ADDRESS, `${segments + .slice(0, 2) + .join('.')}.${segments + .slice(2, 4) + .join('.')}`); + } +} +exports.Address4 = Address4; +//# sourceMappingURL=ipv4.js.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.js.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.js.map new file mode 100644 index 000000000..2b4e92804 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv4.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ipv4.js","sourceRoot":"","sources":["../src/ipv4.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.d.ts new file mode 100644 index 000000000..2a7c7e0b3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.d.ts @@ -0,0 +1,428 @@ +import * as common from './common'; +import { Address4 } from './ipv4'; +interface SixToFourProperties { + prefix: string; + gateway: string; +} +interface TeredoProperties { + prefix: string; + server4: string; + client4: string; + flags: string; + coneNat: boolean; + microsoft: { + reserved: boolean; + universalLocal: boolean; + groupIndividual: boolean; + nonce: string; + }; + udpPort: string; +} +/** + * Represents an IPv6 address + * @class Address6 + * @param {string} address - An IPv6 address string + * @param {number} [groups=8] - How many octets to parse + * @example + * var address = new Address6('2001::/32'); + */ +export declare class Address6 { + address4?: Address4; + address: string; + addressMinusSuffix: string; + elidedGroups?: number; + elisionBegin?: number; + elisionEnd?: number; + groups: number; + parsedAddress4?: string; + parsedAddress: string[]; + parsedSubnet: string; + subnet: string; + subnetMask: number; + v4: boolean; + zone: string; + constructor(address: string, optionalGroups?: number); + static isValid(address: string): boolean; + /** + * Convert a BigInt to a v6 address object + * @memberof Address6 + * @static + * @param {bigint} bigInt - a BigInt to convert + * @returns {Address6} + * @example + * var bigInt = BigInt('1000000000000'); + * var address = Address6.fromBigInt(bigInt); + * address.correctForm(); // '::e8:d4a5:1000' + */ + static fromBigInt(bigInt: bigint): Address6; + /** + * Convert a URL (with optional port number) to an address object + * @memberof Address6 + * @static + * @param {string} url - a URL with optional port number + * @example + * var addressAndPort = Address6.fromURL('http://[ffff::]:8080/foo/'); + * addressAndPort.address.correctForm(); // 'ffff::' + * addressAndPort.port; // 8080 + */ + static fromURL(url: string): { + error: string; + address: null; + port: null; + } | { + address: Address6; + port: number | null; + error?: undefined; + }; + /** + * Create an IPv6-mapped address given an IPv4 address + * @memberof Address6 + * @static + * @param {string} address - An IPv4 address string + * @returns {Address6} + * @example + * var address = Address6.fromAddress4('192.168.0.1'); + * address.correctForm(); // '::ffff:c0a8:1' + * address.to4in6(); // '::ffff:192.168.0.1' + */ + static fromAddress4(address: string): Address6; + /** + * Return an address from ip6.arpa form + * @memberof Address6 + * @static + * @param {string} arpaFormAddress - an 'ip6.arpa' form address + * @returns {Adress6} + * @example + * var address = Address6.fromArpa(e.f.f.f.3.c.2.6.f.f.f.e.6.6.8.e.1.0.6.7.9.4.e.c.0.0.0.0.1.0.0.2.ip6.arpa.) + * address.correctForm(); // '2001:0:ce49:7601:e866:efff:62c3:fffe' + */ + static fromArpa(arpaFormAddress: string): Address6; + /** + * Return the Microsoft UNC transcription of the address + * @memberof Address6 + * @instance + * @returns {String} the Microsoft UNC transcription of the address + */ + microsoftTranscription(): string; + /** + * Return the first n bits of the address, defaulting to the subnet mask + * @memberof Address6 + * @instance + * @param {number} [mask=subnet] - the number of bits to mask + * @returns {String} the first n bits of the address as a string + */ + mask(mask?: number): string; + /** + * Return the number of possible subnets of a given size in the address + * @memberof Address6 + * @instance + * @param {number} [subnetSize=128] - the subnet size + * @returns {String} + */ + possibleSubnets(subnetSize?: number): string; + /** + * Helper function getting start address. + * @memberof Address6 + * @instance + * @returns {bigint} + */ + _startAddress(): bigint; + /** + * The first address in the range given by this address' subnet + * Often referred to as the Network Address. + * @memberof Address6 + * @instance + * @returns {Address6} + */ + startAddress(): Address6; + /** + * The first host address in the range given by this address's subnet ie + * the first address after the Network Address + * @memberof Address6 + * @instance + * @returns {Address6} + */ + startAddressExclusive(): Address6; + /** + * Helper function getting end address. + * @memberof Address6 + * @instance + * @returns {bigint} + */ + _endAddress(): bigint; + /** + * The last address in the range given by this address' subnet + * Often referred to as the Broadcast + * @memberof Address6 + * @instance + * @returns {Address6} + */ + endAddress(): Address6; + /** + * The last host address in the range given by this address's subnet ie + * the last address prior to the Broadcast Address + * @memberof Address6 + * @instance + * @returns {Address6} + */ + endAddressExclusive(): Address6; + /** + * Return the scope of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + getScope(): string; + /** + * Return the type of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + getType(): string; + /** + * Return the bits in the given range as a BigInt + * @memberof Address6 + * @instance + * @returns {bigint} + */ + getBits(start: number, end: number): bigint; + /** + * Return the bits in the given range as a base-2 string + * @memberof Address6 + * @instance + * @returns {String} + */ + getBitsBase2(start: number, end: number): string; + /** + * Return the bits in the given range as a base-16 string + * @memberof Address6 + * @instance + * @returns {String} + */ + getBitsBase16(start: number, end: number): string; + /** + * Return the bits that are set past the subnet mask length + * @memberof Address6 + * @instance + * @returns {String} + */ + getBitsPastSubnet(): string; + /** + * Return the reversed ip6.arpa form of the address + * @memberof Address6 + * @param {Object} options + * @param {boolean} options.omitSuffix - omit the "ip6.arpa" suffix + * @instance + * @returns {String} + */ + reverseForm(options?: common.ReverseFormOptions): string; + /** + * Return the correct form of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + correctForm(): string; + /** + * Return a zero-padded base-2 string representation of the address + * @memberof Address6 + * @instance + * @returns {String} + * @example + * var address = new Address6('2001:4860:4001:803::1011'); + * address.binaryZeroPad(); + * // '0010000000000001010010000110000001000000000000010000100000000011 + * // 0000000000000000000000000000000000000000000000000001000000010001' + */ + binaryZeroPad(): string; + parse4in6(address: string): string; + parse(address: string): string[]; + /** + * Return the canonical form of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + canonicalForm(): string; + /** + * Return the decimal form of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + decimal(): string; + /** + * Return the address as a BigInt + * @memberof Address6 + * @instance + * @returns {bigint} + */ + bigInt(): bigint; + /** + * Return the last two groups of this address as an IPv4 address string + * @memberof Address6 + * @instance + * @returns {Address4} + * @example + * var address = new Address6('2001:4860:4001::1825:bf11'); + * address.to4().correctForm(); // '24.37.191.17' + */ + to4(): Address4; + /** + * Return the v4-in-v6 form of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + to4in6(): string; + /** + * Return an object containing the Teredo properties of the address + * @memberof Address6 + * @instance + * @returns {Object} + */ + inspectTeredo(): TeredoProperties; + /** + * Return an object containing the 6to4 properties of the address + * @memberof Address6 + * @instance + * @returns {Object} + */ + inspect6to4(): SixToFourProperties; + /** + * Return a v6 6to4 address from a v6 v4inv6 address + * @memberof Address6 + * @instance + * @returns {Address6} + */ + to6to4(): Address6 | null; + /** + * Return a byte array + * @memberof Address6 + * @instance + * @returns {Array} + */ + toByteArray(): number[]; + /** + * Return an unsigned byte array + * @memberof Address6 + * @instance + * @returns {Array} + */ + toUnsignedByteArray(): number[]; + /** + * Convert a byte array to an Address6 object + * @memberof Address6 + * @static + * @returns {Address6} + */ + static fromByteArray(bytes: Array): Address6; + /** + * Convert an unsigned byte array to an Address6 object + * @memberof Address6 + * @static + * @returns {Address6} + */ + static fromUnsignedByteArray(bytes: Array): Address6; + /** + * Returns true if the given address is in the subnet of the current address + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isInSubnet: typeof common.isInSubnet; + /** + * Returns true if the address is correct, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isCorrect: (this: Address4 | Address6) => boolean; + /** + * Returns true if the address is in the canonical form, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isCanonical(): boolean; + /** + * Returns true if the address is a link local address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isLinkLocal(): boolean; + /** + * Returns true if the address is a multicast address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isMulticast(): boolean; + /** + * Returns true if the address is a v4-in-v6 address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + is4(): boolean; + /** + * Returns true if the address is a Teredo address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isTeredo(): boolean; + /** + * Returns true if the address is a 6to4 address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + is6to4(): boolean; + /** + * Returns true if the address is a loopback address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isLoopback(): boolean; + /** + * @returns {String} the address in link form with a default port of 80 + */ + href(optionalPort?: number | string): string; + /** + * @returns {String} a link suitable for conveying the address via a URL hash + */ + link(options?: { + className?: string; + prefix?: string; + v4?: boolean; + }): string; + /** + * Groups an address + * @returns {String} + */ + group(): string; + /** + * Generate a regular expression string that can be used to find or validate + * all variations of this address + * @memberof Address6 + * @instance + * @param {boolean} substringSearch + * @returns {string} + */ + regularExpressionString(this: Address6, substringSearch?: boolean): string; + /** + * Generate a regular expression that can be used to find or validate all + * variations of this address. + * @memberof Address6 + * @instance + * @param {boolean} substringSearch + * @returns {RegExp} + */ + regularExpression(this: Address6, substringSearch?: boolean): RegExp; +} +export {}; +//# sourceMappingURL=ipv6.d.ts.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.d.ts.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.d.ts.map new file mode 100644 index 000000000..37ead6aa0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ipv6.d.ts","sourceRoot":"","sources":["../src/ipv6.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.js new file mode 100644 index 000000000..5f88ab63a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.js @@ -0,0 +1,1003 @@ +"use strict"; +/* eslint-disable prefer-destructuring */ +/* eslint-disable no-param-reassign */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Address6 = void 0; +const common = __importStar(require("./common")); +const constants4 = __importStar(require("./v4/constants")); +const constants6 = __importStar(require("./v6/constants")); +const helpers = __importStar(require("./v6/helpers")); +const ipv4_1 = require("./ipv4"); +const regular_expressions_1 = require("./v6/regular-expressions"); +const address_error_1 = require("./address-error"); +const common_1 = require("./common"); +function assert(condition) { + if (!condition) { + throw new Error('Assertion failed.'); + } +} +function addCommas(number) { + const r = /(\d+)(\d{3})/; + while (r.test(number)) { + number = number.replace(r, '$1,$2'); + } + return number; +} +function spanLeadingZeroes4(n) { + n = n.replace(/^(0{1,})([1-9]+)$/, '$1$2'); + n = n.replace(/^(0{1,})(0)$/, '$1$2'); + return n; +} +/* + * A helper function to compact an array + */ +function compact(address, slice) { + const s1 = []; + const s2 = []; + let i; + for (i = 0; i < address.length; i++) { + if (i < slice[0]) { + s1.push(address[i]); + } + else if (i > slice[1]) { + s2.push(address[i]); + } + } + return s1.concat(['compact']).concat(s2); +} +function paddedHex(octet) { + return parseInt(octet, 16).toString(16).padStart(4, '0'); +} +function unsignByte(b) { + // eslint-disable-next-line no-bitwise + return b & 0xff; +} +/** + * Represents an IPv6 address + * @class Address6 + * @param {string} address - An IPv6 address string + * @param {number} [groups=8] - How many octets to parse + * @example + * var address = new Address6('2001::/32'); + */ +class Address6 { + constructor(address, optionalGroups) { + this.addressMinusSuffix = ''; + this.parsedSubnet = ''; + this.subnet = '/128'; + this.subnetMask = 128; + this.v4 = false; + this.zone = ''; + // #region Attributes + /** + * Returns true if the given address is in the subnet of the current address + * @memberof Address6 + * @instance + * @returns {boolean} + */ + this.isInSubnet = common.isInSubnet; + /** + * Returns true if the address is correct, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + this.isCorrect = common.isCorrect(constants6.BITS); + if (optionalGroups === undefined) { + this.groups = constants6.GROUPS; + } + else { + this.groups = optionalGroups; + } + this.address = address; + const subnet = constants6.RE_SUBNET_STRING.exec(address); + if (subnet) { + this.parsedSubnet = subnet[0].replace('/', ''); + this.subnetMask = parseInt(this.parsedSubnet, 10); + this.subnet = `/${this.subnetMask}`; + if (Number.isNaN(this.subnetMask) || + this.subnetMask < 0 || + this.subnetMask > constants6.BITS) { + throw new address_error_1.AddressError('Invalid subnet mask.'); + } + address = address.replace(constants6.RE_SUBNET_STRING, ''); + } + else if (/\//.test(address)) { + throw new address_error_1.AddressError('Invalid subnet mask.'); + } + const zone = constants6.RE_ZONE_STRING.exec(address); + if (zone) { + this.zone = zone[0]; + address = address.replace(constants6.RE_ZONE_STRING, ''); + } + this.addressMinusSuffix = address; + this.parsedAddress = this.parse(this.addressMinusSuffix); + } + static isValid(address) { + try { + // eslint-disable-next-line no-new + new Address6(address); + return true; + } + catch (e) { + return false; + } + } + /** + * Convert a BigInt to a v6 address object + * @memberof Address6 + * @static + * @param {bigint} bigInt - a BigInt to convert + * @returns {Address6} + * @example + * var bigInt = BigInt('1000000000000'); + * var address = Address6.fromBigInt(bigInt); + * address.correctForm(); // '::e8:d4a5:1000' + */ + static fromBigInt(bigInt) { + const hex = bigInt.toString(16).padStart(32, '0'); + const groups = []; + let i; + for (i = 0; i < constants6.GROUPS; i++) { + groups.push(hex.slice(i * 4, (i + 1) * 4)); + } + return new Address6(groups.join(':')); + } + /** + * Convert a URL (with optional port number) to an address object + * @memberof Address6 + * @static + * @param {string} url - a URL with optional port number + * @example + * var addressAndPort = Address6.fromURL('http://[ffff::]:8080/foo/'); + * addressAndPort.address.correctForm(); // 'ffff::' + * addressAndPort.port; // 8080 + */ + static fromURL(url) { + let host; + let port = null; + let result; + // If we have brackets parse them and find a port + if (url.indexOf('[') !== -1 && url.indexOf(']:') !== -1) { + result = constants6.RE_URL_WITH_PORT.exec(url); + if (result === null) { + return { + error: 'failed to parse address with port', + address: null, + port: null, + }; + } + host = result[1]; + port = result[2]; + // If there's a URL extract the address + } + else if (url.indexOf('/') !== -1) { + // Remove the protocol prefix + url = url.replace(/^[a-z0-9]+:\/\//, ''); + // Parse the address + result = constants6.RE_URL.exec(url); + if (result === null) { + return { + error: 'failed to parse address from URL', + address: null, + port: null, + }; + } + host = result[1]; + // Otherwise just assign the URL to the host and let the library parse it + } + else { + host = url; + } + // If there's a port convert it to an integer + if (port) { + port = parseInt(port, 10); + // squelch out of range ports + if (port < 0 || port > 65536) { + port = null; + } + } + else { + // Standardize `undefined` to `null` + port = null; + } + return { + address: new Address6(host), + port, + }; + } + /** + * Create an IPv6-mapped address given an IPv4 address + * @memberof Address6 + * @static + * @param {string} address - An IPv4 address string + * @returns {Address6} + * @example + * var address = Address6.fromAddress4('192.168.0.1'); + * address.correctForm(); // '::ffff:c0a8:1' + * address.to4in6(); // '::ffff:192.168.0.1' + */ + static fromAddress4(address) { + const address4 = new ipv4_1.Address4(address); + const mask6 = constants6.BITS - (constants4.BITS - address4.subnetMask); + return new Address6(`::ffff:${address4.correctForm()}/${mask6}`); + } + /** + * Return an address from ip6.arpa form + * @memberof Address6 + * @static + * @param {string} arpaFormAddress - an 'ip6.arpa' form address + * @returns {Adress6} + * @example + * var address = Address6.fromArpa(e.f.f.f.3.c.2.6.f.f.f.e.6.6.8.e.1.0.6.7.9.4.e.c.0.0.0.0.1.0.0.2.ip6.arpa.) + * address.correctForm(); // '2001:0:ce49:7601:e866:efff:62c3:fffe' + */ + static fromArpa(arpaFormAddress) { + // remove ending ".ip6.arpa." or just "." + let address = arpaFormAddress.replace(/(\.ip6\.arpa)?\.$/, ''); + const semicolonAmount = 7; + // correct ip6.arpa form with ending removed will be 63 characters + if (address.length !== 63) { + throw new address_error_1.AddressError("Invalid 'ip6.arpa' form."); + } + const parts = address.split('.').reverse(); + for (let i = semicolonAmount; i > 0; i--) { + const insertIndex = i * 4; + parts.splice(insertIndex, 0, ':'); + } + address = parts.join(''); + return new Address6(address); + } + /** + * Return the Microsoft UNC transcription of the address + * @memberof Address6 + * @instance + * @returns {String} the Microsoft UNC transcription of the address + */ + microsoftTranscription() { + return `${this.correctForm().replace(/:/g, '-')}.ipv6-literal.net`; + } + /** + * Return the first n bits of the address, defaulting to the subnet mask + * @memberof Address6 + * @instance + * @param {number} [mask=subnet] - the number of bits to mask + * @returns {String} the first n bits of the address as a string + */ + mask(mask = this.subnetMask) { + return this.getBitsBase2(0, mask); + } + /** + * Return the number of possible subnets of a given size in the address + * @memberof Address6 + * @instance + * @param {number} [subnetSize=128] - the subnet size + * @returns {String} + */ + // TODO: probably useful to have a numeric version of this too + possibleSubnets(subnetSize = 128) { + const availableBits = constants6.BITS - this.subnetMask; + const subnetBits = Math.abs(subnetSize - constants6.BITS); + const subnetPowers = availableBits - subnetBits; + if (subnetPowers < 0) { + return '0'; + } + return addCommas((BigInt('2') ** BigInt(subnetPowers)).toString(10)); + } + /** + * Helper function getting start address. + * @memberof Address6 + * @instance + * @returns {bigint} + */ + _startAddress() { + return BigInt(`0b${this.mask() + '0'.repeat(constants6.BITS - this.subnetMask)}`); + } + /** + * The first address in the range given by this address' subnet + * Often referred to as the Network Address. + * @memberof Address6 + * @instance + * @returns {Address6} + */ + startAddress() { + return Address6.fromBigInt(this._startAddress()); + } + /** + * The first host address in the range given by this address's subnet ie + * the first address after the Network Address + * @memberof Address6 + * @instance + * @returns {Address6} + */ + startAddressExclusive() { + const adjust = BigInt('1'); + return Address6.fromBigInt(this._startAddress() + adjust); + } + /** + * Helper function getting end address. + * @memberof Address6 + * @instance + * @returns {bigint} + */ + _endAddress() { + return BigInt(`0b${this.mask() + '1'.repeat(constants6.BITS - this.subnetMask)}`); + } + /** + * The last address in the range given by this address' subnet + * Often referred to as the Broadcast + * @memberof Address6 + * @instance + * @returns {Address6} + */ + endAddress() { + return Address6.fromBigInt(this._endAddress()); + } + /** + * The last host address in the range given by this address's subnet ie + * the last address prior to the Broadcast Address + * @memberof Address6 + * @instance + * @returns {Address6} + */ + endAddressExclusive() { + const adjust = BigInt('1'); + return Address6.fromBigInt(this._endAddress() - adjust); + } + /** + * Return the scope of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + getScope() { + let scope = constants6.SCOPES[parseInt(this.getBits(12, 16).toString(10), 10)]; + if (this.getType() === 'Global unicast' && scope !== 'Link local') { + scope = 'Global'; + } + return scope || 'Unknown'; + } + /** + * Return the type of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + getType() { + for (const subnet of Object.keys(constants6.TYPES)) { + if (this.isInSubnet(new Address6(subnet))) { + return constants6.TYPES[subnet]; + } + } + return 'Global unicast'; + } + /** + * Return the bits in the given range as a BigInt + * @memberof Address6 + * @instance + * @returns {bigint} + */ + getBits(start, end) { + return BigInt(`0b${this.getBitsBase2(start, end)}`); + } + /** + * Return the bits in the given range as a base-2 string + * @memberof Address6 + * @instance + * @returns {String} + */ + getBitsBase2(start, end) { + return this.binaryZeroPad().slice(start, end); + } + /** + * Return the bits in the given range as a base-16 string + * @memberof Address6 + * @instance + * @returns {String} + */ + getBitsBase16(start, end) { + const length = end - start; + if (length % 4 !== 0) { + throw new Error('Length of bits to retrieve must be divisible by four'); + } + return this.getBits(start, end) + .toString(16) + .padStart(length / 4, '0'); + } + /** + * Return the bits that are set past the subnet mask length + * @memberof Address6 + * @instance + * @returns {String} + */ + getBitsPastSubnet() { + return this.getBitsBase2(this.subnetMask, constants6.BITS); + } + /** + * Return the reversed ip6.arpa form of the address + * @memberof Address6 + * @param {Object} options + * @param {boolean} options.omitSuffix - omit the "ip6.arpa" suffix + * @instance + * @returns {String} + */ + reverseForm(options) { + if (!options) { + options = {}; + } + const characters = Math.floor(this.subnetMask / 4); + const reversed = this.canonicalForm() + .replace(/:/g, '') + .split('') + .slice(0, characters) + .reverse() + .join('.'); + if (characters > 0) { + if (options.omitSuffix) { + return reversed; + } + return `${reversed}.ip6.arpa.`; + } + if (options.omitSuffix) { + return ''; + } + return 'ip6.arpa.'; + } + /** + * Return the correct form of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + correctForm() { + let i; + let groups = []; + let zeroCounter = 0; + const zeroes = []; + for (i = 0; i < this.parsedAddress.length; i++) { + const value = parseInt(this.parsedAddress[i], 16); + if (value === 0) { + zeroCounter++; + } + if (value !== 0 && zeroCounter > 0) { + if (zeroCounter > 1) { + zeroes.push([i - zeroCounter, i - 1]); + } + zeroCounter = 0; + } + } + // Do we end with a string of zeroes? + if (zeroCounter > 1) { + zeroes.push([this.parsedAddress.length - zeroCounter, this.parsedAddress.length - 1]); + } + const zeroLengths = zeroes.map((n) => n[1] - n[0] + 1); + if (zeroes.length > 0) { + const index = zeroLengths.indexOf(Math.max(...zeroLengths)); + groups = compact(this.parsedAddress, zeroes[index]); + } + else { + groups = this.parsedAddress; + } + for (i = 0; i < groups.length; i++) { + if (groups[i] !== 'compact') { + groups[i] = parseInt(groups[i], 16).toString(16); + } + } + let correct = groups.join(':'); + correct = correct.replace(/^compact$/, '::'); + correct = correct.replace(/(^compact)|(compact$)/, ':'); + correct = correct.replace(/compact/, ''); + return correct; + } + /** + * Return a zero-padded base-2 string representation of the address + * @memberof Address6 + * @instance + * @returns {String} + * @example + * var address = new Address6('2001:4860:4001:803::1011'); + * address.binaryZeroPad(); + * // '0010000000000001010010000110000001000000000000010000100000000011 + * // 0000000000000000000000000000000000000000000000000001000000010001' + */ + binaryZeroPad() { + return this.bigInt().toString(2).padStart(constants6.BITS, '0'); + } + // TODO: Improve the semantics of this helper function + parse4in6(address) { + const groups = address.split(':'); + const lastGroup = groups.slice(-1)[0]; + const address4 = lastGroup.match(constants4.RE_ADDRESS); + if (address4) { + this.parsedAddress4 = address4[0]; + this.address4 = new ipv4_1.Address4(this.parsedAddress4); + for (let i = 0; i < this.address4.groups; i++) { + if (/^0[0-9]+/.test(this.address4.parsedAddress[i])) { + throw new address_error_1.AddressError("IPv4 addresses can't have leading zeroes.", address.replace(constants4.RE_ADDRESS, this.address4.parsedAddress.map(spanLeadingZeroes4).join('.'))); + } + } + this.v4 = true; + groups[groups.length - 1] = this.address4.toGroup6(); + address = groups.join(':'); + } + return address; + } + // TODO: Make private? + parse(address) { + address = this.parse4in6(address); + const badCharacters = address.match(constants6.RE_BAD_CHARACTERS); + if (badCharacters) { + throw new address_error_1.AddressError(`Bad character${badCharacters.length > 1 ? 's' : ''} detected in address: ${badCharacters.join('')}`, address.replace(constants6.RE_BAD_CHARACTERS, '$1')); + } + const badAddress = address.match(constants6.RE_BAD_ADDRESS); + if (badAddress) { + throw new address_error_1.AddressError(`Address failed regex: ${badAddress.join('')}`, address.replace(constants6.RE_BAD_ADDRESS, '$1')); + } + let groups = []; + const halves = address.split('::'); + if (halves.length === 2) { + let first = halves[0].split(':'); + let last = halves[1].split(':'); + if (first.length === 1 && first[0] === '') { + first = []; + } + if (last.length === 1 && last[0] === '') { + last = []; + } + const remaining = this.groups - (first.length + last.length); + if (!remaining) { + throw new address_error_1.AddressError('Error parsing groups'); + } + this.elidedGroups = remaining; + this.elisionBegin = first.length; + this.elisionEnd = first.length + this.elidedGroups; + groups = groups.concat(first); + for (let i = 0; i < remaining; i++) { + groups.push('0'); + } + groups = groups.concat(last); + } + else if (halves.length === 1) { + groups = address.split(':'); + this.elidedGroups = 0; + } + else { + throw new address_error_1.AddressError('Too many :: groups found'); + } + groups = groups.map((group) => parseInt(group, 16).toString(16)); + if (groups.length !== this.groups) { + throw new address_error_1.AddressError('Incorrect number of groups found'); + } + return groups; + } + /** + * Return the canonical form of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + canonicalForm() { + return this.parsedAddress.map(paddedHex).join(':'); + } + /** + * Return the decimal form of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + decimal() { + return this.parsedAddress.map((n) => parseInt(n, 16).toString(10).padStart(5, '0')).join(':'); + } + /** + * Return the address as a BigInt + * @memberof Address6 + * @instance + * @returns {bigint} + */ + bigInt() { + return BigInt(`0x${this.parsedAddress.map(paddedHex).join('')}`); + } + /** + * Return the last two groups of this address as an IPv4 address string + * @memberof Address6 + * @instance + * @returns {Address4} + * @example + * var address = new Address6('2001:4860:4001::1825:bf11'); + * address.to4().correctForm(); // '24.37.191.17' + */ + to4() { + const binary = this.binaryZeroPad().split(''); + return ipv4_1.Address4.fromHex(BigInt(`0b${binary.slice(96, 128).join('')}`).toString(16)); + } + /** + * Return the v4-in-v6 form of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + to4in6() { + const address4 = this.to4(); + const address6 = new Address6(this.parsedAddress.slice(0, 6).join(':'), 6); + const correct = address6.correctForm(); + let infix = ''; + if (!/:$/.test(correct)) { + infix = ':'; + } + return correct + infix + address4.address; + } + /** + * Return an object containing the Teredo properties of the address + * @memberof Address6 + * @instance + * @returns {Object} + */ + inspectTeredo() { + /* + - Bits 0 to 31 are set to the Teredo prefix (normally 2001:0000::/32). + - Bits 32 to 63 embed the primary IPv4 address of the Teredo server that + is used. + - Bits 64 to 79 can be used to define some flags. Currently only the + higher order bit is used; it is set to 1 if the Teredo client is + located behind a cone NAT, 0 otherwise. For Microsoft's Windows Vista + and Windows Server 2008 implementations, more bits are used. In those + implementations, the format for these 16 bits is "CRAAAAUG AAAAAAAA", + where "C" remains the "Cone" flag. The "R" bit is reserved for future + use. The "U" bit is for the Universal/Local flag (set to 0). The "G" bit + is Individual/Group flag (set to 0). The A bits are set to a 12-bit + randomly generated number chosen by the Teredo client to introduce + additional protection for the Teredo node against IPv6-based scanning + attacks. + - Bits 80 to 95 contains the obfuscated UDP port number. This is the + port number that is mapped by the NAT to the Teredo client with all + bits inverted. + - Bits 96 to 127 contains the obfuscated IPv4 address. This is the + public IPv4 address of the NAT with all bits inverted. + */ + const prefix = this.getBitsBase16(0, 32); + const bitsForUdpPort = this.getBits(80, 96); + // eslint-disable-next-line no-bitwise + const udpPort = (bitsForUdpPort ^ BigInt('0xffff')).toString(); + const server4 = ipv4_1.Address4.fromHex(this.getBitsBase16(32, 64)); + const bitsForClient4 = this.getBits(96, 128); + // eslint-disable-next-line no-bitwise + const client4 = ipv4_1.Address4.fromHex((bitsForClient4 ^ BigInt('0xffffffff')).toString(16)); + const flagsBase2 = this.getBitsBase2(64, 80); + const coneNat = (0, common_1.testBit)(flagsBase2, 15); + const reserved = (0, common_1.testBit)(flagsBase2, 14); + const groupIndividual = (0, common_1.testBit)(flagsBase2, 8); + const universalLocal = (0, common_1.testBit)(flagsBase2, 9); + const nonce = BigInt(`0b${flagsBase2.slice(2, 6) + flagsBase2.slice(8, 16)}`).toString(10); + return { + prefix: `${prefix.slice(0, 4)}:${prefix.slice(4, 8)}`, + server4: server4.address, + client4: client4.address, + flags: flagsBase2, + coneNat, + microsoft: { + reserved, + universalLocal, + groupIndividual, + nonce, + }, + udpPort, + }; + } + /** + * Return an object containing the 6to4 properties of the address + * @memberof Address6 + * @instance + * @returns {Object} + */ + inspect6to4() { + /* + - Bits 0 to 15 are set to the 6to4 prefix (2002::/16). + - Bits 16 to 48 embed the IPv4 address of the 6to4 gateway that is used. + */ + const prefix = this.getBitsBase16(0, 16); + const gateway = ipv4_1.Address4.fromHex(this.getBitsBase16(16, 48)); + return { + prefix: prefix.slice(0, 4), + gateway: gateway.address, + }; + } + /** + * Return a v6 6to4 address from a v6 v4inv6 address + * @memberof Address6 + * @instance + * @returns {Address6} + */ + to6to4() { + if (!this.is4()) { + return null; + } + const addr6to4 = [ + '2002', + this.getBitsBase16(96, 112), + this.getBitsBase16(112, 128), + '', + '/16', + ].join(':'); + return new Address6(addr6to4); + } + /** + * Return a byte array + * @memberof Address6 + * @instance + * @returns {Array} + */ + toByteArray() { + const valueWithoutPadding = this.bigInt().toString(16); + const leadingPad = '0'.repeat(valueWithoutPadding.length % 2); + const value = `${leadingPad}${valueWithoutPadding}`; + const bytes = []; + for (let i = 0, length = value.length; i < length; i += 2) { + bytes.push(parseInt(value.substring(i, i + 2), 16)); + } + return bytes; + } + /** + * Return an unsigned byte array + * @memberof Address6 + * @instance + * @returns {Array} + */ + toUnsignedByteArray() { + return this.toByteArray().map(unsignByte); + } + /** + * Convert a byte array to an Address6 object + * @memberof Address6 + * @static + * @returns {Address6} + */ + static fromByteArray(bytes) { + return this.fromUnsignedByteArray(bytes.map(unsignByte)); + } + /** + * Convert an unsigned byte array to an Address6 object + * @memberof Address6 + * @static + * @returns {Address6} + */ + static fromUnsignedByteArray(bytes) { + const BYTE_MAX = BigInt('256'); + let result = BigInt('0'); + let multiplier = BigInt('1'); + for (let i = bytes.length - 1; i >= 0; i--) { + result += multiplier * BigInt(bytes[i].toString(10)); + multiplier *= BYTE_MAX; + } + return Address6.fromBigInt(result); + } + /** + * Returns true if the address is in the canonical form, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isCanonical() { + return this.addressMinusSuffix === this.canonicalForm(); + } + /** + * Returns true if the address is a link local address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isLinkLocal() { + // Zeroes are required, i.e. we can't check isInSubnet with 'fe80::/10' + if (this.getBitsBase2(0, 64) === + '1111111010000000000000000000000000000000000000000000000000000000') { + return true; + } + return false; + } + /** + * Returns true if the address is a multicast address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isMulticast() { + return this.getType() === 'Multicast'; + } + /** + * Returns true if the address is a v4-in-v6 address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + is4() { + return this.v4; + } + /** + * Returns true if the address is a Teredo address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isTeredo() { + return this.isInSubnet(new Address6('2001::/32')); + } + /** + * Returns true if the address is a 6to4 address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + is6to4() { + return this.isInSubnet(new Address6('2002::/16')); + } + /** + * Returns true if the address is a loopback address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isLoopback() { + return this.getType() === 'Loopback'; + } + // #endregion + // #region HTML + /** + * @returns {String} the address in link form with a default port of 80 + */ + href(optionalPort) { + if (optionalPort === undefined) { + optionalPort = ''; + } + else { + optionalPort = `:${optionalPort}`; + } + return `http://[${this.correctForm()}]${optionalPort}/`; + } + /** + * @returns {String} a link suitable for conveying the address via a URL hash + */ + link(options) { + if (!options) { + options = {}; + } + if (options.className === undefined) { + options.className = ''; + } + if (options.prefix === undefined) { + options.prefix = '/#address='; + } + if (options.v4 === undefined) { + options.v4 = false; + } + let formFunction = this.correctForm; + if (options.v4) { + formFunction = this.to4in6; + } + const form = formFunction.call(this); + if (options.className) { + return `${form}`; + } + return `${form}`; + } + /** + * Groups an address + * @returns {String} + */ + group() { + if (this.elidedGroups === 0) { + // The simple case + return helpers.simpleGroup(this.address).join(':'); + } + assert(typeof this.elidedGroups === 'number'); + assert(typeof this.elisionBegin === 'number'); + // The elided case + const output = []; + const [left, right] = this.address.split('::'); + if (left.length) { + output.push(...helpers.simpleGroup(left)); + } + else { + output.push(''); + } + const classes = ['hover-group']; + for (let i = this.elisionBegin; i < this.elisionBegin + this.elidedGroups; i++) { + classes.push(`group-${i}`); + } + output.push(``); + if (right.length) { + output.push(...helpers.simpleGroup(right, this.elisionEnd)); + } + else { + output.push(''); + } + if (this.is4()) { + assert(this.address4 instanceof ipv4_1.Address4); + output.pop(); + output.push(this.address4.groupForV6()); + } + return output.join(':'); + } + // #endregion + // #region Regular expressions + /** + * Generate a regular expression string that can be used to find or validate + * all variations of this address + * @memberof Address6 + * @instance + * @param {boolean} substringSearch + * @returns {string} + */ + regularExpressionString(substringSearch = false) { + let output = []; + // TODO: revisit why this is necessary + const address6 = new Address6(this.correctForm()); + if (address6.elidedGroups === 0) { + // The simple case + output.push((0, regular_expressions_1.simpleRegularExpression)(address6.parsedAddress)); + } + else if (address6.elidedGroups === constants6.GROUPS) { + // A completely elided address + output.push((0, regular_expressions_1.possibleElisions)(constants6.GROUPS)); + } + else { + // A partially elided address + const halves = address6.address.split('::'); + if (halves[0].length) { + output.push((0, regular_expressions_1.simpleRegularExpression)(halves[0].split(':'))); + } + assert(typeof address6.elidedGroups === 'number'); + output.push((0, regular_expressions_1.possibleElisions)(address6.elidedGroups, halves[0].length !== 0, halves[1].length !== 0)); + if (halves[1].length) { + output.push((0, regular_expressions_1.simpleRegularExpression)(halves[1].split(':'))); + } + output = [output.join(':')]; + } + if (!substringSearch) { + output = [ + '(?=^|', + regular_expressions_1.ADDRESS_BOUNDARY, + '|[^\\w\\:])(', + ...output, + ')(?=[^\\w\\:]|', + regular_expressions_1.ADDRESS_BOUNDARY, + '|$)', + ]; + } + return output.join(''); + } + /** + * Generate a regular expression that can be used to find or validate all + * variations of this address. + * @memberof Address6 + * @instance + * @param {boolean} substringSearch + * @returns {RegExp} + */ + regularExpression(substringSearch = false) { + return new RegExp(this.regularExpressionString(substringSearch), 'i'); + } +} +exports.Address6 = Address6; +//# sourceMappingURL=ipv6.js.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.js.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.js.map new file mode 100644 index 000000000..05d59a086 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/ipv6.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ipv6.js","sourceRoot":"","sources":["../src/ipv6.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.d.ts new file mode 100644 index 000000000..4e85d4a4b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.d.ts @@ -0,0 +1,5 @@ +export declare const BITS = 32; +export declare const GROUPS = 4; +export declare const RE_ADDRESS: RegExp; +export declare const RE_SUBNET_STRING: RegExp; +//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.d.ts.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.d.ts.map new file mode 100644 index 000000000..ea60cedb7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/v4/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,KAAK,CAAC;AACvB,eAAO,MAAM,MAAM,IAAI,CAAC;AAExB,eAAO,MAAM,UAAU,QAC8I,CAAC;AAEtK,eAAO,MAAM,gBAAgB,QAAe,CAAC"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.js new file mode 100644 index 000000000..6fa2518f9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RE_SUBNET_STRING = exports.RE_ADDRESS = exports.GROUPS = exports.BITS = void 0; +exports.BITS = 32; +exports.GROUPS = 4; +exports.RE_ADDRESS = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/g; +exports.RE_SUBNET_STRING = /\/\d{1,2}$/; +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.js.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.js.map new file mode 100644 index 000000000..0a96f8697 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v4/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/v4/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,IAAI,GAAG,EAAE,CAAC;AACV,QAAA,MAAM,GAAG,CAAC,CAAC;AAEX,QAAA,UAAU,GACrB,mKAAmK,CAAC;AAEzJ,QAAA,gBAAgB,GAAG,YAAY,CAAC"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.d.ts new file mode 100644 index 000000000..130237531 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.d.ts @@ -0,0 +1,45 @@ +export declare const BITS = 128; +export declare const GROUPS = 8; +/** + * Represents IPv6 address scopes + * @memberof Address6 + * @static + */ +export declare const SCOPES: { + [key: number]: string | undefined; +}; +/** + * Represents IPv6 address types + * @memberof Address6 + * @static + */ +export declare const TYPES: { + [key: string]: string | undefined; +}; +/** + * A regular expression that matches bad characters in an IPv6 address + * @memberof Address6 + * @static + */ +export declare const RE_BAD_CHARACTERS: RegExp; +/** + * A regular expression that matches an incorrect IPv6 address + * @memberof Address6 + * @static + */ +export declare const RE_BAD_ADDRESS: RegExp; +/** + * A regular expression that matches an IPv6 subnet + * @memberof Address6 + * @static + */ +export declare const RE_SUBNET_STRING: RegExp; +/** + * A regular expression that matches an IPv6 zone + * @memberof Address6 + * @static + */ +export declare const RE_ZONE_STRING: RegExp; +export declare const RE_URL: RegExp; +export declare const RE_URL_WITH_PORT: RegExp; +//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.d.ts.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.d.ts.map new file mode 100644 index 000000000..0f4f412f9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/v6/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,MAAM,CAAC;AACxB,eAAO,MAAM,MAAM,IAAI,CAAC;AAExB;;;;GAIG;AACH,eAAO,MAAM,MAAM,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAS9C,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,KAAK,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAuB7C,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,QAAqB,CAAC;AAEpD;;;;GAIG;AACH,eAAO,MAAM,cAAc,QAA6C,CAAC;AAEzE;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,QAAqB,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,cAAc,QAAS,CAAC;AAErC,eAAO,MAAM,MAAM,QAAgC,CAAC;AACpD,eAAO,MAAM,gBAAgB,QAAkC,CAAC"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.js new file mode 100644 index 000000000..0abc423e0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.js @@ -0,0 +1,76 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RE_URL_WITH_PORT = exports.RE_URL = exports.RE_ZONE_STRING = exports.RE_SUBNET_STRING = exports.RE_BAD_ADDRESS = exports.RE_BAD_CHARACTERS = exports.TYPES = exports.SCOPES = exports.GROUPS = exports.BITS = void 0; +exports.BITS = 128; +exports.GROUPS = 8; +/** + * Represents IPv6 address scopes + * @memberof Address6 + * @static + */ +exports.SCOPES = { + 0: 'Reserved', + 1: 'Interface local', + 2: 'Link local', + 4: 'Admin local', + 5: 'Site local', + 8: 'Organization local', + 14: 'Global', + 15: 'Reserved', +}; +/** + * Represents IPv6 address types + * @memberof Address6 + * @static + */ +exports.TYPES = { + 'ff01::1/128': 'Multicast (All nodes on this interface)', + 'ff01::2/128': 'Multicast (All routers on this interface)', + 'ff02::1/128': 'Multicast (All nodes on this link)', + 'ff02::2/128': 'Multicast (All routers on this link)', + 'ff05::2/128': 'Multicast (All routers in this site)', + 'ff02::5/128': 'Multicast (OSPFv3 AllSPF routers)', + 'ff02::6/128': 'Multicast (OSPFv3 AllDR routers)', + 'ff02::9/128': 'Multicast (RIP routers)', + 'ff02::a/128': 'Multicast (EIGRP routers)', + 'ff02::d/128': 'Multicast (PIM routers)', + 'ff02::16/128': 'Multicast (MLDv2 reports)', + 'ff01::fb/128': 'Multicast (mDNSv6)', + 'ff02::fb/128': 'Multicast (mDNSv6)', + 'ff05::fb/128': 'Multicast (mDNSv6)', + 'ff02::1:2/128': 'Multicast (All DHCP servers and relay agents on this link)', + 'ff05::1:2/128': 'Multicast (All DHCP servers and relay agents in this site)', + 'ff02::1:3/128': 'Multicast (All DHCP servers on this link)', + 'ff05::1:3/128': 'Multicast (All DHCP servers in this site)', + '::/128': 'Unspecified', + '::1/128': 'Loopback', + 'ff00::/8': 'Multicast', + 'fe80::/10': 'Link-local unicast', +}; +/** + * A regular expression that matches bad characters in an IPv6 address + * @memberof Address6 + * @static + */ +exports.RE_BAD_CHARACTERS = /([^0-9a-f:/%])/gi; +/** + * A regular expression that matches an incorrect IPv6 address + * @memberof Address6 + * @static + */ +exports.RE_BAD_ADDRESS = /([0-9a-f]{5,}|:{3,}|[^:]:$|^:[^:]|\/$)/gi; +/** + * A regular expression that matches an IPv6 subnet + * @memberof Address6 + * @static + */ +exports.RE_SUBNET_STRING = /\/\d{1,3}(?=%|$)/; +/** + * A regular expression that matches an IPv6 zone + * @memberof Address6 + * @static + */ +exports.RE_ZONE_STRING = /%.*$/; +exports.RE_URL = /^\[{0,1}([0-9a-f:]+)\]{0,1}/; +exports.RE_URL_WITH_PORT = /\[([0-9a-f:]+)\]:([0-9]{1,5})/; +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.js.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.js.map new file mode 100644 index 000000000..1d313e0c5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/v6/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,IAAI,GAAG,GAAG,CAAC;AACX,QAAA,MAAM,GAAG,CAAC,CAAC;AAExB;;;;GAIG;AACU,QAAA,MAAM,GAA0C;IAC3D,CAAC,EAAE,UAAU;IACb,CAAC,EAAE,iBAAiB;IACpB,CAAC,EAAE,YAAY;IACf,CAAC,EAAE,aAAa;IAChB,CAAC,EAAE,YAAY;IACf,CAAC,EAAE,oBAAoB;IACvB,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,UAAU;CACN,CAAC;AAEX;;;;GAIG;AACU,QAAA,KAAK,GAA0C;IAC1D,aAAa,EAAE,yCAAyC;IACxD,aAAa,EAAE,2CAA2C;IAC1D,aAAa,EAAE,oCAAoC;IACnD,aAAa,EAAE,sCAAsC;IACrD,aAAa,EAAE,sCAAsC;IACrD,aAAa,EAAE,mCAAmC;IAClD,aAAa,EAAE,kCAAkC;IACjD,aAAa,EAAE,yBAAyB;IACxC,aAAa,EAAE,2BAA2B;IAC1C,aAAa,EAAE,yBAAyB;IACxC,cAAc,EAAE,2BAA2B;IAC3C,cAAc,EAAE,oBAAoB;IACpC,cAAc,EAAE,oBAAoB;IACpC,cAAc,EAAE,oBAAoB;IACpC,eAAe,EAAE,4DAA4D;IAC7E,eAAe,EAAE,4DAA4D;IAC7E,eAAe,EAAE,2CAA2C;IAC5D,eAAe,EAAE,2CAA2C;IAC5D,QAAQ,EAAE,aAAa;IACvB,SAAS,EAAE,UAAU;IACrB,UAAU,EAAE,WAAW;IACvB,WAAW,EAAE,oBAAoB;CACzB,CAAC;AAEX;;;;GAIG;AACU,QAAA,iBAAiB,GAAG,kBAAkB,CAAC;AAEpD;;;;GAIG;AACU,QAAA,cAAc,GAAG,0CAA0C,CAAC;AAEzE;;;;GAIG;AACU,QAAA,gBAAgB,GAAG,kBAAkB,CAAC;AAEnD;;;;GAIG;AACU,QAAA,cAAc,GAAG,MAAM,CAAC;AAExB,QAAA,MAAM,GAAG,6BAA6B,CAAC;AACvC,QAAA,gBAAgB,GAAG,+BAA+B,CAAC"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.d.ts new file mode 100644 index 000000000..e72f0311d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.d.ts @@ -0,0 +1,18 @@ +/** + * @returns {String} the string with all zeroes contained in a + */ +export declare function spanAllZeroes(s: string): string; +/** + * @returns {String} the string with each character contained in a + */ +export declare function spanAll(s: string, offset?: number): string; +/** + * @returns {String} the string with leading zeroes contained in a + */ +export declare function spanLeadingZeroes(address: string): string; +/** + * Groups an address + * @returns {String} a grouped address + */ +export declare function simpleGroup(addressString: string, offset?: number): string[]; +//# sourceMappingURL=helpers.d.ts.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.d.ts.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.d.ts.map new file mode 100644 index 000000000..823f26e21 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/v6/helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,MAAM,CAQ7D;AAMD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,MAAM,EAAE,CAU/E"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.js new file mode 100644 index 000000000..fafca0c27 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.js @@ -0,0 +1,45 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.spanAllZeroes = spanAllZeroes; +exports.spanAll = spanAll; +exports.spanLeadingZeroes = spanLeadingZeroes; +exports.simpleGroup = simpleGroup; +/** + * @returns {String} the string with all zeroes contained in a + */ +function spanAllZeroes(s) { + return s.replace(/(0+)/g, '$1'); +} +/** + * @returns {String} the string with each character contained in a + */ +function spanAll(s, offset = 0) { + const letters = s.split(''); + return letters + .map((n, i) => `${spanAllZeroes(n)}`) + .join(''); +} +function spanLeadingZeroesSimple(group) { + return group.replace(/^(0+)/, '$1'); +} +/** + * @returns {String} the string with leading zeroes contained in a + */ +function spanLeadingZeroes(address) { + const groups = address.split(':'); + return groups.map((g) => spanLeadingZeroesSimple(g)).join(':'); +} +/** + * Groups an address + * @returns {String} a grouped address + */ +function simpleGroup(addressString, offset = 0) { + const groups = addressString.split(':'); + return groups.map((g, i) => { + if (/group-v4/.test(g)) { + return g; + } + return `${spanLeadingZeroesSimple(g)}`; + }); +} +//# sourceMappingURL=helpers.js.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.js.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.js.map new file mode 100644 index 000000000..c89545538 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/helpers.js.map @@ -0,0 +1 @@ +{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/v6/helpers.ts"],"names":[],"mappings":";;AAGA,sCAEC;AAKD,0BAQC;AASD,8CAIC;AAMD,kCAUC;AA/CD;;GAEG;AACH,SAAgB,aAAa,CAAC,CAAS;IACrC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,8BAA8B,CAAC,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,SAAgB,OAAO,CAAC,CAAS,EAAE,SAAiB,CAAC;IACnD,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAE5B,OAAO,OAAO;SACX,GAAG,CACF,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,4BAA4B,CAAC,aAAa,CAAC,GAAG,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,SAAS,CAC7F;SACA,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,SAAS,uBAAuB,CAAC,KAAa;IAC5C,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,8BAA8B,CAAC,CAAC;AAChE,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB,CAAC,OAAe;IAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAElC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACjE,CAAC;AAED;;;GAGG;AACH,SAAgB,WAAW,CAAC,aAAqB,EAAE,SAAiB,CAAC;IACnE,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAExC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACzB,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,OAAO,kCAAkC,CAAC,GAAG,MAAM,KAAK,uBAAuB,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9F,CAAC,CAAC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.d.ts new file mode 100644 index 000000000..181b91e81 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.d.ts @@ -0,0 +1,6 @@ +export declare function groupPossibilities(possibilities: string[]): string; +export declare function padGroup(group: string): string; +export declare const ADDRESS_BOUNDARY = "[^A-Fa-f0-9:]"; +export declare function simpleRegularExpression(groups: string[]): string; +export declare function possibleElisions(elidedGroups: number, moreLeft?: boolean, moreRight?: boolean): string; +//# sourceMappingURL=regular-expressions.d.ts.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.d.ts.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.d.ts.map new file mode 100644 index 000000000..20a93f7d9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"regular-expressions.d.ts","sourceRoot":"","sources":["../../src/v6/regular-expressions.ts"],"names":[],"mappings":"AAEA,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,CAElE;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM9C;AAED,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAEhD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,UA+BvD;AAED,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,OAAO,EAClB,SAAS,CAAC,EAAE,OAAO,GAClB,MAAM,CAwCR"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.js new file mode 100644 index 000000000..a2c514593 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.js @@ -0,0 +1,95 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ADDRESS_BOUNDARY = void 0; +exports.groupPossibilities = groupPossibilities; +exports.padGroup = padGroup; +exports.simpleRegularExpression = simpleRegularExpression; +exports.possibleElisions = possibleElisions; +const v6 = __importStar(require("./constants")); +function groupPossibilities(possibilities) { + return `(${possibilities.join('|')})`; +} +function padGroup(group) { + if (group.length < 4) { + return `0{0,${4 - group.length}}${group}`; + } + return group; +} +exports.ADDRESS_BOUNDARY = '[^A-Fa-f0-9:]'; +function simpleRegularExpression(groups) { + const zeroIndexes = []; + groups.forEach((group, i) => { + const groupInteger = parseInt(group, 16); + if (groupInteger === 0) { + zeroIndexes.push(i); + } + }); + // You can technically elide a single 0, this creates the regular expressions + // to match that eventuality + const possibilities = zeroIndexes.map((zeroIndex) => groups + .map((group, i) => { + if (i === zeroIndex) { + const elision = i === 0 || i === v6.GROUPS - 1 ? ':' : ''; + return groupPossibilities([padGroup(group), elision]); + } + return padGroup(group); + }) + .join(':')); + // The simplest case + possibilities.push(groups.map(padGroup).join(':')); + return groupPossibilities(possibilities); +} +function possibleElisions(elidedGroups, moreLeft, moreRight) { + const left = moreLeft ? '' : ':'; + const right = moreRight ? '' : ':'; + const possibilities = []; + // 1. elision of everything (::) + if (!moreLeft && !moreRight) { + possibilities.push('::'); + } + // 2. complete elision of the middle + if (moreLeft && moreRight) { + possibilities.push(''); + } + if ((moreRight && !moreLeft) || (!moreRight && moreLeft)) { + // 3. complete elision of one side + possibilities.push(':'); + } + // 4. elision from the left side + possibilities.push(`${left}(:0{1,4}){1,${elidedGroups - 1}}`); + // 5. elision from the right side + possibilities.push(`(0{1,4}:){1,${elidedGroups - 1}}${right}`); + // 6. no elision + possibilities.push(`(0{1,4}:){${elidedGroups - 1}}0{1,4}`); + // 7. elision (including sloppy elision) from the middle + for (let groups = 1; groups < elidedGroups - 1; groups++) { + for (let position = 1; position < elidedGroups - groups; position++) { + possibilities.push(`(0{1,4}:){${position}}:(0{1,4}:){${elidedGroups - position - groups - 1}}0{1,4}`); + } + } + return groupPossibilities(possibilities); +} +//# sourceMappingURL=regular-expressions.js.map \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.js.map b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.js.map new file mode 100644 index 000000000..190fd4a17 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/dist/v6/regular-expressions.js.map @@ -0,0 +1 @@ +{"version":3,"file":"regular-expressions.js","sourceRoot":"","sources":["../../src/v6/regular-expressions.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/package.json new file mode 100644 index 000000000..5cf811e8c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/package.json @@ -0,0 +1,78 @@ +{ + "name": "ip-address", + "description": "A library for parsing IPv4 and IPv6 IP addresses in node and the browser.", + "keywords": [ + "ipv6", + "ipv4", + "browser", + "validation" + ], + "version": "10.1.0", + "author": "Beau Gunderson (https://beaugunderson.com/)", + "license": "MIT", + "main": "dist/ip-address.js", + "types": "dist/ip-address.d.ts", + "scripts": { + "docs": "documentation build --github --output docs --format html ./ip-address.js", + "build": "rm -rf dist; mkdir dist; tsc", + "prepack": "npm run build", + "release": "release-it", + "test-ci": "nyc mocha", + "test": "mocha", + "watch": "mocha --watch" + }, + "nyc": { + "extension": [ + ".ts" + ], + "exclude": [ + "**/*.d.ts", + ".eslintrc.js", + "coverage/", + "dist/", + "test/", + "tmp/" + ], + "reporter": [ + "html", + "lcov", + "text" + ], + "all": true + }, + "engines": { + "node": ">= 12" + }, + "files": [ + "src", + "dist" + ], + "repository": { + "type": "git", + "url": "git://github.com/beaugunderson/ip-address.git" + }, + "devDependencies": { + "@types/chai": "^5.0.0", + "@types/mocha": "^10.0.8", + "@typescript-eslint/eslint-plugin": "^8.8.0", + "@typescript-eslint/parser": "^8.8.0", + "chai": "^5.1.1", + "documentation": "^14.0.3", + "eslint": "^8.50.0", + "eslint_d": "^14.0.4", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-filenames": "^1.3.2", + "eslint-plugin-import": "^2.30.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-sort-imports-es6-autofix": "^0.6.0", + "mocha": "^10.7.3", + "nyc": "^17.1.0", + "prettier": "^3.3.3", + "release-it": "^17.6.0", + "source-map-support": "^0.5.21", + "tsx": "^4.19.1", + "typescript": "<5.6.0" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/address-error.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/address-error.ts new file mode 100644 index 000000000..032d4cdd7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/address-error.ts @@ -0,0 +1,11 @@ +export class AddressError extends Error { + parseMessage?: string; + + constructor(message: string, parseMessage?: string) { + super(message); + + this.name = 'AddressError'; + + this.parseMessage = parseMessage; + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/common.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/common.ts new file mode 100644 index 000000000..1123fa3b1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/common.ts @@ -0,0 +1,55 @@ +import { Address4 } from './ipv4'; +import { Address6 } from './ipv6'; + +export interface ReverseFormOptions { + omitSuffix?: boolean; +} + +export function isInSubnet(this: Address4 | Address6, address: Address4 | Address6) { + if (this.subnetMask < address.subnetMask) { + return false; + } + + if (this.mask(address.subnetMask) === address.mask()) { + return true; + } + + return false; +} + +export function isCorrect(defaultBits: number) { + return function (this: Address4 | Address6) { + if (this.addressMinusSuffix !== this.correctForm()) { + return false; + } + + if (this.subnetMask === defaultBits && !this.parsedSubnet) { + return true; + } + + return this.parsedSubnet === String(this.subnetMask); + }; +} + +export function numberToPaddedHex(number: number) { + return number.toString(16).padStart(2, '0'); +} + +export function stringToPaddedHex(numberString: string) { + return numberToPaddedHex(parseInt(numberString, 10)); +} + +/** + * @param binaryValue Binary representation of a value (e.g. `10`) + * @param position Byte position, where 0 is the least significant bit + */ +export function testBit(binaryValue: string, position: number): boolean { + const { length } = binaryValue; + + if (position > length) { + return false; + } + + const positionInString = length - position; + return binaryValue.substring(positionInString, positionInString + 1) === '1'; +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/ip-address.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/ip-address.ts new file mode 100644 index 000000000..b4e150267 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/ip-address.ts @@ -0,0 +1,7 @@ +export { Address4 } from './ipv4'; +export { Address6 } from './ipv6'; +export { AddressError } from './address-error'; + +import * as helpers from './v6/helpers'; + +export const v6 = { helpers }; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/ipv4.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/ipv4.ts new file mode 100644 index 000000000..7c7ce308b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/ipv4.ts @@ -0,0 +1,394 @@ +/* eslint-disable no-param-reassign */ + +import * as common from './common'; +import * as constants from './v4/constants'; +import { AddressError } from './address-error'; + +/** + * Represents an IPv4 address + * @class Address4 + * @param {string} address - An IPv4 address string + */ +export class Address4 { + address: string; + addressMinusSuffix?: string; + groups: number = constants.GROUPS; + parsedAddress: string[] = []; + parsedSubnet: string = ''; + subnet: string = '/32'; + subnetMask: number = 32; + v4: boolean = true; + + constructor(address: string) { + this.address = address; + + const subnet = constants.RE_SUBNET_STRING.exec(address); + + if (subnet) { + this.parsedSubnet = subnet[0].replace('/', ''); + this.subnetMask = parseInt(this.parsedSubnet, 10); + this.subnet = `/${this.subnetMask}`; + + if (this.subnetMask < 0 || this.subnetMask > constants.BITS) { + throw new AddressError('Invalid subnet mask.'); + } + + address = address.replace(constants.RE_SUBNET_STRING, ''); + } + + this.addressMinusSuffix = address; + + this.parsedAddress = this.parse(address); + } + + static isValid(address: string): boolean { + try { + // eslint-disable-next-line no-new + new Address4(address); + + return true; + } catch (e) { + return false; + } + } + + /* + * Parses a v4 address + */ + parse(address: string) { + const groups = address.split('.'); + + if (!address.match(constants.RE_ADDRESS)) { + throw new AddressError('Invalid IPv4 address.'); + } + + return groups; + } + + /** + * Returns the correct form of an address + * @memberof Address4 + * @instance + * @returns {String} + */ + correctForm(): string { + return this.parsedAddress.map((part) => parseInt(part, 10)).join('.'); + } + + /** + * Returns true if the address is correct, false otherwise + * @memberof Address4 + * @instance + * @returns {Boolean} + */ + isCorrect = common.isCorrect(constants.BITS); + + /** + * Converts a hex string to an IPv4 address object + * @memberof Address4 + * @static + * @param {string} hex - a hex string to convert + * @returns {Address4} + */ + static fromHex(hex: string): Address4 { + const padded = hex.replace(/:/g, '').padStart(8, '0'); + const groups = []; + let i; + + for (i = 0; i < 8; i += 2) { + const h = padded.slice(i, i + 2); + + groups.push(parseInt(h, 16)); + } + + return new Address4(groups.join('.')); + } + + /** + * Converts an integer into a IPv4 address object + * @memberof Address4 + * @static + * @param {integer} integer - a number to convert + * @returns {Address4} + */ + static fromInteger(integer: number): Address4 { + return Address4.fromHex(integer.toString(16)); + } + + /** + * Return an address from in-addr.arpa form + * @memberof Address4 + * @static + * @param {string} arpaFormAddress - an 'in-addr.arpa' form ipv4 address + * @returns {Adress4} + * @example + * var address = Address4.fromArpa(42.2.0.192.in-addr.arpa.) + * address.correctForm(); // '192.0.2.42' + */ + static fromArpa(arpaFormAddress: string): Address4 { + // remove ending ".in-addr.arpa." or just "." + const leader = arpaFormAddress.replace(/(\.in-addr\.arpa)?\.$/, ''); + + const address = leader.split('.').reverse().join('.'); + + return new Address4(address); + } + + /** + * Converts an IPv4 address object to a hex string + * @memberof Address4 + * @instance + * @returns {String} + */ + toHex(): string { + return this.parsedAddress.map((part) => common.stringToPaddedHex(part)).join(':'); + } + + /** + * Converts an IPv4 address object to an array of bytes + * @memberof Address4 + * @instance + * @returns {Array} + */ + toArray(): number[] { + return this.parsedAddress.map((part) => parseInt(part, 10)); + } + + /** + * Converts an IPv4 address object to an IPv6 address group + * @memberof Address4 + * @instance + * @returns {String} + */ + toGroup6(): string { + const output = []; + let i; + + for (i = 0; i < constants.GROUPS; i += 2) { + output.push( + `${common.stringToPaddedHex(this.parsedAddress[i])}${common.stringToPaddedHex( + this.parsedAddress[i + 1], + )}`, + ); + } + + return output.join(':'); + } + + /** + * Returns the address as a `bigint` + * @memberof Address4 + * @instance + * @returns {bigint} + */ + bigInt(): bigint { + return BigInt(`0x${this.parsedAddress.map((n) => common.stringToPaddedHex(n)).join('')}`); + } + + /** + * Helper function getting start address. + * @memberof Address4 + * @instance + * @returns {bigint} + */ + _startAddress(): bigint { + return BigInt(`0b${this.mask() + '0'.repeat(constants.BITS - this.subnetMask)}`); + } + + /** + * The first address in the range given by this address' subnet. + * Often referred to as the Network Address. + * @memberof Address4 + * @instance + * @returns {Address4} + */ + startAddress(): Address4 { + return Address4.fromBigInt(this._startAddress()); + } + + /** + * The first host address in the range given by this address's subnet ie + * the first address after the Network Address + * @memberof Address4 + * @instance + * @returns {Address4} + */ + startAddressExclusive(): Address4 { + const adjust = BigInt('1'); + return Address4.fromBigInt(this._startAddress() + adjust); + } + + /** + * Helper function getting end address. + * @memberof Address4 + * @instance + * @returns {bigint} + */ + _endAddress(): bigint { + return BigInt(`0b${this.mask() + '1'.repeat(constants.BITS - this.subnetMask)}`); + } + + /** + * The last address in the range given by this address' subnet + * Often referred to as the Broadcast + * @memberof Address4 + * @instance + * @returns {Address4} + */ + endAddress(): Address4 { + return Address4.fromBigInt(this._endAddress()); + } + + /** + * The last host address in the range given by this address's subnet ie + * the last address prior to the Broadcast Address + * @memberof Address4 + * @instance + * @returns {Address4} + */ + endAddressExclusive(): Address4 { + const adjust = BigInt('1'); + return Address4.fromBigInt(this._endAddress() - adjust); + } + + /** + * Converts a BigInt to a v4 address object + * @memberof Address4 + * @static + * @param {bigint} bigInt - a BigInt to convert + * @returns {Address4} + */ + static fromBigInt(bigInt: bigint): Address4 { + return Address4.fromHex(bigInt.toString(16)); + } + + /** + * Convert a byte array to an Address4 object + * @memberof Address4 + * @static + * @param {Array} bytes - an array of 4 bytes (0-255) + * @returns {Address4} + */ + static fromByteArray(bytes: Array): Address4 { + if (bytes.length !== 4) { + throw new AddressError('IPv4 addresses require exactly 4 bytes'); + } + + // Validate that all bytes are within valid range (0-255) + for (let i = 0; i < bytes.length; i++) { + if (!Number.isInteger(bytes[i]) || bytes[i] < 0 || bytes[i] > 255) { + throw new AddressError('All bytes must be integers between 0 and 255'); + } + } + + return this.fromUnsignedByteArray(bytes); + } + + /** + * Convert an unsigned byte array to an Address4 object + * @memberof Address4 + * @static + * @param {Array} bytes - an array of 4 unsigned bytes (0-255) + * @returns {Address4} + */ + static fromUnsignedByteArray(bytes: Array): Address4 { + if (bytes.length !== 4) { + throw new AddressError('IPv4 addresses require exactly 4 bytes'); + } + + const address = bytes.join('.'); + return new Address4(address); + } + + /** + * Returns the first n bits of the address, defaulting to the + * subnet mask + * @memberof Address4 + * @instance + * @returns {String} + */ + mask(mask?: number): string { + if (mask === undefined) { + mask = this.subnetMask; + } + + return this.getBitsBase2(0, mask); + } + + /** + * Returns the bits in the given range as a base-2 string + * @memberof Address4 + * @instance + * @returns {string} + */ + getBitsBase2(start: number, end: number): string { + return this.binaryZeroPad().slice(start, end); + } + + /** + * Return the reversed ip6.arpa form of the address + * @memberof Address4 + * @param {Object} options + * @param {boolean} options.omitSuffix - omit the "in-addr.arpa" suffix + * @instance + * @returns {String} + */ + reverseForm(options?: common.ReverseFormOptions): string { + if (!options) { + options = {}; + } + + const reversed = this.correctForm().split('.').reverse().join('.'); + + if (options.omitSuffix) { + return reversed; + } + + return `${reversed}.in-addr.arpa.`; + } + + /** + * Returns true if the given address is in the subnet of the current address + * @memberof Address4 + * @instance + * @returns {boolean} + */ + isInSubnet = common.isInSubnet; + + /** + * Returns true if the given address is a multicast address + * @memberof Address4 + * @instance + * @returns {boolean} + */ + isMulticast(): boolean { + return this.isInSubnet(new Address4('224.0.0.0/4')); + } + + /** + * Returns a zero-padded base-2 string representation of the address + * @memberof Address4 + * @instance + * @returns {string} + */ + binaryZeroPad(): string { + return this.bigInt().toString(2).padStart(constants.BITS, '0'); + } + + /** + * Groups an IPv4 address for inclusion at the end of an IPv6 address + * @returns {String} + */ + groupForV6(): string { + const segments = this.parsedAddress; + + return this.address.replace( + constants.RE_ADDRESS, + `${segments + .slice(0, 2) + .join('.')}.${segments + .slice(2, 4) + .join('.')}`, + ); + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/ipv6.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/ipv6.ts new file mode 100644 index 000000000..60348e97a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/ipv6.ts @@ -0,0 +1,1212 @@ +/* eslint-disable prefer-destructuring */ +/* eslint-disable no-param-reassign */ + +import * as common from './common'; +import * as constants4 from './v4/constants'; +import * as constants6 from './v6/constants'; +import * as helpers from './v6/helpers'; +import { Address4 } from './ipv4'; +import { + ADDRESS_BOUNDARY, + possibleElisions, + simpleRegularExpression, +} from './v6/regular-expressions'; +import { AddressError } from './address-error'; +import { testBit } from './common'; + +function assert(condition: any): asserts condition { + if (!condition) { + throw new Error('Assertion failed.'); + } +} + +function addCommas(number: string): string { + const r = /(\d+)(\d{3})/; + + while (r.test(number)) { + number = number.replace(r, '$1,$2'); + } + + return number; +} + +function spanLeadingZeroes4(n: string): string { + n = n.replace(/^(0{1,})([1-9]+)$/, '$1$2'); + n = n.replace(/^(0{1,})(0)$/, '$1$2'); + + return n; +} + +/* + * A helper function to compact an array + */ +function compact(address: string[], slice: number[]) { + const s1 = []; + const s2 = []; + let i; + + for (i = 0; i < address.length; i++) { + if (i < slice[0]) { + s1.push(address[i]); + } else if (i > slice[1]) { + s2.push(address[i]); + } + } + + return s1.concat(['compact']).concat(s2); +} + +function paddedHex(octet: string): string { + return parseInt(octet, 16).toString(16).padStart(4, '0'); +} + +function unsignByte(b: number) { + // eslint-disable-next-line no-bitwise + return b & 0xff; +} + +interface SixToFourProperties { + prefix: string; + gateway: string; +} + +interface TeredoProperties { + prefix: string; + server4: string; + client4: string; + flags: string; + coneNat: boolean; + microsoft: { + reserved: boolean; + universalLocal: boolean; + groupIndividual: boolean; + nonce: string; + }; + udpPort: string; +} + +/** + * Represents an IPv6 address + * @class Address6 + * @param {string} address - An IPv6 address string + * @param {number} [groups=8] - How many octets to parse + * @example + * var address = new Address6('2001::/32'); + */ +export class Address6 { + address4?: Address4; + address: string; + addressMinusSuffix: string = ''; + elidedGroups?: number; + elisionBegin?: number; + elisionEnd?: number; + groups: number; + parsedAddress4?: string; + parsedAddress: string[]; + parsedSubnet: string = ''; + subnet: string = '/128'; + subnetMask: number = 128; + v4: boolean = false; + zone: string = ''; + + constructor(address: string, optionalGroups?: number) { + if (optionalGroups === undefined) { + this.groups = constants6.GROUPS; + } else { + this.groups = optionalGroups; + } + + this.address = address; + + const subnet = constants6.RE_SUBNET_STRING.exec(address); + + if (subnet) { + this.parsedSubnet = subnet[0].replace('/', ''); + this.subnetMask = parseInt(this.parsedSubnet, 10); + this.subnet = `/${this.subnetMask}`; + + if ( + Number.isNaN(this.subnetMask) || + this.subnetMask < 0 || + this.subnetMask > constants6.BITS + ) { + throw new AddressError('Invalid subnet mask.'); + } + + address = address.replace(constants6.RE_SUBNET_STRING, ''); + } else if (/\//.test(address)) { + throw new AddressError('Invalid subnet mask.'); + } + + const zone = constants6.RE_ZONE_STRING.exec(address); + + if (zone) { + this.zone = zone[0]; + + address = address.replace(constants6.RE_ZONE_STRING, ''); + } + + this.addressMinusSuffix = address; + + this.parsedAddress = this.parse(this.addressMinusSuffix); + } + + static isValid(address: string): boolean { + try { + // eslint-disable-next-line no-new + new Address6(address); + + return true; + } catch (e) { + return false; + } + } + + /** + * Convert a BigInt to a v6 address object + * @memberof Address6 + * @static + * @param {bigint} bigInt - a BigInt to convert + * @returns {Address6} + * @example + * var bigInt = BigInt('1000000000000'); + * var address = Address6.fromBigInt(bigInt); + * address.correctForm(); // '::e8:d4a5:1000' + */ + static fromBigInt(bigInt: bigint): Address6 { + const hex = bigInt.toString(16).padStart(32, '0'); + const groups = []; + let i; + + for (i = 0; i < constants6.GROUPS; i++) { + groups.push(hex.slice(i * 4, (i + 1) * 4)); + } + + return new Address6(groups.join(':')); + } + + /** + * Convert a URL (with optional port number) to an address object + * @memberof Address6 + * @static + * @param {string} url - a URL with optional port number + * @example + * var addressAndPort = Address6.fromURL('http://[ffff::]:8080/foo/'); + * addressAndPort.address.correctForm(); // 'ffff::' + * addressAndPort.port; // 8080 + */ + static fromURL(url: string) { + let host: string; + let port: string | number | null = null; + let result: string[] | null; + + // If we have brackets parse them and find a port + if (url.indexOf('[') !== -1 && url.indexOf(']:') !== -1) { + result = constants6.RE_URL_WITH_PORT.exec(url); + + if (result === null) { + return { + error: 'failed to parse address with port', + address: null, + port: null, + }; + } + + host = result[1]; + port = result[2]; + // If there's a URL extract the address + } else if (url.indexOf('/') !== -1) { + // Remove the protocol prefix + url = url.replace(/^[a-z0-9]+:\/\//, ''); + + // Parse the address + result = constants6.RE_URL.exec(url); + + if (result === null) { + return { + error: 'failed to parse address from URL', + address: null, + port: null, + }; + } + + host = result[1]; + // Otherwise just assign the URL to the host and let the library parse it + } else { + host = url; + } + + // If there's a port convert it to an integer + if (port) { + port = parseInt(port, 10); + + // squelch out of range ports + if (port < 0 || port > 65536) { + port = null; + } + } else { + // Standardize `undefined` to `null` + port = null; + } + + return { + address: new Address6(host), + port, + }; + } + + /** + * Create an IPv6-mapped address given an IPv4 address + * @memberof Address6 + * @static + * @param {string} address - An IPv4 address string + * @returns {Address6} + * @example + * var address = Address6.fromAddress4('192.168.0.1'); + * address.correctForm(); // '::ffff:c0a8:1' + * address.to4in6(); // '::ffff:192.168.0.1' + */ + static fromAddress4(address: string): Address6 { + const address4 = new Address4(address); + + const mask6 = constants6.BITS - (constants4.BITS - address4.subnetMask); + + return new Address6(`::ffff:${address4.correctForm()}/${mask6}`); + } + + /** + * Return an address from ip6.arpa form + * @memberof Address6 + * @static + * @param {string} arpaFormAddress - an 'ip6.arpa' form address + * @returns {Adress6} + * @example + * var address = Address6.fromArpa(e.f.f.f.3.c.2.6.f.f.f.e.6.6.8.e.1.0.6.7.9.4.e.c.0.0.0.0.1.0.0.2.ip6.arpa.) + * address.correctForm(); // '2001:0:ce49:7601:e866:efff:62c3:fffe' + */ + static fromArpa(arpaFormAddress: string): Address6 { + // remove ending ".ip6.arpa." or just "." + let address = arpaFormAddress.replace(/(\.ip6\.arpa)?\.$/, ''); + const semicolonAmount = 7; + + // correct ip6.arpa form with ending removed will be 63 characters + if (address.length !== 63) { + throw new AddressError("Invalid 'ip6.arpa' form."); + } + + const parts = address.split('.').reverse(); + + for (let i = semicolonAmount; i > 0; i--) { + const insertIndex = i * 4; + parts.splice(insertIndex, 0, ':'); + } + + address = parts.join(''); + + return new Address6(address); + } + + /** + * Return the Microsoft UNC transcription of the address + * @memberof Address6 + * @instance + * @returns {String} the Microsoft UNC transcription of the address + */ + microsoftTranscription(): string { + return `${this.correctForm().replace(/:/g, '-')}.ipv6-literal.net`; + } + + /** + * Return the first n bits of the address, defaulting to the subnet mask + * @memberof Address6 + * @instance + * @param {number} [mask=subnet] - the number of bits to mask + * @returns {String} the first n bits of the address as a string + */ + mask(mask: number = this.subnetMask): string { + return this.getBitsBase2(0, mask); + } + + /** + * Return the number of possible subnets of a given size in the address + * @memberof Address6 + * @instance + * @param {number} [subnetSize=128] - the subnet size + * @returns {String} + */ + // TODO: probably useful to have a numeric version of this too + possibleSubnets(subnetSize: number = 128): string { + const availableBits = constants6.BITS - this.subnetMask; + const subnetBits = Math.abs(subnetSize - constants6.BITS); + const subnetPowers = availableBits - subnetBits; + + if (subnetPowers < 0) { + return '0'; + } + + return addCommas((BigInt('2') ** BigInt(subnetPowers)).toString(10)); + } + + /** + * Helper function getting start address. + * @memberof Address6 + * @instance + * @returns {bigint} + */ + _startAddress(): bigint { + return BigInt(`0b${this.mask() + '0'.repeat(constants6.BITS - this.subnetMask)}`); + } + + /** + * The first address in the range given by this address' subnet + * Often referred to as the Network Address. + * @memberof Address6 + * @instance + * @returns {Address6} + */ + startAddress(): Address6 { + return Address6.fromBigInt(this._startAddress()); + } + + /** + * The first host address in the range given by this address's subnet ie + * the first address after the Network Address + * @memberof Address6 + * @instance + * @returns {Address6} + */ + startAddressExclusive(): Address6 { + const adjust = BigInt('1'); + return Address6.fromBigInt(this._startAddress() + adjust); + } + + /** + * Helper function getting end address. + * @memberof Address6 + * @instance + * @returns {bigint} + */ + _endAddress(): bigint { + return BigInt(`0b${this.mask() + '1'.repeat(constants6.BITS - this.subnetMask)}`); + } + + /** + * The last address in the range given by this address' subnet + * Often referred to as the Broadcast + * @memberof Address6 + * @instance + * @returns {Address6} + */ + endAddress(): Address6 { + return Address6.fromBigInt(this._endAddress()); + } + + /** + * The last host address in the range given by this address's subnet ie + * the last address prior to the Broadcast Address + * @memberof Address6 + * @instance + * @returns {Address6} + */ + endAddressExclusive(): Address6 { + const adjust = BigInt('1'); + return Address6.fromBigInt(this._endAddress() - adjust); + } + + /** + * Return the scope of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + getScope(): string { + let scope = constants6.SCOPES[parseInt(this.getBits(12, 16).toString(10), 10)]; + + if (this.getType() === 'Global unicast' && scope !== 'Link local') { + scope = 'Global'; + } + + return scope || 'Unknown'; + } + + /** + * Return the type of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + getType(): string { + for (const subnet of Object.keys(constants6.TYPES)) { + if (this.isInSubnet(new Address6(subnet))) { + return constants6.TYPES[subnet] as string; + } + } + + return 'Global unicast'; + } + + /** + * Return the bits in the given range as a BigInt + * @memberof Address6 + * @instance + * @returns {bigint} + */ + getBits(start: number, end: number): bigint { + return BigInt(`0b${this.getBitsBase2(start, end)}`); + } + + /** + * Return the bits in the given range as a base-2 string + * @memberof Address6 + * @instance + * @returns {String} + */ + getBitsBase2(start: number, end: number): string { + return this.binaryZeroPad().slice(start, end); + } + + /** + * Return the bits in the given range as a base-16 string + * @memberof Address6 + * @instance + * @returns {String} + */ + getBitsBase16(start: number, end: number): string { + const length = end - start; + + if (length % 4 !== 0) { + throw new Error('Length of bits to retrieve must be divisible by four'); + } + + return this.getBits(start, end) + .toString(16) + .padStart(length / 4, '0'); + } + + /** + * Return the bits that are set past the subnet mask length + * @memberof Address6 + * @instance + * @returns {String} + */ + getBitsPastSubnet(): string { + return this.getBitsBase2(this.subnetMask, constants6.BITS); + } + + /** + * Return the reversed ip6.arpa form of the address + * @memberof Address6 + * @param {Object} options + * @param {boolean} options.omitSuffix - omit the "ip6.arpa" suffix + * @instance + * @returns {String} + */ + reverseForm(options?: common.ReverseFormOptions): string { + if (!options) { + options = {}; + } + + const characters = Math.floor(this.subnetMask / 4); + + const reversed = this.canonicalForm() + .replace(/:/g, '') + .split('') + .slice(0, characters) + .reverse() + .join('.'); + + if (characters > 0) { + if (options.omitSuffix) { + return reversed; + } + + return `${reversed}.ip6.arpa.`; + } + + if (options.omitSuffix) { + return ''; + } + + return 'ip6.arpa.'; + } + + /** + * Return the correct form of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + correctForm(): string { + let i; + let groups = []; + + let zeroCounter = 0; + const zeroes = []; + + for (i = 0; i < this.parsedAddress.length; i++) { + const value = parseInt(this.parsedAddress[i], 16); + + if (value === 0) { + zeroCounter++; + } + + if (value !== 0 && zeroCounter > 0) { + if (zeroCounter > 1) { + zeroes.push([i - zeroCounter, i - 1]); + } + + zeroCounter = 0; + } + } + + // Do we end with a string of zeroes? + if (zeroCounter > 1) { + zeroes.push([this.parsedAddress.length - zeroCounter, this.parsedAddress.length - 1]); + } + + const zeroLengths = zeroes.map((n) => n[1] - n[0] + 1); + + if (zeroes.length > 0) { + const index = zeroLengths.indexOf(Math.max(...zeroLengths) as number); + + groups = compact(this.parsedAddress, zeroes[index]); + } else { + groups = this.parsedAddress; + } + + for (i = 0; i < groups.length; i++) { + if (groups[i] !== 'compact') { + groups[i] = parseInt(groups[i], 16).toString(16); + } + } + + let correct = groups.join(':'); + + correct = correct.replace(/^compact$/, '::'); + correct = correct.replace(/(^compact)|(compact$)/, ':'); + correct = correct.replace(/compact/, ''); + + return correct; + } + + /** + * Return a zero-padded base-2 string representation of the address + * @memberof Address6 + * @instance + * @returns {String} + * @example + * var address = new Address6('2001:4860:4001:803::1011'); + * address.binaryZeroPad(); + * // '0010000000000001010010000110000001000000000000010000100000000011 + * // 0000000000000000000000000000000000000000000000000001000000010001' + */ + binaryZeroPad(): string { + return this.bigInt().toString(2).padStart(constants6.BITS, '0'); + } + + // TODO: Improve the semantics of this helper function + parse4in6(address: string): string { + const groups = address.split(':'); + const lastGroup = groups.slice(-1)[0]; + + const address4 = lastGroup.match(constants4.RE_ADDRESS); + + if (address4) { + this.parsedAddress4 = address4[0]; + this.address4 = new Address4(this.parsedAddress4); + + for (let i = 0; i < this.address4.groups; i++) { + if (/^0[0-9]+/.test(this.address4.parsedAddress[i])) { + throw new AddressError( + "IPv4 addresses can't have leading zeroes.", + address.replace( + constants4.RE_ADDRESS, + this.address4.parsedAddress.map(spanLeadingZeroes4).join('.'), + ), + ); + } + } + + this.v4 = true; + + groups[groups.length - 1] = this.address4.toGroup6(); + + address = groups.join(':'); + } + + return address; + } + + // TODO: Make private? + parse(address: string): string[] { + address = this.parse4in6(address); + + const badCharacters = address.match(constants6.RE_BAD_CHARACTERS); + + if (badCharacters) { + throw new AddressError( + `Bad character${ + badCharacters.length > 1 ? 's' : '' + } detected in address: ${badCharacters.join('')}`, + address.replace(constants6.RE_BAD_CHARACTERS, '$1'), + ); + } + + const badAddress = address.match(constants6.RE_BAD_ADDRESS); + + if (badAddress) { + throw new AddressError( + `Address failed regex: ${badAddress.join('')}`, + address.replace(constants6.RE_BAD_ADDRESS, '$1'), + ); + } + + let groups: string[] = []; + + const halves = address.split('::'); + + if (halves.length === 2) { + let first = halves[0].split(':'); + let last = halves[1].split(':'); + + if (first.length === 1 && first[0] === '') { + first = []; + } + + if (last.length === 1 && last[0] === '') { + last = []; + } + + const remaining = this.groups - (first.length + last.length); + + if (!remaining) { + throw new AddressError('Error parsing groups'); + } + + this.elidedGroups = remaining; + + this.elisionBegin = first.length; + this.elisionEnd = first.length + this.elidedGroups; + + groups = groups.concat(first); + + for (let i = 0; i < remaining; i++) { + groups.push('0'); + } + + groups = groups.concat(last); + } else if (halves.length === 1) { + groups = address.split(':'); + + this.elidedGroups = 0; + } else { + throw new AddressError('Too many :: groups found'); + } + + groups = groups.map((group: string) => parseInt(group, 16).toString(16)); + + if (groups.length !== this.groups) { + throw new AddressError('Incorrect number of groups found'); + } + + return groups; + } + + /** + * Return the canonical form of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + canonicalForm(): string { + return this.parsedAddress.map(paddedHex).join(':'); + } + + /** + * Return the decimal form of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + decimal(): string { + return this.parsedAddress.map((n) => parseInt(n, 16).toString(10).padStart(5, '0')).join(':'); + } + + /** + * Return the address as a BigInt + * @memberof Address6 + * @instance + * @returns {bigint} + */ + bigInt(): bigint { + return BigInt(`0x${this.parsedAddress.map(paddedHex).join('')}`); + } + + /** + * Return the last two groups of this address as an IPv4 address string + * @memberof Address6 + * @instance + * @returns {Address4} + * @example + * var address = new Address6('2001:4860:4001::1825:bf11'); + * address.to4().correctForm(); // '24.37.191.17' + */ + to4(): Address4 { + const binary = this.binaryZeroPad().split(''); + + return Address4.fromHex(BigInt(`0b${binary.slice(96, 128).join('')}`).toString(16)); + } + + /** + * Return the v4-in-v6 form of the address + * @memberof Address6 + * @instance + * @returns {String} + */ + to4in6(): string { + const address4 = this.to4(); + const address6 = new Address6(this.parsedAddress.slice(0, 6).join(':'), 6); + + const correct = address6.correctForm(); + + let infix = ''; + + if (!/:$/.test(correct)) { + infix = ':'; + } + + return correct + infix + address4.address; + } + + /** + * Return an object containing the Teredo properties of the address + * @memberof Address6 + * @instance + * @returns {Object} + */ + inspectTeredo(): TeredoProperties { + /* + - Bits 0 to 31 are set to the Teredo prefix (normally 2001:0000::/32). + - Bits 32 to 63 embed the primary IPv4 address of the Teredo server that + is used. + - Bits 64 to 79 can be used to define some flags. Currently only the + higher order bit is used; it is set to 1 if the Teredo client is + located behind a cone NAT, 0 otherwise. For Microsoft's Windows Vista + and Windows Server 2008 implementations, more bits are used. In those + implementations, the format for these 16 bits is "CRAAAAUG AAAAAAAA", + where "C" remains the "Cone" flag. The "R" bit is reserved for future + use. The "U" bit is for the Universal/Local flag (set to 0). The "G" bit + is Individual/Group flag (set to 0). The A bits are set to a 12-bit + randomly generated number chosen by the Teredo client to introduce + additional protection for the Teredo node against IPv6-based scanning + attacks. + - Bits 80 to 95 contains the obfuscated UDP port number. This is the + port number that is mapped by the NAT to the Teredo client with all + bits inverted. + - Bits 96 to 127 contains the obfuscated IPv4 address. This is the + public IPv4 address of the NAT with all bits inverted. + */ + const prefix = this.getBitsBase16(0, 32); + + const bitsForUdpPort: bigint = this.getBits(80, 96); + // eslint-disable-next-line no-bitwise + const udpPort = (bitsForUdpPort ^ BigInt('0xffff')).toString(); + + const server4 = Address4.fromHex(this.getBitsBase16(32, 64)); + + const bitsForClient4 = this.getBits(96, 128); + // eslint-disable-next-line no-bitwise + const client4 = Address4.fromHex((bitsForClient4 ^ BigInt('0xffffffff')).toString(16)); + + const flagsBase2 = this.getBitsBase2(64, 80); + + const coneNat = testBit(flagsBase2, 15); + const reserved = testBit(flagsBase2, 14); + const groupIndividual = testBit(flagsBase2, 8); + const universalLocal = testBit(flagsBase2, 9); + const nonce = BigInt(`0b${flagsBase2.slice(2, 6) + flagsBase2.slice(8, 16)}`).toString(10); + + return { + prefix: `${prefix.slice(0, 4)}:${prefix.slice(4, 8)}`, + server4: server4.address, + client4: client4.address, + flags: flagsBase2, + coneNat, + microsoft: { + reserved, + universalLocal, + groupIndividual, + nonce, + }, + udpPort, + }; + } + + /** + * Return an object containing the 6to4 properties of the address + * @memberof Address6 + * @instance + * @returns {Object} + */ + inspect6to4(): SixToFourProperties { + /* + - Bits 0 to 15 are set to the 6to4 prefix (2002::/16). + - Bits 16 to 48 embed the IPv4 address of the 6to4 gateway that is used. + */ + + const prefix = this.getBitsBase16(0, 16); + + const gateway = Address4.fromHex(this.getBitsBase16(16, 48)); + + return { + prefix: prefix.slice(0, 4), + gateway: gateway.address, + }; + } + + /** + * Return a v6 6to4 address from a v6 v4inv6 address + * @memberof Address6 + * @instance + * @returns {Address6} + */ + to6to4(): Address6 | null { + if (!this.is4()) { + return null; + } + + const addr6to4 = [ + '2002', + this.getBitsBase16(96, 112), + this.getBitsBase16(112, 128), + '', + '/16', + ].join(':'); + + return new Address6(addr6to4); + } + + /** + * Return a byte array + * @memberof Address6 + * @instance + * @returns {Array} + */ + toByteArray(): number[] { + const valueWithoutPadding = this.bigInt().toString(16); + const leadingPad = '0'.repeat(valueWithoutPadding.length % 2); + + const value = `${leadingPad}${valueWithoutPadding}`; + + const bytes = []; + for (let i = 0, length = value.length; i < length; i += 2) { + bytes.push(parseInt(value.substring(i, i + 2), 16)); + } + + return bytes; + } + + /** + * Return an unsigned byte array + * @memberof Address6 + * @instance + * @returns {Array} + */ + toUnsignedByteArray(): number[] { + return this.toByteArray().map(unsignByte); + } + + /** + * Convert a byte array to an Address6 object + * @memberof Address6 + * @static + * @returns {Address6} + */ + static fromByteArray(bytes: Array): Address6 { + return this.fromUnsignedByteArray(bytes.map(unsignByte)); + } + + /** + * Convert an unsigned byte array to an Address6 object + * @memberof Address6 + * @static + * @returns {Address6} + */ + static fromUnsignedByteArray(bytes: Array): Address6 { + const BYTE_MAX = BigInt('256'); + let result = BigInt('0'); + let multiplier = BigInt('1'); + + for (let i = bytes.length - 1; i >= 0; i--) { + result += multiplier * BigInt(bytes[i].toString(10)); + + multiplier *= BYTE_MAX; + } + + return Address6.fromBigInt(result); + } + + // #region Attributes + /** + * Returns true if the given address is in the subnet of the current address + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isInSubnet = common.isInSubnet; + + /** + * Returns true if the address is correct, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isCorrect = common.isCorrect(constants6.BITS); + + /** + * Returns true if the address is in the canonical form, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isCanonical(): boolean { + return this.addressMinusSuffix === this.canonicalForm(); + } + + /** + * Returns true if the address is a link local address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isLinkLocal(): boolean { + // Zeroes are required, i.e. we can't check isInSubnet with 'fe80::/10' + if ( + this.getBitsBase2(0, 64) === + '1111111010000000000000000000000000000000000000000000000000000000' + ) { + return true; + } + + return false; + } + + /** + * Returns true if the address is a multicast address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isMulticast(): boolean { + return this.getType() === 'Multicast'; + } + + /** + * Returns true if the address is a v4-in-v6 address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + is4(): boolean { + return this.v4; + } + + /** + * Returns true if the address is a Teredo address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isTeredo(): boolean { + return this.isInSubnet(new Address6('2001::/32')); + } + + /** + * Returns true if the address is a 6to4 address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + is6to4(): boolean { + return this.isInSubnet(new Address6('2002::/16')); + } + + /** + * Returns true if the address is a loopback address, false otherwise + * @memberof Address6 + * @instance + * @returns {boolean} + */ + isLoopback(): boolean { + return this.getType() === 'Loopback'; + } + // #endregion + + // #region HTML + /** + * @returns {String} the address in link form with a default port of 80 + */ + href(optionalPort?: number | string): string { + if (optionalPort === undefined) { + optionalPort = ''; + } else { + optionalPort = `:${optionalPort}`; + } + + return `http://[${this.correctForm()}]${optionalPort}/`; + } + + /** + * @returns {String} a link suitable for conveying the address via a URL hash + */ + link(options?: { className?: string; prefix?: string; v4?: boolean }): string { + if (!options) { + options = {}; + } + + if (options.className === undefined) { + options.className = ''; + } + + if (options.prefix === undefined) { + options.prefix = '/#address='; + } + + if (options.v4 === undefined) { + options.v4 = false; + } + + let formFunction = this.correctForm; + + if (options.v4) { + formFunction = this.to4in6; + } + + const form = formFunction.call(this); + + if (options.className) { + return `${form}`; + } + + return `${form}`; + } + + /** + * Groups an address + * @returns {String} + */ + group(): string { + if (this.elidedGroups === 0) { + // The simple case + return helpers.simpleGroup(this.address).join(':'); + } + + assert(typeof this.elidedGroups === 'number'); + assert(typeof this.elisionBegin === 'number'); + + // The elided case + const output = []; + + const [left, right] = this.address.split('::'); + + if (left.length) { + output.push(...helpers.simpleGroup(left)); + } else { + output.push(''); + } + + const classes = ['hover-group']; + + for (let i = this.elisionBegin; i < this.elisionBegin + this.elidedGroups; i++) { + classes.push(`group-${i}`); + } + + output.push(``); + + if (right.length) { + output.push(...helpers.simpleGroup(right, this.elisionEnd)); + } else { + output.push(''); + } + + if (this.is4()) { + assert(this.address4 instanceof Address4); + + output.pop(); + output.push(this.address4.groupForV6()); + } + + return output.join(':'); + } + // #endregion + + // #region Regular expressions + /** + * Generate a regular expression string that can be used to find or validate + * all variations of this address + * @memberof Address6 + * @instance + * @param {boolean} substringSearch + * @returns {string} + */ + regularExpressionString(this: Address6, substringSearch: boolean = false): string { + let output: string[] = []; + + // TODO: revisit why this is necessary + const address6 = new Address6(this.correctForm()); + + if (address6.elidedGroups === 0) { + // The simple case + output.push(simpleRegularExpression(address6.parsedAddress)); + } else if (address6.elidedGroups === constants6.GROUPS) { + // A completely elided address + output.push(possibleElisions(constants6.GROUPS)); + } else { + // A partially elided address + const halves = address6.address.split('::'); + + if (halves[0].length) { + output.push(simpleRegularExpression(halves[0].split(':'))); + } + + assert(typeof address6.elidedGroups === 'number'); + + output.push( + possibleElisions(address6.elidedGroups, halves[0].length !== 0, halves[1].length !== 0), + ); + + if (halves[1].length) { + output.push(simpleRegularExpression(halves[1].split(':'))); + } + + output = [output.join(':')]; + } + + if (!substringSearch) { + output = [ + '(?=^|', + ADDRESS_BOUNDARY, + '|[^\\w\\:])(', + ...output, + ')(?=[^\\w\\:]|', + ADDRESS_BOUNDARY, + '|$)', + ]; + } + + return output.join(''); + } + + /** + * Generate a regular expression that can be used to find or validate all + * variations of this address. + * @memberof Address6 + * @instance + * @param {boolean} substringSearch + * @returns {RegExp} + */ + regularExpression(this: Address6, substringSearch: boolean = false): RegExp { + return new RegExp(this.regularExpressionString(substringSearch), 'i'); + } + // #endregion +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v4/constants.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v4/constants.ts new file mode 100644 index 000000000..73c32f1fd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v4/constants.ts @@ -0,0 +1,7 @@ +export const BITS = 32; +export const GROUPS = 4; + +export const RE_ADDRESS = + /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/g; + +export const RE_SUBNET_STRING = /\/\d{1,2}$/; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v6/constants.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v6/constants.ts new file mode 100644 index 000000000..e23bfa56f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v6/constants.ts @@ -0,0 +1,79 @@ +export const BITS = 128; +export const GROUPS = 8; + +/** + * Represents IPv6 address scopes + * @memberof Address6 + * @static + */ +export const SCOPES: { [key: number]: string | undefined } = { + 0: 'Reserved', + 1: 'Interface local', + 2: 'Link local', + 4: 'Admin local', + 5: 'Site local', + 8: 'Organization local', + 14: 'Global', + 15: 'Reserved', +} as const; + +/** + * Represents IPv6 address types + * @memberof Address6 + * @static + */ +export const TYPES: { [key: string]: string | undefined } = { + 'ff01::1/128': 'Multicast (All nodes on this interface)', + 'ff01::2/128': 'Multicast (All routers on this interface)', + 'ff02::1/128': 'Multicast (All nodes on this link)', + 'ff02::2/128': 'Multicast (All routers on this link)', + 'ff05::2/128': 'Multicast (All routers in this site)', + 'ff02::5/128': 'Multicast (OSPFv3 AllSPF routers)', + 'ff02::6/128': 'Multicast (OSPFv3 AllDR routers)', + 'ff02::9/128': 'Multicast (RIP routers)', + 'ff02::a/128': 'Multicast (EIGRP routers)', + 'ff02::d/128': 'Multicast (PIM routers)', + 'ff02::16/128': 'Multicast (MLDv2 reports)', + 'ff01::fb/128': 'Multicast (mDNSv6)', + 'ff02::fb/128': 'Multicast (mDNSv6)', + 'ff05::fb/128': 'Multicast (mDNSv6)', + 'ff02::1:2/128': 'Multicast (All DHCP servers and relay agents on this link)', + 'ff05::1:2/128': 'Multicast (All DHCP servers and relay agents in this site)', + 'ff02::1:3/128': 'Multicast (All DHCP servers on this link)', + 'ff05::1:3/128': 'Multicast (All DHCP servers in this site)', + '::/128': 'Unspecified', + '::1/128': 'Loopback', + 'ff00::/8': 'Multicast', + 'fe80::/10': 'Link-local unicast', +} as const; + +/** + * A regular expression that matches bad characters in an IPv6 address + * @memberof Address6 + * @static + */ +export const RE_BAD_CHARACTERS = /([^0-9a-f:/%])/gi; + +/** + * A regular expression that matches an incorrect IPv6 address + * @memberof Address6 + * @static + */ +export const RE_BAD_ADDRESS = /([0-9a-f]{5,}|:{3,}|[^:]:$|^:[^:]|\/$)/gi; + +/** + * A regular expression that matches an IPv6 subnet + * @memberof Address6 + * @static + */ +export const RE_SUBNET_STRING = /\/\d{1,3}(?=%|$)/; + +/** + * A regular expression that matches an IPv6 zone + * @memberof Address6 + * @static + */ +export const RE_ZONE_STRING = /%.*$/; + +export const RE_URL = /^\[{0,1}([0-9a-f:]+)\]{0,1}/; +export const RE_URL_WITH_PORT = /\[([0-9a-f:]+)\]:([0-9]{1,5})/; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v6/helpers.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v6/helpers.ts new file mode 100644 index 000000000..e40074c9f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v6/helpers.ts @@ -0,0 +1,48 @@ +/** + * @returns {String} the string with all zeroes contained in a + */ +export function spanAllZeroes(s: string): string { + return s.replace(/(0+)/g, '$1'); +} + +/** + * @returns {String} the string with each character contained in a + */ +export function spanAll(s: string, offset: number = 0): string { + const letters = s.split(''); + + return letters + .map( + (n, i) => `${spanAllZeroes(n)}`, + ) + .join(''); +} + +function spanLeadingZeroesSimple(group: string): string { + return group.replace(/^(0+)/, '$1'); +} + +/** + * @returns {String} the string with leading zeroes contained in a + */ +export function spanLeadingZeroes(address: string): string { + const groups = address.split(':'); + + return groups.map((g) => spanLeadingZeroesSimple(g)).join(':'); +} + +/** + * Groups an address + * @returns {String} a grouped address + */ +export function simpleGroup(addressString: string, offset: number = 0): string[] { + const groups = addressString.split(':'); + + return groups.map((g, i) => { + if (/group-v4/.test(g)) { + return g; + } + + return `${spanLeadingZeroesSimple(g)}`; + }); +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v6/regular-expressions.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v6/regular-expressions.ts new file mode 100644 index 000000000..a511b8499 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ip-address/src/v6/regular-expressions.ts @@ -0,0 +1,94 @@ +import * as v6 from './constants'; + +export function groupPossibilities(possibilities: string[]): string { + return `(${possibilities.join('|')})`; +} + +export function padGroup(group: string): string { + if (group.length < 4) { + return `0{0,${4 - group.length}}${group}`; + } + + return group; +} + +export const ADDRESS_BOUNDARY = '[^A-Fa-f0-9:]'; + +export function simpleRegularExpression(groups: string[]) { + const zeroIndexes: number[] = []; + + groups.forEach((group, i) => { + const groupInteger = parseInt(group, 16); + + if (groupInteger === 0) { + zeroIndexes.push(i); + } + }); + + // You can technically elide a single 0, this creates the regular expressions + // to match that eventuality + const possibilities = zeroIndexes.map((zeroIndex) => + groups + .map((group, i) => { + if (i === zeroIndex) { + const elision = i === 0 || i === v6.GROUPS - 1 ? ':' : ''; + + return groupPossibilities([padGroup(group), elision]); + } + + return padGroup(group); + }) + .join(':'), + ); + + // The simplest case + possibilities.push(groups.map(padGroup).join(':')); + + return groupPossibilities(possibilities); +} + +export function possibleElisions( + elidedGroups: number, + moreLeft?: boolean, + moreRight?: boolean, +): string { + const left = moreLeft ? '' : ':'; + const right = moreRight ? '' : ':'; + + const possibilities = []; + + // 1. elision of everything (::) + if (!moreLeft && !moreRight) { + possibilities.push('::'); + } + + // 2. complete elision of the middle + if (moreLeft && moreRight) { + possibilities.push(''); + } + + if ((moreRight && !moreLeft) || (!moreRight && moreLeft)) { + // 3. complete elision of one side + possibilities.push(':'); + } + + // 4. elision from the left side + possibilities.push(`${left}(:0{1,4}){1,${elidedGroups - 1}}`); + + // 5. elision from the right side + possibilities.push(`(0{1,4}:){1,${elidedGroups - 1}}${right}`); + + // 6. no elision + possibilities.push(`(0{1,4}:){${elidedGroups - 1}}0{1,4}`); + + // 7. elision (including sloppy elision) from the middle + for (let groups = 1; groups < elidedGroups - 1; groups++) { + for (let position = 1; position < elidedGroups - groups; position++) { + possibilities.push( + `(0{1,4}:){${position}}:(0{1,4}:){${elidedGroups - position - groups - 1}}0{1,4}`, + ); + } + } + + return groupPossibilities(possibilities); +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/LICENSE new file mode 100644 index 000000000..f6b37b52d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2011-2017 whitequark + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/README.md new file mode 100644 index 000000000..f57725b0f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/README.md @@ -0,0 +1,233 @@ +# ipaddr.js — an IPv6 and IPv4 address manipulation library [![Build Status](https://travis-ci.org/whitequark/ipaddr.js.svg)](https://travis-ci.org/whitequark/ipaddr.js) + +ipaddr.js is a small (1.9K minified and gzipped) library for manipulating +IP addresses in JavaScript environments. It runs on both CommonJS runtimes +(e.g. [nodejs]) and in a web browser. + +ipaddr.js allows you to verify and parse string representation of an IP +address, match it against a CIDR range or range list, determine if it falls +into some reserved ranges (examples include loopback and private ranges), +and convert between IPv4 and IPv4-mapped IPv6 addresses. + +[nodejs]: http://nodejs.org + +## Installation + +`npm install ipaddr.js` + +or + +`bower install ipaddr.js` + +## API + +ipaddr.js defines one object in the global scope: `ipaddr`. In CommonJS, +it is exported from the module: + +```js +var ipaddr = require('ipaddr.js'); +``` + +The API consists of several global methods and two classes: ipaddr.IPv6 and ipaddr.IPv4. + +### Global methods + +There are three global methods defined: `ipaddr.isValid`, `ipaddr.parse` and +`ipaddr.process`. All of them receive a string as a single parameter. + +The `ipaddr.isValid` method returns `true` if the address is a valid IPv4 or +IPv6 address, and `false` otherwise. It does not throw any exceptions. + +The `ipaddr.parse` method returns an object representing the IP address, +or throws an `Error` if the passed string is not a valid representation of an +IP address. + +The `ipaddr.process` method works just like the `ipaddr.parse` one, but it +automatically converts IPv4-mapped IPv6 addresses to their IPv4 counterparts +before returning. It is useful when you have a Node.js instance listening +on an IPv6 socket, and the `net.ivp6.bindv6only` sysctl parameter (or its +equivalent on non-Linux OS) is set to 0. In this case, you can accept IPv4 +connections on your IPv6-only socket, but the remote address will be mangled. +Use `ipaddr.process` method to automatically demangle it. + +### Object representation + +Parsing methods return an object which descends from `ipaddr.IPv6` or +`ipaddr.IPv4`. These objects share some properties, but most of them differ. + +#### Shared properties + +One can determine the type of address by calling `addr.kind()`. It will return +either `"ipv6"` or `"ipv4"`. + +An address can be converted back to its string representation with `addr.toString()`. +Note that this method: + * does not return the original string used to create the object (in fact, there is + no way of getting that string) + * returns a compact representation (when it is applicable) + +A `match(range, bits)` method can be used to check if the address falls into a +certain CIDR range. +Note that an address can be (obviously) matched only against an address of the same type. + +For example: + +```js +var addr = ipaddr.parse("2001:db8:1234::1"); +var range = ipaddr.parse("2001:db8::"); + +addr.match(range, 32); // => true +``` + +Alternatively, `match` can also be called as `match([range, bits])`. In this way, +it can be used together with the `parseCIDR(string)` method, which parses an IP +address together with a CIDR range. + +For example: + +```js +var addr = ipaddr.parse("2001:db8:1234::1"); + +addr.match(ipaddr.parseCIDR("2001:db8::/32")); // => true +``` + +A `range()` method returns one of predefined names for several special ranges defined +by IP protocols. The exact names (and their respective CIDR ranges) can be looked up +in the source: [IPv6 ranges] and [IPv4 ranges]. Some common ones include `"unicast"` +(the default one) and `"reserved"`. + +You can match against your own range list by using +`ipaddr.subnetMatch(address, rangeList, defaultName)` method. It can work with a mix of IPv6 or IPv4 addresses, and accepts a name-to-subnet map as the range list. For example: + +```js +var rangeList = { + documentationOnly: [ ipaddr.parse('2001:db8::'), 32 ], + tunnelProviders: [ + [ ipaddr.parse('2001:470::'), 32 ], // he.net + [ ipaddr.parse('2001:5c0::'), 32 ] // freenet6 + ] +}; +ipaddr.subnetMatch(ipaddr.parse('2001:470:8:66::1'), rangeList, 'unknown'); // => "tunnelProviders" +``` + +The addresses can be converted to their byte representation with `toByteArray()`. +(Actually, JavaScript mostly does not know about byte buffers. They are emulated with +arrays of numbers, each in range of 0..255.) + +```js +var bytes = ipaddr.parse('2a00:1450:8007::68').toByteArray(); // ipv6.google.com +bytes // => [42, 0x00, 0x14, 0x50, 0x80, 0x07, 0x00, , 0x00, 0x68 ] +``` + +The `ipaddr.IPv4` and `ipaddr.IPv6` objects have some methods defined, too. All of them +have the same interface for both protocols, and are similar to global methods. + +`ipaddr.IPvX.isValid(string)` can be used to check if the string is a valid address +for particular protocol, and `ipaddr.IPvX.parse(string)` is the error-throwing parser. + +`ipaddr.IPvX.isValid(string)` uses the same format for parsing as the POSIX `inet_ntoa` function, which accepts unusual formats like `0xc0.168.1.1` or `0x10000000`. The function `ipaddr.IPv4.isValidFourPartDecimal(string)` validates the IPv4 address and also ensures that it is written in four-part decimal format. + +[IPv6 ranges]: https://github.com/whitequark/ipaddr.js/blob/master/src/ipaddr.coffee#L186 +[IPv4 ranges]: https://github.com/whitequark/ipaddr.js/blob/master/src/ipaddr.coffee#L71 + +#### IPv6 properties + +Sometimes you will want to convert IPv6 not to a compact string representation (with +the `::` substitution); the `toNormalizedString()` method will return an address where +all zeroes are explicit. + +For example: + +```js +var addr = ipaddr.parse("2001:0db8::0001"); +addr.toString(); // => "2001:db8::1" +addr.toNormalizedString(); // => "2001:db8:0:0:0:0:0:1" +``` + +The `isIPv4MappedAddress()` method will return `true` if this address is an IPv4-mapped +one, and `toIPv4Address()` will return an IPv4 object address. + +To access the underlying binary representation of the address, use `addr.parts`. + +```js +var addr = ipaddr.parse("2001:db8:10::1234:DEAD"); +addr.parts // => [0x2001, 0xdb8, 0x10, 0, 0, 0, 0x1234, 0xdead] +``` + +A IPv6 zone index can be accessed via `addr.zoneId`: + +```js +var addr = ipaddr.parse("2001:db8::%eth0"); +addr.zoneId // => 'eth0' +``` + +#### IPv4 properties + +`toIPv4MappedAddress()` will return a corresponding IPv4-mapped IPv6 address. + +To access the underlying representation of the address, use `addr.octets`. + +```js +var addr = ipaddr.parse("192.168.1.1"); +addr.octets // => [192, 168, 1, 1] +``` + +`prefixLengthFromSubnetMask()` will return a CIDR prefix length for a valid IPv4 netmask or +null if the netmask is not valid. + +```js +ipaddr.IPv4.parse('255.255.255.240').prefixLengthFromSubnetMask() == 28 +ipaddr.IPv4.parse('255.192.164.0').prefixLengthFromSubnetMask() == null +``` + +`subnetMaskFromPrefixLength()` will return an IPv4 netmask for a valid CIDR prefix length. + +```js +ipaddr.IPv4.subnetMaskFromPrefixLength(24) == "255.255.255.0" +ipaddr.IPv4.subnetMaskFromPrefixLength(29) == "255.255.255.248" +``` + +`broadcastAddressFromCIDR()` will return the broadcast address for a given IPv4 interface and netmask in CIDR notation. +```js +ipaddr.IPv4.broadcastAddressFromCIDR("172.0.0.1/24") == "172.0.0.255" +``` +`networkAddressFromCIDR()` will return the network address for a given IPv4 interface and netmask in CIDR notation. +```js +ipaddr.IPv4.networkAddressFromCIDR("172.0.0.1/24") == "172.0.0.0" +``` + +#### Conversion + +IPv4 and IPv6 can be converted bidirectionally to and from network byte order (MSB) byte arrays. + +The `fromByteArray()` method will take an array and create an appropriate IPv4 or IPv6 object +if the input satisfies the requirements. For IPv4 it has to be an array of four 8-bit values, +while for IPv6 it has to be an array of sixteen 8-bit values. + +For example: +```js +var addr = ipaddr.fromByteArray([0x7f, 0, 0, 1]); +addr.toString(); // => "127.0.0.1" +``` + +or + +```js +var addr = ipaddr.fromByteArray([0x20, 1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) +addr.toString(); // => "2001:db8::1" +``` + +Both objects also offer a `toByteArray()` method, which returns an array in network byte order (MSB). + +For example: +```js +var addr = ipaddr.parse("127.0.0.1"); +addr.toByteArray(); // => [0x7f, 0, 0, 1] +``` + +or + +```js +var addr = ipaddr.parse("2001:db8::1"); +addr.toByteArray(); // => [0x20, 1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] +``` diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/ipaddr.min.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/ipaddr.min.js new file mode 100644 index 000000000..b54a7cc42 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/ipaddr.min.js @@ -0,0 +1 @@ +(function(){var r,t,n,e,i,o,a,s;t={},s=this,"undefined"!=typeof module&&null!==module&&module.exports?module.exports=t:s.ipaddr=t,a=function(r,t,n,e){var i,o;if(r.length!==t.length)throw new Error("ipaddr: cannot match CIDR for objects with different lengths");for(i=0;e>0;){if((o=n-e)<0&&(o=0),r[i]>>o!=t[i]>>o)return!1;e-=n,i+=1}return!0},t.subnetMatch=function(r,t,n){var e,i,o,a,s;null==n&&(n="unicast");for(o in t)for(!(a=t[o])[0]||a[0]instanceof Array||(a=[a]),e=0,i=a.length;e=0;t=n+=-1){if(!((e=this.octets[t])in a))return null;if(o=a[e],i&&0!==o)return null;8!==o&&(i=!0),r+=o}return 32-r},r}(),n="(0?\\d+|0x[a-f0-9]+)",e={fourOctet:new RegExp("^"+n+"\\."+n+"\\."+n+"\\."+n+"$","i"),longValue:new RegExp("^"+n+"$","i")},t.IPv4.parser=function(r){var t,n,i,o,a;if(n=function(r){return"0"===r[0]&&"x"!==r[1]?parseInt(r,8):parseInt(r)},t=r.match(e.fourOctet))return function(){var r,e,o,a;for(a=[],r=0,e=(o=t.slice(1,6)).length;r4294967295||a<0)throw new Error("ipaddr: address outside defined range");return function(){var r,t;for(t=[],o=r=0;r<=24;o=r+=8)t.push(a>>o&255);return t}().reverse()}return null},t.IPv6=function(){function r(r,t){var n,e,i,o,a,s;if(16===r.length)for(this.parts=[],n=e=0;e<=14;n=e+=2)this.parts.push(r[n]<<8|r[n+1]);else{if(8!==r.length)throw new Error("ipaddr: ipv6 part count should be 8 or 16");this.parts=r}for(i=0,o=(s=this.parts).length;it&&(r=n.index,t=n[0].length);return t<0?i:i.substring(0,r)+"::"+i.substring(r+t)},r.prototype.toByteArray=function(){var r,t,n,e,i;for(r=[],t=0,n=(i=this.parts).length;t>8),r.push(255&e);return r},r.prototype.toNormalizedString=function(){var r,t,n;return r=function(){var r,n,e,i;for(i=[],r=0,n=(e=this.parts).length;r>8,255&r,n>>8,255&n])},r.prototype.prefixLengthFromSubnetMask=function(){var r,t,n,e,i,o,a;for(a={0:16,32768:15,49152:14,57344:13,61440:12,63488:11,64512:10,65024:9,65280:8,65408:7,65472:6,65504:5,65520:4,65528:3,65532:2,65534:1,65535:0},r=0,i=!1,t=n=7;n>=0;t=n+=-1){if(!((e=this.parts[t])in a))return null;if(o=a[e],i&&0!==o)return null;16!==o&&(i=!0),r+=o}return 128-r},r}(),i="(?:[0-9a-f]+::?)+",o={zoneIndex:new RegExp("%[0-9a-z]{1,}","i"),native:new RegExp("^(::)?("+i+")?([0-9a-f]+)?(::)?(%[0-9a-z]{1,})?$","i"),transitional:new RegExp("^((?:"+i+")|(?:::)(?:"+i+")?)"+n+"\\."+n+"\\."+n+"\\."+n+"(%[0-9a-z]{1,})?$","i")},r=function(r,t){var n,e,i,a,s,p;if(r.indexOf("::")!==r.lastIndexOf("::"))return null;for((p=(r.match(o.zoneIndex)||[])[0])&&(p=p.substring(1),r=r.replace(/%.+$/,"")),n=0,e=-1;(e=r.indexOf(":",e+1))>=0;)n++;if("::"===r.substr(0,2)&&n--,"::"===r.substr(-2,2)&&n--,n>t)return null;for(s=t-n,a=":";s--;)a+="0:";return":"===(r=r.replace("::",a))[0]&&(r=r.slice(1)),":"===r[r.length-1]&&(r=r.slice(0,-1)),t=function(){var t,n,e,o;for(o=[],t=0,n=(e=r.split(":")).length;t=0&&t<=32)return e=[this.parse(n[1]),t],Object.defineProperty(e,"toString",{value:function(){return this.join("/")}}),e;throw new Error("ipaddr: string is not formatted like an IPv4 CIDR range")},t.IPv4.subnetMaskFromPrefixLength=function(r){var t,n,e;if((r=parseInt(r))<0||r>32)throw new Error("ipaddr: invalid IPv4 prefix length");for(e=[0,0,0,0],n=0,t=Math.floor(r/8);n=0&&t<=128)return e=[this.parse(n[1]),t],Object.defineProperty(e,"toString",{value:function(){return this.join("/")}}),e;throw new Error("ipaddr: string is not formatted like an IPv6 CIDR range")},t.isValid=function(r){return t.IPv6.isValid(r)||t.IPv4.isValid(r)},t.parse=function(r){if(t.IPv6.isValid(r))return t.IPv6.parse(r);if(t.IPv4.isValid(r))return t.IPv4.parse(r);throw new Error("ipaddr: the address has neither IPv6 nor IPv4 format")},t.parseCIDR=function(r){try{return t.IPv6.parseCIDR(r)}catch(n){n;try{return t.IPv4.parseCIDR(r)}catch(r){throw r,new Error("ipaddr: the address has neither IPv6 nor IPv4 CIDR format")}}},t.fromByteArray=function(r){var n;if(4===(n=r.length))return new t.IPv4(r);if(16===n)return new t.IPv6(r);throw new Error("ipaddr: the binary input is neither an IPv6 nor IPv4 address")},t.process=function(r){var t;return t=this.parse(r),"ipv6"===t.kind()&&t.isIPv4MappedAddress()?t.toIPv4Address():t}}).call(this); \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/lib/ipaddr.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/lib/ipaddr.js new file mode 100644 index 000000000..18bd93b5e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/lib/ipaddr.js @@ -0,0 +1,673 @@ +(function() { + var expandIPv6, ipaddr, ipv4Part, ipv4Regexes, ipv6Part, ipv6Regexes, matchCIDR, root, zoneIndex; + + ipaddr = {}; + + root = this; + + if ((typeof module !== "undefined" && module !== null) && module.exports) { + module.exports = ipaddr; + } else { + root['ipaddr'] = ipaddr; + } + + matchCIDR = function(first, second, partSize, cidrBits) { + var part, shift; + if (first.length !== second.length) { + throw new Error("ipaddr: cannot match CIDR for objects with different lengths"); + } + part = 0; + while (cidrBits > 0) { + shift = partSize - cidrBits; + if (shift < 0) { + shift = 0; + } + if (first[part] >> shift !== second[part] >> shift) { + return false; + } + cidrBits -= partSize; + part += 1; + } + return true; + }; + + ipaddr.subnetMatch = function(address, rangeList, defaultName) { + var k, len, rangeName, rangeSubnets, subnet; + if (defaultName == null) { + defaultName = 'unicast'; + } + for (rangeName in rangeList) { + rangeSubnets = rangeList[rangeName]; + if (rangeSubnets[0] && !(rangeSubnets[0] instanceof Array)) { + rangeSubnets = [rangeSubnets]; + } + for (k = 0, len = rangeSubnets.length; k < len; k++) { + subnet = rangeSubnets[k]; + if (address.kind() === subnet[0].kind()) { + if (address.match.apply(address, subnet)) { + return rangeName; + } + } + } + } + return defaultName; + }; + + ipaddr.IPv4 = (function() { + function IPv4(octets) { + var k, len, octet; + if (octets.length !== 4) { + throw new Error("ipaddr: ipv4 octet count should be 4"); + } + for (k = 0, len = octets.length; k < len; k++) { + octet = octets[k]; + if (!((0 <= octet && octet <= 255))) { + throw new Error("ipaddr: ipv4 octet should fit in 8 bits"); + } + } + this.octets = octets; + } + + IPv4.prototype.kind = function() { + return 'ipv4'; + }; + + IPv4.prototype.toString = function() { + return this.octets.join("."); + }; + + IPv4.prototype.toNormalizedString = function() { + return this.toString(); + }; + + IPv4.prototype.toByteArray = function() { + return this.octets.slice(0); + }; + + IPv4.prototype.match = function(other, cidrRange) { + var ref; + if (cidrRange === void 0) { + ref = other, other = ref[0], cidrRange = ref[1]; + } + if (other.kind() !== 'ipv4') { + throw new Error("ipaddr: cannot match ipv4 address with non-ipv4 one"); + } + return matchCIDR(this.octets, other.octets, 8, cidrRange); + }; + + IPv4.prototype.SpecialRanges = { + unspecified: [[new IPv4([0, 0, 0, 0]), 8]], + broadcast: [[new IPv4([255, 255, 255, 255]), 32]], + multicast: [[new IPv4([224, 0, 0, 0]), 4]], + linkLocal: [[new IPv4([169, 254, 0, 0]), 16]], + loopback: [[new IPv4([127, 0, 0, 0]), 8]], + carrierGradeNat: [[new IPv4([100, 64, 0, 0]), 10]], + "private": [[new IPv4([10, 0, 0, 0]), 8], [new IPv4([172, 16, 0, 0]), 12], [new IPv4([192, 168, 0, 0]), 16]], + reserved: [[new IPv4([192, 0, 0, 0]), 24], [new IPv4([192, 0, 2, 0]), 24], [new IPv4([192, 88, 99, 0]), 24], [new IPv4([198, 51, 100, 0]), 24], [new IPv4([203, 0, 113, 0]), 24], [new IPv4([240, 0, 0, 0]), 4]] + }; + + IPv4.prototype.range = function() { + return ipaddr.subnetMatch(this, this.SpecialRanges); + }; + + IPv4.prototype.toIPv4MappedAddress = function() { + return ipaddr.IPv6.parse("::ffff:" + (this.toString())); + }; + + IPv4.prototype.prefixLengthFromSubnetMask = function() { + var cidr, i, k, octet, stop, zeros, zerotable; + zerotable = { + 0: 8, + 128: 7, + 192: 6, + 224: 5, + 240: 4, + 248: 3, + 252: 2, + 254: 1, + 255: 0 + }; + cidr = 0; + stop = false; + for (i = k = 3; k >= 0; i = k += -1) { + octet = this.octets[i]; + if (octet in zerotable) { + zeros = zerotable[octet]; + if (stop && zeros !== 0) { + return null; + } + if (zeros !== 8) { + stop = true; + } + cidr += zeros; + } else { + return null; + } + } + return 32 - cidr; + }; + + return IPv4; + + })(); + + ipv4Part = "(0?\\d+|0x[a-f0-9]+)"; + + ipv4Regexes = { + fourOctet: new RegExp("^" + ipv4Part + "\\." + ipv4Part + "\\." + ipv4Part + "\\." + ipv4Part + "$", 'i'), + longValue: new RegExp("^" + ipv4Part + "$", 'i') + }; + + ipaddr.IPv4.parser = function(string) { + var match, parseIntAuto, part, shift, value; + parseIntAuto = function(string) { + if (string[0] === "0" && string[1] !== "x") { + return parseInt(string, 8); + } else { + return parseInt(string); + } + }; + if (match = string.match(ipv4Regexes.fourOctet)) { + return (function() { + var k, len, ref, results; + ref = match.slice(1, 6); + results = []; + for (k = 0, len = ref.length; k < len; k++) { + part = ref[k]; + results.push(parseIntAuto(part)); + } + return results; + })(); + } else if (match = string.match(ipv4Regexes.longValue)) { + value = parseIntAuto(match[1]); + if (value > 0xffffffff || value < 0) { + throw new Error("ipaddr: address outside defined range"); + } + return ((function() { + var k, results; + results = []; + for (shift = k = 0; k <= 24; shift = k += 8) { + results.push((value >> shift) & 0xff); + } + return results; + })()).reverse(); + } else { + return null; + } + }; + + ipaddr.IPv6 = (function() { + function IPv6(parts, zoneId) { + var i, k, l, len, part, ref; + if (parts.length === 16) { + this.parts = []; + for (i = k = 0; k <= 14; i = k += 2) { + this.parts.push((parts[i] << 8) | parts[i + 1]); + } + } else if (parts.length === 8) { + this.parts = parts; + } else { + throw new Error("ipaddr: ipv6 part count should be 8 or 16"); + } + ref = this.parts; + for (l = 0, len = ref.length; l < len; l++) { + part = ref[l]; + if (!((0 <= part && part <= 0xffff))) { + throw new Error("ipaddr: ipv6 part should fit in 16 bits"); + } + } + if (zoneId) { + this.zoneId = zoneId; + } + } + + IPv6.prototype.kind = function() { + return 'ipv6'; + }; + + IPv6.prototype.toString = function() { + return this.toNormalizedString().replace(/((^|:)(0(:|$))+)/, '::'); + }; + + IPv6.prototype.toRFC5952String = function() { + var bestMatchIndex, bestMatchLength, match, regex, string; + regex = /((^|:)(0(:|$)){2,})/g; + string = this.toNormalizedString(); + bestMatchIndex = 0; + bestMatchLength = -1; + while ((match = regex.exec(string))) { + if (match[0].length > bestMatchLength) { + bestMatchIndex = match.index; + bestMatchLength = match[0].length; + } + } + if (bestMatchLength < 0) { + return string; + } + return string.substring(0, bestMatchIndex) + '::' + string.substring(bestMatchIndex + bestMatchLength); + }; + + IPv6.prototype.toByteArray = function() { + var bytes, k, len, part, ref; + bytes = []; + ref = this.parts; + for (k = 0, len = ref.length; k < len; k++) { + part = ref[k]; + bytes.push(part >> 8); + bytes.push(part & 0xff); + } + return bytes; + }; + + IPv6.prototype.toNormalizedString = function() { + var addr, part, suffix; + addr = ((function() { + var k, len, ref, results; + ref = this.parts; + results = []; + for (k = 0, len = ref.length; k < len; k++) { + part = ref[k]; + results.push(part.toString(16)); + } + return results; + }).call(this)).join(":"); + suffix = ''; + if (this.zoneId) { + suffix = '%' + this.zoneId; + } + return addr + suffix; + }; + + IPv6.prototype.toFixedLengthString = function() { + var addr, part, suffix; + addr = ((function() { + var k, len, ref, results; + ref = this.parts; + results = []; + for (k = 0, len = ref.length; k < len; k++) { + part = ref[k]; + results.push(part.toString(16).padStart(4, '0')); + } + return results; + }).call(this)).join(":"); + suffix = ''; + if (this.zoneId) { + suffix = '%' + this.zoneId; + } + return addr + suffix; + }; + + IPv6.prototype.match = function(other, cidrRange) { + var ref; + if (cidrRange === void 0) { + ref = other, other = ref[0], cidrRange = ref[1]; + } + if (other.kind() !== 'ipv6') { + throw new Error("ipaddr: cannot match ipv6 address with non-ipv6 one"); + } + return matchCIDR(this.parts, other.parts, 16, cidrRange); + }; + + IPv6.prototype.SpecialRanges = { + unspecified: [new IPv6([0, 0, 0, 0, 0, 0, 0, 0]), 128], + linkLocal: [new IPv6([0xfe80, 0, 0, 0, 0, 0, 0, 0]), 10], + multicast: [new IPv6([0xff00, 0, 0, 0, 0, 0, 0, 0]), 8], + loopback: [new IPv6([0, 0, 0, 0, 0, 0, 0, 1]), 128], + uniqueLocal: [new IPv6([0xfc00, 0, 0, 0, 0, 0, 0, 0]), 7], + ipv4Mapped: [new IPv6([0, 0, 0, 0, 0, 0xffff, 0, 0]), 96], + rfc6145: [new IPv6([0, 0, 0, 0, 0xffff, 0, 0, 0]), 96], + rfc6052: [new IPv6([0x64, 0xff9b, 0, 0, 0, 0, 0, 0]), 96], + '6to4': [new IPv6([0x2002, 0, 0, 0, 0, 0, 0, 0]), 16], + teredo: [new IPv6([0x2001, 0, 0, 0, 0, 0, 0, 0]), 32], + reserved: [[new IPv6([0x2001, 0xdb8, 0, 0, 0, 0, 0, 0]), 32]] + }; + + IPv6.prototype.range = function() { + return ipaddr.subnetMatch(this, this.SpecialRanges); + }; + + IPv6.prototype.isIPv4MappedAddress = function() { + return this.range() === 'ipv4Mapped'; + }; + + IPv6.prototype.toIPv4Address = function() { + var high, low, ref; + if (!this.isIPv4MappedAddress()) { + throw new Error("ipaddr: trying to convert a generic ipv6 address to ipv4"); + } + ref = this.parts.slice(-2), high = ref[0], low = ref[1]; + return new ipaddr.IPv4([high >> 8, high & 0xff, low >> 8, low & 0xff]); + }; + + IPv6.prototype.prefixLengthFromSubnetMask = function() { + var cidr, i, k, part, stop, zeros, zerotable; + zerotable = { + 0: 16, + 32768: 15, + 49152: 14, + 57344: 13, + 61440: 12, + 63488: 11, + 64512: 10, + 65024: 9, + 65280: 8, + 65408: 7, + 65472: 6, + 65504: 5, + 65520: 4, + 65528: 3, + 65532: 2, + 65534: 1, + 65535: 0 + }; + cidr = 0; + stop = false; + for (i = k = 7; k >= 0; i = k += -1) { + part = this.parts[i]; + if (part in zerotable) { + zeros = zerotable[part]; + if (stop && zeros !== 0) { + return null; + } + if (zeros !== 16) { + stop = true; + } + cidr += zeros; + } else { + return null; + } + } + return 128 - cidr; + }; + + return IPv6; + + })(); + + ipv6Part = "(?:[0-9a-f]+::?)+"; + + zoneIndex = "%[0-9a-z]{1,}"; + + ipv6Regexes = { + zoneIndex: new RegExp(zoneIndex, 'i'), + "native": new RegExp("^(::)?(" + ipv6Part + ")?([0-9a-f]+)?(::)?(" + zoneIndex + ")?$", 'i'), + transitional: new RegExp(("^((?:" + ipv6Part + ")|(?:::)(?:" + ipv6Part + ")?)") + (ipv4Part + "\\." + ipv4Part + "\\." + ipv4Part + "\\." + ipv4Part) + ("(" + zoneIndex + ")?$"), 'i') + }; + + expandIPv6 = function(string, parts) { + var colonCount, lastColon, part, replacement, replacementCount, zoneId; + if (string.indexOf('::') !== string.lastIndexOf('::')) { + return null; + } + zoneId = (string.match(ipv6Regexes['zoneIndex']) || [])[0]; + if (zoneId) { + zoneId = zoneId.substring(1); + string = string.replace(/%.+$/, ''); + } + colonCount = 0; + lastColon = -1; + while ((lastColon = string.indexOf(':', lastColon + 1)) >= 0) { + colonCount++; + } + if (string.substr(0, 2) === '::') { + colonCount--; + } + if (string.substr(-2, 2) === '::') { + colonCount--; + } + if (colonCount > parts) { + return null; + } + replacementCount = parts - colonCount; + replacement = ':'; + while (replacementCount--) { + replacement += '0:'; + } + string = string.replace('::', replacement); + if (string[0] === ':') { + string = string.slice(1); + } + if (string[string.length - 1] === ':') { + string = string.slice(0, -1); + } + parts = (function() { + var k, len, ref, results; + ref = string.split(":"); + results = []; + for (k = 0, len = ref.length; k < len; k++) { + part = ref[k]; + results.push(parseInt(part, 16)); + } + return results; + })(); + return { + parts: parts, + zoneId: zoneId + }; + }; + + ipaddr.IPv6.parser = function(string) { + var addr, k, len, match, octet, octets, zoneId; + if (ipv6Regexes['native'].test(string)) { + return expandIPv6(string, 8); + } else if (match = string.match(ipv6Regexes['transitional'])) { + zoneId = match[6] || ''; + addr = expandIPv6(match[1].slice(0, -1) + zoneId, 6); + if (addr.parts) { + octets = [parseInt(match[2]), parseInt(match[3]), parseInt(match[4]), parseInt(match[5])]; + for (k = 0, len = octets.length; k < len; k++) { + octet = octets[k]; + if (!((0 <= octet && octet <= 255))) { + return null; + } + } + addr.parts.push(octets[0] << 8 | octets[1]); + addr.parts.push(octets[2] << 8 | octets[3]); + return { + parts: addr.parts, + zoneId: addr.zoneId + }; + } + } + return null; + }; + + ipaddr.IPv4.isIPv4 = ipaddr.IPv6.isIPv6 = function(string) { + return this.parser(string) !== null; + }; + + ipaddr.IPv4.isValid = function(string) { + var e; + try { + new this(this.parser(string)); + return true; + } catch (error1) { + e = error1; + return false; + } + }; + + ipaddr.IPv4.isValidFourPartDecimal = function(string) { + if (ipaddr.IPv4.isValid(string) && string.match(/^(0|[1-9]\d*)(\.(0|[1-9]\d*)){3}$/)) { + return true; + } else { + return false; + } + }; + + ipaddr.IPv6.isValid = function(string) { + var addr, e; + if (typeof string === "string" && string.indexOf(":") === -1) { + return false; + } + try { + addr = this.parser(string); + new this(addr.parts, addr.zoneId); + return true; + } catch (error1) { + e = error1; + return false; + } + }; + + ipaddr.IPv4.parse = function(string) { + var parts; + parts = this.parser(string); + if (parts === null) { + throw new Error("ipaddr: string is not formatted like ip address"); + } + return new this(parts); + }; + + ipaddr.IPv6.parse = function(string) { + var addr; + addr = this.parser(string); + if (addr.parts === null) { + throw new Error("ipaddr: string is not formatted like ip address"); + } + return new this(addr.parts, addr.zoneId); + }; + + ipaddr.IPv4.parseCIDR = function(string) { + var maskLength, match, parsed; + if (match = string.match(/^(.+)\/(\d+)$/)) { + maskLength = parseInt(match[2]); + if (maskLength >= 0 && maskLength <= 32) { + parsed = [this.parse(match[1]), maskLength]; + Object.defineProperty(parsed, 'toString', { + value: function() { + return this.join('/'); + } + }); + return parsed; + } + } + throw new Error("ipaddr: string is not formatted like an IPv4 CIDR range"); + }; + + ipaddr.IPv4.subnetMaskFromPrefixLength = function(prefix) { + var filledOctetCount, j, octets; + prefix = parseInt(prefix); + if (prefix < 0 || prefix > 32) { + throw new Error('ipaddr: invalid IPv4 prefix length'); + } + octets = [0, 0, 0, 0]; + j = 0; + filledOctetCount = Math.floor(prefix / 8); + while (j < filledOctetCount) { + octets[j] = 255; + j++; + } + if (filledOctetCount < 4) { + octets[filledOctetCount] = Math.pow(2, prefix % 8) - 1 << 8 - (prefix % 8); + } + return new this(octets); + }; + + ipaddr.IPv4.broadcastAddressFromCIDR = function(string) { + var cidr, error, i, ipInterfaceOctets, octets, subnetMaskOctets; + try { + cidr = this.parseCIDR(string); + ipInterfaceOctets = cidr[0].toByteArray(); + subnetMaskOctets = this.subnetMaskFromPrefixLength(cidr[1]).toByteArray(); + octets = []; + i = 0; + while (i < 4) { + octets.push(parseInt(ipInterfaceOctets[i], 10) | parseInt(subnetMaskOctets[i], 10) ^ 255); + i++; + } + return new this(octets); + } catch (error1) { + error = error1; + throw new Error('ipaddr: the address does not have IPv4 CIDR format'); + } + }; + + ipaddr.IPv4.networkAddressFromCIDR = function(string) { + var cidr, error, i, ipInterfaceOctets, octets, subnetMaskOctets; + try { + cidr = this.parseCIDR(string); + ipInterfaceOctets = cidr[0].toByteArray(); + subnetMaskOctets = this.subnetMaskFromPrefixLength(cidr[1]).toByteArray(); + octets = []; + i = 0; + while (i < 4) { + octets.push(parseInt(ipInterfaceOctets[i], 10) & parseInt(subnetMaskOctets[i], 10)); + i++; + } + return new this(octets); + } catch (error1) { + error = error1; + throw new Error('ipaddr: the address does not have IPv4 CIDR format'); + } + }; + + ipaddr.IPv6.parseCIDR = function(string) { + var maskLength, match, parsed; + if (match = string.match(/^(.+)\/(\d+)$/)) { + maskLength = parseInt(match[2]); + if (maskLength >= 0 && maskLength <= 128) { + parsed = [this.parse(match[1]), maskLength]; + Object.defineProperty(parsed, 'toString', { + value: function() { + return this.join('/'); + } + }); + return parsed; + } + } + throw new Error("ipaddr: string is not formatted like an IPv6 CIDR range"); + }; + + ipaddr.isValid = function(string) { + return ipaddr.IPv6.isValid(string) || ipaddr.IPv4.isValid(string); + }; + + ipaddr.parse = function(string) { + if (ipaddr.IPv6.isValid(string)) { + return ipaddr.IPv6.parse(string); + } else if (ipaddr.IPv4.isValid(string)) { + return ipaddr.IPv4.parse(string); + } else { + throw new Error("ipaddr: the address has neither IPv6 nor IPv4 format"); + } + }; + + ipaddr.parseCIDR = function(string) { + var e; + try { + return ipaddr.IPv6.parseCIDR(string); + } catch (error1) { + e = error1; + try { + return ipaddr.IPv4.parseCIDR(string); + } catch (error1) { + e = error1; + throw new Error("ipaddr: the address has neither IPv6 nor IPv4 CIDR format"); + } + } + }; + + ipaddr.fromByteArray = function(bytes) { + var length; + length = bytes.length; + if (length === 4) { + return new ipaddr.IPv4(bytes); + } else if (length === 16) { + return new ipaddr.IPv6(bytes); + } else { + throw new Error("ipaddr: the binary input is neither an IPv6 nor IPv4 address"); + } + }; + + ipaddr.process = function(string) { + var addr; + addr = this.parse(string); + if (addr.kind() === 'ipv6' && addr.isIPv4MappedAddress()) { + return addr.toIPv4Address(); + } else { + return addr; + } + }; + +}).call(this); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/lib/ipaddr.js.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/lib/ipaddr.js.d.ts new file mode 100644 index 000000000..52174b6b6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/lib/ipaddr.js.d.ts @@ -0,0 +1,68 @@ +declare module "ipaddr.js" { + type IPv4Range = 'unicast' | 'unspecified' | 'broadcast' | 'multicast' | 'linkLocal' | 'loopback' | 'carrierGradeNat' | 'private' | 'reserved'; + type IPv6Range = 'unicast' | 'unspecified' | 'linkLocal' | 'multicast' | 'loopback' | 'uniqueLocal' | 'ipv4Mapped' | 'rfc6145' | 'rfc6052' | '6to4' | 'teredo' | 'reserved'; + + interface RangeList { + [name: string]: [T, number] | [T, number][]; + } + + // Common methods/properties for IPv4 and IPv6 classes. + class IP { + prefixLengthFromSubnetMask(): number | null; + toByteArray(): number[]; + toNormalizedString(): string; + toString(): string; + } + + namespace Address { + export function isValid(addr: string): boolean; + export function fromByteArray(bytes: number[]): IPv4 | IPv6; + export function parse(addr: string): IPv4 | IPv6; + export function parseCIDR(mask: string): [IPv4 | IPv6, number]; + export function process(addr: string): IPv4 | IPv6; + export function subnetMatch(addr: IPv4, rangeList: RangeList, defaultName?: string): string; + export function subnetMatch(addr: IPv6, rangeList: RangeList, defaultName?: string): string; + + export class IPv4 extends IP { + static broadcastAddressFromCIDR(addr: string): IPv4; + static isIPv4(addr: string): boolean; + static isValidFourPartDecimal(addr: string): boolean; + static isValid(addr: string): boolean; + static networkAddressFromCIDR(addr: string): IPv4; + static parse(addr: string): IPv4; + static parseCIDR(addr: string): [IPv4, number]; + static subnetMaskFromPrefixLength(prefix: number): IPv4; + constructor(octets: number[]); + octets: number[] + + kind(): 'ipv4'; + match(addr: IPv4, bits: number): boolean; + match(mask: [IPv4, number]): boolean; + range(): IPv4Range; + subnetMatch(rangeList: RangeList, defaultName?: string): string; + toIPv4MappedAddress(): IPv6; + } + + export class IPv6 extends IP { + static broadcastAddressFromCIDR(addr: string): IPv6; + static isIPv6(addr: string): boolean; + static isValid(addr: string): boolean; + static parse(addr: string): IPv6; + static parseCIDR(addr: string): [IPv6, number]; + static subnetMaskFromPrefixLength(prefix: number): IPv6; + constructor(parts: number[]); + parts: number[] + zoneId?: string + + isIPv4MappedAddress(): boolean; + kind(): 'ipv6'; + match(addr: IPv6, bits: number): boolean; + match(mask: [IPv6, number]): boolean; + range(): IPv6Range; + subnetMatch(rangeList: RangeList, defaultName?: string): string; + toIPv4Address(): IPv4; + } + } + + export = Address; +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/package.json new file mode 100644 index 000000000..f4d35475d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/ipaddr.js/package.json @@ -0,0 +1,35 @@ +{ + "name": "ipaddr.js", + "description": "A library for manipulating IPv4 and IPv6 addresses in JavaScript.", + "version": "1.9.1", + "author": "whitequark ", + "directories": { + "lib": "./lib" + }, + "dependencies": {}, + "devDependencies": { + "coffee-script": "~1.12.6", + "nodeunit": "^0.11.3", + "uglify-js": "~3.0.19" + }, + "scripts": { + "test": "cake build test" + }, + "files": [ + "lib/", + "LICENSE", + "ipaddr.min.js" + ], + "keywords": [ + "ip", + "ipv4", + "ipv6" + ], + "repository": "git://github.com/whitequark/ipaddr.js", + "main": "./lib/ipaddr.js", + "engines": { + "node": ">= 0.10" + }, + "license": "MIT", + "types": "./lib/ipaddr.js.d.ts" +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/.eslintrc b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/.eslintrc new file mode 100644 index 000000000..f2e072681 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/.eslintrc @@ -0,0 +1,18 @@ +{ + "extends": "@ljharb", + "root": true, + "rules": { + "func-style": 1, + }, + "overrides": [ + { + "files": "test/**", + "rules": { + "global-require": 0, + "max-depth": 0, + "max-lines-per-function": 0, + "no-negated-condition": 0, + }, + }, + ], +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/.nycrc b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/.nycrc new file mode 100644 index 000000000..bdd626ce9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/.nycrc @@ -0,0 +1,9 @@ +{ + "all": true, + "check-coverage": false, + "reporter": ["text-summary", "text", "html", "json"], + "exclude": [ + "coverage", + "test" + ] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/CHANGELOG.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/CHANGELOG.md new file mode 100644 index 000000000..0177c82b7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/CHANGELOG.md @@ -0,0 +1,218 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [v2.16.1](https://github.com/inspect-js/is-core-module/compare/v2.16.0...v2.16.1) - 2024-12-21 + +### Fixed + +- [Fix] `node:sqlite` is available in node ^22.13 [`#17`](https://github.com/inspect-js/is-core-module/issues/17) + +## [v2.16.0](https://github.com/inspect-js/is-core-module/compare/v2.15.1...v2.16.0) - 2024-12-13 + +### Commits + +- [New] add `node:sqlite` [`1ee94d2`](https://github.com/inspect-js/is-core-module/commit/1ee94d20857e22cdb24e9b4bb1a2097f2e03e26f) +- [Dev Deps] update `auto-changelog`, `tape` [`aa84aa3`](https://github.com/inspect-js/is-core-module/commit/aa84aa34face677f14e08ec1c737f0c4bba27260) + +## [v2.15.1](https://github.com/inspect-js/is-core-module/compare/v2.15.0...v2.15.1) - 2024-08-21 + +### Commits + +- [Tests] add `process.getBuiltinModule` tests [`28c7791`](https://github.com/inspect-js/is-core-module/commit/28c7791c196d58c64cfdf638b7e68ed1b62a4da0) +- [Fix] `test/mock_loader` is no longer exposed as of v22.7 [`68b08b0`](https://github.com/inspect-js/is-core-module/commit/68b08b0d7963447dbffa5142e8810dca550383af) +- [Tests] replace `aud` with `npm audit` [`32f8060`](https://github.com/inspect-js/is-core-module/commit/32f806026dac14f9016be4401a643851240c76b9) +- [Dev Deps] update `mock-property` [`f7d3c8f`](https://github.com/inspect-js/is-core-module/commit/f7d3c8f01e922be49621683eb41477c4f50522e1) +- [Dev Deps] add missing peer dep [`eaee885`](https://github.com/inspect-js/is-core-module/commit/eaee885b67238819e9c8ed5bd2098766e1d05331) + +## [v2.15.0](https://github.com/inspect-js/is-core-module/compare/v2.14.0...v2.15.0) - 2024-07-17 + +### Commits + +- [New] add `node:sea` [`2819fb3`](https://github.com/inspect-js/is-core-module/commit/2819fb3eae312fa64643bc5430ebd06ec0f3fb88) + +## [v2.14.0](https://github.com/inspect-js/is-core-module/compare/v2.13.1...v2.14.0) - 2024-06-20 + +### Commits + +- [Dev Deps] update `@ljharb/eslint-config`, `aud`, `mock-property`, `npmignore`, `tape` [`0e43200`](https://github.com/inspect-js/is-core-module/commit/0e432006d97237cc082d41e6a593e87c81068364) +- [meta] add missing `engines.node` [`4ea3af8`](https://github.com/inspect-js/is-core-module/commit/4ea3af88891a1d4f96026f0ec0ef08c67cd1bd24) +- [New] add `test/mock_loader` [`e9fbd29`](https://github.com/inspect-js/is-core-module/commit/e9fbd2951383be070aeffb9ebbf3715237282610) +- [Deps] update `hasown` [`57f1940`](https://github.com/inspect-js/is-core-module/commit/57f1940947b3e368abdf529232d2f17d88909358) + +## [v2.13.1](https://github.com/inspect-js/is-core-module/compare/v2.13.0...v2.13.1) - 2023-10-20 + +### Commits + +- [Refactor] use `hasown` instead of `has` [`0e52096`](https://github.com/inspect-js/is-core-module/commit/0e520968b0a725276b67420ab4b877486b243ae0) +- [Dev Deps] update `mock-property`, `tape` [`8736b35`](https://github.com/inspect-js/is-core-module/commit/8736b35464d0f297b55da2c6b30deee04b8303c5) + +## [v2.13.0](https://github.com/inspect-js/is-core-module/compare/v2.12.1...v2.13.0) - 2023-08-05 + +### Commits + +- [Dev Deps] update `@ljharb/eslint-config`, `aud`, `semver`, `tape` [`c75b263`](https://github.com/inspect-js/is-core-module/commit/c75b263d047cb53430c3970107e5eb64d6cd6c0c) +- [New] `node:test/reporters` and `wasi`/`node:wasi` are in v18.17 [`d76cbf8`](https://github.com/inspect-js/is-core-module/commit/d76cbf8e9b208acfd98913fed5a5f45cb15fe5dc) + +## [v2.12.1](https://github.com/inspect-js/is-core-module/compare/v2.12.0...v2.12.1) - 2023-05-16 + +### Commits + +- [Fix] `test/reporters` now requires the `node:` prefix as of v20.2 [`12183d0`](https://github.com/inspect-js/is-core-module/commit/12183d0d8e4edf56b6ce18a1b3be54bfce10175b) + +## [v2.12.0](https://github.com/inspect-js/is-core-module/compare/v2.11.0...v2.12.0) - 2023-04-10 + +### Commits + +- [actions] update rebase action to use reusable workflow [`c0a7251`](https://github.com/inspect-js/is-core-module/commit/c0a7251f734f3c621932c5fcdfd1bf966b42ca32) +- [Dev Deps] update `@ljharb/eslint-config`, `aud`, `tape` [`9ae8b7f`](https://github.com/inspect-js/is-core-module/commit/9ae8b7fac03c369861d0991b4a2ce8d4848e6a7d) +- [New] `test/reporters` added in v19.9, `wasi` added in v20 [`9d5341a`](https://github.com/inspect-js/is-core-module/commit/9d5341ab32053f25b7fa7db3c0e18461db24a79c) +- [Dev Deps] add missing `in-publish` dep [`5980245`](https://github.com/inspect-js/is-core-module/commit/59802456e9ac919fa748f53be9d8fbf304a197df) + +## [v2.11.0](https://github.com/inspect-js/is-core-module/compare/v2.10.0...v2.11.0) - 2022-10-18 + +### Commits + +- [meta] use `npmignore` to autogenerate an npmignore file [`3360011`](https://github.com/inspect-js/is-core-module/commit/33600118857b46177178072fba2affcdeb009d12) +- [Dev Deps] update `aud`, `tape` [`651c6b0`](https://github.com/inspect-js/is-core-module/commit/651c6b0cc2799d4130866cf43ad333dcade3d26c) +- [New] `inspector/promises` and `node:inspector/promises` is now available in node 19 [`22d332f`](https://github.com/inspect-js/is-core-module/commit/22d332fe22ac050305444e0781ff85af819abcb0) + +## [v2.10.0](https://github.com/inspect-js/is-core-module/compare/v2.9.0...v2.10.0) - 2022-08-03 + +### Commits + +- [New] `node:test` is now available in node ^16.17 [`e8fd36e`](https://github.com/inspect-js/is-core-module/commit/e8fd36e9b86c917775a07cc473b62a3294f459f2) +- [Tests] improve skip message [`c014a4c`](https://github.com/inspect-js/is-core-module/commit/c014a4c0cd6eb15fff573ae4709191775e70cab4) + +## [v2.9.0](https://github.com/inspect-js/is-core-module/compare/v2.8.1...v2.9.0) - 2022-04-19 + +### Commits + +- [New] add `node:test`, in node 18+ [`f853eca`](https://github.com/inspect-js/is-core-module/commit/f853eca801d0a7d4e1dbb670f1b6d9837d9533c5) +- [Tests] use `mock-property` [`03b3644`](https://github.com/inspect-js/is-core-module/commit/03b3644dff4417f4ba5a7d0aa0138f5f6b3e5c46) +- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `auto-changelog`, `tape` [`7c0e2d0`](https://github.com/inspect-js/is-core-module/commit/7c0e2d06ed2a89acf53abe2ab34d703ed5b03455) +- [meta] simplify "exports" [`d6ed201`](https://github.com/inspect-js/is-core-module/commit/d6ed201eba7fbba0e59814a9050fc49a6e9878c8) + +## [v2.8.1](https://github.com/inspect-js/is-core-module/compare/v2.8.0...v2.8.1) - 2022-01-05 + +### Commits + +- [actions] reuse common workflows [`cd2cf9b`](https://github.com/inspect-js/is-core-module/commit/cd2cf9b3b66c8d328f65610efe41e9325db7716d) +- [Fix] update node 0.4 results [`062195d`](https://github.com/inspect-js/is-core-module/commit/062195d89f0876a88b95d378b43f7fcc1205bc5b) +- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `safe-publish-latest`, `tape` [`0790b62`](https://github.com/inspect-js/is-core-module/commit/0790b6222848c6167132f9f73acc3520fa8d1298) +- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `tape` [`7d139a6`](https://github.com/inspect-js/is-core-module/commit/7d139a6d767709eabf0a0251e074ec1fb230c06e) +- [Tests] run `nyc` in `tests-only`, not `test` [`780e8a0`](https://github.com/inspect-js/is-core-module/commit/780e8a049951c71cf78b1707f0871c48a28bde14) + +## [v2.8.0](https://github.com/inspect-js/is-core-module/compare/v2.7.0...v2.8.0) - 2021-10-14 + +### Commits + +- [actions] update codecov uploader [`0cfe94e`](https://github.com/inspect-js/is-core-module/commit/0cfe94e106a7d005ea03e008c0a21dec13a77904) +- [New] add `readline/promises` to node v17+ [`4f78c30`](https://github.com/inspect-js/is-core-module/commit/4f78c3008b1b58b4db6dc91d99610b1bc859da7e) +- [Tests] node ^14.18 supports `node:` prefixes for CJS [`43e2f17`](https://github.com/inspect-js/is-core-module/commit/43e2f177452cea2f0eaf34f61b5407217bbdb6f4) + +## [v2.7.0](https://github.com/inspect-js/is-core-module/compare/v2.6.0...v2.7.0) - 2021-09-27 + +### Commits + +- [New] node `v14.18` added `node:`-prefixed core modules to `require` [`6d943ab`](https://github.com/inspect-js/is-core-module/commit/6d943abe81382b9bbe344384d80fbfebe1cc0526) +- [Tests] add coverage for Object.prototype pollution [`c6baf5f`](https://github.com/inspect-js/is-core-module/commit/c6baf5f942311a1945c1af41167bb80b84df2af7) +- [Dev Deps] update `@ljharb/eslint-config` [`6717f00`](https://github.com/inspect-js/is-core-module/commit/6717f000d063ea57beb772bded36c2f056ac404c) +- [eslint] fix linter warning [`594c10b`](https://github.com/inspect-js/is-core-module/commit/594c10bb7d39d7eb00925c90924199ff596184b2) +- [meta] add `sideEffects` flag [`c32cfa5`](https://github.com/inspect-js/is-core-module/commit/c32cfa5195632944c4dd4284a142b8476e75be13) + +## [v2.6.0](https://github.com/inspect-js/is-core-module/compare/v2.5.0...v2.6.0) - 2021-08-17 + +### Commits + +- [Dev Deps] update `eslint`, `tape` [`6cc928f`](https://github.com/inspect-js/is-core-module/commit/6cc928f8a4bba66aeeccc4f6beeac736d4bd3081) +- [New] add `stream/consumers` to node `>= 16.7` [`a1a423e`](https://github.com/inspect-js/is-core-module/commit/a1a423e467e4cc27df180234fad5bab45943e67d) +- [Refactor] Remove duplicated `&&` operand [`86faea7`](https://github.com/inspect-js/is-core-module/commit/86faea738213a2433c62d1098488dc9314dca832) +- [Tests] include prereleases [`a4da7a6`](https://github.com/inspect-js/is-core-module/commit/a4da7a6abf7568e2aa4fd98e69452179f1850963) + +## [v2.5.0](https://github.com/inspect-js/is-core-module/compare/v2.4.0...v2.5.0) - 2021-07-12 + +### Commits + +- [Dev Deps] update `auto-changelog`, `eslint` [`6334cc9`](https://github.com/inspect-js/is-core-module/commit/6334cc94f3af7469685bd8f236740991baaf2705) +- [New] add `stream/web` to node v16.5+ [`17ac59b`](https://github.com/inspect-js/is-core-module/commit/17ac59b662d63e220a2e5728625f005c24f177b2) + +## [v2.4.0](https://github.com/inspect-js/is-core-module/compare/v2.3.0...v2.4.0) - 2021-05-09 + +### Commits + +- [readme] add actions and codecov badges [`82b7faa`](https://github.com/inspect-js/is-core-module/commit/82b7faa12b56dbe47fbea67e1a5b9e447027ba40) +- [Dev Deps] update `@ljharb/eslint-config`, `aud` [`8096868`](https://github.com/inspect-js/is-core-module/commit/8096868c024a161ccd4d44110b136763e92eace8) +- [Dev Deps] update `eslint` [`6726824`](https://github.com/inspect-js/is-core-module/commit/67268249b88230018c510f6532a8046d7326346f) +- [New] add `diagnostics_channel` to node `^14.17` [`86c6563`](https://github.com/inspect-js/is-core-module/commit/86c65634201b8ff9b3e48a9a782594579c7f5c3c) +- [meta] fix prepublish script [`697a01e`](https://github.com/inspect-js/is-core-module/commit/697a01e3c9c0be074066520954f30fb28532ec57) + +## [v2.3.0](https://github.com/inspect-js/is-core-module/compare/v2.2.0...v2.3.0) - 2021-04-24 + +### Commits + +- [meta] do not publish github action workflow files [`060d4bb`](https://github.com/inspect-js/is-core-module/commit/060d4bb971a29451c19ff336eb56bee27f9fa95a) +- [New] add support for `node:` prefix, in node 16+ [`7341223`](https://github.com/inspect-js/is-core-module/commit/73412230a769f6e81c05eea50b6520cebf54ed2f) +- [actions] use `node/install` instead of `node/run`; use `codecov` action [`016269a`](https://github.com/inspect-js/is-core-module/commit/016269abae9f6657a5254adfbb813f09a05067f9) +- [patch] remove unneeded `.0` in version ranges [`cb466a6`](https://github.com/inspect-js/is-core-module/commit/cb466a6d89e52b8389e5c12715efcd550c41cea3) +- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `tape` [`c9f9c39`](https://github.com/inspect-js/is-core-module/commit/c9f9c396ace60ef81906f98059c064e6452473ed) +- [actions] update workflows [`3ee4a89`](https://github.com/inspect-js/is-core-module/commit/3ee4a89fd5a02fccd43882d905448ea6a98e9a3c) +- [Dev Deps] update `eslint`, `@ljharb/eslint-config` [`dee4fed`](https://github.com/inspect-js/is-core-module/commit/dee4fed79690c1d43a22f7fa9426abebdc6d727f) +- [Dev Deps] update `eslint`, `@ljharb/eslint-config` [`7d046ba`](https://github.com/inspect-js/is-core-module/commit/7d046ba07ae8c9292e43652694ca808d7b309de8) +- [meta] use `prepublishOnly` script for npm 7+ [`149e677`](https://github.com/inspect-js/is-core-module/commit/149e6771a5ede6d097e71785b467a9c4b4977cc7) +- [readme] remove travis badge [`903b51d`](https://github.com/inspect-js/is-core-module/commit/903b51d6b69b98abeabfbc3695c345b02646f19c) + +## [v2.2.0](https://github.com/inspect-js/is-core-module/compare/v2.1.0...v2.2.0) - 2020-11-26 + +### Commits + +- [Tests] migrate tests to Github Actions [`c919f57`](https://github.com/inspect-js/is-core-module/commit/c919f573c0a92d10a0acad0b650b5aecb033d426) +- [patch] `core.json`: %s/ /\t/g [`db3f685`](https://github.com/inspect-js/is-core-module/commit/db3f68581f53e73cc09cd675955eb1bdd6a5a39b) +- [Tests] run `nyc` on all tests [`b2f925f`](https://github.com/inspect-js/is-core-module/commit/b2f925f8866f210ef441f39fcc8cc42692ab89b1) +- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`; add `safe-publish-latest` [`89f02a2`](https://github.com/inspect-js/is-core-module/commit/89f02a2b4162246dea303a6ee31bb9a550b05c72) +- [New] add `path/posix`, `path/win32`, `util/types` [`77f94f1`](https://github.com/inspect-js/is-core-module/commit/77f94f1e90ffd7c0be2a3f1aa8574ebf7fd981b3) + +## [v2.1.0](https://github.com/inspect-js/is-core-module/compare/v2.0.0...v2.1.0) - 2020-11-04 + +### Commits + +- [Dev Deps] update `eslint` [`5e0034e`](https://github.com/inspect-js/is-core-module/commit/5e0034eae57c09c8f1bd769f502486a00f56c6e4) +- [New] Add `diagnostics_channel` [`c2d83d0`](https://github.com/inspect-js/is-core-module/commit/c2d83d0a0225a1a658945d9bab7036ea347d29ec) + +## [v2.0.0](https://github.com/inspect-js/is-core-module/compare/v1.0.2...v2.0.0) - 2020-09-29 + +### Commits + +- v2 implementation [`865aeb5`](https://github.com/inspect-js/is-core-module/commit/865aeb5ca0e90248a3dfff5d7622e4751fdeb9cd) +- Only apps should have lockfiles [`5a5e660`](https://github.com/inspect-js/is-core-module/commit/5a5e660d568e37eb44e17fb1ebb12a105205fc2b) +- Initial commit for v2 [`5a51524`](https://github.com/inspect-js/is-core-module/commit/5a51524e06f92adece5fbb138c69b7b9748a2348) +- Tests [`116eae4`](https://github.com/inspect-js/is-core-module/commit/116eae4fccd01bc72c1fd3cc4b7561c387afc496) +- [meta] add `auto-changelog` [`c24388b`](https://github.com/inspect-js/is-core-module/commit/c24388bee828d223040519d1f5b226ca35beee63) +- [actions] add "Automatic Rebase" and "require allow edits" actions [`34292db`](https://github.com/inspect-js/is-core-module/commit/34292dbcbadae0868aff03c22dbd8b7b8a11558a) +- [Tests] add `npm run lint` [`4f9eeee`](https://github.com/inspect-js/is-core-module/commit/4f9eeee7ddff10698bbf528620f4dc8d4fa3e697) +- [readme] fix travis badges, https all URLs [`e516a73`](https://github.com/inspect-js/is-core-module/commit/e516a73b0dccce20938c432b1ba512eae8eff9e9) +- [meta] create FUNDING.yml [`1aabebc`](https://github.com/inspect-js/is-core-module/commit/1aabebca98d01f8a04e46bc2e2520fa93cf21ac6) +- [Fix] `domain`: domain landed sometime > v0.7.7 and <= v0.7.12 [`2df7d37`](https://github.com/inspect-js/is-core-module/commit/2df7d37595d41b15eeada732b706b926c2771655) +- [Fix] `sys`: worked in 0.6, not 0.7, and 0.8+ [`a75c134`](https://github.com/inspect-js/is-core-module/commit/a75c134229e1e9441801f6b73f6a52489346eb65) + +## [v1.0.2](https://github.com/inspect-js/is-core-module/compare/v1.0.1...v1.0.2) - 2014-09-28 + +### Commits + +- simpler [`66fe90f`](https://github.com/inspect-js/is-core-module/commit/66fe90f9771581b9adc0c3900baa52c21b5baea2) + +## [v1.0.1](https://github.com/inspect-js/is-core-module/compare/v1.0.0...v1.0.1) - 2014-09-28 + +### Commits + +- remove stupid [`f21f906`](https://github.com/inspect-js/is-core-module/commit/f21f906f882c2bd656a5fc5ed6fbe48ddaffb2ac) +- update readme [`1eff0ec`](https://github.com/inspect-js/is-core-module/commit/1eff0ec69798d1ec65771552d1562911e90a8027) + +## v1.0.0 - 2014-09-28 + +### Commits + +- init [`48e5e76`](https://github.com/inspect-js/is-core-module/commit/48e5e76cac378fddb8c1f7d4055b8dfc943d6b96) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/LICENSE new file mode 100644 index 000000000..2e502872a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Dave Justice + +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. \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/README.md new file mode 100644 index 000000000..062d9068e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/README.md @@ -0,0 +1,40 @@ +# is-core-module [![Version Badge][2]][1] + +[![github actions][actions-image]][actions-url] +[![coverage][codecov-image]][codecov-url] +[![dependency status][5]][6] +[![dev dependency status][7]][8] +[![License][license-image]][license-url] +[![Downloads][downloads-image]][downloads-url] + +[![npm badge][11]][1] + +Is this specifier a node.js core module? Optionally provide a node version to check; defaults to the current node version. + +## Example + +```js +var isCore = require('is-core-module'); +var assert = require('assert'); +assert(isCore('fs')); +assert(!isCore('butts')); +``` + +## Tests +Clone the repo, `npm install`, and run `npm test` + +[1]: https://npmjs.org/package/is-core-module +[2]: https://versionbadg.es/inspect-js/is-core-module.svg +[5]: https://david-dm.org/inspect-js/is-core-module.svg +[6]: https://david-dm.org/inspect-js/is-core-module +[7]: https://david-dm.org/inspect-js/is-core-module/dev-status.svg +[8]: https://david-dm.org/inspect-js/is-core-module#info=devDependencies +[11]: https://nodei.co/npm/is-core-module.png?downloads=true&stars=true +[license-image]: https://img.shields.io/npm/l/is-core-module.svg +[license-url]: LICENSE +[downloads-image]: https://img.shields.io/npm/dm/is-core-module.svg +[downloads-url]: https://npm-stat.com/charts.html?package=is-core-module +[codecov-image]: https://codecov.io/gh/inspect-js/is-core-module/branch/main/graphs/badge.svg +[codecov-url]: https://app.codecov.io/gh/inspect-js/is-core-module/ +[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/inspect-js/is-core-module +[actions-url]: https://github.com/inspect-js/is-core-module/actions diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/core.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/core.json new file mode 100644 index 000000000..930ec6825 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/core.json @@ -0,0 +1,162 @@ +{ + "assert": true, + "node:assert": [">= 14.18 && < 15", ">= 16"], + "assert/strict": ">= 15", + "node:assert/strict": ">= 16", + "async_hooks": ">= 8", + "node:async_hooks": [">= 14.18 && < 15", ">= 16"], + "buffer_ieee754": ">= 0.5 && < 0.9.7", + "buffer": true, + "node:buffer": [">= 14.18 && < 15", ">= 16"], + "child_process": true, + "node:child_process": [">= 14.18 && < 15", ">= 16"], + "cluster": ">= 0.5", + "node:cluster": [">= 14.18 && < 15", ">= 16"], + "console": true, + "node:console": [">= 14.18 && < 15", ">= 16"], + "constants": true, + "node:constants": [">= 14.18 && < 15", ">= 16"], + "crypto": true, + "node:crypto": [">= 14.18 && < 15", ">= 16"], + "_debug_agent": ">= 1 && < 8", + "_debugger": "< 8", + "dgram": true, + "node:dgram": [">= 14.18 && < 15", ">= 16"], + "diagnostics_channel": [">= 14.17 && < 15", ">= 15.1"], + "node:diagnostics_channel": [">= 14.18 && < 15", ">= 16"], + "dns": true, + "node:dns": [">= 14.18 && < 15", ">= 16"], + "dns/promises": ">= 15", + "node:dns/promises": ">= 16", + "domain": ">= 0.7.12", + "node:domain": [">= 14.18 && < 15", ">= 16"], + "events": true, + "node:events": [">= 14.18 && < 15", ">= 16"], + "freelist": "< 6", + "fs": true, + "node:fs": [">= 14.18 && < 15", ">= 16"], + "fs/promises": [">= 10 && < 10.1", ">= 14"], + "node:fs/promises": [">= 14.18 && < 15", ">= 16"], + "_http_agent": ">= 0.11.1", + "node:_http_agent": [">= 14.18 && < 15", ">= 16"], + "_http_client": ">= 0.11.1", + "node:_http_client": [">= 14.18 && < 15", ">= 16"], + "_http_common": ">= 0.11.1", + "node:_http_common": [">= 14.18 && < 15", ">= 16"], + "_http_incoming": ">= 0.11.1", + "node:_http_incoming": [">= 14.18 && < 15", ">= 16"], + "_http_outgoing": ">= 0.11.1", + "node:_http_outgoing": [">= 14.18 && < 15", ">= 16"], + "_http_server": ">= 0.11.1", + "node:_http_server": [">= 14.18 && < 15", ">= 16"], + "http": true, + "node:http": [">= 14.18 && < 15", ">= 16"], + "http2": ">= 8.8", + "node:http2": [">= 14.18 && < 15", ">= 16"], + "https": true, + "node:https": [">= 14.18 && < 15", ">= 16"], + "inspector": ">= 8", + "node:inspector": [">= 14.18 && < 15", ">= 16"], + "inspector/promises": [">= 19"], + "node:inspector/promises": [">= 19"], + "_linklist": "< 8", + "module": true, + "node:module": [">= 14.18 && < 15", ">= 16"], + "net": true, + "node:net": [">= 14.18 && < 15", ">= 16"], + "node-inspect/lib/_inspect": ">= 7.6 && < 12", + "node-inspect/lib/internal/inspect_client": ">= 7.6 && < 12", + "node-inspect/lib/internal/inspect_repl": ">= 7.6 && < 12", + "os": true, + "node:os": [">= 14.18 && < 15", ">= 16"], + "path": true, + "node:path": [">= 14.18 && < 15", ">= 16"], + "path/posix": ">= 15.3", + "node:path/posix": ">= 16", + "path/win32": ">= 15.3", + "node:path/win32": ">= 16", + "perf_hooks": ">= 8.5", + "node:perf_hooks": [">= 14.18 && < 15", ">= 16"], + "process": ">= 1", + "node:process": [">= 14.18 && < 15", ">= 16"], + "punycode": ">= 0.5", + "node:punycode": [">= 14.18 && < 15", ">= 16"], + "querystring": true, + "node:querystring": [">= 14.18 && < 15", ">= 16"], + "readline": true, + "node:readline": [">= 14.18 && < 15", ">= 16"], + "readline/promises": ">= 17", + "node:readline/promises": ">= 17", + "repl": true, + "node:repl": [">= 14.18 && < 15", ">= 16"], + "node:sea": [">= 20.12 && < 21", ">= 21.7"], + "smalloc": ">= 0.11.5 && < 3", + "node:sqlite": [">= 22.13 && < 23", ">= 23.4"], + "_stream_duplex": ">= 0.9.4", + "node:_stream_duplex": [">= 14.18 && < 15", ">= 16"], + "_stream_transform": ">= 0.9.4", + "node:_stream_transform": [">= 14.18 && < 15", ">= 16"], + "_stream_wrap": ">= 1.4.1", + "node:_stream_wrap": [">= 14.18 && < 15", ">= 16"], + "_stream_passthrough": ">= 0.9.4", + "node:_stream_passthrough": [">= 14.18 && < 15", ">= 16"], + "_stream_readable": ">= 0.9.4", + "node:_stream_readable": [">= 14.18 && < 15", ">= 16"], + "_stream_writable": ">= 0.9.4", + "node:_stream_writable": [">= 14.18 && < 15", ">= 16"], + "stream": true, + "node:stream": [">= 14.18 && < 15", ">= 16"], + "stream/consumers": ">= 16.7", + "node:stream/consumers": ">= 16.7", + "stream/promises": ">= 15", + "node:stream/promises": ">= 16", + "stream/web": ">= 16.5", + "node:stream/web": ">= 16.5", + "string_decoder": true, + "node:string_decoder": [">= 14.18 && < 15", ">= 16"], + "sys": [">= 0.4 && < 0.7", ">= 0.8"], + "node:sys": [">= 14.18 && < 15", ">= 16"], + "test/reporters": ">= 19.9 && < 20.2", + "node:test/reporters": [">= 18.17 && < 19", ">= 19.9", ">= 20"], + "test/mock_loader": ">= 22.3 && < 22.7", + "node:test/mock_loader": ">= 22.3 && < 22.7", + "node:test": [">= 16.17 && < 17", ">= 18"], + "timers": true, + "node:timers": [">= 14.18 && < 15", ">= 16"], + "timers/promises": ">= 15", + "node:timers/promises": ">= 16", + "_tls_common": ">= 0.11.13", + "node:_tls_common": [">= 14.18 && < 15", ">= 16"], + "_tls_legacy": ">= 0.11.3 && < 10", + "_tls_wrap": ">= 0.11.3", + "node:_tls_wrap": [">= 14.18 && < 15", ">= 16"], + "tls": true, + "node:tls": [">= 14.18 && < 15", ">= 16"], + "trace_events": ">= 10", + "node:trace_events": [">= 14.18 && < 15", ">= 16"], + "tty": true, + "node:tty": [">= 14.18 && < 15", ">= 16"], + "url": true, + "node:url": [">= 14.18 && < 15", ">= 16"], + "util": true, + "node:util": [">= 14.18 && < 15", ">= 16"], + "util/types": ">= 15.3", + "node:util/types": ">= 16", + "v8/tools/arguments": ">= 10 && < 12", + "v8/tools/codemap": [">= 4.4 && < 5", ">= 5.2 && < 12"], + "v8/tools/consarray": [">= 4.4 && < 5", ">= 5.2 && < 12"], + "v8/tools/csvparser": [">= 4.4 && < 5", ">= 5.2 && < 12"], + "v8/tools/logreader": [">= 4.4 && < 5", ">= 5.2 && < 12"], + "v8/tools/profile_view": [">= 4.4 && < 5", ">= 5.2 && < 12"], + "v8/tools/splaytree": [">= 4.4 && < 5", ">= 5.2 && < 12"], + "v8": ">= 1", + "node:v8": [">= 14.18 && < 15", ">= 16"], + "vm": true, + "node:vm": [">= 14.18 && < 15", ">= 16"], + "wasi": [">= 13.4 && < 13.5", ">= 18.17 && < 19", ">= 20"], + "node:wasi": [">= 18.17 && < 19", ">= 20"], + "worker_threads": ">= 11.7", + "node:worker_threads": [">= 14.18 && < 15", ">= 16"], + "zlib": ">= 0.5", + "node:zlib": [">= 14.18 && < 15", ">= 16"] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/index.js new file mode 100644 index 000000000..423e20c0d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/index.js @@ -0,0 +1,69 @@ +'use strict'; + +var hasOwn = require('hasown'); + +function specifierIncluded(current, specifier) { + var nodeParts = current.split('.'); + var parts = specifier.split(' '); + var op = parts.length > 1 ? parts[0] : '='; + var versionParts = (parts.length > 1 ? parts[1] : parts[0]).split('.'); + + for (var i = 0; i < 3; ++i) { + var cur = parseInt(nodeParts[i] || 0, 10); + var ver = parseInt(versionParts[i] || 0, 10); + if (cur === ver) { + continue; // eslint-disable-line no-restricted-syntax, no-continue + } + if (op === '<') { + return cur < ver; + } + if (op === '>=') { + return cur >= ver; + } + return false; + } + return op === '>='; +} + +function matchesRange(current, range) { + var specifiers = range.split(/ ?&& ?/); + if (specifiers.length === 0) { + return false; + } + for (var i = 0; i < specifiers.length; ++i) { + if (!specifierIncluded(current, specifiers[i])) { + return false; + } + } + return true; +} + +function versionIncluded(nodeVersion, specifierValue) { + if (typeof specifierValue === 'boolean') { + return specifierValue; + } + + var current = typeof nodeVersion === 'undefined' + ? process.versions && process.versions.node + : nodeVersion; + + if (typeof current !== 'string') { + throw new TypeError(typeof nodeVersion === 'undefined' ? 'Unable to determine current node version' : 'If provided, a valid node version is required'); + } + + if (specifierValue && typeof specifierValue === 'object') { + for (var i = 0; i < specifierValue.length; ++i) { + if (matchesRange(current, specifierValue[i])) { + return true; + } + } + return false; + } + return matchesRange(current, specifierValue); +} + +var data = require('./core.json'); + +module.exports = function isCore(x, nodeVersion) { + return hasOwn(data, x) && versionIncluded(nodeVersion, data[x]); +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/package.json new file mode 100644 index 000000000..266825646 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/package.json @@ -0,0 +1,76 @@ +{ + "name": "is-core-module", + "version": "2.16.1", + "description": "Is this specifier a node.js core module?", + "main": "index.js", + "sideEffects": false, + "exports": { + ".": "./index.js", + "./package.json": "./package.json" + }, + "scripts": { + "prepack": "npmignore --auto --commentLines=autogenerated", + "prepublish": "not-in-publish || npm run prepublishOnly", + "prepublishOnly": "safe-publish-latest", + "lint": "eslint .", + "pretest": "npm run lint", + "tests-only": "nyc tape 'test/**/*.js'", + "test": "npm run tests-only", + "posttest": "npx npm@'>=10.2' audit --production", + "version": "auto-changelog && git add CHANGELOG.md", + "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/inspect-js/is-core-module.git" + }, + "keywords": [ + "core", + "modules", + "module", + "npm", + "node", + "dependencies" + ], + "author": "Jordan Harband ", + "funding": { + "url": "https://github.com/sponsors/ljharb" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/inspect-js/is-core-module/issues" + }, + "homepage": "https://github.com/inspect-js/is-core-module", + "dependencies": { + "hasown": "^2.0.2" + }, + "devDependencies": { + "@ljharb/eslint-config": "^21.1.1", + "auto-changelog": "^2.5.0", + "encoding": "^0.1.13", + "eslint": "=8.8.0", + "in-publish": "^2.0.1", + "mock-property": "^1.1.0", + "npmignore": "^0.3.1", + "nyc": "^10.3.2", + "safe-publish-latest": "^2.0.0", + "semver": "^6.3.1", + "tape": "^5.9.0" + }, + "auto-changelog": { + "output": "CHANGELOG.md", + "template": "keepachangelog", + "unreleased": false, + "commitLimit": false, + "backfillLimit": false, + "hideCredit": true + }, + "publishConfig": { + "ignore": [ + ".github" + ] + }, + "engines": { + "node": ">= 0.4" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/test/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/test/index.js new file mode 100644 index 000000000..7a81e1c7e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-core-module/test/index.js @@ -0,0 +1,157 @@ +'use strict'; + +var test = require('tape'); +var keys = require('object-keys'); +var semver = require('semver'); +var mockProperty = require('mock-property'); + +var isCore = require('../'); +var data = require('../core.json'); + +var supportsNodePrefix = semver.satisfies(process.versions.node, '^14.18 || >= 16', { includePrerelease: true }); + +test('core modules', function (t) { + t.test('isCore()', function (st) { + st.ok(isCore('fs')); + st.ok(isCore('net')); + st.ok(isCore('http')); + + st.ok(!isCore('seq')); + st.ok(!isCore('../')); + + st.ok(!isCore('toString')); + + st.end(); + }); + + t.test('core list', function (st) { + var cores = keys(data); + st.plan(cores.length); + + for (var i = 0; i < cores.length; ++i) { + var mod = cores[i]; + var requireFunc = function () { require(mod); }; // eslint-disable-line no-loop-func + if (isCore(mod)) { + st.doesNotThrow(requireFunc, mod + ' supported; requiring does not throw'); + } else { + st['throws'](requireFunc, mod + ' not supported; requiring throws'); + } + } + + st.end(); + }); + + t.test('core via repl module', { skip: !data.repl }, function (st) { + var libs = require('repl')._builtinLibs; // eslint-disable-line no-underscore-dangle + if (!libs) { + st.skip('repl._builtinLibs does not exist'); + } else { + for (var i = 0; i < libs.length; ++i) { + var mod = libs[i]; + st.ok(data[mod], mod + ' is a core module'); + st.doesNotThrow( + function () { require(mod); }, // eslint-disable-line no-loop-func + 'requiring ' + mod + ' does not throw' + ); + if (mod.slice(0, 5) !== 'node:') { + if (supportsNodePrefix) { + st.doesNotThrow( + function () { require('node:' + mod); }, // eslint-disable-line no-loop-func + 'requiring node:' + mod + ' does not throw' + ); + } else { + st['throws']( + function () { require('node:' + mod); }, // eslint-disable-line no-loop-func + 'requiring node:' + mod + ' throws' + ); + } + } + } + } + st.end(); + }); + + t.test('core via builtinModules list', { skip: !data.module }, function (st) { + var Module = require('module'); + var libs = Module.builtinModules; + if (!libs) { + st.skip('module.builtinModules does not exist'); + } else { + var excludeList = [ + '_debug_agent', + 'v8/tools/tickprocessor-driver', + 'v8/tools/SourceMap', + 'v8/tools/tickprocessor', + 'v8/tools/profile' + ]; + + // see https://github.com/nodejs/node/issues/42785 + if (semver.satisfies(process.version, '>= 18')) { + libs = libs.concat('node:test'); + } + if (semver.satisfies(process.version, '^20.12 || >= 21.7')) { + libs = libs.concat('node:sea'); + } + if (semver.satisfies(process.version, '>= 23.4')) { + libs = libs.concat('node:sqlite'); + } + + for (var i = 0; i < libs.length; ++i) { + var mod = libs[i]; + if (excludeList.indexOf(mod) === -1) { + st.ok(data[mod], mod + ' is a core module'); + + if (Module.isBuiltin) { + st.ok(Module.isBuiltin(mod), 'module.isBuiltin(' + mod + ') is true'); + } + + st.doesNotThrow( + function () { require(mod); }, // eslint-disable-line no-loop-func + 'requiring ' + mod + ' does not throw' + ); + + if (process.getBuiltinModule) { + st.equal( + process.getBuiltinModule(mod), + require(mod), + 'process.getBuiltinModule(' + mod + ') === require(' + mod + ')' + ); + } + + if (mod.slice(0, 5) !== 'node:') { + if (supportsNodePrefix) { + st.doesNotThrow( + function () { require('node:' + mod); }, // eslint-disable-line no-loop-func + 'requiring node:' + mod + ' does not throw' + ); + } else { + st['throws']( + function () { require('node:' + mod); }, // eslint-disable-line no-loop-func + 'requiring node:' + mod + ' throws' + ); + } + } + } + } + } + + st.end(); + }); + + t.test('Object.prototype pollution', function (st) { + var nonKey = 'not a core module'; + st.teardown(mockProperty(Object.prototype, 'fs', { value: false })); + st.teardown(mockProperty(Object.prototype, 'path', { value: '>= 999999999' })); + st.teardown(mockProperty(Object.prototype, 'http', { value: data.http })); + st.teardown(mockProperty(Object.prototype, nonKey, { value: true })); + + st.equal(isCore('fs'), true, 'fs is a core module even if Object.prototype lies'); + st.equal(isCore('path'), true, 'path is a core module even if Object.prototype lies'); + st.equal(isCore('http'), true, 'path is a core module even if Object.prototype matches data'); + st.equal(isCore(nonKey), false, '"' + nonKey + '" is not a core module even if Object.prototype lies'); + + st.end(); + }); + + t.end(); +}); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/index.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/index.d.ts new file mode 100644 index 000000000..729d20205 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/index.d.ts @@ -0,0 +1,17 @@ +/** +Check if the character represented by a given [Unicode code point](https://en.wikipedia.org/wiki/Code_point) is [fullwidth](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms). + +@param codePoint - The [code point](https://en.wikipedia.org/wiki/Code_point) of a character. + +@example +``` +import isFullwidthCodePoint from 'is-fullwidth-code-point'; + +isFullwidthCodePoint('谢'.codePointAt(0)); +//=> true + +isFullwidthCodePoint('a'.codePointAt(0)); +//=> false +``` +*/ +export default function isFullwidthCodePoint(codePoint: number): boolean; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/index.js new file mode 100644 index 000000000..671f97f76 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/index.js @@ -0,0 +1,50 @@ +/* eslint-disable yoda */ +'use strict'; + +const isFullwidthCodePoint = codePoint => { + if (Number.isNaN(codePoint)) { + return false; + } + + // Code points are derived from: + // http://www.unix.org/Public/UNIDATA/EastAsianWidth.txt + if ( + codePoint >= 0x1100 && ( + codePoint <= 0x115F || // Hangul Jamo + codePoint === 0x2329 || // LEFT-POINTING ANGLE BRACKET + codePoint === 0x232A || // RIGHT-POINTING ANGLE BRACKET + // CJK Radicals Supplement .. Enclosed CJK Letters and Months + (0x2E80 <= codePoint && codePoint <= 0x3247 && codePoint !== 0x303F) || + // Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A + (0x3250 <= codePoint && codePoint <= 0x4DBF) || + // CJK Unified Ideographs .. Yi Radicals + (0x4E00 <= codePoint && codePoint <= 0xA4C6) || + // Hangul Jamo Extended-A + (0xA960 <= codePoint && codePoint <= 0xA97C) || + // Hangul Syllables + (0xAC00 <= codePoint && codePoint <= 0xD7A3) || + // CJK Compatibility Ideographs + (0xF900 <= codePoint && codePoint <= 0xFAFF) || + // Vertical Forms + (0xFE10 <= codePoint && codePoint <= 0xFE19) || + // CJK Compatibility Forms .. Small Form Variants + (0xFE30 <= codePoint && codePoint <= 0xFE6B) || + // Halfwidth and Fullwidth Forms + (0xFF01 <= codePoint && codePoint <= 0xFF60) || + (0xFFE0 <= codePoint && codePoint <= 0xFFE6) || + // Kana Supplement + (0x1B000 <= codePoint && codePoint <= 0x1B001) || + // Enclosed Ideographic Supplement + (0x1F200 <= codePoint && codePoint <= 0x1F251) || + // CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane + (0x20000 <= codePoint && codePoint <= 0x3FFFD) + ) + ) { + return true; + } + + return false; +}; + +module.exports = isFullwidthCodePoint; +module.exports.default = isFullwidthCodePoint; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/license b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/license new file mode 100644 index 000000000..e7af2f771 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/package.json new file mode 100644 index 000000000..2137e888f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/package.json @@ -0,0 +1,42 @@ +{ + "name": "is-fullwidth-code-point", + "version": "3.0.0", + "description": "Check if the character represented by a given Unicode code point is fullwidth", + "license": "MIT", + "repository": "sindresorhus/is-fullwidth-code-point", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=8" + }, + "scripts": { + "test": "xo && ava && tsd-check" + }, + "files": [ + "index.js", + "index.d.ts" + ], + "keywords": [ + "fullwidth", + "full-width", + "full", + "width", + "unicode", + "character", + "string", + "codepoint", + "code", + "point", + "is", + "detect", + "check" + ], + "devDependencies": { + "ava": "^1.3.1", + "tsd-check": "^0.5.0", + "xo": "^0.24.0" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/readme.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/readme.md new file mode 100644 index 000000000..4236bba98 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-fullwidth-code-point/readme.md @@ -0,0 +1,39 @@ +# is-fullwidth-code-point [![Build Status](https://travis-ci.org/sindresorhus/is-fullwidth-code-point.svg?branch=master)](https://travis-ci.org/sindresorhus/is-fullwidth-code-point) + +> Check if the character represented by a given [Unicode code point](https://en.wikipedia.org/wiki/Code_point) is [fullwidth](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms) + + +## Install + +``` +$ npm install is-fullwidth-code-point +``` + + +## Usage + +```js +const isFullwidthCodePoint = require('is-fullwidth-code-point'); + +isFullwidthCodePoint('谢'.codePointAt(0)); +//=> true + +isFullwidthCodePoint('a'.codePointAt(0)); +//=> false +``` + + +## API + +### isFullwidthCodePoint(codePoint) + +#### codePoint + +Type: `number` + +The [code point](https://en.wikipedia.org/wiki/Code_point) of a character. + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/.npmignore b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/.npmignore new file mode 100644 index 000000000..3c3629e64 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/.travis.yml b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/.travis.yml new file mode 100644 index 000000000..03dcca57b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/.travis.yml @@ -0,0 +1,8 @@ +language: node_js +node_js: +- '7' +- '6' +- '5' +- '4' +- '0.12' +- '0.10' diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/LICENSE new file mode 100644 index 000000000..4a59c9417 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016-2017 Thomas Watson Steen + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/README.md new file mode 100644 index 000000000..31a8f566c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/README.md @@ -0,0 +1,27 @@ +# is-lambda + +Returns `true` if the current environment is an [AWS +Lambda](https://aws.amazon.com/lambda/) server. + +[![Build status](https://travis-ci.org/watson/is-lambda.svg?branch=master)](https://travis-ci.org/watson/is-lambda) +[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard) + +## Installation + +``` +npm install is-lambda +``` + +## Usage + +```js +var isLambda = require('is-lambda') + +if (isLambda) { + console.log('The code is running on a AWS Lambda') +} +``` + +## License + +MIT diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/index.js new file mode 100644 index 000000000..b245ab1c6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/index.js @@ -0,0 +1,6 @@ +'use strict' + +module.exports = !!( + (process.env.LAMBDA_TASK_ROOT && process.env.AWS_EXECUTION_ENV) || + false +) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/package.json new file mode 100644 index 000000000..d8550898b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/package.json @@ -0,0 +1,35 @@ +{ + "name": "is-lambda", + "version": "1.0.1", + "description": "Detect if your code is running on an AWS Lambda server", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "clear-require": "^1.0.1", + "standard": "^10.0.2" + }, + "scripts": { + "test": "standard && node test.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/watson/is-lambda.git" + }, + "keywords": [ + "aws", + "hosting", + "hosted", + "lambda", + "detect" + ], + "author": "Thomas Watson Steen (https://twitter.com/wa7son)", + "license": "MIT", + "bugs": { + "url": "https://github.com/watson/is-lambda/issues" + }, + "homepage": "https://github.com/watson/is-lambda", + "coordinates": [ + 37.3859955, + -122.0838831 + ] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/test.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/test.js new file mode 100644 index 000000000..e8e73257a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-lambda/test.js @@ -0,0 +1,16 @@ +'use strict' + +var assert = require('assert') +var clearRequire = require('clear-require') + +process.env.AWS_EXECUTION_ENV = 'AWS_Lambda_nodejs6.10' +process.env.LAMBDA_TASK_ROOT = '/var/task' + +var isCI = require('./') +assert(isCI) + +delete process.env.AWS_EXECUTION_ENV + +clearRequire('./') +isCI = require('./') +assert(!isCI) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/LICENSE new file mode 100644 index 000000000..27cc9f377 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 Forbes Lindesay + +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. \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/index.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/index.d.ts new file mode 100644 index 000000000..2107b4289 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/index.d.ts @@ -0,0 +1,2 @@ +declare function isPromise(obj: PromiseLike | S): obj is PromiseLike; +export default isPromise; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/index.js new file mode 100644 index 000000000..1bed0871b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/index.js @@ -0,0 +1,6 @@ +module.exports = isPromise; +module.exports.default = isPromise; + +function isPromise(obj) { + return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function'; +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/index.mjs b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/index.mjs new file mode 100644 index 000000000..bf9e99b5c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/index.mjs @@ -0,0 +1,3 @@ +export default function isPromise(obj) { + return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function'; +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/package.json new file mode 100644 index 000000000..2a3c5404a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/package.json @@ -0,0 +1,30 @@ +{ + "name": "is-promise", + "version": "4.0.0", + "description": "Test whether an object looks like a promises-a+ promise", + "main": "./index.js", + "scripts": { + "test": "node test" + }, + "files": [ + "index.js", + "index.mjs", + "index.d.ts" + ], + "exports": { + ".": [ + { + "import": "./index.mjs", + "require": "./index.js", + "default": "./index.js" + }, + "./index.js" + ] + }, + "repository": { + "type": "git", + "url": "https://github.com/then/is-promise.git" + }, + "author": "ForbesLindesay", + "license": "MIT" +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/readme.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/readme.md new file mode 100644 index 000000000..d53d34bd5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/is-promise/readme.md @@ -0,0 +1,33 @@ + + +# is-promise + + Test whether an object looks like a promises-a+ promise + + [![Build Status](https://img.shields.io/travis/then/is-promise/master.svg)](https://travis-ci.org/then/is-promise) + [![Dependency Status](https://img.shields.io/david/then/is-promise.svg)](https://david-dm.org/then/is-promise) + [![NPM version](https://img.shields.io/npm/v/is-promise.svg)](https://www.npmjs.org/package/is-promise) + + + +## Installation + + $ npm install is-promise + +You can also use it client side via npm. + +## API + +```typescript +import isPromise from 'is-promise'; + +isPromise(Promise.resolve());//=>true +isPromise({then:function () {...}});//=>true +isPromise(null);//=>false +isPromise({});//=>false +isPromise({then: true})//=>false +``` + +## License + + MIT diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/.npmignore b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/.npmignore new file mode 100644 index 000000000..c1cb757ac --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/.npmignore @@ -0,0 +1,2 @@ +.nyc_output/ +coverage/ diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/LICENSE new file mode 100644 index 000000000..19129e315 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/README.md new file mode 100644 index 000000000..35769e844 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/README.md @@ -0,0 +1,51 @@ +# isexe + +Minimal module to check if a file is executable, and a normal file. + +Uses `fs.stat` and tests against the `PATHEXT` environment variable on +Windows. + +## USAGE + +```javascript +var isexe = require('isexe') +isexe('some-file-name', function (err, isExe) { + if (err) { + console.error('probably file does not exist or something', err) + } else if (isExe) { + console.error('this thing can be run') + } else { + console.error('cannot be run') + } +}) + +// same thing but synchronous, throws errors +var isExe = isexe.sync('some-file-name') + +// treat errors as just "not executable" +isexe('maybe-missing-file', { ignoreErrors: true }, callback) +var isExe = isexe.sync('maybe-missing-file', { ignoreErrors: true }) +``` + +## API + +### `isexe(path, [options], [callback])` + +Check if the path is executable. If no callback provided, and a +global `Promise` object is available, then a Promise will be returned. + +Will raise whatever errors may be raised by `fs.stat`, unless +`options.ignoreErrors` is set to true. + +### `isexe.sync(path, [options])` + +Same as `isexe` but returns the value and throws any errors raised. + +### Options + +* `ignoreErrors` Treat all errors as "no, this is not executable", but + don't raise them. +* `uid` Number to use as the user id +* `gid` Number to use as the group id +* `pathExt` List of path extensions to use instead of `PATHEXT` + environment variable on Windows. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/index.js new file mode 100644 index 000000000..553fb32b1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/index.js @@ -0,0 +1,57 @@ +var fs = require('fs') +var core +if (process.platform === 'win32' || global.TESTING_WINDOWS) { + core = require('./windows.js') +} else { + core = require('./mode.js') +} + +module.exports = isexe +isexe.sync = sync + +function isexe (path, options, cb) { + if (typeof options === 'function') { + cb = options + options = {} + } + + if (!cb) { + if (typeof Promise !== 'function') { + throw new TypeError('callback not provided') + } + + return new Promise(function (resolve, reject) { + isexe(path, options || {}, function (er, is) { + if (er) { + reject(er) + } else { + resolve(is) + } + }) + }) + } + + core(path, options || {}, function (er, is) { + // ignore EACCES because that just means we aren't allowed to run it + if (er) { + if (er.code === 'EACCES' || options && options.ignoreErrors) { + er = null + is = false + } + } + cb(er, is) + }) +} + +function sync (path, options) { + // my kingdom for a filtered catch + try { + return core.sync(path, options || {}) + } catch (er) { + if (options && options.ignoreErrors || er.code === 'EACCES') { + return false + } else { + throw er + } + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/mode.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/mode.js new file mode 100644 index 000000000..1995ea4a0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/mode.js @@ -0,0 +1,41 @@ +module.exports = isexe +isexe.sync = sync + +var fs = require('fs') + +function isexe (path, options, cb) { + fs.stat(path, function (er, stat) { + cb(er, er ? false : checkStat(stat, options)) + }) +} + +function sync (path, options) { + return checkStat(fs.statSync(path), options) +} + +function checkStat (stat, options) { + return stat.isFile() && checkMode(stat, options) +} + +function checkMode (stat, options) { + var mod = stat.mode + var uid = stat.uid + var gid = stat.gid + + var myUid = options.uid !== undefined ? + options.uid : process.getuid && process.getuid() + var myGid = options.gid !== undefined ? + options.gid : process.getgid && process.getgid() + + var u = parseInt('100', 8) + var g = parseInt('010', 8) + var o = parseInt('001', 8) + var ug = u | g + + var ret = (mod & o) || + (mod & g) && gid === myGid || + (mod & u) && uid === myUid || + (mod & ug) && myUid === 0 + + return ret +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/package.json new file mode 100644 index 000000000..e45268944 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/package.json @@ -0,0 +1,31 @@ +{ + "name": "isexe", + "version": "2.0.0", + "description": "Minimal module to check if a file is executable.", + "main": "index.js", + "directories": { + "test": "test" + }, + "devDependencies": { + "mkdirp": "^0.5.1", + "rimraf": "^2.5.0", + "tap": "^10.3.0" + }, + "scripts": { + "test": "tap test/*.js --100", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --all; git push origin --tags" + }, + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "license": "ISC", + "repository": { + "type": "git", + "url": "git+https://github.com/isaacs/isexe.git" + }, + "keywords": [], + "bugs": { + "url": "https://github.com/isaacs/isexe/issues" + }, + "homepage": "https://github.com/isaacs/isexe#readme" +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/test/basic.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/test/basic.js new file mode 100644 index 000000000..d926df64b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/test/basic.js @@ -0,0 +1,221 @@ +var t = require('tap') +var fs = require('fs') +var path = require('path') +var fixture = path.resolve(__dirname, 'fixtures') +var meow = fixture + '/meow.cat' +var mine = fixture + '/mine.cat' +var ours = fixture + '/ours.cat' +var fail = fixture + '/fail.false' +var noent = fixture + '/enoent.exe' +var mkdirp = require('mkdirp') +var rimraf = require('rimraf') + +var isWindows = process.platform === 'win32' +var hasAccess = typeof fs.access === 'function' +var winSkip = isWindows && 'windows' +var accessSkip = !hasAccess && 'no fs.access function' +var hasPromise = typeof Promise === 'function' +var promiseSkip = !hasPromise && 'no global Promise' + +function reset () { + delete require.cache[require.resolve('../')] + return require('../') +} + +t.test('setup fixtures', function (t) { + rimraf.sync(fixture) + mkdirp.sync(fixture) + fs.writeFileSync(meow, '#!/usr/bin/env cat\nmeow\n') + fs.chmodSync(meow, parseInt('0755', 8)) + fs.writeFileSync(fail, '#!/usr/bin/env false\n') + fs.chmodSync(fail, parseInt('0644', 8)) + fs.writeFileSync(mine, '#!/usr/bin/env cat\nmine\n') + fs.chmodSync(mine, parseInt('0744', 8)) + fs.writeFileSync(ours, '#!/usr/bin/env cat\nours\n') + fs.chmodSync(ours, parseInt('0754', 8)) + t.end() +}) + +t.test('promise', { skip: promiseSkip }, function (t) { + var isexe = reset() + t.test('meow async', function (t) { + isexe(meow).then(function (is) { + t.ok(is) + t.end() + }) + }) + t.test('fail async', function (t) { + isexe(fail).then(function (is) { + t.notOk(is) + t.end() + }) + }) + t.test('noent async', function (t) { + isexe(noent).catch(function (er) { + t.ok(er) + t.end() + }) + }) + t.test('noent ignore async', function (t) { + isexe(noent, { ignoreErrors: true }).then(function (is) { + t.notOk(is) + t.end() + }) + }) + t.end() +}) + +t.test('no promise', function (t) { + global.Promise = null + var isexe = reset() + t.throws('try to meow a promise', function () { + isexe(meow) + }) + t.end() +}) + +t.test('access', { skip: accessSkip || winSkip }, function (t) { + runTest(t) +}) + +t.test('mode', { skip: winSkip }, function (t) { + delete fs.access + delete fs.accessSync + var isexe = reset() + t.ok(isexe.sync(ours, { uid: 0, gid: 0 })) + t.ok(isexe.sync(mine, { uid: 0, gid: 0 })) + runTest(t) +}) + +t.test('windows', function (t) { + global.TESTING_WINDOWS = true + var pathExt = '.EXE;.CAT;.CMD;.COM' + t.test('pathExt option', function (t) { + runTest(t, { pathExt: '.EXE;.CAT;.CMD;.COM' }) + }) + t.test('pathExt env', function (t) { + process.env.PATHEXT = pathExt + runTest(t) + }) + t.test('no pathExt', function (t) { + // with a pathExt of '', any filename is fine. + // so the "fail" one would still pass. + runTest(t, { pathExt: '', skipFail: true }) + }) + t.test('pathext with empty entry', function (t) { + // with a pathExt of '', any filename is fine. + // so the "fail" one would still pass. + runTest(t, { pathExt: ';' + pathExt, skipFail: true }) + }) + t.end() +}) + +t.test('cleanup', function (t) { + rimraf.sync(fixture) + t.end() +}) + +function runTest (t, options) { + var isexe = reset() + + var optionsIgnore = Object.create(options || {}) + optionsIgnore.ignoreErrors = true + + if (!options || !options.skipFail) { + t.notOk(isexe.sync(fail, options)) + } + t.notOk(isexe.sync(noent, optionsIgnore)) + if (!options) { + t.ok(isexe.sync(meow)) + } else { + t.ok(isexe.sync(meow, options)) + } + + t.ok(isexe.sync(mine, options)) + t.ok(isexe.sync(ours, options)) + t.throws(function () { + isexe.sync(noent, options) + }) + + t.test('meow async', function (t) { + if (!options) { + isexe(meow, function (er, is) { + if (er) { + throw er + } + t.ok(is) + t.end() + }) + } else { + isexe(meow, options, function (er, is) { + if (er) { + throw er + } + t.ok(is) + t.end() + }) + } + }) + + t.test('mine async', function (t) { + isexe(mine, options, function (er, is) { + if (er) { + throw er + } + t.ok(is) + t.end() + }) + }) + + t.test('ours async', function (t) { + isexe(ours, options, function (er, is) { + if (er) { + throw er + } + t.ok(is) + t.end() + }) + }) + + if (!options || !options.skipFail) { + t.test('fail async', function (t) { + isexe(fail, options, function (er, is) { + if (er) { + throw er + } + t.notOk(is) + t.end() + }) + }) + } + + t.test('noent async', function (t) { + isexe(noent, options, function (er, is) { + t.ok(er) + t.notOk(is) + t.end() + }) + }) + + t.test('noent ignore async', function (t) { + isexe(noent, optionsIgnore, function (er, is) { + if (er) { + throw er + } + t.notOk(is) + t.end() + }) + }) + + t.test('directory is not executable', function (t) { + isexe(__dirname, options, function (er, is) { + if (er) { + throw er + } + t.notOk(is) + t.end() + }) + }) + + t.end() +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/windows.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/windows.js new file mode 100644 index 000000000..34996734d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/isexe/windows.js @@ -0,0 +1,42 @@ +module.exports = isexe +isexe.sync = sync + +var fs = require('fs') + +function checkPathExt (path, options) { + var pathext = options.pathExt !== undefined ? + options.pathExt : process.env.PATHEXT + + if (!pathext) { + return true + } + + pathext = pathext.split(';') + if (pathext.indexOf('') !== -1) { + return true + } + for (var i = 0; i < pathext.length; i++) { + var p = pathext[i].toLowerCase() + if (p && path.substr(-p.length).toLowerCase() === p) { + return true + } + } + return false +} + +function checkStat (stat, path, options) { + if (!stat.isSymbolicLink() && !stat.isFile()) { + return false + } + return checkPathExt(path, options) +} + +function isexe (path, options, cb) { + fs.stat(path, function (er, stat) { + cb(er, er ? false : checkStat(stat, path, options)) + }) +} + +function sync (path, options) { + return checkStat(fs.statSync(path), path, options) +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/CHANGELOG.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/CHANGELOG.md new file mode 100644 index 000000000..4879fb6fa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/CHANGELOG.md @@ -0,0 +1,2380 @@ +# Master (Unreleased) + +# 3.1.0 - 8 December, 2023 + +### Bug fixes + +- andWhereNotJsonObject calling wrong function (#5683) +- PostgreSQL: fix error when setting query_timeout (#5673) +- MySQL: Missing comments on delete, update and insert (#5738) +- MySQL: Fixed issue with bigincrements not working with composite primary key - #5341 (#5343) + +### Types + +- Add type definitions for orHavingNull and orHavingNotNull (#5669) +- Import knex as type in TS migration template (#5741) +- Fix conditional constraint error (#5747) +- PostgreSQL: Fix typing to reflect pg typing change (#5647) + +### New features + +- Add transactor.parentTransaction (#5567) +- MySQL: Added implementation for upsert (#5743) +- Oracle: Support Object Names Greater than 30 Characters for Oracle DB Versions 12.2 and Greater (#5197) + +# 3.0.1 - 6 October, 2023 + +- Build fix + +# 3.0.0 - 6 October, 2023 + +- Fix raw bindings typing (#5401) +- Fix migrate:unlock when used with custom identifier wrapping. (#5353) +- Fix driver options specified with .options() method being ignored for oracledb dialect (#5123) +- Drop compatibility for Node < 16 +- Fix knex d.ts to work with mixed modules (#5659) +- Fix Lexical error from "Instaed" to "Instead" (#5655) + +### Bug fixes + +- Fix Linting #5455 - #5460 + +# 2.5.1 - 12 July, 2023 + +### Bug fixes + +- Fix Linting #5455 - #5460 + +# 2.5.0 - 08 July, 2023 + +### New features + +- Add uuid helper function (#5617) +- Add `nativeBindings` option to `better-sqlite3` options (#5461) +- Add QueryBuilder#updateFrom (#5386) +- Add readonly transaction access mode (#5445) +- Add readonly option to Better-SQLite3 (#5530) +- Add EXCEPT as a valid keyword (#5357) +- Add ability to prepend query comments (#5289) +- Add fetchAsString option (#5484) + +### Bug fixes + +- Avoid password leaks on query logs (#5559) +- Add knex.mjs to files in package.json (#5518) +- Handle numeric array elements in .orderBy() (#5551) +- Attach error handler early enough (#5552) +- Fix Returning \* in Oracle (#5598) +- Fix indexType option in `Postgres` (#5601) +- Add mjs extension type (#5616) +- Use implicit check on json fields for OracleDB (#5478) +- Fix when manually close source stream (#5466) +- Fix case sensitive issue with get table (#5509) + +### Typings + +- Add Object syntax overload to increment method (#5512) +- Add object syntax overload to decrement method (#5555) +- Fix typing for toSql (#5594) +- Add ResolveTableType for `.merge()` (#5605) +- Add missing types for havingNull and havingNotNull (#5529) +- Add collate to the columnbuilder interface (#5568) +- TableBuilder methods return the SchemaBuilder. (#5486) + +# 2.4.2 - 22 January, 2023 + +### Bug fixes + +- CLI: Fix incorrent EOL causing errors on Linux #5455 + +# 2.4.1 - 18 January, 2023 + +### Bug fixes + +- PostgreSQL: Fix Malformed array literal 2.4.0 Regression #5439 + +# 2.4.0 - 06 January, 2023 + +### New features: + +- Support partial unique indexes #5316 +- Make compiling SQL in error message optional #5282 + +### Bug fixes + +- Insert array into json column #5321 +- Fix unexpected max acquire-timeout #5377 +- Fix: orWhereJson #5361 +- MySQL: Add assertion for basic where clause not to be object or array #1227 +- SQLite: Fix changing the default value of a boolean column in SQLite #5319 + +### Typings: + +- add missing type for 'expirationChecker' on PgConnectionConfig #5334 + +# 2.3.0 - 31 August, 2022 + +### New features: + +- PostgreSQL: Explicit jsonb support for custom pg clients #5201 +- SQLite: Support returning with sqlite3 and better-sqlite3 #5285 +- MSSQL: Implement mapBinding mssql dialect option #5292 + +### Typings: + +- Update types for TS 4.8 #5279 +- Fix typo #5267 +- Fix WhereJsonObject withCompositeTableType #5306 +- Fix AnalyticFunction type #5304 +- Infer specific column value type in aggregations #5297 + +# 2.2.0 - 19 July, 2022 + +### New features: + +- Inline primary key creation for postgres flavours #5233 +- SQLite: Add warning for undefined connection file #5223 +- MSSQL: Add JSON parameter support for connection #5200 + +### Bug fixes: + +- PostgreSQL: add primaryKey option for uuid #5212 + +### Typings: + +- Add promisable and better types #5222 +- Update raw query bind parameter type #5208 + +# 2.1.0 - 26 May, 2022 + +### New features: + +- Improve bundling experience to safely import dialects while using static paths #5142 +- Implement extendable builders #5041 +- PostgreSQL: Refresh materialized view concurrently #5166 + +### Bug fixes: + +- Use correct paths in package.json browser field #5174 +- MariaDB: Fix 'NULL' returned instead of NULL on MariaDB 10.2.6+ #5181 +- MySQL: fix hasColumn Error (hasColumn ('a_id') is true, but hasColumn('a_Id') is false) #5148 +- MSSQL: Fix .hasTable result when using .withSchema #5176 +- Oracle: correctly INSERTS Buffer #4869 + +### Typings: + +- Update type definitions for pg connection #5139 + +# 2.0.0 - 21 April, 2022 + +### Breaking changes + +- Restore sqlite3 package #5136 + +### Test / internal changes: + +- Migrate Husky from 4 to 7 #5137 +- Migrate Jake to 10.8.5 #5138 + +# 1.0.7 - 13 April, 2022 + +### Bug fixes: + +- CLI: Fix cli migrate:make SQLite dependency #5106 + +# 1.0.6 - 12 April, 2022 + +### Bug fixes: + +- PostgreSQL: Wait for search path to be set before returning connection #5107 +- CLI: No client override during migrate:make #5109 + +# 1.0.5 - 05 April, 2022 + +### New features: + +- Override knexfile options with CLI options #4047 + +### Bug fixes: + +- Stringify json value in update #5063 +- Fix isModuleType() for yarn #4447 +- Wrapped Unions Fixes #5072 +- SQLite: Fix @vscode-sqlite3 error message #5081 +- CLI: Fix completed migration listing #5060 + +### Typings: + +- Make default generic parameters of `Knex` match the generic parameter types of `knex` #5021 +- Update knex types for TS 4.7 #5095 + +# 1.0.4 - 13 March, 2022 + +### New features: + +- Add whereLike functions #5044 + +### Bug fixes: + +- Fix orWhereJsonPath clause #5022 +- Subquery in on clause missing parenthesis #5049 +- Rework Union Wrapping #5030 +- Oracle: Fix batch inserts with DEFAULT values with OracleDB #2592 #5037 + +### Typings: + +- Fix types for "returning" methods #5031 +- createTableLike callback should be optional #5055 + +### Documentation: + +- Website URL changed to https://knex.github.io/documentation/ + +# 1.0.3 - 11 February, 2022 + +### Bug fixes: + +- Fix error message for missing migration files #4937 +- Add withMaterialized and withNotMaterialized to method-constants #5009 +- PostgreSQL: Fix whereJsonPath queries #5011 +- PostgreSQL: Fix delete joins #5016 +- CockroachDB: Fix whereJsonPath queries #5011 +- MySQL: Create primary keys in same statement #5017 + +### Typings: + +- Fix type definition for getMigration in MigrationSource #4998 +- Fix argument type of alter method #4996 + +### Improvements: + +- Use async / await syntax in seeds as default #5005 + +### Documentation: + +- Add Firebird dialect to ECOSYSTEM.md #5003 + +# 1.0.2 - 02 February, 2022 + +### New features: + +- Support of MATERIALIZED and NOT MATERIALIZED with WITH/CTE #4940 +- Add raw support in onConflict clause #4960 +- Alter nullable constraint when alterNullable is set to true #4730 +- Add alterType parameter for alter function #4967 +- Support string json in json values #4988 +- MySQL: add with clause #4508 + +### Bug fixes: + +- Fix error message for missing migration files #4937 +- Move deferrable to after on update/on delete #4976 +- Do not use sys.tables to find if a table exists #2328 +- PostgreSQL: Fix Order nulls #4989 +- MySQL: Fix collation when renaming column #2666 +- SQLite: Same boolean handling in better-sqlite3 as in sqlite3 #4982 + +### Typings: + +- WhereILike - fix typo #4941 + +# 1.0.1 - 16 January, 2022 + +### Bug fixes: + +- Fix package.json metadata + +# 1.0.0 - 16 January, 2022 + +### Breaking changes + +- Dropped support for Node 10; +- Replaced unsupported `sqlite3` driver with `@vscode/sqlite3`; +- Changed data structure from `RETURNING` operation to be consistent with `SELECT`; +- Changed Migrator to return list of migrations as objects consistently. + +### New features: + +- Support fromRaw #4781 +- Support zero precision in timestamp/datetime #4784 +- Support whereLike and whereILike #4779 +- Add JSDoc (TS flavor) to stub files #4809 +- Allow skip binding in limit and offset #4811 +- Support creating a new table in the database based on another table #4821 +- Accept Raw on onIn joins #4830 +- Implement support for custom seed sources #4842 +- Add binary uuid option #4836 +- ForUpdate array parameter #4882 +- Add camel case to timestamps method #4803 +- Advanced JSON support #4859 +- Add type to TypeScript knexfile #4909 +- Checks Constraints Support #4874 +- Support creating multiple PKs with increments #4903 +- Enable wrapIdentifier for SQLite .hasTable #4915 +- MSSQL: Add support for unique constraint #4887 +- SQLite: New dialect, using better-sqlite3 driver #4871 +- SQLite: Switch to @vscode/sqlite3 #4866 +- SQLite: Support createViewOrReplace #4856 +- SQLite: Support RETURNING statements for better-sqlite3 driver #4934 +- PostgreSQL: Support JOIN and USING syntax for Delete Statement #4800 + +### Bug fixes: + +- Fix overzealous warning on use of whereNot with "in" or "between" #4780 +- Fix Union all + first syntax error #4799 +- Make view columns optional in create view like #4829 +- Insert lock row fix during migration #4865 +- Fix for createViewOrReplace #4856 +- SQLite: Fix foreign key constraints when altering a table #4189 +- MySQL: Validate connection fix #4794 +- MySQL: Set comment size warning limit to 1024 #4867 + +### Typings: + +- Allow string indexType in index creation #4791 +- Add missing ints typings #4832 +- Returning method types #4881 +- Improve columnInfo type #4868 + +# 0.95.15 - 22 December, 2021 + +### Bug fixes: + +- Oracle: +- MariaDB: lock row fix during migration in MariaDB and Oracle #4865 + +# 0.95.14 - 09 November, 2021 + +### Bug fixes: + +- MySQL: mysql2 dialect validate connection fix #4794 + +# 0.95.13 - 02 November, 2021 + +### Bug fixes: + +- PostgreSQL: Support zero precision in timestamp/datetime #4784 + +### Typings: + +- Allow string indexType in index creation #4791 + +# 0.95.12 - 28 October, 2021 + +### New features: + +- New dialect: CockroachDB #4742 +- New dialect: pg-native #4327 +- CockroachDB: add support for upsert #4767 +- PostgreSQL: Support SELECT .. FOR NO KEY UPDATE / KEY SHARE row level locking clauses #4755 +- PostgreSQL: Add support for 'CASCADE' in PostgreSQL 'DROP SCHEMA' queries #4713 +- MySQL: Add storage engine index Type support to index() and unique() schema #4756 +- MSSQL: Support table.primary, table.unique variant with options object #4710 +- SQLite: Add setNullable support to SQLite #4684 +- Add geometry column building #4776 +- Add support for creating table copies #1373 +- Implement support for views and materialized views #1626 +- Implement partial index support #4768 +- Support for 'is null' in 'order by' #3667 + +### Bug fixes: + +- Fix support for Oracle connections passed via knex.connection() #4757 +- Avoid inserting multiple locks if a migration lock already exists #4694 + +### Typings: + +- Some TableBuilder methods return wrong types #4764 +- Update JoinRaw bindings type to accept arrays #4752 +- fix onDelete/onUpdate for ColumnBuilder #4656 + +# 0.95.11 - 03 September, 2021 + +### New features: + +- Add support for nullability modification via schema builder (table.setNullable() and table.dropNullable()) #4657 +- MySQL: Add support for mysql/mariadb-client JSON parameters in connectionURIs #4629 +- MSSQL: Support comments as MS_Description properties #4632 + +### Bug fixes: + +- Fix Analytic orderBy and partitionBy to follow the SQL documentation #4602 +- CLI: fix migrate:up for migrations disabling transactions #4550 +- SQLite: Fix adding a column with a foreign key constraint in SQLite #4649 +- MSSQL: columnInfo() support case-sensitive database collations #4633 +- MSSQL: Generate valid SQL for withRecursive() #4514 +- Oracle: withRecursive: omit invalid RECURSIVE keyword, include column list #4514 + +### Improvements: + +- Add .mjs migration and seed stubs #4631 +- SQLite: Clean up DDL handling and move all operations to the parser-based approach #4648 + +# 0.95.10 - 20 August, 2021 + +### Improvements: + +- Use sys info function instead of connection db name #4623 + +### Typings: + +- Deferrable and withkeyName should not be in ColumnBuilder #4600 + +# 0.95.9 - 31 July, 2021 + +### New features: + +- Oracle: support specifying schema for dropTable and dropSequence #4596 +- Oracle: support specifying schema for autoincrement #4594 + +### Typings: + +- Add TypeScript support for deferrable, new Primary/Unique syntax #4589 + +# 0.95.8 - 25 July, 2021 + +### New features: + +- Add deferrable support for constraint #4584 +- Implement delete with join #4568 +- Add DPI error codes for Oracle #4536 + +### Bug fixes: + +- Fixing PostgreSQL datetime and timestamp column created with wrong format #4578 + +### Typings: + +- Improve analytic types #4576 +- MSSQL: Add trustServerCertificate option #4500 + +# 0.95.7 - 10 July, 2021 + +### New features: + +- Add ability to omit columns on an onConflict().ignore() #4557 +- CLI: Log error message #4534 + +### Typings: + +- Export Knex.TransactionConfig #4498 +- Include options object in count(Distinct) typings #4491 +- Add types for analytic functions #4544 + +# 0.95.6 - 17 May, 2021 + +### Typings: + +- Export TransactionProvider type #4489 + +# 0.95.5 - 11 May, 2021 + +### New features: + +- SQLite: Add support for file open flags #4446 +- Add .cjs extension to Seeder.js to support Node ESM #4381 #4382 + +### Bug fixes: + +- Remove peerDependencies to avoid auto-install on npm 7 #4480 + +### Typings: + +- Fix typing for increments and bigIncrements #4406 +- Add typings for on JoinClause for onVal #4436 +- Adding Type Definition for isTransaction #4418 +- Export client class from knex namespace #4479 + +# 0.95.4 - 26 March, 2021 + +### Typings: + +- Fix mistyping of stream #4400 + +# 0.95.3 - 25 March, 2021 + +### New features: + +- PostgreSQL: Add "same" as operator #4372 +- MSSQL: Improve an estimate of the max comment length #4362 +- Throw an error if negative offset is provided #4361 + +### Bug fixes: + +- Fix timeout method #4324 +- SQLite: prevent dropForeign from being silently ignored #4376 + +### Typings: + +- Allow config.client to be non-client instance #4367 +- Add dropForeign arg type for single column #4363 +- Update typings for TypePreservingAggregation and stream #4377 + +# 0.95.2 - 11 March, 2021 + +### New features: + +- Improve ESM import support #4350 + +### Bug fixes: + +- CLI: update ts.stub files to new TypeScript namespace #4344 +- CLI: fix TypeScript migration stub after 0.95.0 changes #4366 + +### Typings: + +- Move QueryBuilder and KnexTimeoutError into knex namespace #4358 + +### Test / internal changes: + +- Unify db test helpers #4356 + +# 0.95.1 - 04 March, 2021 + +### Bug fixes: + +- CLI: fix `knex init` not finding default knexfile #4339 + +# 0.95.0 - 03 March, 2021 + +Note: there are many breaking changes in this version, particularly in TypeScript support. Please see `UPGRADING.md` for details. + +### New features: + +- Add transaction isolation support #4185 +- Add analytic functions #4188 +- Change default to not trigger a promise rejection for transactions with a specified handler #4195 +- Make toSQL().toNative() work for Raw to match the API for QueryBuilder #4058 +- Allow 'match' operator #3569 +- Support optimizer hints #4243 +- Add parameter to prevent autoincrement columns from being primary keys #4266 +- Make "first" and "pluck" mutually exclusive #4280 +- Added merge strategy to allow selecting columns to upsert. #4252 +- Throw error if the array passed to insert is empty #4289 +- Events: introduce queryContext on query-error #4301 +- CLI: Use UTC timestamp for new migrations #4245 +- MSSQL: Replace MSSQL dialect with Tedious.js implementation #2857 #4281 +- MSSQL: Use "nvarchar(max)" for ".json()" #4278 +- MSSQL: Schema builder - add predictable constraint names for default values #4319 +- MSSQL: Schema builder - attempt to drop default constraints when changing default value on columns #4321 +- SQLite: Fallback to json for sqlite3 when using jsonb #4186 +- SQLite: Return complete list of DDL commands for creating foreign keys #4194 +- SQLite: Support dropping composite foreign keys #4202 +- SQLite: Recreate indices when altering a table #4277 +- SQLite: Add support for altering columns #4322 + +### Bug fixes: + +- Fix issue with .withSchema usage with joins on a subquery #4267 +- Fix issue with schema usage with FROM clause contain QueryBuilder, function or Raw #4268 +- CLI: Address raised security warnings by dropping liftoff #4122 +- CLI: Fix an issue with npm@7 and ESM when `type` was set to `'module'` in `package.json` #4295 +- PostgreSQL: Add check to only create native enum once #3658 +- SQLite: Fix foreign key "on delete" when altering a table #4225 +- SQLite: Made the constraint detection case-insensitive #4330 +- MySQL: Keep auto increment after rename #4266 +- MSSQL: don't raise query-error twice #4314 +- MSSQL: Alter column must have its own query #4317 + +### Typings: + +- TypeScript 4.1+ is now required +- Add missing onConflict overrides #4182 +- Introduce the "infamous triplet" export #4181 +- Fix type definition of Transaction #4172 +- Add typedefinitions for havingNotIn #4265 +- Include 'name' property in MigratorConfig #4300 +- Improve join and conflict types #4318 +- Fix ArrayIfAlready type #4331 + +### Test / internal changes: + +- Drop global Knex.raw #4180 +- Stop using legacy url.parse API #3702 +- Various internal refactorings #4175 #4177 #4178 #4192 +- Refactor to classes #4190 #4191 #4193 #4210 #4253 +- Move transaction type tests to TSD #4208 +- Clean up destroy logic #4248 +- Colorize code snippets in readme files #4234 +- Add "Ecosystem" documentation for Knex plugins #4183 +- Documentation cleanup +- SQLite: Use SQLite "rename column" instead of a DDL helper #4200 +- SQLite: Simplify reinsert logic when altering a table #4272 + +# 0.21.19 - 02 March, 2021 + +- SQLite: Made the constraint detection case-insensitive #4332 + +# 0.21.18 - 22 February, 2021 + +- CLI: Fix an issue with npm@7 and ESM when type was set to 'module' in package.json #4295 + +# 0.21.17 - 30 January, 2021 + +### Bug fixes: + +- SQLite: Fix SQLite foreign on delete when altering a table #4261 + +### New features: + +- Add support for optimizer hints (see https://github.com/knex/documentation/pull/306 for documentation) #4243 + +# 0.21.16 - 17 January, 2021 + +### Bug fixes: + +- MSSQL: Avoid passing unsupported pool param. Fixes node-mssql 7+ support #4236 + +# 0.21.15 - 26 December, 2020 + +### New features: + +- SQLite: Add primary/foreign support on alterTable #4162 +- SQLite: Add dropPrimary/dropForeign support on alterTable #4162 + +### Typings: + +- Add "after" and "first" to columnBuilder types #3549 #4169 + +### Test / internal changes: + +- Extract knex config resolution logic #4166 +- Run CI using GitHub Actions #4168 +- Add Node.js 15 to CI matrix #4173 + +# 0.21.14 - 18 December, 2020 + +### New features: + +- MSSQL: support "returning" on inserts, updates and deletes on tables with triggers #4152 +- Use esm import if package.json type is "module" #4158 + +### Bug fixes: + +- Make sure query-response and query-error events contain \_knexTxId #4160 + +### Test / internal changes: + +- Improved integration test framework #4161 + +# 0.21.13 - 12 December, 2020 + +### New features: + +- SQLite: Add support for `dropForeign` #4092 +- Add support for WHERE clauses to "upsert" queries #4148 + +### Bug fixes: + +- MSSQL: Avoid connection getting stuck on socket hangup #4157 +- Oracle: Support specifying non-default DB port #4147 +- Oracle: Support inserts with only default values (empty body) #4092 +- CLI: fix irregular seed file execution order #4156 +- Fix performance of asyncStackTraces with enable-source-maps node flag #4154 + +### Typings: + +- PostgreSQL: Add support for application_name #4153 +- Fix types for insert to allow array #4105 +- Add types for userParams and withUserParams #4119 +- Added type for withKeyName #4139 +- Fix batchInsert definitions #4131 +- Fix types for WhereIn signature (value or query builder) #3863 +- Add types for connection config of mysql2 driver #4144 + +### Test / internal changes: + +- Move TS tests to tsd (WIP) #4109 #4110 + +# 0.21.12 - 02 November, 2020 + +### Typings: + +- Reintroduce support for globally defining table/record mapping #4100 +- Add a few missing types for MSSQL Connection #4103 +- Make .ignore() and .merge() return QueryBuilder rather than QueryInterface #4102 +- Use tarn config TS types instead of generic-pool #4064 + +# 0.21.11 - 01 November, 2020 + +### Typings: + +- Revert support for globally defining table/record mapping #4099 + +# 0.21.10 - 31 October, 2020 + +### New features: + +- Upsert support (Postgres/MySQL/Sqlite) #3763 + +### Bug fixes: + +- Switch to non-uuid knexQueryUids to avoid issues when mocking global date #4089 + +### Typings: + +- Allow to globally define table/record mapping #4071 + +# 0.21.9 - 27 October, 2020 + +### New features: + +- add method clear(statement) to QueryBuilder #4051 + +### Bug fixes: + +- CLI: fix help text being printed twice #4072 +- Oracle: columnInfo() no longer requires an Owner User #4053 +- Add missing "start" event propagation from transaction #4087 + +# 0.21.8 - 27 October, 2020 + +### Bug fixes: + +- MSSQL: Escape properly if literal '?' is needed #4053 +- Make toQuery behavior consistent with pre-0.21.7 (do not break on empty builder) #4083 +- Fix comment escaping for MySQL and PostgreSQL #4084 + +# 0.21.7 - 25 October, 2020 + +### New features: + +- CLI: Add migration stub for .cjs extension #4065 + +### Bug fixes: + +- MSSQL: Add dynamic scaling for decimal values and prevents a UInt64 overflow #3910 +- MSSQL: Fix apostrophe escaping #4077 +- Ensure that semicolon is not appended to statements that already end with a semicolon #4052 + +### Typings: + +- Add arguments to QueryCallback in Where #4034 + +### Test / internal changes: + +- Replace lodash type-checks with native solutions #4056 +- Replace mkdirp with native recursive flag #4060 +- Replace inherits package with builtin utility #4059 + +# 0.21.6 - 27 September, 2020 + +### New features: + +- CLI: New config parameter / CLI flag to prefixing seed filename with timestamp #3873 +- CLI: throw an error when specific seed file cannot be found #4011 +- Warn if whereNot is used with 'in' or 'between' #4038 + +### Bug fixes: + +- CLI: Fix double merging of config for migrator #4040 + +### Typings: + +- Unify SeedsConfig and SeederConfig #4003 +- Allow string[] type for directory in SeedsConfig #4033 + +# 0.21.5 - 17 August, 2020 + +### New features: + +- CLI: Improve Esm interop #3985 +- CLI: Improve mjs module support #3980 + +### Test / internal changes: + +- Bump version of dtslint #3984 +- Test/document esm interop mixed formats (knexfile/migrations/seeds) #3986 + +# 0.21.4 - 10 August, 2020 + +### New features: + +- CLI: Add new option for seed: recursive #3974 + +### Bug fixes: + +- CLI: Do not load seeds from subfolders recursively by default #3974 + +# 0.21.3 - 08 August, 2020 + +### New features: + +- CLI: Support multiple directories for seeds #3967 + +### Bug fixes: + +- Ensure DB stream is destroyed when the PassThrough is destroyed #2324 +- Support postProcessResponse for streams #3931 +- Fix ESM module interop for calling module/package of type 'module' #3938 +- CLI: Fix migration source name in rollback all #3956 +- Fix getMergedConfig calls to include client logger #3920 +- Escape single quoted values passed to defaultTo function #3899 + +### Typings: + +- Add .timeout(ms) to .raw()'s typescript typings #3885 +- Add typing for double table column builder #3950 +- Add a phantom tag to Ref type to mark received type parameters as used #3934 +- Add `null` as valid binding type #3946 + +### Test / internal changes: + +- Change query lab link to https #3933 + +# 0.21.2 - 10 July, 2020 + +### New features: + +- Warn user if custom migration source is being reset #3839 +- Prefer `void` as return type on migration generator ts stub #3865 +- MSSQL: Added the removal of a columns default constraint, before dropping the column #3855 + +### Typings: + +- Fix definition for raw querybuilders #3846 + +### Test / internal changes: + +- Refactor migration logic to use async/await #3838 + +# 0.21.1 - 28 April, 2020 + +### New features: + +- CLI: Add migrate:unlock command, truncate on forceFreeMigrationsLock #3822 +- CLI: Add support for cjs files by default #3829 + +### Bug fixes: + +- CLI: Fix inference of seed/migration extension from knexfile extension #3814 +- rewrite delay to not node-only version. Fixes compatibility with browsers #3820 + +### Test / internal changes: + +- Update dependencies. Explicitly support Node.js 14 #3825 #3830 + +# 0.21.0 - 18 April, 2020 + +### Improvements + +- Reduce size of lodash in bundle #3804 + +### Breaking changes + +- Dropped support for Node 8 +- Breaking upstream change in `pg-query-stream`: `Changed stream.close to stream.destroy which is the official way to terminate a readable stream. This is a breaking change if you rely on the stream.close method on pg-query-stream...though should be just a find/replace type operation to upgrade as the semantics remain very similar (not exactly the same, since internals are rewritten, but more in line with how streams are "supposed" to behave).` + +### Test / internal changes: + +- Updated Tarn.js to a version 3.0.0 +- Updated mkdirp to a version 1.0.4 +- Updated examples to use ES2015 style #3810 + +# 0.20.15 - 16 April, 2020 + +### Bug fixes: + +- Support for `.finally(..)` on knex's Promise-alikes #3800 + +### Typings: + +- Add types for `.distinctOn` #3784 + +# 0.20.14 - 13 April, 2020 + +### New features: + +- CLI: adds support for asynchronous knexfile loading #3748 +- Add clearGroup method #3771 + +### Typings: + +- Support Raw types for insert, where, update #3730 +- Add typings for MigrationSource #3756 +- Update signature of orderBy to support QueryBuilder inside array #3757 +- Add toSQL and toString to SchemaBuilder #3758 +- `interface Knex` and `function Knex` should have the same types #3787 +- Fix minor issues around typings #3765 + +### Test / internal changes: + +- Minor test internal enhancements #3747 +- Minor improvements on the usage of fs utilities #3749 +- Split tests in groups #3785 + +# 0.20.13 - 23 March, 2020 + +### Bug fixes: + +- Correctly handle dateToString escaping without timezone passed #3742 +- Make protocol length check more defensive #3744 + +### Typings: + +- Make the ChainableInterface conform to Promise #3724 + +# 0.20.12 - 19 March, 2020 + +### Bug fixes: + +- Added missing call to \_reject in Transactor#transaction #3706 +- Fix method binding on knex proxy #3717 +- Oracle: Transaction_OracleDB can use config.connection #3731 + +### Typings: + +- Fix incorrect type signature of Having #3719 + +### Test / internal changes: + +- Cleanup/remove transaction stalling #3716 +- Rewrote Transaction#acquireConnection() methods to use async #3707 + +# 0.20.11 - 26 February, 2020 + +### Breaking changes: + +- Knex returns native JS promises instead of Bluebird ones. This means that you no longer use such methods as `map`, `spread` and `reduce` on QueryBuilder instance. + +### New features: + +- Oracle: Add OracleDB handling for buffer type in fetchAsString #3685 + +### Bug fixes: + +- Fix race condition in non-container transactions #3671 + +### Typings: + +- Mark knex arguments of composite/collection types to be readonly #3680 + +### Test / internal changes: + +- Remove dependency on Bluebird methods from sources #3683 +- Cleanup and extract Transaction Workflow logic #3674 + +# 0.20.10 - 13 February, 2020 + +### Bug fixes: + +- Oracle: commit was a no-op causing race conditions #3668 +- CLI: Knex calls process.chdir() before opening Knexfile #3661 +- Fixed unresolved promise in cancelQuery() #3666 + +### Typings: + +- `fn.now` takes optionally a precision argument. #3662 +- PG: Include SSL in connection definition #3659 + +### Test / internal changes: + +- replace Bluebird.timeout #3634 + +# 0.20.9 - 08 February, 2020 + +### Bug fixes: + +- CLI: Improve Support for Liftoff's Preloaders - this should fix some cases like using TS for your migrations #3613 + +### Typings: + +- MSSQL: Add `enableArithAbort` to `MsSqlConnectionConfig` + +### Test / internal changes: + +- Refactor more tests to use cli-testlab #3640 +- Update QueryCompiler implementation to use classes #3647 + +# 0.20.8 - 14 January, 2020 + +### New features: + +- CLI: Support ES6 modules via flag --esm #3616 + +### Bug fixes: + +- CLI: Print help only when there are no arguments #3617 + +### Typings: + +- Fix incorrect type of QueryBuilder.first('\*') result #3621 + +# 0.20.7 - 07 January, 2020 + +### New features: + +- Throw better error when trying to modify schema while using unsupported dialect #3609 + +### Bug fixes: + +- Oracle: dispose connection on connection error #3611 +- Oracle: fix not releasing connection from pool on disconnect #3605 +- CLI: prevent warning with root command #3604 + +### Typings: + +- Add create/drop schema methods to SchemaBuilder #3579 + +# 0.20.6 - 29 December, 2019 + +### Bug fixes: + +- Enforce Unix (lf) line terminators #3598 + +# 0.20.5 - 29 December, 2019 + +### New features: + +- Return more information about empty updates #3597 + +### Bug fixes: + +- Fix colors in debug logs #3592 + +### Test / internal changes: + +- Use more efficient algorithm for generating internal ids #3595 #3596 +- Use Buffer.alloc() instead of deprecated constructor #3574 + +# 0.20.4 - 08 December, 2019 + +### Bug fixes: + +- Fix debug logger messing up queries with % #3566 +- Make logger methods mutually consistent #3567 + +### Typings: + +- Add missing methods to client type #3565 +- Fix queryContext function defintion #3562 +- Fix QueryBuilder.extend this type #3526 #3528 + +### Test / internal changes: + +- Remove bluebird.using #3552 + +# 0.20.3 - 27 November, 2019 + +### New features: + +- MSSQL, MySQL: Add connection string qs to connection params #3547 + +### Bug fixes: + +- Oracle: Fix issue retrieving BLOB from database #3545 +- PostgreSQL: Timeout for postgresql use cancel instead of terminate #3518 +- Make sure CLI works for namespaced knex packages #2539 + +### Typings: + +- Lift up dialect specific methods in the CreateTableBuilder #3532 +- Add client property to QueryBuilder type #3541 +- Support 'only' option #3551 + +# 0.20.2 - 14 November, 2019 + +### New features: + +- Add support for distinct on for postgres #3513 + +### Bug fixes: + +- Make sqlite3 hasColumn case insensitive #3435 + +### Typings: + +- Fix PoolConfig typing #3505 +- Expand SeedsConfig types #3531 +- Make the default type parameters of QueryBuilder less strict #3520 +- Fix regression in older version of node when Promise#finally was not available #3507 + +# 0.20.1 - 29 October, 2019 + +### New features: + +- Declare drivers as optional peerDependencies #3081 +- Dynamic connection configuration resolution #3497 + +### Bug fixes: + +- Wrap subQuery with parenthesis when it appears as table name #3496 +- Fix Oracle error codes #3498 + +### Typings: + +- Add interface for PG Connection object #3372 +- Gracefully handle global promise pollution #3502 + +# 0.20.0 - 25 October, 2019 + +### New features: + +- orderBy accepts QueryBuilder #3491 +- Add validation in `.offset()` #2908 +- disable_migrations_list_validation feature #3448 + +### Bug fixes: + +- Fix oracledb driver v4 support #3480 +- Fix some issues around seed and migration generation #3479 +- Fix bugs in replacement logic used when dropping columns in SQLite #3476 + +### Typings: + +- Add types to the Migrator interface #3459 +- Fix typings of index and dropIndex TableBuilder methods #3486 +- Fixes types for Seeder#run #3438 + +### Test / internal changes: + +- Execute CI on Node.js 13 +- Bluebird: remove usage of `return`, `reflect`, `fromCallback` methods #3483 +- Bluebird: remove Bluebird.bind #3477 +- Bluebird: use util.promisify instead of Bluebird.promisify #3470 +- Bluebird: remove Bluebird.each #3471 +- Bluebird: remove Bluebird.map and Bluebird.mapSeries #3474 +- Bluebird: replace Bluebird.map with Promise.all #3469 +- Update badges #3482 + +# 0.19.5 - 06 October, 2019 + +### New features: + +- CLI: Migrations up/down commands - filename parameter #3416 +- Oracle: Support stored procedures #3449 + +### Bug fixes: + +- MSSQL: Escape column ids correctly in all cases (reported by Snyk Security Research Team) #3382 +- SQLite: Fix handling of multiline SQL in SQLite3 schema #3411 +- Fix concurrent child transactions failing #2213 #3440 + +### Typings: + +- Add missing Migrator.list typing #3460 +- Fix Typescript type inference for to better support wildcard (\*) calls #3444 +- Make options argument optional in timeout #3442 + +### Test / internal changes: + +- Enable linting in CI #3450 + +# 0.19.4 - 09 September, 2019 + +### New features: + +- Add undefined columns to undefined binding(s) error #3425 + +### Typings: + +- Add `specific` to SeederConfig type #3429 +- Fix some issues with QueryBuilder types #3427 + +# 0.19.3 - 25 August, 2019 + +### Bug fixes: + +- Fix migrations for native enums to use table schema #3307 + +### New features: + +- Add ability to manually define schema for native enums #3307 +- Add SSL/TLS support for Postgres connection string #3410 +- CLI: new command that lists all migrations with status #3390 + +### Typings: + +- Include schemaName in EnumOptions #3415 +- Allow `ColumnBuilder.defaultTo()` to be `null` #3407 + +### Changes: + +- migrate: Refactor \_lockMigrations to avoid forUpdate - makes migrations compatible with CockroachDB #3395 + +# 0.19.2 - 17 August, 2019 + +### Changes: + +- Make transaction rejection consistent across dialects #3399 +- More consistent handling of nested transactions #3393 + +### New features: + +- Fallback to JSON when using JSONB in MySQL #3394 + +# 0.19.1 - 23 July, 2019 + +### New features: + +- Allow to extend knex query builder #3334 +- Add .isCompleted() to transaction #3368 +- Minor enhancements around aliasing of aggregates #3354 + +### Typings: + +- Update configuration typings to allow for oracle db connectionstring #3361 +- Update Knex.raw type to be any by default because the actual type is dialect specific #3349 + +# 0.19.0 - 11 July, 2019 + +### Changes: + +- Pooling: tarn.js connection pool was updated to version 2.0.0. This fixes issue with destroying connections and introduces support for connection pool event handlers. Please see tarn.js documentation for more details #3345 +- Pooling: Passing unsupported pooling configuration options now throws an error +- Pooling: `beforeDestroy` configuration option was removed + +# 0.18.4 - 10 July, 2019 + +### New features: + +- Seeds: Option to run specific seed file #3335 +- Implement "skipLocked()" and "noWait()" #2961 + +### Bug fixes: + +- CLI: Respect the knexfile stub option while generating a migration #3337 +- Fix mssql import not being ignored, breaking webpack builds #3336 + +# 0.18.3 - 04 July, 2019 + +### New features: + +- CLI: add --stub option to migration:make #3316 + +### Bug fixes: + +- Fix return duplicate transaction promise for standalone transactions #3328 + +# 0.18.2 - 03 July, 2019 + +### Bug fixes: + +- Fix remove duplicate transaction rejection #3324 +- Fix issues around specifying default values for columns #3318 +- CLI: Fix empty --version output #3312 + +# 0.18.1 - 30 June, 2019 + +### Bug fixes: + +- Do not reject duplicate promise on transaction rollback #3319 + +# 0.18.0 - 26 June, 2019 + +### Bug fixes: + +- Do not reject promise on transaction rollback (by default only for new, non-callback, style of transactions for now to avoid breaking old code) #3235 + +### New features: + +- Added `doNotRejectOnRollback` options for starting transactions, to prevent rejecting promises on rollback for callback-style transactions. +- Use extension from knexfile for generating migrations unless overriden #3282 +- Use migrations.extension from config when generating migration #3242 +- Expose executionPromise for transactors #3297 + +### Bug fixes: + +- Oracle: Updated handling of connection errors for disposal #2608 +- Fix extension resolution from env configs #3294 + +### Test / internal changes: + +- Drop support for Node.js 6 #3227 +- Remove Babel #3227 +- Remove Bluebird #3290 #3287 #3285 #3267 #3266 #3263 +- Fix comments that were modified by find & replace #3308 + +### Typings: + +- Add workarounds for degraded inference when strictNullChecks is set to false #3275 +- Add stub type definition for Migrator config #3279 +- Add stub to seeds type #3296 +- Fix MSSQL config typings #3269 +- Add pgsql specific table builder method typings #3146 + +# 0.17.5 - 8 June, 2019 + +### Typings: + +- Include result.d.ts in published package #3271 + +# 0.17.4 - 8 June, 2019 + +### Typings: + +- Fix some cases of left-to-right inference causing type mismatch #3265 +- Improve count typings #3249 + +### Bug fixes: + +- Fix error message bubbling up on seed error #3248 + +# 0.17.3 - 2 June, 2019 + +### Typings: + +- Improve typings for aggregations #3245 +- Add decimalNumbers to MySqlConnectionConfig interface #3244 + +# 0.17.2 - 1 June, 2019 + +### Typings + +- Improve count typings #3239 + +### Bug fixes: + +- "colorette" dependency breaks browserify builds #3238 + +# 0.17.1 - 31 May, 2019 + +### New features: + +- Add migrate:down functionality #3228 + +### Typings: + +- Update type of aggregation results to not be arrays when first has been invoked before #3237 +- Include undefined in type of single row results #3231 +- Fix incorrect type definitions for single row queries #3230 + +# 0.17.0 - 28 May, 2019 + +### New features: + +- Add support for returning started transaction without immediately executing it #3099 +- Add support for passing transaction around with only starting it when needed #3099 +- Add clearHaving function #3141 +- Add --all flag for rollback in CLI #3187 +- Add error detail log to knex CLI #3149 +- Support multi-column whereIn in sqlite through values clause #3220 +- Allow users to specify the migrations "tableName" parameter via the CLI #3214 +- Unify object options handling for datetime/timestamp across dialects #3181 +- Add "up" command for migrations #3205 + +### Typings: + +- Add default values for generic types (fixes backwards compatibility broken by 0.16.6) #3189 +- Make function types generic in type definitions #3168 +- Add missing types to MigratorConfig #3174 +- Add types for havingBetween, orHavingBetween, havingNotBetween and orHavingNotBetween #3144 +- Update Knex.Config types to include log #3221 +- Fix some more cases of missing typings #3223 +- Support type safe refs #3215 +- Expose some utility types #3211 +- Fix issues with typings of joins and some conflicts with Bluebird typings #3209 + +### Bug fixes: + +- Fix order of migration rollback #3172 + +### Test / internal changes: + +- Execute CI tests on Node.js 12 #3171 +- Docker-based test dbs #3157 +- Use cli-testlab for testing CLI #3191 + +# 0.16.5 - 11 Apr, 2019 + +- Bundle polyfills with knex for 0.16.x line again #3139 + +# 0.16.4 - 11 Apr, 2019 + +### New features: + +- Boolean param for rollback() to rollback all migrations #2968 +- seed:run print the file name of the failing seed #2972 #2973 +- verbose option to CLI commands #2887 +- add intersect() #3023 +- Improved format for TS stubs #3080 +- MySQL: Support nullable timestamps #3100 +- MySQL: Warn `.returning()` does not have any effect #3039 + +### Bug fixes: + +- Respect "loadExtensions" configuration #2969 +- Fix event listener duplication when using Migrator #2982 +- Fix fs-migrations breaking docs #3022 +- Fix sqlite3 drop/renameColumn() breaks with postProcessResponse #3040 +- Fix transaction support for migrations #3084 +- Fix queryContext not being passed to raw queries #3111 +- Typings: Allow to pass query builders, identifiers and raw in various places as parameters #2960 +- Typings: toNative() definition #2996 +- Typings: asCallback() definition #2963 +- Typings: queryContext() type definition Knex.Raw #3002 +- Typings: Add "constraintName" arg to primary() definition #3006 +- Typings: Add missing schemaName in MigratorConfig #3016 +- Typings: Add missing supported parameter types and toSQL method #2960 +- Typings: Update enum arguments to reflect latest signature #3043 +- Typings: Add size parameter to integer method #3074 +- Typings: Add 'string' as accepted Knex constructor type definition #3105 +- Typings: Add boolean as a column name in join #3121 +- Typings: Add missing clearOrder & clearCounters types #3109 +- Dependencies: Fix security warning #3082 +- Do not use unsupported column width/length arguments on data types int and tinyint in MSSQL #2738 + +### Changes: + +- Make unionAll()'s call signature match union() #3055 + +### Test / internal changes: + +- Swap chalk→colorette / minimist→getopts #2718 +- Always use well documented pg client query() config argument #3004 +- Do not bundle polyfills with knex #3024 + +# 0.16.3 - 19 Dec, 2018 + +### Bug fixes: + +- @babel/polyfill loaded multiple times #2955 +- Resolve migrations and seeds relatively to knexfile directory when specified (the way it used to be before 0.16.1) #2952 + +# 0.16.2 - 10 Dec, 2018 + +### Bug fixes: + +- Add TypeScript types to the "files" entry so they are properly included in the release #2943 + +# 0.16.1 - 28 Nov, 2018 + +### Breaking Changes: + +- Use datetime2 for MSSQL datetime + timestamp types. This change is incompatible with MSSQL older than 2008 #2757 +- Knex.VERSION() method was removed, run "require('knex/package').version" instead #2776 +- Knex transpilation now targets Node.js 6, meaning it will no longer run on older Node.js versions #2813 +- Add json type support for SQLite 3.9+ (tested to work with Node package 'sqlite3' 4.0.2+) #2814 + +### New features: + +- Support passing explicit connection to query builder (#2817) +- Introduced abstraction for getting migrations to make migration bundling easier #2775 +- Allow timestamp with timezone on mssql databases #2724 +- Allow specifying multiple migration directories #2735 +- Allow cloning query builder with .userParams({}) assigned to it #2802 +- Allow chaining of increment, decrement, and update #2740 +- Allow table names with `forUpdate`/`forShare` #2834 +- Added `whereColumn` and the associated `not` / `and` / `or` methods for using columns on the right side of a where clause #2837 +- Added `whereRecursive` method to make self-referential CTEs possible #2889 +- Added support for named unique, primary and foreign keys to SQLite3 #2840 +- Added support for generating new migration and seed files without knexfile #2884 #2905 #2935 +- Added support for multiple columns in `.orderBy()` #2881 +- Added option of `existingType` to `.enum()` method to support repeated use of enums #2719 +- Added option to pass `indexType` for MySQL dialect #2890 +- Added `onVal` and the associated `not` / `and` / `or` methods for using values in `on` clauses within joins #2746 +- Kill queries after timeout for PostgreSQL #2636 +- Manage TypeScript types internally #2845 +- Support 5.0.0+ versions of mssql driver #2861 +- Typescript migration stub #2816 +- Options object for passing timestamp parameters + regression tests #2919 + +### Bug fixes: + +- Implement fail-fast logic for dialect resolution #2776 +- Fixed identifier wrapping for `using()`. Use columnize instead of wrap in using() #2713 +- Fix issues with warnPromise when migration does not return a promise #2730 +- Compile with before update so that bindings are put in correct order #2733 +- Fix join using builder withSchema #2744 +- Throw instead of process.exit when client module missing #2843 +- Display correct filename of a migration that failed #2910 +- Fixed support of knexSnakeCaseWrappers in migrations #2914 +- SQlite3 renameColunm quote fix #2833 +- Adjust typing for forUpdate()/forShare() variant with table names #2858 +- Fix execution of Oracle tests on Node 11 #2920 +- Fix failures in oracle test bench and added it back to mandatory CI tests #2924 +- Knex client knexfile resolution fix #2923 +- Add queryContext to type declarations #2931 + +### Test / internal changes: + +- Add tests for multiple union arguments with callbacks and builders #2749 +- Update dependencies #2772 #2810 #2842 #2848 #2893 #2904 +- Separate migration generator #2786 +- Do not postprocess internal queries in Migrator #2914 #2934 +- Use Babel 7 #2813 +- Introduce LGTM.com badge #2755 +- Cleanup based on analysis by https://lgtm.com #2870 +- Add test for retrieving null dates #2865 +- Add link to wiki #2866 +- Add tests for specifying explicit pg version #2895 +- Execute tests on Node.js 11 #2873 +- Version upgrade guide #2894 + +# 0.16.0 - 27 Nov, 2018 + +### Changes: + +- THIS RELEASE WAS UNPUBLISHED FROM NPM BECAUSE IT HAD BROKEN MIGRATIONS USING `postprocessResponse` FEATURE (#2644) + +# 0.15.2 - 19 Jul, 2018 + +### Changes: + +- Rolled back changes introduced by #2542, in favor of opt-in behavior by adding a precision option in `date` / `timestamp` / `datetime` / `knex.fn.now` (#2715, #2721) + +# 0.15.1 - 12 Jul, 2018 + +### Bug fixes: + +- Fix warning erroneously displayed for mysql #2705 + +# 0.15.0 - 1 Jul, 2018 + +### Breaking Changes: + +- Stop executing tests on Node 4 and 5. #2451 (not supported anymore) +- `json` data type is no longer converted to `text` within a schema builder migration for MySQL databases (note that JSON data type is only supported for MySQL 5.7.8+) #2635 +- Removed WebSQL dialect #2461 +- Drop mariadb support #2681 +- Primary Key for Migration Lock Table #2569. This shouldn't affect to old loc tables, but if you like to have your locktable to have primary key, delete the old table and it will be recreated when migrations are ran next time. +- Ensure knex.destroy() returns a bluebird promise #2589 +- Increment floats #2614 +- Testing removal of 'skim' #2520, Now rows are not converted to plain js objects, returned row objects might have changed type with oracle, mssql, mysql and sqlite3 +- Drop support for strong-oracle #2487 +- Timeout errors doesn't silently ignore the passed errors anymore #2626 +- Removed WebSQL dialect #2647 +- Various fixes to mssql dialect to make it compatible with other dialects #2653, Unique constraint now allow multiple null values, float type is now float instead of decimal, rolling back transaction with undefined rejects with Error, select for update and select for share actually locks selected row, so basically old schema migrations will work a lot different and produce different schema like before. Also now MSSQL is included in CI tests. + +### Bug fixes: + +- Fixes onIn with empty values array #2513 +- fix wrapIdentifier not being called in postgres alter column #2612 +- fixes wrapIdentifier to work with postgres `returning` statement 2630 #2642 +- Fix mssql driver crashing in certain cases when conneciton is closed unexpectedly #2637 +- Removed semicolon from rollback stmt for oracle #2564 +- Make the stream catch errors in the query #2638 + +### New Features: + +- Create timestamp columns with microsecond precision on MySQL 5.6 and newer #2542 +- Allow storing stacktrace, where builder is initialized to be able trace back where certain query was created #2500 #2505 +- Added 'ref' function #2509, no need for knex.raw('??', ['id']) anymore, one can do knex.ref('id') +- Support postgresql connection uri protocol #2609 +- Add support for native enums on Postgres #2632 +- Allow overwriting log functions #2625 + +### Test / internal changes: + +- chore: cache node_modules #2595 +- Remove babel-plugin-lodash #2634 +- Remove readable-stream and safe-buffer #2640 +- chore: add Node.js 10 #2594 +- add homepage field to package.json #2650 + +# 0.14.6 - 12 Apr, 2018 + +### Bug fixes: + +- Restored functionality of query event #2566 (#2549) + +# 0.14.5 - 8 Apr, 2018 + +### Bug fixes: + +- Fix wrapping returning column on oracledb #2554 + +### New Features: + +- Support passing DB schema name for migrations #2499 #2559 +- add clearOrder method #2360 #2553 +- Added knexTxId to query events and debug calls #2476 +- Support multi-column `whereIn` with query #1390 +- Added error if chaining update/insert/etc with first() #2506 +- Checks for an empty, undefined or null object on transacting #2494 +- countDistinct with multiple columns #2449 + +### Test / internal changes: + +- Added npm run test:oracledb command that runs oracledb tests in docker #2491 +- Runnin mssql tests in docker #2496 +- Update dependencies #2561 + +# 0.14.4 - 19 Feb, 2018 + +### Bug fixes: + +- containsUndefined only validate plain objects. Fixes #1898 (#2468) +- Add warning when using .returning() in sqlite3. Fixes #1660 (#2471) +- Throw an error if .update() results in an empty sql (#2472) +- Removed unnecessary createTableIfNotExist and replaced with createTable (#2473) + +### New Features: + +- Allow calling lock procedures (such as forUpdate) outside of transaction. Fixes #2403. (#2475) +- Added test and documentation for Event 'start' (#2488) + +### Test / internal changes: + +- Added stress test, which uses TCP proxy to simulate flaky connection #2460 +- Removed old docker tests, new stress test setup (#2474) +- Removed unused property \_\_cid on the base client (#2481) +- Changed rm to rimraf in 'npm run dev' (#2483) +- Changed babel preset and use latest node as target when running dev (#2484) + +# 0.14.3 - 8 Feb, 2018 + +### Bug fixes: + +- Use tarn as pool instead of generic-pool which has been given various problems #2450 +- Fixed mysql issue where add columns failed if using both after and collate #2432 +- CLI sets exit-code 1 if the command supplied was not parseable #2358 +- Set toNative() to be not enumerable #2388 +- Use wrapIdentifier in columnInfo. fixes #2402 #2405 +- Fixed a bug when using .returning (OUTPUT) in an update query with joins in MSSQL #2399 +- Better error message when running migrations fail before even starting run migrations #2373 +- Read oracle's UV_THREADPOOL_SIZE env variable correctly #2372 +- Added decimal variable precision / scale support #2353 + +### New Features: + +- Added queryContext to schema and query builders #2314 +- Added redshift dialect #2233 +- Added warning when one uses .createTableIfNotExist and deprecated it from docs #2458 + +### Test / internal changes: + +- Update dependencies and fix ESLint warnings accordingly #2433 +- Disable oracledb tests from non LTS nodes #2407 +- Update dependencies #2422 + +# 0.14.2 - 24 Nov, 2017 + +### Bug fixes: + +- Fix sqlite3 truncate method to work again #2348 + +# 0.14.1 - 19 Nov, 2017 + +### Bug fixes: + +- Fix support for multiple schema names in in postgres `searchPath` #2340 +- Fix create new connection to pass errors to query instead of retry loop #2336 +- Fix recognition of connections closed by server #2341 + +# 0.14.0 - 6 Nov, 2017 + +### Breaking Changes: + +- Remove sorting of statements from update queries #2171 +- Updated allowed operator list with some missing operators and make all to lower case #2239 +- Use node-mssql 4.0.0 #2029 +- Support for enum columns to SQlite3 dialect #2055 +- Better identifier quoting in Sqlite3 #2087 +- Migration Errors - Display filename of of failed migration #2272 + +### Other Features: + +- Post processing hook for query result #2261 +- Build native SQL where binding parameters are dialect specific #2237 +- Configuration option to allow override identifier wrapping #2217 +- Implemented select syntax: select({ alias: 'column' }) #2227 +- Allows to filter seeds and migrations by extensions #2168 +- Reconnecting after database server disconnect/reconnect + tests #2017 +- Removed filering from allowed configuration settings of mysql2 #2040 +- Allow raw expressions in query builder aggregate methods #2257 +- Throw error on non-string table comment #2126 +- Support for mysql stream query options #2301 + +### Bug fixes: + +- Allow update queries and passing query builder to with statements #2298 +- Fix escape table name in SQLite columnInfo call #2281 +- Preventing containsUndefined from going to recursion loop #1711 +- Fix error caused by call to knex.migrate.currentVersion #2123 +- Upgraded generic-pool to 3.1.7 (did resolve some memory issues) #2208 +- Allow using NOT ILIKE operator #2195 +- Fix postgres searchPath to be case-sensitive #2172 +- Fix drop of multiple columns in sqlite3 #2107 +- Fix adding multiple columns in Oracle #2115 +- Use selected schema when dropping indices in Postgres. #2105 +- Fix hasTable for MySQL to not do partial matches #2097 +- Fix setting autoTransaction in batchInsert #2113 +- Fix connection error propagation when streaming #2199 +- Fix comments not being applied to increments columns #2243 +- Fix mssql wrong binding order of queries that combine a limit with select raw or update #2066 +- Fixed mysql alter table attributes order #2062 + +### Test / internal changes: + +- Update each out-of-date dependency according to david-dm.org #2297 +- Update v8flags to version 3.0.0 #2288 +- Update interpret version #2283 +- Fix debug output typo #2187 +- Docker CI tests #2164 +- Unit test for right/rightOuterJoin combination #2117 +- Unit test for fullOuterJoin #2118 +- Unit tests for table comment #2098 +- Test referencing non-existent column with sqlite3 #2104 +- Unit test for renaming column in postgresql #2099 +- Unit test for cross-join #2102 +- Fix incorrect parameter name #2068 + +# 0.13.0 - 29 Apr, 2017 + +### Breaking Changes: + +- Multiple concurrent migration runners blocks instead of throwing error when possible #1962 +- Fixed transaction promise mutation issue #1991 + +### Other Changes: + +- Allow passing version of connected db in configuration file #1993 +- Bugfixes on batchInsert and transactions for mysql/maria #1992 +- Add fetchAsString optional parameter to oracledb dialect #1998 +- fix: escapeObject parameter order for Postgres dialect. #2003 + +# 0.12.9 - 23 Mar, 2017 + +- Fixed unhandled exception in batchInsert when the rows to be inserted resulted in duplicate key violation #1880 + +# 0.12.8 - 15 Mar, 2017 + +- Added clearSelect and clearWhere to query builder #1912 +- Properly close Postgres query streams on error #1935 +- Transactions should never reject with undefined #1970 +- Clear acquireConnectionTimeout if an error occurs when acquiring a connection #1973 + +# 0.12.7 - 17 Feb, 2017 + +### Accidental Breaking Change: + +- Ensure that 'client' is provided in knex config object #1822 + +### Other Changes: + +- Support custom foreign key names #1311, #1726 +- Fixed named bindings to work with queries containing `:`-chars #1890 +- Exposed more promise functions #1896 +- Pass rollback errors to transaction promise in mssql #1885 +- ONLY keyword support for PostgreSQL (for table inheritance) #1874 +- Fixed Mssql update with join syntax #1777 +- Replace migrations and seed for react-native packager #1813 +- Support knexfile, migration and seeds in TypeScript #1769 +- Fix float to integer conversion of decimal fields in MSSQL #1781 +- External authentication capability when using oracledb driver #1716 +- Fixed MSSQL incorect query build when locks are used #1707 +- Allow to use `first` method as aliased select #1784 +- Alter column for nullability, type and default value #46, #1759 +- Add more having* methods / join clause on* methods #1674 +- Compatibility fixes and cleanups #1788, #1792, #1794, #1814, #1857, #1649 + +# 0.12.6 - 19 Oct, 2016 + +- Address warnings mentioned in #1388 (#1740) +- Remove postinstall script (#1746) + +# 0.12.5 - 12 Oct, 2016 + +- Fix broken 0.12.4 build (removed from npm) +- Fix #1733, #920, incorrect postgres array bindings + +# 0.12.3 - 9 Oct, 2016 + +- Fix #1703, #1694 - connections should be returned to pool if acquireConnectionTimeout is triggered +- Fix #1710 regression in postgres array escaping + +# 0.12.2 - 27 Sep, 2016 + +- Restore pool min: 1 for sqlite3, #1701 +- Fix for connection error after it's closed / released, #1691 +- Fix oracle prefetchRowCount setting, #1675 + +# 0.12.1 - 16 Sep, 2016 + +- Fix MSSQL sql execution error, #1669 +- Added DEBUG=knex:bindings for debugging query bindings, #1557 + +# 0.12.0 - 13 Sep, 2016 + +- Remove build / built files, #1616 +- Upgrade to Babel 6, #1617 +- Reference Bluebird module directly, remove deprecated .exec method, #1618 +- Remove documentation files from main repo +- Fix broken behavior on WebSQL build, #1638 +- Oracle id sequence now handles manual inserts, #906 +- Cleanup PG escaping, fix #1602, #1548 +- Added [`with`](#Builder-with) to builder for [common table expressions](https://www.postgresql.org/docs/9.4/static/queries-with.html), #1599 +- Fix #1619, pluck with explicit column names +- Switching back to [generic-pool](https://github.com/coopernurse/node-pool) for pooling resource management +- Removed index.html, please direct all PR's for docs against the files in [knex/documentation](https://github.com/knex/documentation) + +# 0.11.10 - 9 Aug, 2016 + +- Added CHANGELOG.md for a [new documentation](https://github.com/knex/documentation) builder coming soon, #1615 +- Minor documentation tweaks +- PG: Fix Uint8Array being considered undefined, #1601 +- MSSQL: Make columnInfo schema dynamic, #1585 + +# 0.11.9 - 21 Jul, 2016 + +- Reverted knex client breaking change (commit b74cd69e906), fixes #1587 + +# 0.11.8 - 21 Jul, 2016 + +- Oracledb dialect #990 +- Documentation fix #1532 +- Allow named bindings to be escaped. #1576 +- Several bugs with MS SQL schema creation and installing from gihub fix #1577 +- Fix incorrect escaping of backslashes in SqlString.escape #1545 + +# 0.11.7 - 19 Jun, 2016 + +- Add missing dependency. #1516 + +# 0.11.6 - 18 Jun, 2016 + +- Allow cancellation on timeout (MySQL) #1454 +- Better bigint support. (MSSQL) #1445 +- More consistent handling of `undefined` values in `QueryBuilder#where` and `Raw`. #1459 +- Fix Webpack build. #1447 +- Fix code that triggered Bluebird warnings. #1460, #1489 +- Fix `ping` function. (Oracle) #1486 +- Fix `columnInfo`. (MSSQL) #1464 +- Fix `ColumnCompiler#binary`. (MSSQL) #1464 +- Allow connection strings that do not contain a password. #1473 +- Fix race condition in seed stubs. #1493 +- Give each query a UUID. #1510 + +# 0.11.5 - 26 May, 2016 + +- Bugfix: Using `Raw` or `QueryBuilder` as a binding to `Raw` now works as intended + +# 0.11.4 - 22 May, 2016 + +- Bugfix: Inconsistency of `.primary()` and `.dropPrimary()` between dialects #1430 +- Feature: Allow using custom Client/Dialect (you can pass your own client in knex config) #1428 +- Docs: Add documentation for .dropTimestamps #1432 +- Bugfix: Fixed passing undefined fields for insert/update inside transaction #1423 +- Feature: `batchInsert` with existing transaction #1354 +- Build: eslint instead of jshint #1416 +- Bugfix: Pooled connections not releasing #1382 +- Bugfix: Support passing `knex.raw` to `.whereNot` #1402 +- Docs: Fixed list of dialects which supports `.returning` #1398 +- Bugfix: rename table does not fail anymore even with schema defined #1403 + +# 0.11.3 - 14 May, 2016 + +- Support nested joins. #1397 + +# 0.11.2 - 14 May, 2016 + +- Prevent crash on `knex seed:make`. #1389 +- Improvements to `batchInsert`. #1391 +- Improvements to inserting `DEFAULT` with `undefined` binding. #1396 +- Correct generated code for adding/dropping multiple columns. (MSSQL) #1401 + +# 0.11.1 - 6 May, 2016 + +- Fix error in CLI command `migrate:make`. #1386 + +# 0.11.0 - 5 May, 2016 + +### Breaking Changes: + +- `QueryBuilder#orWhere` joins multiple arguments with `AND`. #1164 + +### Other Changes: + +- Collate for columns. (MySQL) #1147 +- Add `QueryBuilder#timeout`, `Raw#timeout`. #1201 #1260 +- Exit with error code when appropriate. #1238 +- MSSQL connection accepts `host` as an alias for `server` in accordance with other dialects. #1239 +- Add `query-response` event. #1231 +- Correct behaviour of sibling nested transactions. #1226 +- Support `RETURNING` with `UPDATE`. (Oracle) #1253 +- Throwing callbacks from transactions automatically rolls them back. #1257 +- Fixes to named `Raw` bindings. #1251 +- `timestamps` accepts an argument to set `NOT NULL` and default to current timestamp. +- Add `TableBuilder#inherits` for PostgreSQL. #601 +- Wrap index names. #1289 +- Restore coffeescript knexfiles and configurations. #1292 +- Add `andWhereBetween` and `andWhereNotBetween` #1132 +- Fix `valueForUndefined` failure. #1269 +- `renameColumn` no longer drops default value or nullability. #1326 +- Correct MySQL2 error handling. #1315 +- Fix MSSQL `createTableIfNotExists`. #1362 +- Fix MSSQL URL parsing. #1342 +- Update Lodash to 4.6.0 #1242 +- Update Bluebird to 3.3.4 #1279 + +# 0.10.0 - 15 Feb, 2016 + +### Breaking Changes: + +- `insert` and `update` now ignore `undefined` values. Back compatibility is provided through the option `useNullAsDefault`. #1174, #1043 + +### Other Changes: + +- Add [`countDistinct`](#Builder-countDistinct), [`avgDistinct`](#Builder-avgDistinct) and [`sumDistinct`](#Builder-sumDistinct). #1046 +- Add [`schema.jsonb`](#Schema-jsonb). Deprecated `schema.json(column, true)`. #991 +- Support binding identifiers with `??`. #1103 +- Restore `query` event when triggered by transactions. #855 +- Correct question mark escaping in rendered queries. #519, #1058 +- Add per-dialect escaping, allowing quotes to be escaped correctly. #886, #1095 +- Add MSSQL support. #1090 +- Add migration locking. #1094 +- Allow column aliases to contain `.`. #1181 +- Add `batchInsert`. #1182 +- Support non-array arguments to [`knex.raw`](#Raw-Bindings). +- Global `query-error` event. #1163 +- Add `batchInsert`. #1182 +- Better support for Mysql2 dialect options. #980 +- Support for `acquireConnectionTimeout` default 60 seconds preventing #1040 from happening. #1177 +- Fixed constraint name escaping when dropping a constraint. #1177 +- Show also `.raw` queries in debug output. #1169 +- Support for `cli` to use basic configuration without specific environment set. #1101 + +# 0.9.0 - Nov 2, 2015 + +- Fix error when merging `knex.raw` instances without arguments. #853 +- Fix error that caused the connection to time out while streaming. #849 +- Correctly parse SSL query parameter for PostgreSQL. #852 +- Pass `compress` option to MySQL2. #843 +- Schema: Use `timestamp with timezone` by default for `time`, `datetime` and `timestamp` for Oracle. #876 +- Add [`QueryBuilder#modify`](#Builder-modify) #881 +- Add LiveScript and Early Gray support for seeds and migrations. +- Add [`QueryBuilder#withSchema`](#Builder-withSchema) #518 +- Allow escaping of `?` in `knex.raw` queries. #946 +- Allow `0` in join clause. #953 +- Add migration config to allow disabling/enabling transactions per migration. #834 + +# 0.8.6 - May 20, 2015 + +- Fix for several transaction / migration issues, #832, #833, #834, #835 + +# 0.8.5 - May 14, 2015 + +- Pool should be initialized if no pool options are specified + +# 0.8.4 - May 13, 2015 + +- Pool should not be initialized if {max: 0} is sent in config options + +# 0.8.3 - May 2, 2015 + +- Alias postgresql -> postgres in connection config options + +# 0.8.2 - May 1, 2015 + +- Fix regression in using query string in connection config + +# 0.8.1 - May 1, 2015 + +- Warn rather than error when implicit commits wipe out savepoints in mysql / mariadb, #805. +- Fix for incorrect seed config reference, #804 + +# 0.8.0 - Apr 30, 2015 + +### New Features: + +- Fixes several major outstanding bugs with the connection pool, switching to [Pool2](https://github.com/myndzi/pool2) in place of generic-pool-redux +- strong-oracle module support +- Nested transactions automatically become savepoints, with `commit` & `rollback` releasing or rolling back the current savepoint. +- Database seed file support, #391 +- Improved support for sub-raw queries within raw statements +- Migrations are now wrapped in transactions where possible +- Subqueries supported in insert statements, #627 +- Support for nested having, #572 +- Support object syntax for joins, similar to "where" #743 + +### Major Changes: + +- Transactions are immediately invoked as A+ promises, #470 (this is a feature and should not actually break anything in practice) +- Heavy refactoring internal APIs (public APIs should not be affected) + +### "Other Changes: + +- Allow mysql2 to use non-default port, #588 +- Support creating & dropping extensions in PostgreSQL, #540 +- CLI support for knexfiles that do not provide environment keys, #527 +- Added sqlite3 dialect version of whereRaw/andWhereRaw (#477) + +# 0.7.5 - Mar 9, 2015 + +- Fix bug in validateMigrationList, (#697) + +# 0.7.4 - Feb 25, 2015 + +- Fix incorrect order of query parameters when using subqueries, #704 +- Properly handle limit 0, (#655) +- Apply promise args from then instead of [explicitly passing](https://github.com/petkaantonov/bluebird/issues/482). +- Respect union parameter as last argument (#660). +- Added sqlite3 dialect version of whereRaw/andWhereRaw (#477). +- Fix SQLite dropColumn doesn't work for last column (#544). +- Add POSIX operator support for Postgres (#562) +- Sample seed files now correctly (#391) + +# 0.7.3 - Oct 3, 2014 + +- Support for `join(table, rawOrBuilder)` syntax. +- Fix for regression in PostgreSQL connection (#516) + +# 0.7.2 - Oct 1, 2014 + +- Fix for regression in migrations + +# 0.7.1 - Oct 1, 2014 + +- Better disconnect handling & pool removal for MySQL clients, #452 + +# 0.7.0 - Oct 1, 2014 + +### New Features: + +- Oracle support, #419 +- Database seed file support, #391 +- Improved support for sub-raw queries within raw statements + +### Breaking Changes: + +- "collate nocase" no longer used by default in sqlite3 #396 + +### Other Changes: + +- Bumping Bluebird to ^2.x +- Transactions in websql are now a no-op (unsupported) #375 +- Improved test suite +- knex.fn namespace as function helper (knex.fn.now), #372 +- Better handling of disconnect errors +- Support for offset without limit, #446 +- Chainable first method for mysql schema, #406 +- Support for empty array in `whereIn` +- Create/drop schema for postgres, #511 +- Inserting multiple rows with default values, #468 +- Join columns are optional for cross-join, #508 +- Flag for creating jsonb columns in Postgresql, #500 + +# 0.6.22 - July 10, 2014 + +- Bug fix for properly binding postgresql streaming queries, (#363) + +# 0.6.21 - July 9, 2014 + +- Bug fix for raw queries not being transaction context aware, (#351). +- Properly forward stream errors in sqlite3 runner, (#359) + +# 0.6.20 - June 30, 2014 + +- Allow case insensitive operators in sql clauses, (#344) + +# 0.6.19 - June 27, 2014 + +- Add `groupByRaw` / `orderByRaw` methods, better support for raw statements in group / order (#282). +- Support more config options for node-mysql2 dialect (#341). +- CLI help text fix, (#342) + +# 0.6.18 - June 25, 2014 + +- Patch for the method, calling without a handler should return the stream, not a promise (#337) + +# 0.6.17 - June 23, 2014 + +- Adding missing map / reduce proxies to bluebird's implementation + +# 0.6.16 - June 18, 2014 + +- Increment / decrement returns the number of affectedRows (#330). +- Allow --cwd option flag to be passed to CLI tool (#326) + +# 0.6.15 - June 14, 2014 + +- Added the as method for aliasing subqueries + +# 0.6.14 - June 14, 2014 + +- whereExists / whereNotExists may now take a query builder instance as well as a callback + +# 0.6.13 - June 12, 2014 + +- Fix regression with onUpdate / onDelete in PostgreSQL, (#308). +- Add missing `Promise` require to knex.js, unit test for knex.destroy (#314) + +# 0.6.12 - June 10, 2014 + +- Fix for regression with boolean default types in PostgreSQL + +# 0.6.11 - June 10, 2014 + +- Fix for regression with queries containing multiple order by statements in sqlite3 + +# 0.6.10 - June 10, 2014 + +- Fix for big regression in memoization of column names from 0.5 -> 0.6 + +# 0.6.9 - June 9, 2014 + +- Fix for regression in specificType method + +# 0.6.8 - June 9, 2014 + +- Package.json fix for CLI + +# 0.6.7 - June 9, 2014 + +- Adds support for [node-mysql2](https://github.com/sidorares/node-mysql2) library. +- Bundles CLI with the knex install, various related migrate CLI fixes + +# 0.6.6 - June 9, 2014 + +- console.warn rather than throw when adding foreignKeys in SQLite3. +- Add support for dropColumn in SQLite3. +- Document `raw.wrap` + +# 0.6.5 - June 9, 2014 + +- Add missing \_ require to WebSQL builds + +# 0.6.4 - June 9, 2014 + +- Fix & document schema.raw method + +# 0.6.3 - June 6, 2014 + +- Schema methods on transaction object are now transaction aware (#301). +- Fix for resolved value from transactions, (#298). +- Undefined columns are not added to builder + +# 0.6.2 - June 4, 2014 + +- Fix regression in raw query output, (#297). +- Fix regression in "pluck" method (#296). +- Document [first](#Builder-first) method + +# 0.6.1 - June 4, 2014 + +- Reverting to using .npmignore, the "files" syntax forgot the knex.js file + +# 0.6.0 - June 4, 2014 + +### Major Library refactor: + +- Major internal overhaul to clean up the various dialect code. +- Improved unit test suite. +- Support for the [mariasql](https://github.com/mscdex/node-mariasql) driver. +- More consistent use of raw query bindings throughout the library. +- Queries are more composable, may be injected in various points throughout the builder. +- Added [streaming](#Interfaces-Streams) interface +- Deprecated 5 argument [join](#Builder-join) in favor of additional join methods. +- The wrapValue function to allow for array column operations in PostgreSQL (#287). +- An explicit connection can be passed for any query (#56). +- Drop column support for sqlite3 +- All schema actions are run sequentially on the same connection if chained. +- Schema actions can now be wrapped in a transaction +- `.references(tableName.columnName)` as shorthand for `.references(columnName).inTable(tableName)` +- `.join('table.column', 'otherTable.column')` as shorthand for .join('table.column', '=', 'otherTable.column') +- Streams are supported for selects, passing through to the streaming capabilities of node-mysql and node-postgres +- For More information, see this [pull-request](https://github.com/tgriesser/knex/pull/252) + +# 0.5.15 - June 4, 2014 + +- Dropped indexes feature now functions correctly, (#278) + +# 0.5.14 - May 6, 2014 + +- Remove the charset encoding if it's utf8 for mysql, as it's the default but also currently causes some issues in recent versions of node-mysql + +# 0.5.13 - April 2, 2014 + +- Fix regression in array bindings for postgresql (#228) + +# 0.5.12 - Mar 31, 2014 + +- Add more operators for where clauses, including && (#226) + +# 0.5.11 - Mar 25, 2014 + +- `.where(col, 'is', null)` or `.where(col, 'is not', null)` are not supported (#221). +- Case insensitive `where` operators now allowed (#212). +- Fix bug in increment/decrement truncating to an integer (#210). +- Disconnected connections are now properly handled & removed from the pool (#206). +- Internal tweaks to binding concatenations for performance (#207) + +# 0.5.10 - Mar 19, 2014 + +- Add the .exec method to the internal promise shim + +# 0.5.9 - Mar 18, 2014 + +- Remove error'ed connections from the connection pool (#206), added support for node-postgres-pure (pg.js) (#200) + +# 0.5.8 - Feb 27, 2014 + +- Fix for chaining on forUpdate / forShare, adding map & reduce from bluebird + +# 0.5.7 - Feb 18, 2014 + +- Fix for a null limit / offset breaking query chain (#182) + +# 0.5.6 - Feb 5, 2014 + +- Bump bluebird dependency to ~1.0.0, fixing regression in Bluebird 1.0.2 (#176) + +# 0.5.5 - Jan 28, 2014 + +- Fix for the exit code on the migrations cli (#151). +- The `init` method in `knex.migrate` now uses `this.config` if one isn't passed in (#156) + +# 0.5.4 - Jan 7, 2014 + +- Fix for using raw statements in defaultTo schema builder methods (#146) + +# 0.5.3 - Jan 2, 2014 + +- Fix for incorrectly formed sql when aggregates are used with columns (#144) + +# 0.5.2 - Dec 18, 2013 + +- Adding passthrough "catch", "finally" to bluebird implementations, use bluebird's "nodeify" internally for exec + +# 0.5.1 - Dec 12, 2013 + +- The [returning](#Builder-returning) in PostgreSQL may now accept \* or an array of columns to return. If either of these are passed, the response will be an array of objects rather than an array of values. Updates may also now use a `returning` value. (#132) +- Added `bigint` and `bigserial` type to PostgreSQL. (#111) +- Fix for the [specificType](#Schema-specificType) schema call (#118) +- Several fixes for migrations, including migration file path fixes, passing a Promise constructor to the migration `up` and `down` methods, allowing the "knex" module to be used globally, file ordering on migrations, and other small improvements. (#112-115, #125, #135) + +# 0.5.0 - Nov 25, 2013 + +- Initial pass at a [migration](#Migrations) api. +- Aggregate methods are no longer aliased as "aggregate", but may now be aliased and have more than one aggregate in a query (#108, #110). +- Adding bigint and bigserial to PostgreSQL (#111). +- Bugfix on increment/decrement values (#100). +- Bugfix with having method (#107). +- Switched from when.js to [bluebird](https://github.com/petkaantonov/bluebird) for promise implementation, with shim for backward compatibility. +- Switched from underscore to lodash, for semver reliability + +# 0.4.13 - Oct 31, 2013 + +- Fix for aggregate methods on toString and clone, (#98) + +# 0.4.12 - Oct 29, 2013 + +- Fix incorrect values passed to float in MySQL and decimal in PostgreSQL + +# 0.4.11 - Oct 15, 2013 + +- Fix potential sql injection vulnerability in orderBy, thanks to @sebgie + +# 0.4.10 - Oct 14, 2013 + +- Added [forUpdate](#Builder-forUpdate) and [forShare](#Builder-forShare) for select modes in transactions. (#84) +- Fix bug where current query chain type is not copied on [clone](#Builder-clone). (#90) +- Charset and collate are now added as methods on the schema builder. (#89) +- Added `into` as an alias of [from](#Builder-from), for builder syntax of: `insert(value).into(tableName)` +- Internal pool fixes. (#90) + +# 0.4.9 - Oct 7, 2013 + +- Fix for documentation of [hasColumn](#Schema-hasColumn), ensure that `hasColumn` works with MySQL (#87). +- More cleanup of error messages, showing the original error message concatenated with the sql and bindings + +# 0.4.8 - Oct 2, 2013 + +- Connections are no longer pushed back into the pool if they never existed to begin with (#85) + +# 0.4.7 - Sep 27, 2013 + +- The column is now a documented method on the builder api, and takes either an individual column or an array of columns to select + +# 0.4.6 - Sep 25, 2013 + +- Standardizing handling of errors for easier debugging, as noted in (#39) + +# 0.4.5 - Sep 24, 2013 + +- Fix for hasTable always returning true in MySQL (#82), fix where sql queries were duplicated with multiple calls on toSql with the schema builder + +# 0.4.4 - Sep 22, 2013 + +- Fix for debug method not properly debugging individual queries + +# 0.4.3 - Sep 18, 2013 + +- Fix for underscore not being defined in various grammar files + +# 0.4.2 - Sep 17, 2013 + +- Fix for an error being thrown when an initialized ClientBase instance was passed into Knex.initialize. pool.destroy now optionally accepts a callback to notify when it has completed draining and destroying all connections + +# 0.4.1 - Sep 16, 2013 + +- Cleanup from the 0.4.0 release, fix a potential exploit in "where" clauses pointed out by Andri Möll, fix for clients not being properly released from the pool #70, fix for where("foo", "<>", null) doing an "IS NULL" statement + +# 0.4.0 - Sep 13, 2013 + +### Breaking Changes: + +- Global state is no longer stored in the library, an instance is returned from `Knex.initialize`, so you will need to call this once and then reference this `knex` client elsewhere in your application. +- Lowercasing of `knex.raw`, `knex.transaction`, and `knex.schema`. +- Created columns are now nullable by default, unless `notNullable` is chained as an option. +- Keys created with `increments` are now assumed to be unsigned (MySQL) by default. +- The `destroyAllNow` is no longer called by the library on `process.exit` event. If you need to call it explicitly yourself, you may use `knex.client.destroyPool` + +# 0.2.6 - Aug 29, 2013 + +- Reject the transaction promise if the transaction "commit" fails, (#50) + +# 0.2.5 - Aug 25, 2013 + +- Fix error if a callback isn't specified for exec, (#49) + +# 0.2.4 - Aug 22, 2013 + +- Fix SQLite3 delete not returning affected row count, (#45) + +# 0.2.3 - Aug 22, 2013 + +- Fix insert with default values in PostgreSQL and SQLite3, (#44) + +# 0.2.2 - Aug 20, 2013 + +- Allowing Raw queries to be passed as the primary table names + +# 0.2.1 - Aug 13, 2013 + +- Fix for an array passed to insert being mutated + +# 0.2.0 - Aug 7, 2013 + +### Breaking changes: + +- [hasTable](#Schema-hasTable) now returns a boolean rather than a failed promise. +- Changed syntax for insert in postgresql, where the `id` is not assumed on inserts (#18). The second parameter of [insert](#Builder-insert) is now required to return an array of insert id's for the last insert. +- The [timestamp](#Schema-timestamp) method on the schema builder now uses a `dateTime` rather than a `timestamp` + +# 0.1.8 - July 7, 2013 + +- Somehow missing the != operator. Using _.find rather than _.where in getCommandsByName(#22) + +# 0.1.7 - June 12, 2013 + +- Ensures unhandled errors in the exec callback interface are re-thrown + +# 0.1.6 - June 9, 2013 + +- Renaming beforeCreate to afterCreate. Better handling of errors in the connection pooling + +# 0.1.5 - June 9, 2013 + +- Added the ability to specify beforeCreate and beforeDestroy hooks on the initialize's options.pool to perform any necessary database setup/teardown on connections before use (#14). where and having may now accept Knex.Raw instances, for consistency (#15). Added an orHaving method to the builder. The ability to specify bindings on Raw queries has been removed + +# 0.1.4 - May 22, 2013 + +- defaultTo now accepts "false" for boolean columns, allows for empty strings as default values + +# 0.1.3 - May 18, 2013 + +- Enabling table aliases (#11). Fix for issues with transactions not functioning (#12) + +# 0.1.2 - May 15, 2013 + +- Bug fixes for groupBy (#7). Mysql using collation, charset config settings in createTable. Added engine on schemaBuilder specifier (#6). Other doc fixes, tests + +# 0.1.1 - May 14, 2013 + +- Bug fixes for sub-queries, minor changes to initializing "main" instance, adding "pg" as a valid parameter for the client name in the connection settings + +# 0.1.0 - May 13, 2013 + +- Initial Knex release diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/CONTRIBUTING.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/CONTRIBUTING.md new file mode 100644 index 000000000..6540defd4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/CONTRIBUTING.md @@ -0,0 +1,194 @@ +## How to contribute to Knex.js + +- Make changes in the `/lib` directory. + +- Before sending a pull request for a feature or bug fix, be sure to have + [tests](https://github.com/knex/knex/tree/master/test). Every pull request that changes the queries should have + also **integration tests which are ran against real database** (in addition to unit tests which checks which kind of queries + are being created). + +- Use the same coding style as the rest of the + [codebase](https://github.com/knex/knex/blob/master/knex.js). + +- All pull requests should be made to the `master` branch. + +- Pull request description should have link to corresponding PR of documentation branch. + +- All pull requests that modify the public API should be updated in [types/index.d.ts](https://github.com/knex/knex/blob/master/types/index.d.ts) + +## Documentation + +Documentation is no longer maintained in knex master repository. All the documentation pull requests should be sent to https://github.com/knex/documentation + +Documentation pull requests should not be merged before knex version which has the new documented feature is released. + +## I would like to add support for new dialect to knex, is it possible? + +Currently there are already way too many dialects supported in `knex` and instead of adding new dialect to central codebase, all the dialects should be moved to separate npm packages out from `knex` core library with their respective maintainers and test suites. + +So if you like to write your own dialect, you can just inherit own dialect from knex base classes and use it by passing dialect to knex in knex configuration (https://runkit.com/embed/90b3cpyr4jh2): + +```js +// simple dialect overriding sqlite3 dialect to use sqlite3-offline driver +require('sqlite3-offline'); +const Knex = require('knex'); + +const Dialect = require(`knex/lib/dialects/sqlite3/index.js`); +Dialect.prototype._driver = () => require('sqlite3-offline'); + +const knex = Knex({ + client: Dialect, + connection: ':memory:', +}); + +console.log(knex.select(knex.raw(1)).toSQL()); + +await knex.schema.createTable('fooobar', (t) => { + t.bigincrements('id'); + t.string('data'); +}); +await knex('fooobar').insert({ data: 'nomnom' }); + +console.log('Gimme all the data:', await knex('fooobar')); +``` + +## What is minimal code to reproduce bug and why I have to provide that when I can just tell whats the problem is + +Writing minimal reproduction code for the problem is time-consuming and sometimes it is also really hard, for +example when the original code where the bug happens is written using express or mocha. So why is it necessary +for me to commit so much time to it when the problem is in `knex`? Contributors should be grateful that I reported +the bug I found. + +The point of runnable code to reproduce the problem is to easily verify that there really is a problem and that the one +who did the report did nothing wrong (surprisingly often problem is in the user code). So instead of just description +what to do the complete code encourages devs to actually test out that problem exists and start solving it and it +saves lots of time. + +tl;dr list: + +1. Actually in most of the cases developer already figures out what was the problem when writing the minimal test case + or if there was problem how stuff was initialized or how async code was written it is easy to point out the problem. + +2. It motivates developer to actually try out if the bug really exist by not having to figure out from incomplete example + environment in which and how bug actually manifests. + +3. There are currently very few people fixing knex issues and if one has to put easily 15-30 minutes time to issue just + to see that I cannot reproduce this issue it just wastes development hours that were available for improving knex. + +Test case should initialize needed tables, insert needed data and fail... + +```js +const knex = require('knex')({ + client: 'pg', + connection: 'postgres:///knex_test' +}); + +async function main() { + await knex.schema.createTable(...); + await knex('table').insert({foo: 'bar}'); + await knex.destroy(); +} + +main(); +``` + +Usually issues without reproduction code available are just closed and if the same issue is reported multiple +times maybe someone looks into it. + +One easy way to setup database for your reproduction is to use database from knex's docker-compose setup (npm run db:start) and by checking the connection settings from tests' `test/knexfile.js`. + +## Integration Tests + +### The Easy Way + +By default, Knex runs tests against sqlite3, postgresql, mysql, mysql2, mssql and oracledb drivers. All databases can be initialized and ran with docker. + +Docker databases can be started and initialized with: + +```bash +npm run db:start +``` + +and stopped with: + +```bash +npm run db:stop +``` + +In case you don't need all of the databases, you can use simplified dev Docker configuration that only runs PostgreSQL, by running `npm run db:start:postgres` and `npm run db:stop:postgres` accordingly. + +### Installing support for oracledb + +Oracle has started providing precompiled driver libs for all the platforms, which makes it viable to run oracle tests also locally against oracledb running in docker. + +Check message when running + +```bash +npm install oracledb +``` + +and download driver library binary packages and unzip it to ~/lib directory. + +### Specifying Databases + +You can optionally specify which dialects to test using the `DB` environment variable. Values should be space separated and can include: + +- mysql +- mysql2 +- postgres +- sqlite3 +- oracledb +- mssql + +```bash +$ DB='postgres mysql' npm test +``` + +### Custom Configuration + +If you'd like to override the database configuration (to use a different host, for example), you can override the path to the [default test configuration](https://github.com/knex/knex/blob/master/test/knexfile.js) using the `KNEX_TEST` environment variable. + +```bash +$ KNEX_TEST='./path/to/my/config.js' npm test +``` + +### Creating Postgres User + +If you are running tests against own local database one might need to setup test user and database for knex to connect. + +To create a new user, login to Postgres and use the following queries to add the user. This assumes you've already created the `knex_test` database. + +``` +CREATE ROLE postgres WITH LOGIN PASSWORD ''; +GRANT ALL PRIVILEGES ON DATABASE "knex_test" TO postgres; +``` + +Once this is done, check it works by attempting to login: + +``` +psql -h localhost -U postgres -d knex_test +``` + +## Typescript source files + +> TL;DR: Starting with release 2.0.0 Knex is adding support for Typescript source files. Thus to develop in this repo you will need to run `npm run build` each time you edit `.ts` files to generate the resulting `.js` files. This is automatically run whenever you run `npm install` or checkout a new Git branch so when developing in Javascript you don't have to worry about it. It is encouraged that new functionality and sources be written in Typescript but this is not required. + +Starting with release 2.0.0, Knex is support source additions in Typescript! This allows for better safety in the code added. However, pre-2.0.0 Knex was always written in pure Javascript and thus a "hybrid" approach is being used for 2.0.0 to allow for the new `.ts` files to exist along `.js` files that make up the majority of this repository. + +To develop in this repository use the `npm run build` and `npm run clean` commands to compile and delete the `.js` and related files from `.ts` files. If you wish to have the `tsc` compiled watch and recompile on changes then run `npm run build:ts -- --watch`. Note that for easy integration with Javascript the outputted files are done in a "side-by-side" manner meaning that `lib/foo/bar.ts` will result in `lib/foo/bar.js`. This is done automatically via the npm script command `"prepare"` whenever you run `npm install` and Git hook for `post-checkout` (added by Husky) which executes when you run commands like `git checkout` , thus making it easier to not have to worry about this if you're working in pure Javascript. + +The script file `./scripts/update_gitignore_for_tsc_output.js` file is called as part of the `npm run build` command which will update the `lib/.gitignore` file which is used to ensure generated `.js` and related files from `tsc` compilation are not checked into the git repo. + +## Want to be Collaborator? + +There is always room for more collaborators. Be active on resolving github issues / sending pull requests / reviewing code and we will ask you to join. + +### Etiquette (/ˈɛtᵻkɛt/ or /ˈɛtᵻkɪt/, French: [e.ti.kɛt]) + +Make pull requests for your changes, do not commit directly to master (release stuff like fixing changelog are ok though). + +All the pull requests must be peer reviewed by other collaborator, so don't merge your request before that. If there is no response ping others. + +If you are going to add new feature to knex (not just a bugfix) it should be discussed first with others to agree on details. + +Join Gitter chat if you feel to chat outside of github issues. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/LICENSE new file mode 100644 index 000000000..9c8ee26d6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2013-present Tim Griesser + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/README.md new file mode 100644 index 000000000..a019bdc9f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/README.md @@ -0,0 +1,149 @@ +# [knex.js](https://knex.github.io/documentation/) + +[![npm version](http://img.shields.io/npm/v/knex.svg)](https://npmjs.org/package/knex) +[![npm downloads](https://img.shields.io/npm/dm/knex.svg)](https://npmjs.org/package/knex) +![](https://github.com/knex/knex/workflows/CI/badge.svg) +[![Coverage Status](https://coveralls.io/repos/knex/knex/badge.svg?branch=master)](https://coveralls.io/r/knex/knex?branch=master) +[![Dependencies Status](https://img.shields.io/librariesio/github/knex/knex)](https://libraries.io/npm/knex) +[![Gitter chat](https://badges.gitter.im/tgriesser/knex.svg)](https://gitter.im/tgriesser/knex) + +> **A SQL query builder that is _flexible_, _portable_, and _fun_ to use!** + +A batteries-included, multi-dialect (PostgreSQL, MySQL, CockroachDB, MSSQL, SQLite3, Oracle (including Oracle Wallet Authentication)) query builder for +Node.js, featuring: + +- [transactions](https://knex.github.io/documentation/#Transactions) +- [connection pooling](https://knex.github.io/documentation/#Installation-pooling) +- [streaming queries](https://knex.github.io/documentation/#Interfaces-Streams) +- both a [promise](https://knex.github.io/documentation/#Interfaces-Promises) and [callback](https://knex.github.io/documentation/#Interfaces-Callbacks) API +- a [thorough test suite](https://github.com/knex/knex/actions) + +Node.js versions 12+ are supported. + +- Take a look at the [full documentation](https://knex.github.io/documentation) to get started! +- Browse the [list of plugins and tools](https://github.com/knex/knex/blob/master/ECOSYSTEM.md) built for knex +- Check out our [recipes wiki](https://github.com/knex/knex/wiki/Recipes) to search for solutions to some specific problems +- In case of upgrading from an older version, see [migration guide](https://github.com/knex/knex/blob/master/UPGRADING.md) + +You can report bugs and discuss features on the [GitHub issues page](https://github.com/knex/knex/issues) or send tweets to [@kibertoad](http://twitter.com/kibertoad). + +For support and questions, join our [Gitter channel](https://gitter.im/tgriesser/knex). + +For knex-based Object Relational Mapper, see: + +- https://github.com/Vincit/objection.js +- https://github.com/mikro-orm/mikro-orm +- https://bookshelfjs.org + +To see the SQL that Knex will generate for a given query, you can use [Knex Query Lab](https://michaelavila.com/knex-querylab/) + +## Examples + +We have several examples [on the website](http://knexjs.org). Here is the first one to get you started: + +```js +const knex = require('knex')({ + client: 'sqlite3', + connection: { + filename: './data.db', + }, +}); + +try { + // Create a table + await knex.schema + .createTable('users', (table) => { + table.increments('id'); + table.string('user_name'); + }) + // ...and another + .createTable('accounts', (table) => { + table.increments('id'); + table.string('account_name'); + table.integer('user_id').unsigned().references('users.id'); + }); + + // Then query the table... + const insertedRows = await knex('users').insert({ user_name: 'Tim' }); + + // ...and using the insert id, insert into the other table. + await knex('accounts').insert({ + account_name: 'knex', + user_id: insertedRows[0], + }); + + // Query both of the rows. + const selectedRows = await knex('users') + .join('accounts', 'users.id', 'accounts.user_id') + .select('users.user_name as user', 'accounts.account_name as account'); + + // map over the results + const enrichedRows = selectedRows.map((row) => ({ ...row, active: true })); + + // Finally, add a catch statement +} catch (e) { + console.error(e); +} +``` + +## TypeScript example + +```ts +import { Knex, knex } from 'knex'; + +interface User { + id: number; + age: number; + name: string; + active: boolean; + departmentId: number; +} + +const config: Knex.Config = { + client: 'sqlite3', + connection: { + filename: './data.db', + }, +}; + +const knexInstance = knex(config); + +try { + const users = await knex('users').select('id', 'age'); +} catch (err) { + // error handling +} +``` + +## Usage as ESM module + +If you are launching your Node application with `--experimental-modules`, `knex.mjs` should be picked up automatically and named ESM import should work out-of-the-box. +Otherwise, if you want to use named imports, you'll have to import knex like this: + +```js +import { knex } from 'knex/knex.mjs'; +``` + +You can also just do the default import: + +```js +import knex from 'knex'; +``` + +If you are not using TypeScript and would like the IntelliSense of your IDE to work correctly, it is recommended to set the type explicitly: + +```js +/** + * @type {Knex} + */ +const database = knex({ + client: 'mysql', + connection: { + host: '127.0.0.1', + user: 'your_database_user', + password: 'your_database_password', + database: 'myapp_test', + }, +}); +database.migrate.latest(); +``` diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/UPGRADING.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/UPGRADING.md new file mode 100644 index 000000000..9bd3ef8fd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/UPGRADING.md @@ -0,0 +1,245 @@ +## Upgrading to new knex.js versions + +### Upgrading to version 2.0.0+ + +- Since `sqlite3` is maintained again, we switched back to it. If you are using `@vscode/sqlite3` driver dependency, please replace it with `sqlite3` in your `package.json`; + +### Upgrading to version 1.0.0+ + +- Node.js older than 12 is no longer supported, make sure to update your environment; +- If you are using `sqlite3` driver dependency, please replace it with `@vscode/sqlite3` in your `package.json`; +- `RETURNING` operations now always return an object with column names; +- Migrator now returns list of migrations as objects. + +### Upgrading to version 0.95.0+ + +- TypeScript type exports changed significantly. While `import Knex from 'knex';` used to import the knex instantiation function, the namespace and the interface for the knex instantiation function/object, there is now a clear distinction between them: + +```typescript +import { knex } from 'knex'; // this is a function that you call to instantiate knex +import { Knex } from 'knex'; // this is a namespace, and a type of a knex object +import KnexTimeoutError = Knex.KnexTimeoutError; // this is a class from the Knex namespace + +const config: Knex.Config = {}; // this is a type from the Knex namespace +const knexInstance: Knex = knex(config); +``` + +If your code looked like this: + +```typescript +import knex from 'knex'; + +const config: knex.Config = {}; // this is a type from the Knex namespace +const knexInstance = knex(config); +``` + +Change it to + +```typescript +import { knex, Knex } from 'knex'; + +const config: Knex.Config = {}; // this is a type from the Knex namespace +const knexInstance = knex(config); +``` + +- If you were importing types such as `Config` or `QueryBuilder` directly, use `Knex` namespace instead. + +So change this: + +```ts +import { QueryBuilder } from 'knex'; + +const qb: QueryBuilder = knex('table').select('*'); +``` + +to this: + +```ts +import { Knex } from 'knex'; + +const qb: Knex.QueryBuilder = knex('table').select('*'); +``` + +- IDE autocomplete may stop working if you are using JavaScript (not TypeScript). There are reports for autocomplete still working correctly if knex is used this way: + +```js +const knex = require('knex').knex({ + //connection parameters +}); +``` + +It also works when using ESM imports: + +```js +import { knex } from 'knex'; + +const kn = knex({ + //connection parameters +}); +``` + +For usage as param it can be addressed like this: + +```js +/** + * @param {import("knex").Knex} db + */ +function up(db) { + // Your code +} +``` + +- Syntax for QueryBuilder augmentation changed. Previously it looked like this: + +```ts +declare module 'knex' { + interface QueryBuilder { + paginate( + params: IPaginateParams + ): KnexQB>; + } +} +``` + +This should be changed into this: + +```ts +declare module 'knex' { + namespace Knex { + interface QueryBuilder { + paginate( + params: IPaginateParams + ): KnexQB>; + } + } +} +``` + +- TypeScript version 4.1+ is needed when using knex types now. + +- MSSQL driver was completely reworked in order to address the multitude of connection pool, error handling and performance issues. Since the new implementation uses `tedious` library directly instead of `mssql`, please replace `mssql` with `tedious` in your dependencies if you are using a MSSQL database. + +- Transaction rollback does not trigger a promise rejection for transactions with specified handler. If you want to preserve previous behavior, pass `config` object with `doNotRejectOnRollback: false`: + +```js +await knex.transaction( + async (trx) => { + const ids = await trx('catalogues').insert({ name: 'Old Books' }, 'id'); + }, + { doNotRejectOnRollback: false } +); +``` + +- Connection url parsing changed from legacy [url.parse](https://nodejs.org/docs/latest-v10.x/api/url.html#url_legacy_url_api) to [WHATWG URL](https://nodejs.org/docs/latest-v10.x/api/url.html#url_the_whatwg_url_api). If you have symbols, unusual for a URL (not A-z, not digits, not dot, not dash) - check [Node.js docs](https://nodejs.org/docs/latest-v10.x/api/url.html#url_percent_encoding_in_urls) for details + +- Global static `Knex.raw` support dropped, use instance `knex.raw` instead. (`require('knex').raw()` won't work anymore) + +- v8 flags are no longer supported in cli. To pass these flags use [`NODE_OPTIONS` environment variable](https://nodejs.org/api/cli.html#cli_node_options_options). + For example `NODE_OPTIONS="--max-old-space-size=1536" npm run knex` + +- Clients are now classes instead of new-able functions. Please migrate your custom clients to classes. + +```js +const Client = require('knex'); +const { inherits } = require('util'); + +// old +function CustomClient(config) { + Client.call(this, config); + // construction logic +} +inherits(CustomClient, Client); +CustomClient.prototype.methodOverride = function () { + // logic +}; + +// new +class CustomClient extends Client { + // node 12+ + driverName = 'abcd'; + constructor(config) { + super(config); + this.driverName = 'abcd'; // bad way, will not work + // construction logic + } + methodOverride() { + // logic + } +} +// alternative to declare driverName +CustomClient.prototype.driverName = 'abcd'; +``` + +- There was a major internal restructuring and renaming effort. Most dialect-specific compilers/builder have dialect name as a prefix now. Also some files were moved. Make sure to make adjustments accordingly if you were referencing specific knex library files directly from your code. + +- "first" and "pluck" can no longer be both chained on the same operation. Previously only the last one chained was used, now this would throw an error. + +- Trying to execute an operation resulting in an empty query such as inserting an empty array, will now throw an error on all database drivers. + +### Upgrading to version 0.21.0+ + +- Node.js older than 10 is no longer supported, make sure to update your environment; + +### Upgrading to version 0.19.0+ + +- Passing unknown properties to connection pool configuration now throws errors (see https://github.com/Vincit/tarn.js/issues/19 for details); +- `beforeDestroy` pool configuration option was removed. You should use tarn.js event handlers if you still need similar functionality. + +### Upgrading to version 0.18.0+ + +- Node.js older than 8 is no longer supported, make sure to update your environment; +- Knex returns native promises instead of bluebird ones now. You will need to update your code not to rely on bluebird-specific functionality; +- Knex.Promise was removed, use native promises; +- Promise is no longer passed to migrations and seeds, use native one; +- If you are using TypeScript, make sure to include 'es6' in compilerOptions.lib, otherwise you may get errors for methods `.catch()` and `then()` not being recognized. + +### Upgrading to version 0.17.0+ + +- Generic support was implemented for TypeScript bindings, which may break TS builds in some edge cases. Please refer to https://knexjs.org/#typescript-support for more elaborate documentation. + +### Upgrading to version 0.16.0+ + +- MSSQL: DB versions older than 2008 are no longer supported, make sure to update your DB; +- PostgreSQL|MySQL: it is recommended to use options object for `table.datetime` and `table.timestamp` methods instead of argument options. See documentation for these methods for more details; +- Node 6: There are known issues with duplicate event listeners when using knex.js with Node.js 6 (resulting in MaxListenersExceededWarning under certain use-cases (such as reusing single knex instance to run migrations or seeds multiple times)). Please upgrade to Node.js 8+ as soon as possible (knex 0.17.0 will be dropping Node.js 6 support altogether); + +### Upgrading to version 0.15.0+ + +- Node.js older than 6 is no longer supported, make sure to update your environment; + +- MSSQL: Creating a unique index on the table targeted by stored procedures that were created with QUOTED_IDENTIFIER = OFF fails. + +You can use this query to identify all affected stored procedures: + +``` +SELECT name = OBJECT_NAME([object_id]), uses_quoted_identifier +FROM sys.sql_modules +WHERE uses_quoted_identifier = 0; +``` + +The only known solution is to recreate all stored procedures with QUOTED_IDENTIFIER = OFF + +- MariaDB: `mariadb` dialect is no longer supported; + +Instead, use "mysql" or "mysql2" dialects. + +### Upgrading to version 0.14.4+ + +- Including schema in tableName parameter in migrations no longer works, so this is invalid: + +```js +await knex.migrate.latest({ + directory: 'src/services/orders/database/migrations', + tableName: 'orders.orders_migrations', +}); +``` + +Instead, starting from 0.14.5 you should use new parameter schemaName: + +```js +await knex.migrate.latest({ + directory: 'src/services/orders/database/migrations', + tableName: 'orders_migrations', + schemaName: 'orders', +}); +``` diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/cli.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/cli.js new file mode 100644 index 000000000..70fe701cd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/cli.js @@ -0,0 +1,475 @@ +#!/usr/bin/env node +const rechoir = require('rechoir'); +const merge = require('lodash/merge'); +const interpret = require('interpret'); +const resolveFrom = require('resolve-from'); +const path = require('path'); +const tildify = require('tildify'); +const commander = require('commander'); +const color = require('colorette'); +const argv = require('getopts')(process.argv.slice(2)); +const cliPkg = require('../package'); +const { + parseConfigObj, + mkConfigObj, + resolveEnvironmentConfig, + exit, + success, + checkLocalModule, + checkConfigurationOptions, + getMigrationExtension, + getSeedExtension, + getStubPath, + findUpModulePath, + findUpConfig, +} = require('./utils/cli-config-utils'); +const { + existsSync, + readFile, + writeFile, +} = require('../lib/migrations/util/fs'); + +const { listMigrations } = require('./utils/migrationsLister'); + +async function openKnexfile(configPath) { + const importFile = require('../lib/migrations/util/import-file'); // require me late! + let config = await importFile(configPath); + if (config && config.default) { + config = config.default; + } + if (typeof config === 'function') { + config = await config(); + } + return config; +} + +async function initKnex(env, opts, useDefaultClientIfNotSpecified) { + checkLocalModule(env); + if (process.cwd() !== env.cwd) { + process.chdir(env.cwd); + console.log( + 'Working directory changed to', + color.magenta(tildify(env.cwd)) + ); + } + + if (!useDefaultClientIfNotSpecified) { + checkConfigurationOptions(env, opts); + } + + env.configuration = env.configPath + ? await openKnexfile(env.configPath) + : mkConfigObj(opts); + + const resolvedConfig = resolveEnvironmentConfig( + opts, + env.configuration, + env.configPath + ); + + const optionsConfig = parseConfigObj(opts); + const config = merge(resolvedConfig, optionsConfig); + + // Migrations directory gets defaulted if it is undefined. + if (!env.configPath && !config.migrations.directory) { + config.migrations.directory = null; + } + + // Client gets defaulted if undefined and it's allowed + if (useDefaultClientIfNotSpecified && config.client === undefined) { + config.client = 'sqlite3'; + } + + const knex = require(env.modulePath); + return knex(config); +} + +function invoke() { + const filetypes = ['js', 'mjs', 'coffee', 'ts', 'eg', 'ls']; + + const cwd = argv.knexfile + ? path.dirname(path.resolve(argv.knexfile)) + : process.cwd(); + + // TODO add knexpath here eventually + const modulePath = + resolveFrom.silent(cwd, 'knex') || + findUpModulePath(cwd, 'knex') || + process.env.KNEX_PATH; + + const configPath = + argv.knexfile && existsSync(argv.knexfile) + ? path.resolve(argv.knexfile) + : findUpConfig(cwd, 'knexfile', filetypes); + + if (configPath) { + const autoloads = rechoir.prepare( + interpret.jsVariants, + configPath, + cwd, + true + ); + if (autoloads instanceof Error) { + // Only errors + autoloads.failures.forEach(function (failed) { + console.log( + color.red('Failed to load external module'), + color.magenta(failed.moduleName) + ); + }); + } else if (Array.isArray(autoloads)) { + const succeeded = autoloads[autoloads.length - 1]; + console.log( + 'Requiring external module', + color.magenta(succeeded.moduleName) + ); + } + } + + const env = { + cwd, + modulePath, + configPath, + configuration: null, + }; + + let modulePackage = {}; + try { + modulePackage = require(path.join( + path.dirname(env.modulePath), + 'package.json' + )); + } catch (e) { + /* empty */ + } + + const cliVersion = [ + color.blue('Knex CLI version:'), + color.green(cliPkg.version), + ].join(' '); + + const localVersion = [ + color.blue('Knex Local version:'), + color.green(modulePackage.version || 'None'), + ].join(' '); + + commander + .version(`${cliVersion}\n${localVersion}`) + .option('--debug', 'Run with debugging.') + .option('--knexfile [path]', 'Specify the knexfile path.') + .option('--knexpath [path]', 'Specify the path to knex instance.') + .option('--cwd [path]', 'Specify the working directory.') + .option('--client [name]', 'Set DB client.') + .option('--connection [address]', 'Set DB connection.') + .option('--migrations-directory [path]', 'Set migrations directory.') + .option('--migrations-table-name [path]', 'Set migrations table name.') + .option( + '--env [name]', + 'environment, default: process.env.NODE_ENV || development' + ) + .option('--esm', 'Enable ESM interop.') + .option('--specific [path]', 'Specify one seed file to execute.') + .option( + '--timestamp-filename-prefix', + 'Enable a timestamp prefix on name of generated seed files.' + ); + + commander + .command('init') + .description(' Create a fresh knexfile.') + .option( + `-x [${filetypes.join('|')}]`, + 'Specify the knexfile extension (default js)' + ) + .action(() => { + const type = (argv.x || 'js').toLowerCase(); + if (filetypes.indexOf(type) === -1) { + exit(`Invalid filetype specified: ${type}`); + } + if (env.configuration) { + exit(`Error: ${env.knexfile} already exists`); + } + checkLocalModule(env); + const stubPath = `./knexfile.${type}`; + readFile( + path.dirname(env.modulePath) + + '/lib/migrations/migrate/stub/knexfile-' + + type + + '.stub' + ) + .then((code) => { + return writeFile(stubPath, code); + }) + .then(() => { + success(color.green(`Created ${stubPath}`)); + }) + .catch(exit); + }); + + commander + .command('migrate:make ') + .description(' Create a named migration file.') + .option( + `-x [${filetypes.join('|')}]`, + 'Specify the stub extension (default js)' + ) + .option( + `--stub [|]`, + 'Specify the migration stub to use. If using the file must be located in config.migrations.directory' + ) + .action(async (name) => { + try { + const opts = commander.opts(); + const instance = await initKnex(env, opts, true); // Skip config check, we don't really care about client when creating migrations + const ext = getMigrationExtension(env, opts); + const configOverrides = { extension: ext }; + + const stub = getStubPath('migrations', env, opts); + if (stub) { + configOverrides.stub = stub; + } + + instance.migrate + .make(name, configOverrides) + .then((name) => { + success(color.green(`Created Migration: ${name}`)); + }) + .catch(exit); + } catch (err) { + exit(err); + } + }); + + commander + .command('migrate:latest') + .description(' Run all migrations that have not yet been run.') + .option('--verbose', 'verbose') + .action(async () => { + try { + const instance = await initKnex(env, commander.opts()); + const [batchNo, log] = await instance.migrate.latest(); + if (log.length === 0) { + success(color.cyan('Already up to date')); + } + success( + color.green(`Batch ${batchNo} run: ${log.length} migrations`) + + (argv.verbose ? `\n${color.cyan(log.join('\n'))}` : '') + ); + } catch (err) { + exit(err); + } + }); + + commander + .command('migrate:up []') + .description( + ' Run the next or the specified migration that has not yet been run.' + ) + .action((name) => { + initKnex(env, commander.opts()) + .then((instance) => instance.migrate.up({ name })) + .then(([batchNo, log]) => { + if (log.length === 0) { + success(color.cyan('Already up to date')); + } + + success( + color.green( + `Batch ${batchNo} ran the following migrations:\n${log.join( + '\n' + )}` + ) + ); + }) + .catch(exit); + }); + + commander + .command('migrate:rollback') + .description(' Rollback the last batch of migrations performed.') + .option('--all', 'rollback all completed migrations') + .option('--verbose', 'verbose') + .action((cmd) => { + const { all } = cmd; + + initKnex(env, commander.opts()) + .then((instance) => instance.migrate.rollback(null, all)) + .then(([batchNo, log]) => { + if (log.length === 0) { + success(color.cyan('Already at the base migration')); + } + success( + color.green( + `Batch ${batchNo} rolled back: ${log.length} migrations` + ) + (argv.verbose ? `\n${color.cyan(log.join('\n'))}` : '') + ); + }) + .catch(exit); + }); + + commander + .command('migrate:down []') + .description( + ' Undo the last or the specified migration that was already run.' + ) + .action((name) => { + initKnex(env, commander.opts()) + .then((instance) => instance.migrate.down({ name })) + .then(([batchNo, log]) => { + if (log.length === 0) { + success(color.cyan('Already at the base migration')); + } + success( + color.green( + `Batch ${batchNo} rolled back the following migrations:\n${log.join( + '\n' + )}` + ) + ); + }) + .catch(exit); + }); + + commander + .command('migrate:currentVersion') + .description(' View the current version for the migration.') + .action(() => { + initKnex(env, commander.opts()) + .then((instance) => instance.migrate.currentVersion()) + .then((version) => { + success(color.green('Current Version: ') + color.blue(version)); + }) + .catch(exit); + }); + + commander + .command('migrate:list') + .alias('migrate:status') + .description(' List all migrations files with status.') + .action(() => { + initKnex(env, commander.opts()) + .then((instance) => { + return instance.migrate.list(); + }) + .then(([completed, newMigrations]) => { + listMigrations(completed, newMigrations); + }) + .catch(exit); + }); + + commander + .command('migrate:unlock') + .description(' Forcibly unlocks the migrations lock table.') + .action(() => { + initKnex(env, commander.opts()) + .then((instance) => instance.migrate.forceFreeMigrationsLock()) + .then(() => { + success( + color.green(`Succesfully unlocked the migrations lock table`) + ); + }) + .catch(exit); + }); + + commander + .command('seed:make ') + .description(' Create a named seed file.') + .option( + `-x [${filetypes.join('|')}]`, + 'Specify the stub extension (default js)' + ) + .option( + `--stub [|]`, + 'Specify the seed stub to use. If using the file must be located in config.seeds.directory' + ) + .option( + '--timestamp-filename-prefix', + 'Enable a timestamp prefix on name of generated seed files.', + false + ) + .action(async (name) => { + try { + const opts = commander.opts(); + const instance = await initKnex(env, opts, true); // Skip config check, we don't really care about client when creating seeds + const ext = getSeedExtension(env, opts); + const configOverrides = { extension: ext }; + const stub = getStubPath('seeds', env, opts); + if (stub) { + configOverrides.stub = stub; + } + + if (opts.timestampFilenamePrefix) { + configOverrides.timestampFilenamePrefix = + opts.timestampFilenamePrefix; + } + + instance.seed + .make(name, configOverrides) + .then((name) => { + success(color.green(`Created seed file: ${name}`)); + }) + .catch(exit); + } catch (err) { + exit(err); + } + }); + + commander + .command('seed:run') + .description(' Run seed files.') + .option('--verbose', 'verbose') + .option('--specific', 'run specific seed file') + .action(() => { + initKnex(env, commander.opts()) + .then((instance) => instance.seed.run({ specific: argv.specific })) + .then(([log]) => { + if (log.length === 0) { + success(color.cyan('No seed files exist')); + } + success( + color.green(`Ran ${log.length} seed files`) + + (argv.verbose ? `\n${color.cyan(log.join('\n'))}` : '') + ); + }) + .catch(exit); + }); + + commander.parse(process.argv); +} + +// FYI: The handling for the `--cwd` and `--knexfile` arguments is a bit strange, +// but we decided to retain the behavior for backwards-compatibility. In +// particular: if `--knexfile` is a relative path, then it will be resolved +// relative to `--cwd` instead of the shell's CWD. +// +// So, the easiest way to replicate this behavior is to have the CLI change +// its CWD to `--cwd` immediately before initializing everything else. This +// ensures that path.resolve will then resolve the path to `--knexfile` correctly. +if (argv.cwd) { + process.chdir(argv.cwd); +} +// Initialize 'esm' before cli.launch +if (argv.esm) { + // enable esm interop via 'esm' module + // eslint-disable-next-line no-global-assign + require = require('esm')(module); + // https://github.com/standard-things/esm/issues/868 + const ext = require.extensions['.js']; + require.extensions['.js'] = (m, fileName) => { + try { + // default to the original extension + // this fails if target file parent is of type='module' + return ext(m, fileName); + } catch (err) { + if (err && err.code === 'ERR_REQUIRE_ESM') { + return m._compile( + require('fs').readFileSync(fileName, 'utf8'), + fileName + ); + } + throw err; + } + }; +} + +invoke(); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/utils/cli-config-utils.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/utils/cli-config-utils.js new file mode 100644 index 000000000..144013d5f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/utils/cli-config-utils.js @@ -0,0 +1,212 @@ +const { DEFAULT_EXT, DEFAULT_TABLE_NAME } = require('./constants'); +const { resolveClientNameWithAliases } = require('../../lib/util/helpers'); +const path = require('path'); +const escalade = require('escalade/sync'); +const tildify = require('tildify'); +const color = require('colorette'); +const argv = require('getopts')(process.argv.slice(2)); + +function parseConfigObj(opts) { + const config = { migrations: {} }; + + if (opts.client) { + config.client = opts.client; + } + + if (opts.connection) { + config.connection = opts.connection; + } + + if (opts.migrationsDirectory) { + config.migrations.directory = opts.migrationsDirectory; + } + + if (opts.migrationsTableName) { + config.migrations.tableName = opts.migrationsTableName; + } + + return config; +} + +function mkConfigObj(opts) { + const envName = opts.env || process.env.NODE_ENV || 'development'; + const resolvedClientName = resolveClientNameWithAliases(opts.client); + const useNullAsDefault = resolvedClientName === 'sqlite3'; + const parsedConfig = parseConfigObj(opts); + + return { + ext: DEFAULT_EXT, + [envName]: { + ...parsedConfig, + useNullAsDefault, + tableName: parsedConfig.tableName || DEFAULT_TABLE_NAME, + }, + }; +} + +function resolveEnvironmentConfig(opts, allConfigs, configFilePath) { + const environment = opts.env || process.env.NODE_ENV || 'development'; + const result = allConfigs[environment] || allConfigs; + + if (allConfigs[environment]) { + console.log('Using environment:', color.magenta(environment)); + } + + if (!result) { + console.log(color.red('Warning: unable to read knexfile config')); + process.exit(1); + } + + if (argv.debug !== undefined) { + result.debug = argv.debug; + } + + // It is safe to assume that unless explicitly specified, we would want + // migrations, seeds etc. to be generated with same extension + if (configFilePath) { + result.ext = result.ext || path.extname(configFilePath).replace('.', ''); + } + + return result; +} + +function exit(text) { + if (text instanceof Error) { + if (text.message) { + console.error(color.red(text.message)); + } + console.error( + color.red(`${text.detail ? `${text.detail}\n` : ''}${text.stack}`) + ); + } else { + console.error(color.red(text)); + } + process.exit(1); +} + +function success(text) { + console.log(text); + process.exit(0); +} + +function checkLocalModule(env) { + if (!env.modulePath) { + console.log( + color.red('No local knex install found in:'), + color.magenta(tildify(env.cwd)) + ); + exit('Try running: npm install knex'); + } +} + +function checkConfigurationOptions(env, opts) { + if (!env.configPath && !opts.client) { + throw new Error( + `No configuration file found and no commandline connection parameters passed` + ); + } +} + +function getMigrationExtension(env, opts) { + const config = resolveEnvironmentConfig( + opts, + env.configuration, + env.configPath + ); + + let ext = DEFAULT_EXT; + if (argv.x) { + ext = argv.x; + } else if (config.migrations && config.migrations.extension) { + ext = config.migrations.extension; + } else if (config.ext) { + ext = config.ext; + } + return ext.toLowerCase(); +} + +function getSeedExtension(env, opts) { + const config = resolveEnvironmentConfig( + opts, + env.configuration, + env.configPath + ); + + let ext = DEFAULT_EXT; + if (argv.x) { + ext = argv.x; + } else if (config.seeds && config.seeds.extension) { + ext = config.seeds.extension; + } else if (config.ext) { + ext = config.ext; + } + return ext.toLowerCase(); +} + +function getStubPath(configKey, env, opts) { + const config = resolveEnvironmentConfig(opts, env.configuration); + const stubDirectory = config[configKey] && config[configKey].directory; + + const { stub } = argv; + if (!stub) { + return null; + } else if (stub.includes('/')) { + // relative path to stub + return stub; + } + + // using stub must have config[configKey].directory defined + if (!stubDirectory) { + console.log(color.red('Failed to load stub'), color.magenta(stub)); + exit(`config.${configKey}.directory in knexfile must be defined`); + } + + return path.join(stubDirectory, stub); +} + +function findUpModulePath(cwd, packageName) { + const modulePackagePath = escalade(cwd, (dir, names) => { + if (names.includes('package.json')) { + return 'package.json'; + } + return false; + }); + try { + const modulePackage = require(modulePackagePath); + if (modulePackage.name === packageName) { + return path.join( + path.dirname(modulePackagePath), + modulePackage.main || 'index.js' + ); + } + } catch (e) { + /* empty */ + } +} + +function findUpConfig(cwd, name, extensions) { + return escalade(cwd, (dir, names) => { + for (const ext of extensions) { + const filename = `${name}.${ext}`; + if (names.includes(filename)) { + return filename; + } + } + return false; + }); +} + +module.exports = { + parseConfigObj, + mkConfigObj, + resolveEnvironmentConfig, + exit, + success, + checkLocalModule, + checkConfigurationOptions, + getSeedExtension, + getMigrationExtension, + getStubPath, + findUpModulePath, + findUpConfig, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/utils/constants.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/utils/constants.js new file mode 100644 index 000000000..bdfe48b8b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/utils/constants.js @@ -0,0 +1,7 @@ +const DEFAULT_EXT = 'js'; +const DEFAULT_TABLE_NAME = 'knex_migrations'; + +module.exports = { + DEFAULT_EXT, + DEFAULT_TABLE_NAME, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/utils/migrationsLister.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/utils/migrationsLister.js new file mode 100644 index 000000000..ebfdfe437 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/bin/utils/migrationsLister.js @@ -0,0 +1,37 @@ +const color = require('colorette'); + +const { success } = require('./cli-config-utils'); + +function listMigrations(completed, newMigrations) { + let message = ''; + + if (completed.length === 0) { + message += color.red('No Completed Migration files Found.\n'); + } else { + message = color.green( + `Found ${completed.length} Completed Migration file/files.\n` + ); + + for (let i = 0; i < completed.length; i++) { + const file = completed[i]; + message += color.cyan(`${file.name}\n`); + } + } + + if (newMigrations.length === 0) { + message += color.red('No Pending Migration files Found.\n'); + } else { + message += color.green( + `Found ${newMigrations.length} Pending Migration file/files.\n` + ); + + for (let i = 0; i < newMigrations.length; i++) { + const file = newMigrations[i]; + message += color.cyan(`${file.file}\n`); + } + } + + success(message); +} + +module.exports = { listMigrations }; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/knex.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/knex.js new file mode 100644 index 000000000..d56961edb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/knex.js @@ -0,0 +1,23 @@ +// Knex.js +// -------------- +// (c) 2013-present Tim Griesser +// Knex may be freely distributed under the MIT license. +// For details and documentation: +// http://knexjs.org + +const knex = require('./lib/index'); + +/** + * These export configurations enable JS and TS developers + * to consume knex in whatever way best suits their needs. + * Some examples of supported import syntax includes: + * - `const knex = require('knex')` + * - `const { knex } = require('knex')` + * - `import * as knex from 'knex'` + * - `import { knex } from 'knex'` + * - `import knex from 'knex'` + */ +knex.knex = knex; +knex.default = knex; + +module.exports = knex; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/knex.mjs b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/knex.mjs new file mode 100644 index 000000000..94f213bb6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/knex.mjs @@ -0,0 +1,11 @@ +// Knex.js +// -------------- +// (c) 2013-present Tim Griesser +// Knex may be freely distributed under the MIT license. +// For details and documentation: +// http://knexjs.org + +import knex from './lib/index.js'; + +export { knex }; +export default knex; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/builder-interface-augmenter.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/builder-interface-augmenter.js new file mode 100644 index 000000000..87bc1b858 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/builder-interface-augmenter.js @@ -0,0 +1,120 @@ +const clone = require('lodash/clone'); +const isEmpty = require('lodash/isEmpty'); +const { callbackify } = require('util'); +const finallyMixin = require('./util/finally-mixin'); +const { formatQuery } = require('./execution/internal/query-executioner'); + +function augmentWithBuilderInterface(Target) { + Target.prototype.toQuery = function (tz) { + let data = this.toSQL(this._method, tz); + if (!Array.isArray(data)) data = [data]; + if (!data.length) { + return ''; + } + + return data + .map((statement) => { + return formatQuery(statement.sql, statement.bindings, tz, this.client); + }) + .reduce((a, c) => a.concat(a.endsWith(';') ? '\n' : ';\n', c)); + }; + + // Create a new instance of the `Runner`, passing in the current object. + Target.prototype.then = function (/* onFulfilled, onRejected */) { + let result = this.client.runner(this).run(); + + if (this.client.config.asyncStackTraces) { + result = result.catch((err) => { + err.originalStack = err.stack; + const firstLine = err.stack.split('\n')[0]; + + // a hack to get a callstack into the client code despite this + // node.js bug https://github.com/nodejs/node/issues/11865 + // see lib/util/save-async-stack.js for more details + const { error, lines } = this._asyncStack; + const stackByLines = error.stack.split('\n'); + const asyncStack = stackByLines.slice(lines); + asyncStack.unshift(firstLine); + + // put the fake more helpful "async" stack on the thrown error + err.stack = asyncStack.join('\n'); + throw err; + }); + } + + return result.then.apply(result, arguments); + }; + + // Add additional "options" to the builder. Typically used for client specific + // items, like the `mysql` and `sqlite3` drivers. + Target.prototype.options = function (opts) { + this._options = this._options || []; + this._options.push(clone(opts) || {}); + return this; + }; + + // Sets an explicit "connection" we wish to use for this query. + Target.prototype.connection = function (connection) { + this._connection = connection; + this.client.processPassedConnection(connection); + return this; + }; + + // Set a debug flag for the current schema query stack. + Target.prototype.debug = function (enabled) { + this._debug = arguments.length ? enabled : true; + return this; + }; + + // Set the transaction object for this query. + Target.prototype.transacting = function (transaction) { + if (transaction && transaction.client) { + if (!transaction.client.transacting) { + transaction.client.logger.warn( + `Invalid transaction value: ${transaction.client}` + ); + } else { + this.client = transaction.client; + } + } + if (isEmpty(transaction)) { + this.client.logger.error( + 'Invalid value on transacting call, potential bug' + ); + throw Error( + 'Invalid transacting value (null, undefined or empty object)' + ); + } + return this; + }; + + // Initializes a stream. + Target.prototype.stream = function (options) { + return this.client.runner(this).stream(options); + }; + + // Initialize a stream & pipe automatically. + Target.prototype.pipe = function (writable, options) { + return this.client.runner(this).pipe(writable, options); + }; + + Target.prototype.asCallback = function (cb) { + const promise = this.then(); + callbackify(() => promise)(cb); + return promise; + }; + + Target.prototype.catch = function (onReject) { + return this.then().catch(onReject); + }; + + Object.defineProperty(Target.prototype, Symbol.toStringTag, { + get: () => 'object', + }); + + finallyMixin(Target.prototype); +} + +module.exports = { + augmentWithBuilderInterface, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/client.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/client.js new file mode 100644 index 000000000..00ee2893a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/client.js @@ -0,0 +1,495 @@ +const { Pool, TimeoutError } = require('tarn'); +const { EventEmitter } = require('events'); +const { promisify } = require('util'); +const { makeEscape } = require('./util/string'); +const cloneDeep = require('lodash/cloneDeep'); +const defaults = require('lodash/defaults'); +const uniqueId = require('lodash/uniqueId'); + +const Runner = require('./execution/runner'); +const Transaction = require('./execution/transaction'); +const { + executeQuery, + enrichQueryObject, +} = require('./execution/internal/query-executioner'); +const QueryBuilder = require('./query/querybuilder'); +const QueryCompiler = require('./query/querycompiler'); +const SchemaBuilder = require('./schema/builder'); +const SchemaCompiler = require('./schema/compiler'); +const TableBuilder = require('./schema/tablebuilder'); +const TableCompiler = require('./schema/tablecompiler'); +const ColumnBuilder = require('./schema/columnbuilder'); +const ColumnCompiler = require('./schema/columncompiler'); +const { KnexTimeoutError } = require('./util/timeout'); +const { outputQuery, unwrapRaw } = require('./formatter/wrappingFormatter'); +const { compileCallback } = require('./formatter/formatterUtils'); +const Raw = require('./raw'); +const Ref = require('./ref'); +const Formatter = require('./formatter'); +const Logger = require('./logger'); +const { POOL_CONFIG_OPTIONS } = require('./constants'); +const ViewBuilder = require('./schema/viewbuilder.js'); +const ViewCompiler = require('./schema/viewcompiler.js'); +const isPlainObject = require('lodash/isPlainObject'); +const { setHiddenProperty } = require('./util/security.js'); + +const debug = require('debug')('knex:client'); + +// The base client provides the general structure +// for a dialect specific client object. + +class Client extends EventEmitter { + constructor(config = {}) { + super(); + this.config = config; + this.logger = new Logger(config); + + if (this.config.connection && this.config.connection.password) { + setHiddenProperty(this.config.connection); + } + + //Client is a required field, so throw error if it's not supplied. + //If 'this.dialect' is set, then this is a 'super()' call, in which case + //'client' does not have to be set as it's already assigned on the client prototype. + + if (this.dialect && !this.config.client) { + this.logger.warn( + `Using 'this.dialect' to identify the client is deprecated and support for it will be removed in the future. Please use configuration option 'client' instead.` + ); + } + + const dbClient = this.config.client || this.dialect; + if (!dbClient) { + throw new Error( + `knex: Required configuration option 'client' is missing.` + ); + } + + if (config.version) { + this.version = config.version; + } + + if (config.connection && config.connection instanceof Function) { + this.connectionConfigProvider = config.connection; + this.connectionConfigExpirationChecker = () => true; // causes the provider to be called on first use + } else { + this.connectionSettings = cloneDeep(config.connection || {}); + if (config.connection && config.connection.password) { + setHiddenProperty(this.connectionSettings, config.connection); + } + this.connectionConfigExpirationChecker = null; + } + if (this.driverName && config.connection) { + this.initializeDriver(); + if (!config.pool || (config.pool && config.pool.max !== 0)) { + this.initializePool(config); + } + } + this.valueForUndefined = this.raw('DEFAULT'); + if (config.useNullAsDefault) { + this.valueForUndefined = null; + } + } + formatter(builder) { + return new Formatter(this, builder); + } + + queryBuilder() { + return new QueryBuilder(this); + } + + queryCompiler(builder, formatter) { + return new QueryCompiler(this, builder, formatter); + } + + schemaBuilder() { + return new SchemaBuilder(this); + } + + schemaCompiler(builder) { + return new SchemaCompiler(this, builder); + } + + tableBuilder(type, tableName, tableNameLike, fn) { + return new TableBuilder(this, type, tableName, tableNameLike, fn); + } + + viewBuilder(type, viewBuilder, fn) { + return new ViewBuilder(this, type, viewBuilder, fn); + } + + tableCompiler(tableBuilder) { + return new TableCompiler(this, tableBuilder); + } + + viewCompiler(viewCompiler) { + return new ViewCompiler(this, viewCompiler); + } + + columnBuilder(tableBuilder, type, args) { + return new ColumnBuilder(this, tableBuilder, type, args); + } + + columnCompiler(tableBuilder, columnBuilder) { + return new ColumnCompiler(this, tableBuilder, columnBuilder); + } + + runner(builder) { + return new Runner(this, builder); + } + + transaction(container, config, outerTx) { + return new Transaction(this, container, config, outerTx); + } + + raw() { + return new Raw(this).set(...arguments); + } + + ref() { + return new Ref(this, ...arguments); + } + query(connection, queryParam) { + const queryObject = enrichQueryObject(connection, queryParam, this); + return executeQuery(connection, queryObject, this); + } + + stream(connection, queryParam, stream, options) { + const queryObject = enrichQueryObject(connection, queryParam, this); + return this._stream(connection, queryObject, stream, options); + } + + prepBindings(bindings) { + return bindings; + } + + positionBindings(sql) { + return sql; + } + + postProcessResponse(resp, queryContext) { + if (this.config.postProcessResponse) { + return this.config.postProcessResponse(resp, queryContext); + } + return resp; + } + + wrapIdentifier(value, queryContext) { + return this.customWrapIdentifier( + value, + this.wrapIdentifierImpl, + queryContext + ); + } + + customWrapIdentifier(value, origImpl, queryContext) { + if (this.config.wrapIdentifier) { + return this.config.wrapIdentifier(value, origImpl, queryContext); + } + return origImpl(value); + } + + wrapIdentifierImpl(value) { + return value !== '*' ? `"${value.replace(/"/g, '""')}"` : '*'; + } + + initializeDriver() { + try { + this.driver = this._driver(); + } catch (e) { + const message = `Knex: run\n$ npm install ${this.driverName} --save`; + this.logger.error(`${message}\n${e.message}\n${e.stack}`); + throw new Error(`${message}\n${e.message}`); + } + } + + poolDefaults() { + return { min: 2, max: 10, propagateCreateError: true }; + } + + getPoolSettings(poolConfig) { + poolConfig = defaults({}, poolConfig, this.poolDefaults()); + + POOL_CONFIG_OPTIONS.forEach((option) => { + if (option in poolConfig) { + this.logger.warn( + [ + `Pool config option "${option}" is no longer supported.`, + `See https://github.com/Vincit/tarn.js for possible pool config options.`, + ].join(' ') + ); + } + }); + + const DEFAULT_ACQUIRE_TIMEOUT = 60000; + const timeouts = [ + this.config.acquireConnectionTimeout, + poolConfig.acquireTimeoutMillis, + ].filter((timeout) => timeout !== undefined); + + if (!timeouts.length) { + timeouts.push(DEFAULT_ACQUIRE_TIMEOUT); + } + + // acquire connection timeout can be set on config or config.pool + // choose the smallest, positive timeout setting and set on poolConfig + poolConfig.acquireTimeoutMillis = Math.min(...timeouts); + + const updatePoolConnectionSettingsFromProvider = async () => { + if (!this.connectionConfigProvider) { + return; // static configuration, nothing to update + } + if ( + !this.connectionConfigExpirationChecker || + !this.connectionConfigExpirationChecker() + ) { + return; // not expired, reuse existing connection + } + const providerResult = await this.connectionConfigProvider(); + if (providerResult.expirationChecker) { + this.connectionConfigExpirationChecker = + providerResult.expirationChecker; + delete providerResult.expirationChecker; // MySQL2 driver warns on receiving extra properties + } else { + this.connectionConfigExpirationChecker = null; + } + this.connectionSettings = providerResult; + }; + + return Object.assign(poolConfig, { + create: async () => { + await updatePoolConnectionSettingsFromProvider(); + const connection = await this.acquireRawConnection(); + connection.__knexUid = uniqueId('__knexUid'); + if (poolConfig.afterCreate) { + await promisify(poolConfig.afterCreate)(connection); + } + return connection; + }, + + destroy: (connection) => { + if (connection !== void 0) { + return this.destroyRawConnection(connection); + } + }, + + validate: (connection) => { + if (connection.__knex__disposed) { + this.logger.warn(`Connection Error: ${connection.__knex__disposed}`); + return false; + } + + return this.validateConnection(connection); + }, + }); + } + + initializePool(config = this.config) { + if (this.pool) { + this.logger.warn('The pool has already been initialized'); + return; + } + + const tarnPoolConfig = { + ...this.getPoolSettings(config.pool), + }; + // afterCreate is an internal knex param, tarn.js does not support it + if (tarnPoolConfig.afterCreate) { + delete tarnPoolConfig.afterCreate; + } + + this.pool = new Pool(tarnPoolConfig); + } + + validateConnection(connection) { + return true; + } + + // Acquire a connection from the pool. + async acquireConnection() { + if (!this.pool) { + throw new Error('Unable to acquire a connection'); + } + try { + const connection = await this.pool.acquire().promise; + debug('acquired connection from pool: %s', connection.__knexUid); + if (connection.config) { + if (connection.config.password) { + setHiddenProperty(connection.config); + } + if ( + connection.config.authentication && + connection.config.authentication.options && + connection.config.authentication.options.password + ) { + setHiddenProperty(connection.config.authentication.options); + } + } + return connection; + } catch (error) { + let convertedError = error; + if (error instanceof TimeoutError) { + convertedError = new KnexTimeoutError( + 'Knex: Timeout acquiring a connection. The pool is probably full. ' + + 'Are you missing a .transacting(trx) call?' + ); + } + throw convertedError; + } + } + + // Releases a connection back to the connection pool, + // returning a promise resolved when the connection is released. + releaseConnection(connection) { + debug('releasing connection to pool: %s', connection.__knexUid); + const didRelease = this.pool.release(connection); + + if (!didRelease) { + debug('pool refused connection: %s', connection.__knexUid); + } + + return Promise.resolve(); + } + + // Destroy the current connection pool for the client. + async destroy(callback) { + try { + if (this.pool && this.pool.destroy) { + await this.pool.destroy(); + } + this.pool = undefined; + + if (typeof callback === 'function') { + callback(); + } + } catch (err) { + if (typeof callback === 'function') { + return callback(err); + } + throw err; + } + } + + // Return the database being used by this client. + database() { + return this.connectionSettings.database; + } + + toString() { + return '[object KnexClient]'; + } + + assertCanCancelQuery() { + if (!this.canCancelQuery) { + throw new Error('Query cancelling not supported for this dialect'); + } + } + + cancelQuery() { + throw new Error('Query cancelling not supported for this dialect'); + } + + // Formatter part + + alias(first, second) { + return first + ' as ' + second; + } + + // Checks whether a value is a function... if it is, we compile it + // otherwise we check whether it's a raw + parameter(value, builder, bindingsHolder) { + if (typeof value === 'function') { + return outputQuery( + compileCallback(value, undefined, this, bindingsHolder), + true, + builder, + this + ); + } + return unwrapRaw(value, true, builder, this, bindingsHolder) || '?'; + } + + // Turns a list of values into a list of ?'s, joining them with commas unless + // a "joining" value is specified (e.g. ' and ') + parameterize(values, notSetValue, builder, bindingsHolder) { + if (typeof values === 'function') + return this.parameter(values, builder, bindingsHolder); + values = Array.isArray(values) ? values : [values]; + let str = '', + i = -1; + while (++i < values.length) { + if (i > 0) str += ', '; + let value = values[i]; + // json columns can have object in values. + if (isPlainObject(value)) { + value = JSON.stringify(value); + } + str += this.parameter( + value === undefined ? notSetValue : value, + builder, + bindingsHolder + ); + } + return str; + } + + // Formats `values` into a parenthesized list of parameters for a `VALUES` + // clause. + // + // [1, 2] -> '(?, ?)' + // [[1, 2], [3, 4]] -> '((?, ?), (?, ?))' + // knex('table') -> '(select * from "table")' + // knex.raw('select ?', 1) -> '(select ?)' + // + values(values, builder, bindingsHolder) { + if (Array.isArray(values)) { + if (Array.isArray(values[0])) { + return `(${values + .map( + (value) => + `(${this.parameterize( + value, + undefined, + builder, + bindingsHolder + )})` + ) + .join(', ')})`; + } + return `(${this.parameterize( + values, + undefined, + builder, + bindingsHolder + )})`; + } + + if (values && values.isRawInstance) { + return `(${this.parameter(values, builder, bindingsHolder)})`; + } + + return this.parameter(values, builder, bindingsHolder); + } + + processPassedConnection(connection) { + // Default implementation is noop + } + + toPathForJson(jsonPath) { + // By default, we want a json path, so if this function is not overriden, + // we return the path. + return jsonPath; + } +} + +Object.assign(Client.prototype, { + _escapeBinding: makeEscape({ + escapeString(str) { + return `'${str.replace(/'/g, "''")}'`; + }, + }), + + canCancelQuery: false, +}); + +module.exports = Client; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/constants.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/constants.js new file mode 100644 index 000000000..326b13729 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/constants.js @@ -0,0 +1,61 @@ +// The client names we'll allow in the `{name: lib}` pairing. +const CLIENT_ALIASES = Object.freeze({ + pg: 'postgres', + postgresql: 'postgres', + sqlite: 'sqlite3', +}); + +const SUPPORTED_CLIENTS = Object.freeze( + [ + 'mssql', + 'mysql', + 'mysql2', + 'oracledb', + 'postgres', + 'pgnative', + 'redshift', + 'sqlite3', + 'cockroachdb', + 'better-sqlite3', + ].concat(Object.keys(CLIENT_ALIASES)) +); + +const DRIVER_NAMES = Object.freeze({ + MsSQL: 'mssql', + MySQL: 'mysql', + MySQL2: 'mysql2', + Oracle: 'oracledb', + PostgreSQL: 'pg', + PgNative: 'pgnative', + Redshift: 'pg-redshift', + SQLite: 'sqlite3', + CockroachDB: 'cockroachdb', + BetterSQLite3: 'better-sqlite3', +}); + +const POOL_CONFIG_OPTIONS = Object.freeze([ + 'maxWaitingClients', + 'testOnBorrow', + 'fifo', + 'priorityRange', + 'autostart', + 'evictionRunIntervalMillis', + 'numTestsPerRun', + 'softIdleTimeoutMillis', + 'Promise', +]); + +/** + * Regex that only matches comma's in strings that aren't wrapped in parentheses. Can be used to + * safely split strings like `id int, name string, body text, primary key (id, name)` into definition + * rows + */ +const COMMA_NO_PAREN_REGEX = /,[\s](?![^(]*\))/g; + +module.exports = { + CLIENT_ALIASES, + SUPPORTED_CLIENTS, + POOL_CONFIG_OPTIONS, + COMMA_NO_PAREN_REGEX, + DRIVER_NAMES, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/better-sqlite3/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/better-sqlite3/index.js new file mode 100644 index 000000000..85a5ba692 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/better-sqlite3/index.js @@ -0,0 +1,77 @@ +// better-sqlite3 Client +// ------- +const Client_SQLite3 = require('../sqlite3'); + +class Client_BetterSQLite3 extends Client_SQLite3 { + _driver() { + return require('better-sqlite3'); + } + + // Get a raw connection from the database, returning a promise with the connection object. + async acquireRawConnection() { + const options = this.connectionSettings.options || {}; + + return new this.driver(this.connectionSettings.filename, { + nativeBinding: options.nativeBinding, + readonly: !!options.readonly, + }); + } + + // Used to explicitly close a connection, called internally by the pool when + // a connection times out or the pool is shutdown. + async destroyRawConnection(connection) { + return connection.close(); + } + + // Runs the query on the specified connection, providing the bindings and any + // other necessary prep work. + async _query(connection, obj) { + if (!obj.sql) throw new Error('The query is empty'); + + if (!connection) { + throw new Error('No connection provided'); + } + + const statement = connection.prepare(obj.sql); + const bindings = this._formatBindings(obj.bindings); + + if (statement.reader) { + const response = await statement.all(bindings); + obj.response = response; + return obj; + } + + const response = await statement.run(bindings); + obj.response = response; + obj.context = { + lastID: response.lastInsertRowid, + changes: response.changes, + }; + + return obj; + } + + _formatBindings(bindings) { + if (!bindings) { + return []; + } + return bindings.map((binding) => { + if (binding instanceof Date) { + return binding.valueOf(); + } + + if (typeof binding === 'boolean') { + return Number(binding); + } + + return binding; + }); + } +} + +Object.assign(Client_BetterSQLite3.prototype, { + // The "dialect", for reference . + driverName: 'better-sqlite3', +}); + +module.exports = Client_BetterSQLite3; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-columncompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-columncompiler.js new file mode 100644 index 000000000..6a35557ef --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-columncompiler.js @@ -0,0 +1,14 @@ +const ColumnCompiler_PG = require('../postgres/schema/pg-columncompiler.js'); + +class ColumnCompiler_CRDB extends ColumnCompiler_PG { + uuid(options = { primaryKey: false }) { + return ( + 'uuid' + + (this.tableCompiler._canBeAddPrimaryKey(options) + ? ' primary key default gen_random_uuid()' + : '') + ); + } +} + +module.exports = ColumnCompiler_CRDB; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-querybuilder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-querybuilder.js new file mode 100644 index 000000000..c6f041aca --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-querybuilder.js @@ -0,0 +1,11 @@ +const QueryBuilder = require('../../query/querybuilder'); +const isEmpty = require('lodash/isEmpty'); + +module.exports = class QueryBuilder_CockroachDB extends QueryBuilder { + upsert(values, returning, options) { + this._method = 'upsert'; + if (!isEmpty(returning)) this.returning(returning, options); + this._single.upsert = values; + return this; + } +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-querycompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-querycompiler.js new file mode 100644 index 000000000..0a9cf105a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-querycompiler.js @@ -0,0 +1,122 @@ +const QueryCompiler_PG = require('../postgres/query/pg-querycompiler'); +const { + columnize: columnize_, + wrap: wrap_, + operator: operator_, +} = require('../../formatter/wrappingFormatter'); + +class QueryCompiler_CRDB extends QueryCompiler_PG { + truncate() { + return `truncate ${this.tableName}`; + } + + upsert() { + let sql = this._upsert(); + if (sql === '') return sql; + const { returning } = this.single; + if (returning) sql += this._returning(returning); + return { + sql: sql, + returning, + }; + } + + _upsert() { + const upsertValues = this.single.upsert || []; + const sql = this.with() + `upsert into ${this.tableName} `; + const body = this._insertBody(upsertValues); + return body === '' ? '' : sql + body; + } + + _groupOrder(item, type) { + // CockroachDB don't support PostgreSQL order nulls first/last syntax, we take the generic one. + return this._basicGroupOrder(item, type); + } + + whereJsonPath(statement) { + let castValue = ''; + if (!isNaN(statement.value) && parseInt(statement.value)) { + castValue = '::int'; + } else if (!isNaN(statement.value) && parseFloat(statement.value)) { + castValue = '::float'; + } else { + castValue = " #>> '{}'"; + } + return `json_extract_path(${this._columnClause( + statement + )}, ${this.client.toArrayPathFromJsonPath( + statement.jsonPath, + this.builder, + this.bindingsHolder + )})${castValue} ${operator_( + statement.operator, + this.builder, + this.client, + this.bindingsHolder + )} ${this._jsonValueClause(statement)}`; + } + + // Json common functions + _jsonExtract(nameFunction, params) { + let extractions; + if (Array.isArray(params.column)) { + extractions = params.column; + } else { + extractions = [params]; + } + return extractions + .map((extraction) => { + const jsonCol = `json_extract_path(${columnize_( + extraction.column || extraction[0], + this.builder, + this.client, + this.bindingsHolder + )}, ${this.client.toArrayPathFromJsonPath( + extraction.path || extraction[1], + this.builder, + this.bindingsHolder + )})`; + const alias = extraction.alias || extraction[2]; + return alias + ? this.client.alias(jsonCol, this.formatter.wrap(alias)) + : jsonCol; + }) + .join(', '); + } + + _onJsonPathEquals(nameJoinFunction, clause) { + return ( + 'json_extract_path(' + + wrap_( + clause.columnFirst, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ', ' + + this.client.toArrayPathFromJsonPath( + clause.jsonPathFirst, + this.builder, + this.bindingsHolder + ) + + ') = json_extract_path(' + + wrap_( + clause.columnSecond, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ', ' + + this.client.toArrayPathFromJsonPath( + clause.jsonPathSecond, + this.builder, + this.bindingsHolder + ) + + ')' + ); + } +} + +module.exports = QueryCompiler_CRDB; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-tablecompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-tablecompiler.js new file mode 100644 index 000000000..5b5995d52 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-tablecompiler.js @@ -0,0 +1,37 @@ +/* eslint max-len: 0 */ + +const TableCompiler = require('../postgres/schema/pg-tablecompiler'); + +class TableCompiler_CRDB extends TableCompiler { + constructor(client, tableBuilder) { + super(client, tableBuilder); + } + + addColumns(columns, prefix, colCompilers) { + if (prefix === this.alterColumnsPrefix) { + // alter columns + for (const col of colCompilers) { + this.client.logger.warn( + 'Experimental alter column in use, see issue: https://github.com/cockroachdb/cockroach/issues/49329' + ); + this.pushQuery({ + sql: 'SET enable_experimental_alter_column_type_general = true', + bindings: [], + }); + super._addColumn(col); + } + } else { + // base class implementation for normal add + super.addColumns(columns, prefix); + } + } + + dropUnique(columns, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('unique', this.tableNameRaw, columns); + this.pushQuery(`drop index ${this.tableName()}@${indexName} cascade `); + } +} + +module.exports = TableCompiler_CRDB; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-viewcompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-viewcompiler.js new file mode 100644 index 000000000..4faed5574 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/crdb-viewcompiler.js @@ -0,0 +1,15 @@ +const ViewCompiler_PG = require('../postgres/schema/pg-viewcompiler.js'); + +class ViewCompiler_CRDB extends ViewCompiler_PG { + renameColumn(from, to) { + throw new Error('rename column of views is not supported by this dialect.'); + } + + defaultTo(column, defaultValue) { + throw new Error( + 'change default values of views is not supported by this dialect.' + ); + } +} + +module.exports = ViewCompiler_CRDB; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/index.js new file mode 100644 index 000000000..63aa8c789 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/cockroachdb/index.js @@ -0,0 +1,86 @@ +// CockroachDB Client +// ------- +const Client_PostgreSQL = require('../postgres'); +const Transaction = require('../postgres/execution/pg-transaction'); +const QueryCompiler = require('./crdb-querycompiler'); +const ColumnCompiler = require('./crdb-columncompiler'); +const TableCompiler = require('./crdb-tablecompiler'); +const ViewCompiler = require('./crdb-viewcompiler'); +const QueryBuilder = require('./crdb-querybuilder'); + +// Always initialize with the "QueryBuilder" and "QueryCompiler" +// objects, which extend the base 'lib/query/builder' and +// 'lib/query/compiler', respectively. +class Client_CockroachDB extends Client_PostgreSQL { + transaction() { + return new Transaction(this, ...arguments); + } + + queryCompiler(builder, formatter) { + return new QueryCompiler(this, builder, formatter); + } + + columnCompiler() { + return new ColumnCompiler(this, ...arguments); + } + + tableCompiler() { + return new TableCompiler(this, ...arguments); + } + + viewCompiler() { + return new ViewCompiler(this, ...arguments); + } + + queryBuilder() { + return new QueryBuilder(this); + } + + _parseVersion(versionString) { + return versionString.split(' ')[2]; + } + + async cancelQuery(connectionToKill) { + try { + return await this._wrappedCancelQueryCall(null, connectionToKill); + } catch (err) { + this.logger.warn(`Connection Error: ${err}`); + throw err; + } + } + + _wrappedCancelQueryCall(emptyConnection, connectionToKill) { + // FixMe https://github.com/cockroachdb/cockroach/issues/41335 + if ( + connectionToKill.activeQuery.processID === 0 && + connectionToKill.activeQuery.secretKey === 0 + ) { + return; + } + + return connectionToKill.cancel( + connectionToKill, + connectionToKill.activeQuery + ); + } + + toArrayPathFromJsonPath(jsonPath, builder, bindingsHolder) { + return jsonPath + .replace(/^(\$\.)/, '') // remove the first dollar + .replace(/\[([0-9]+)]/, '.$1') + .split('.') + .map( + function (v) { + return this.parameter(v, builder, bindingsHolder); + }.bind(this) + ) + .join(', '); + } +} + +Object.assign(Client_CockroachDB.prototype, { + // The "dialect", for reference elsewhere. + driverName: 'cockroachdb', +}); + +module.exports = Client_CockroachDB; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/index.js new file mode 100644 index 000000000..559a36668 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/index.js @@ -0,0 +1,34 @@ +'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); +exports.getDialectByNameOrAlias = void 0; +const { resolveClientNameWithAliases } = require('../util/helpers'); +const dbNameToDialectLoader = Object.freeze({ + 'better-sqlite3': () => require('./better-sqlite3'), + cockroachdb: () => require('./cockroachdb'), + mssql: () => require('./mssql'), + mysql: () => require('./mysql'), + mysql2: () => require('./mysql2'), + oracle: () => require('./oracle'), + oracledb: () => require('./oracledb'), + pgnative: () => require('./pgnative'), + postgres: () => require('./postgres'), + redshift: () => require('./redshift'), + sqlite3: () => require('./sqlite3'), +}); +/** + * Gets the Dialect object with the given client name or throw an + * error if not found. + * + * NOTE: This is a replacement for prior practice of doing dynamic + * string construction for imports of Dialect objects. + */ +function getDialectByNameOrAlias(clientName) { + const resolvedClientName = resolveClientNameWithAliases(clientName); + const dialectLoader = dbNameToDialectLoader[resolvedClientName]; + if (!dialectLoader) { + throw new Error(`Invalid clientName given: ${clientName}`); + } + return dialectLoader(); +} +exports.getDialectByNameOrAlias = getDialectByNameOrAlias; +//# sourceMappingURL=index.js.map diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/index.js new file mode 100644 index 000000000..67fba0288 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/index.js @@ -0,0 +1,500 @@ +// MSSQL Client +// ------- +const map = require('lodash/map'); +const isNil = require('lodash/isNil'); + +const Client = require('../../client'); +const MSSQL_Formatter = require('./mssql-formatter'); +const Transaction = require('./transaction'); +const QueryCompiler = require('./query/mssql-querycompiler'); +const SchemaCompiler = require('./schema/mssql-compiler'); +const TableCompiler = require('./schema/mssql-tablecompiler'); +const ViewCompiler = require('./schema/mssql-viewcompiler'); +const ColumnCompiler = require('./schema/mssql-columncompiler'); +const QueryBuilder = require('../../query/querybuilder'); +const { setHiddenProperty } = require('../../util/security'); + +const debug = require('debug')('knex:mssql'); + +const SQL_INT4 = { MIN: -2147483648, MAX: 2147483647 }; +const SQL_BIGINT_SAFE = { MIN: -9007199254740991, MAX: 9007199254740991 }; + +// Always initialize with the "QueryBuilder" and "QueryCompiler" objects, which +// extend the base 'lib/query/builder' and 'lib/query/compiler', respectively. +class Client_MSSQL extends Client { + constructor(config = {}) { + super(config); + } + + /** + * @param {import('knex').Config} options + */ + _generateConnection() { + const settings = this.connectionSettings; + settings.options = settings.options || {}; + + /** @type {import('tedious').ConnectionConfig} */ + const cfg = { + authentication: { + type: settings.type || 'default', + options: { + userName: settings.userName || settings.user, + password: settings.password, + domain: settings.domain, + token: settings.token, + clientId: settings.clientId, + clientSecret: settings.clientSecret, + tenantId: settings.tenantId, + msiEndpoint: settings.msiEndpoint, + }, + }, + server: settings.server || settings.host, + options: { + database: settings.database, + encrypt: settings.encrypt || false, + port: settings.port || 1433, + connectTimeout: settings.connectionTimeout || settings.timeout || 15000, + requestTimeout: !isNil(settings.requestTimeout) + ? settings.requestTimeout + : 15000, + rowCollectionOnDone: false, + rowCollectionOnRequestCompletion: false, + useColumnNames: false, + tdsVersion: settings.options.tdsVersion || '7_4', + appName: settings.options.appName || 'knex', + trustServerCertificate: false, + ...settings.options, + }, + }; + + if (cfg.authentication.options.password) { + setHiddenProperty(cfg.authentication.options); + } + + // tedious always connect via tcp when port is specified + if (cfg.options.instanceName) delete cfg.options.port; + + if (isNaN(cfg.options.requestTimeout)) cfg.options.requestTimeout = 15000; + if (cfg.options.requestTimeout === Infinity) cfg.options.requestTimeout = 0; + if (cfg.options.requestTimeout < 0) cfg.options.requestTimeout = 0; + + if (settings.debug) { + cfg.options.debug = { + packet: true, + token: true, + data: true, + payload: true, + }; + } + + return cfg; + } + + _driver() { + const tds = require('tedious'); + + return tds; + } + + formatter() { + return new MSSQL_Formatter(this, ...arguments); + } + + transaction() { + return new Transaction(this, ...arguments); + } + + queryCompiler() { + return new QueryCompiler(this, ...arguments); + } + + schemaCompiler() { + return new SchemaCompiler(this, ...arguments); + } + + tableCompiler() { + return new TableCompiler(this, ...arguments); + } + + viewCompiler() { + return new ViewCompiler(this, ...arguments); + } + queryBuilder() { + const b = new QueryBuilder(this); + return b; + } + + columnCompiler() { + return new ColumnCompiler(this, ...arguments); + } + + wrapIdentifierImpl(value) { + if (value === '*') { + return '*'; + } + + return `[${value.replace(/[[\]]+/g, '')}]`; + } + + // Get a raw connection, called by the `pool` whenever a new + // connection needs to be added to the pool. + acquireRawConnection() { + return new Promise((resolver, rejecter) => { + debug('connection::connection new connection requested'); + const Driver = this._driver(); + const settings = Object.assign({}, this._generateConnection()); + + const connection = new Driver.Connection(settings); + + connection.connect((err) => { + if (err) { + debug('connection::connect error: %s', err.message); + return rejecter(err); + } + + debug('connection::connect connected to server'); + + connection.connected = true; + connection.on('error', (e) => { + debug('connection::error message=%s', e.message); + connection.__knex__disposed = e; + connection.connected = false; + }); + + connection.once('end', () => { + connection.connected = false; + connection.__knex__disposed = 'Connection to server was terminated.'; + debug('connection::end connection ended.'); + }); + + return resolver(connection); + }); + }); + } + + validateConnection(connection) { + return connection && connection.connected; + } + + // Used to explicitly close a connection, called internally by the pool + // when a connection times out or the pool is shutdown. + destroyRawConnection(connection) { + debug('connection::destroy'); + + return new Promise((resolve) => { + connection.once('end', () => { + resolve(); + }); + + connection.close(); + }); + } + + // Position the bindings for the query. + positionBindings(sql) { + let questionCount = -1; + return sql.replace(/\\?\?/g, (match) => { + if (match === '\\?') { + return '?'; + } + + questionCount += 1; + return `@p${questionCount}`; + }); + } + + _chomp(connection) { + if (connection.state.name === 'LoggedIn') { + const nextRequest = this.requestQueue.pop(); + if (nextRequest) { + debug( + 'connection::query executing query, %d more in queue', + this.requestQueue.length + ); + + connection.execSql(nextRequest); + } + } + } + + _enqueueRequest(request, connection) { + this.requestQueue.push(request); + this._chomp(connection); + } + + _makeRequest(query, callback) { + const Driver = this._driver(); + const sql = typeof query === 'string' ? query : query.sql; + let rowCount = 0; + + if (!sql) throw new Error('The query is empty'); + + debug('request::request sql=%s', sql); + + const request = new Driver.Request(sql, (err, remoteRowCount) => { + if (err) { + debug('request::error message=%s', err.message); + return callback(err); + } + + rowCount = remoteRowCount; + debug('request::callback rowCount=%d', rowCount); + }); + + request.on('prepared', () => { + debug('request %s::request prepared', this.id); + }); + + request.on('done', (rowCount, more) => { + debug('request::done rowCount=%d more=%s', rowCount, more); + }); + + request.on('doneProc', (rowCount, more) => { + debug( + 'request::doneProc id=%s rowCount=%d more=%s', + request.id, + rowCount, + more + ); + }); + + request.on('doneInProc', (rowCount, more) => { + debug( + 'request::doneInProc id=%s rowCount=%d more=%s', + request.id, + rowCount, + more + ); + }); + + request.once('requestCompleted', () => { + debug('request::completed id=%s', request.id); + return callback(null, rowCount); + }); + + request.on('error', (err) => { + debug('request::error id=%s message=%s', request.id, err.message); + return callback(err); + }); + + return request; + } + + // Grab a connection, run the query via the MSSQL streaming interface, + // and pass that through to the stream we've sent back to the client. + _stream(connection, query, /** @type {NodeJS.ReadWriteStream} */ stream) { + return new Promise((resolve, reject) => { + const request = this._makeRequest(query, (err) => { + if (err) { + stream.emit('error', err); + return reject(err); + } + + resolve(); + }); + + request.on('row', (row) => { + stream.write( + row.reduce( + (prev, curr) => ({ + ...prev, + [curr.metadata.colName]: curr.value, + }), + {} + ) + ); + }); + request.on('error', (err) => { + stream.emit('error', err); + reject(err); + }); + request.once('requestCompleted', () => { + stream.end(); + resolve(); + }); + + this._assignBindings(request, query.bindings); + this._enqueueRequest(request, connection); + }); + } + + _assignBindings(request, bindings) { + if (Array.isArray(bindings)) { + for (let i = 0; i < bindings.length; i++) { + const binding = bindings[i]; + this._setReqInput(request, i, binding); + } + } + } + + _scaleForBinding(binding) { + if (binding % 1 === 0) { + throw new Error(`The binding value ${binding} must be a decimal number.`); + } + + return { scale: 10 }; + } + + _typeForBinding(binding) { + const Driver = this._driver(); + + if ( + this.connectionSettings.options && + this.connectionSettings.options.mapBinding + ) { + const result = this.connectionSettings.options.mapBinding(binding); + if (result) { + return [result.value, result.type]; + } + } + + switch (typeof binding) { + case 'string': + return [binding, Driver.TYPES.NVarChar]; + case 'boolean': + return [binding, Driver.TYPES.Bit]; + case 'number': { + if (binding % 1 !== 0) { + return [binding, Driver.TYPES.Float]; + } + + if (binding < SQL_INT4.MIN || binding > SQL_INT4.MAX) { + if (binding < SQL_BIGINT_SAFE.MIN || binding > SQL_BIGINT_SAFE.MAX) { + throw new Error( + `Bigint must be safe integer or must be passed as string, saw ${binding}` + ); + } + + return [binding, Driver.TYPES.BigInt]; + } + + return [binding, Driver.TYPES.Int]; + } + default: { + if (binding instanceof Date) { + return [binding, Driver.TYPES.DateTime]; + } + + if (binding instanceof Buffer) { + return [binding, Driver.TYPES.VarBinary]; + } + + return [binding, Driver.TYPES.NVarChar]; + } + } + } + + // Runs the query on the specified connection, providing the bindings + // and any other necessary prep work. + _query(connection, query) { + return new Promise((resolve, reject) => { + const rows = []; + const request = this._makeRequest(query, (err, count) => { + if (err) { + return reject(err); + } + + query.response = rows; + + process.nextTick(() => this._chomp(connection)); + + resolve(query); + }); + + request.on('row', (row) => { + debug('request::row'); + rows.push(row); + }); + + this._assignBindings(request, query.bindings); + this._enqueueRequest(request, connection); + }); + } + + // sets a request input parameter. Detects bigints and decimals and sets type appropriately. + _setReqInput(req, i, inputBinding) { + const [binding, tediousType] = this._typeForBinding(inputBinding); + const bindingName = 'p'.concat(i); + let options; + + if (typeof binding === 'number' && binding % 1 !== 0) { + options = this._scaleForBinding(binding); + } + + debug( + 'request::binding pos=%d type=%s value=%s', + i, + tediousType.name, + binding + ); + + if (Buffer.isBuffer(binding)) { + options = { + length: 'max', + }; + } + + req.addParameter(bindingName, tediousType, binding, options); + } + + // Process the response as returned from the query. + processResponse(query, runner) { + if (query == null) return; + let { response } = query; + const { method } = query; + + if (query.output) { + return query.output.call(runner, response); + } + + response = response.map((row) => + row.reduce((columns, r) => { + const colName = r.metadata.colName; + + if (columns[colName]) { + if (!Array.isArray(columns[colName])) { + columns[colName] = [columns[colName]]; + } + + columns[colName].push(r.value); + } else { + columns[colName] = r.value; + } + + return columns; + }, {}) + ); + + if (query.output) return query.output.call(runner, response); + switch (method) { + case 'select': + return response; + case 'first': + return response[0]; + case 'pluck': + return map(response, query.pluck); + case 'insert': + case 'del': + case 'update': + case 'counter': + if (query.returning) { + if (query.returning === '@@rowcount') { + return response[0]['']; + } + } + return response; + default: + return response; + } + } +} + +Object.assign(Client_MSSQL.prototype, { + requestQueue: [], + + dialect: 'mssql', + + driverName: 'mssql', +}); + +module.exports = Client_MSSQL; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/mssql-formatter.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/mssql-formatter.js new file mode 100644 index 000000000..354afef03 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/mssql-formatter.js @@ -0,0 +1,34 @@ +const Formatter = require('../../formatter'); + +class MSSQL_Formatter extends Formatter { + // Accepts a string or array of columns to wrap as appropriate. + columnizeWithPrefix(prefix, target) { + const columns = typeof target === 'string' ? [target] : target; + let str = '', + i = -1; + while (++i < columns.length) { + if (i > 0) str += ', '; + str += prefix + this.wrap(columns[i]); + } + return str; + } + + /** + * Returns its argument with single quotes escaped, so it can be included into a single-quoted string. + * + * For example, it converts "has'quote" to "has''quote". + * + * This assumes QUOTED_IDENTIFIER ON so it is only ' that need escaping, + * never ", because " cannot be used to quote a string when that's on; + * otherwise we'd need to be aware of whether the string is quoted with " or '. + * + * This assumption is consistent with the SQL Knex generates. + * @param {string} string + * @returns {string} + */ + escapingStringDelimiters(string) { + return (string || '').replace(/'/g, "''"); + } +} + +module.exports = MSSQL_Formatter; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/query/mssql-querycompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/query/mssql-querycompiler.js new file mode 100644 index 000000000..74c9b8aeb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/query/mssql-querycompiler.js @@ -0,0 +1,601 @@ +// MSSQL Query Compiler +// ------ +const QueryCompiler = require('../../../query/querycompiler'); + +const compact = require('lodash/compact'); +const identity = require('lodash/identity'); +const isEmpty = require('lodash/isEmpty'); +const Raw = require('../../../raw.js'); +const { + columnize: columnize_, +} = require('../../../formatter/wrappingFormatter'); + +const components = [ + 'comments', + 'columns', + 'join', + 'lock', + 'where', + 'union', + 'group', + 'having', + 'order', + 'limit', + 'offset', +]; + +class QueryCompiler_MSSQL extends QueryCompiler { + constructor(client, builder, formatter) { + super(client, builder, formatter); + + const { onConflict } = this.single; + if (onConflict) { + throw new Error('.onConflict() is not supported for mssql.'); + } + + this._emptyInsertValue = 'default values'; + } + + with() { + // WITH RECURSIVE is a syntax error: + // SQL Server does not syntactically distinguish recursive and non-recursive CTEs. + // So mark all statements as non-recursive, generate the SQL, then restore. + // This approach ensures any changes in base class with() get propagated here. + const undoList = []; + if (this.grouped.with) { + for (const stmt of this.grouped.with) { + if (stmt.recursive) { + undoList.push(stmt); + stmt.recursive = false; + } + } + } + + const result = super.with(); + + // Restore the recursive markings, in case this same query gets cloned and passed to other drivers. + for (const stmt of undoList) { + stmt.recursive = true; + } + return result; + } + + select() { + const sql = this.with(); + const statements = components.map((component) => this[component](this)); + return sql + compact(statements).join(' '); + } + + //#region Insert + // Compiles an "insert" query, allowing for multiple + // inserts using a single query statement. + insert() { + if ( + this.single.options && + this.single.options.includeTriggerModifications + ) { + return this.insertWithTriggers(); + } else { + return this.standardInsert(); + } + } + + insertWithTriggers() { + const insertValues = this.single.insert || []; + const { returning } = this.single; + let sql = + this.with() + + `${this._buildTempTable(returning)}insert into ${this.tableName} `; + const returningSql = returning + ? this._returning('insert', returning, true) + ' ' + : ''; + + if (Array.isArray(insertValues)) { + if (insertValues.length === 0) { + return ''; + } + } else if (typeof insertValues === 'object' && isEmpty(insertValues)) { + return { + sql: + sql + + returningSql + + this._emptyInsertValue + + this._buildReturningSelect(returning), + returning, + }; + } + sql += this._buildInsertData(insertValues, returningSql); + + if (returning) { + sql += this._buildReturningSelect(returning); + } + + return { + sql, + returning, + }; + } + + _buildInsertData(insertValues, returningSql) { + let sql = ''; + const insertData = this._prepInsert(insertValues); + if (typeof insertData === 'string') { + sql += insertData; + } else { + if (insertData.columns.length) { + sql += `(${this.formatter.columnize(insertData.columns)}`; + sql += + `) ${returningSql}values (` + + this._buildInsertValues(insertData) + + ')'; + } else if (insertValues.length === 1 && insertValues[0]) { + sql += returningSql + this._emptyInsertValue; + } else { + return ''; + } + } + return sql; + } + + standardInsert() { + const insertValues = this.single.insert || []; + let sql = this.with() + `insert into ${this.tableName} `; + const { returning } = this.single; + const returningSql = returning + ? this._returning('insert', returning) + ' ' + : ''; + + if (Array.isArray(insertValues)) { + if (insertValues.length === 0) { + return ''; + } + } else if (typeof insertValues === 'object' && isEmpty(insertValues)) { + return { + sql: sql + returningSql + this._emptyInsertValue, + returning, + }; + } + + sql += this._buildInsertData(insertValues, returningSql); + + return { + sql, + returning, + }; + } + //#endregion + + //#region Update + // Compiles an `update` query, allowing for a return value. + update() { + if ( + this.single.options && + this.single.options.includeTriggerModifications + ) { + return this.updateWithTriggers(); + } else { + return this.standardUpdate(); + } + } + + updateWithTriggers() { + const top = this.top(); + const withSQL = this.with(); + const updates = this._prepUpdate(this.single.update); + const join = this.join(); + const where = this.where(); + const order = this.order(); + const { returning } = this.single; + const declaredTemp = this._buildTempTable(returning); + return { + sql: + withSQL + + declaredTemp + + `update ${top ? top + ' ' : ''}${this.tableName}` + + ' set ' + + updates.join(', ') + + (returning ? ` ${this._returning('update', returning, true)}` : '') + + (join ? ` from ${this.tableName} ${join}` : '') + + (where ? ` ${where}` : '') + + (order ? ` ${order}` : '') + + (!returning + ? this._returning('rowcount', '@@rowcount') + : this._buildReturningSelect(returning)), + returning: returning || '@@rowcount', + }; + } + + _formatGroupsItemValue(value, nulls) { + const column = super._formatGroupsItemValue(value); + // MSSQL dont support 'is null' syntax in order by, + // so we override this function and add MSSQL specific syntax. + if (nulls && !(value instanceof Raw)) { + const collNulls = `IIF(${column} is null,`; + if (nulls === 'first') { + return `${collNulls}0,1)`; + } else if (nulls === 'last') { + return `${collNulls}1,0)`; + } + } + return column; + } + + standardUpdate() { + const top = this.top(); + const withSQL = this.with(); + const updates = this._prepUpdate(this.single.update); + const join = this.join(); + const where = this.where(); + const order = this.order(); + const { returning } = this.single; + return { + sql: + withSQL + + `update ${top ? top + ' ' : ''}${this.tableName}` + + ' set ' + + updates.join(', ') + + (returning ? ` ${this._returning('update', returning)}` : '') + + (join ? ` from ${this.tableName} ${join}` : '') + + (where ? ` ${where}` : '') + + (order ? ` ${order}` : '') + + (!returning ? this._returning('rowcount', '@@rowcount') : ''), + returning: returning || '@@rowcount', + }; + } + //#endregion + + //#region Delete + // Compiles a `delete` query. + del() { + if ( + this.single.options && + this.single.options.includeTriggerModifications + ) { + return this.deleteWithTriggers(); + } else { + return this.standardDelete(); + } + } + + deleteWithTriggers() { + // Make sure tableName is processed by the formatter first. + const withSQL = this.with(); + const { tableName } = this; + const wheres = this.where(); + const joins = this.join(); + const { returning } = this.single; + const returningStr = returning + ? ` ${this._returning('del', returning, true)}` + : ''; + const deleteSelector = joins ? `${tableName}${returningStr} ` : ''; + return { + sql: + withSQL + + `${this._buildTempTable( + returning + )}delete ${deleteSelector}from ${tableName}` + + (!joins ? returningStr : '') + + (joins ? ` ${joins}` : '') + + (wheres ? ` ${wheres}` : '') + + (!returning + ? this._returning('rowcount', '@@rowcount') + : this._buildReturningSelect(returning)), + returning: returning || '@@rowcount', + }; + } + + standardDelete() { + // Make sure tableName is processed by the formatter first. + const withSQL = this.with(); + const { tableName } = this; + const wheres = this.where(); + const joins = this.join(); + const { returning } = this.single; + const returningStr = returning + ? ` ${this._returning('del', returning)}` + : ''; + // returning needs to be before "from" when using join + const deleteSelector = joins ? `${tableName}${returningStr} ` : ''; + return { + sql: + withSQL + + `delete ${deleteSelector}from ${tableName}` + + (!joins ? returningStr : '') + + (joins ? ` ${joins}` : '') + + (wheres ? ` ${wheres}` : '') + + (!returning ? this._returning('rowcount', '@@rowcount') : ''), + returning: returning || '@@rowcount', + }; + } + //#endregion + + // Compiles the columns in the query, specifying if an item was distinct. + columns() { + let distinctClause = ''; + if (this.onlyUnions()) return ''; + const top = this.top(); + const hints = this._hintComments(); + const columns = this.grouped.columns || []; + let i = -1, + sql = []; + if (columns) { + while (++i < columns.length) { + const stmt = columns[i]; + if (stmt.distinct) distinctClause = 'distinct '; + if (stmt.distinctOn) { + distinctClause = this.distinctOn(stmt.value); + continue; + } + if (stmt.type === 'aggregate') { + sql.push(...this.aggregate(stmt)); + } else if (stmt.type === 'aggregateRaw') { + sql.push(this.aggregateRaw(stmt)); + } else if (stmt.type === 'analytic') { + sql.push(this.analytic(stmt)); + } else if (stmt.type === 'json') { + sql.push(this.json(stmt)); + } else if (stmt.value && stmt.value.length > 0) { + sql.push(this.formatter.columnize(stmt.value)); + } + } + } + if (sql.length === 0) sql = ['*']; + const select = this.onlyJson() ? '' : 'select '; + return ( + `${select}${hints}${distinctClause}` + + (top ? top + ' ' : '') + + sql.join(', ') + + (this.tableName ? ` from ${this.tableName}` : '') + ); + } + + _returning(method, value, withTrigger) { + switch (method) { + case 'update': + case 'insert': + return value + ? `output ${this.formatter.columnizeWithPrefix('inserted.', value)}${ + withTrigger ? ' into #out' : '' + }` + : ''; + case 'del': + return value + ? `output ${this.formatter.columnizeWithPrefix('deleted.', value)}${ + withTrigger ? ' into #out' : '' + }` + : ''; + case 'rowcount': + return value ? ';select @@rowcount' : ''; + } + } + + _buildTempTable(values) { + // If value is nothing then return an empty string + if (values && values.length > 0) { + let selections = ''; + + // Build values that will be returned from this procedure + if (Array.isArray(values)) { + selections = values + .map((value) => `[t].${this.formatter.columnize(value)}`) + .join(','); + } else { + selections = `[t].${this.formatter.columnize(values)}`; + } + + // Force #out to be correctly populated with the correct column structure. + let sql = `select top(0) ${selections} into #out `; + sql += `from ${this.tableName} as t `; + sql += `left join ${this.tableName} on 0=1;`; + + return sql; + } + + return ''; + } + + _buildReturningSelect(values) { + // If value is nothing then return an empty string + if (values && values.length > 0) { + let selections = ''; + + // Build columns to return + if (Array.isArray(values)) { + selections = values + .map((value) => `${this.formatter.columnize(value)}`) + .join(','); + } else { + selections = this.formatter.columnize(values); + } + + // Get the returned values + let sql = `; select ${selections} from #out; `; + // Drop the temp table to prevent memory leaks + sql += `drop table #out;`; + + return sql; + } + + return ''; + } + + // Compiles a `truncate` query. + truncate() { + return `truncate table ${this.tableName}`; + } + + forUpdate() { + // this doesn't work exacltly as it should, one should also mention index while locking + // https://stackoverflow.com/a/9818448/360060 + return 'with (UPDLOCK)'; + } + + forShare() { + // http://www.sqlteam.com/article/introduction-to-locking-in-sql-server + return 'with (HOLDLOCK)'; + } + + // Compiles a `columnInfo` query. + columnInfo() { + const column = this.single.columnInfo; + let schema = this.single.schema; + + // The user may have specified a custom wrapIdentifier function in the config. We + // need to run the identifiers through that function, but not format them as + // identifiers otherwise. + const table = this.client.customWrapIdentifier(this.single.table, identity); + + if (schema) { + schema = this.client.customWrapIdentifier(schema, identity); + } + + // GOTCHA: INFORMATION_SCHEMA.COLUMNS must be capitalized to work when the database has a case-sensitive collation. [#4573] + let sql = `select [COLUMN_NAME], [COLUMN_DEFAULT], [DATA_TYPE], [CHARACTER_MAXIMUM_LENGTH], [IS_NULLABLE] from INFORMATION_SCHEMA.COLUMNS where table_name = ? and table_catalog = ?`; + const bindings = [table, this.client.database()]; + + if (schema) { + sql += ' and table_schema = ?'; + bindings.push(schema); + } else { + sql += ` and table_schema = 'dbo'`; + } + + return { + sql, + bindings: bindings, + output(resp) { + const out = resp.reduce((columns, val) => { + columns[val[0].value] = { + defaultValue: val[1].value, + type: val[2].value, + maxLength: val[3].value, + nullable: val[4].value === 'YES', + }; + return columns; + }, {}); + return (column && out[column]) || out; + }, + }; + } + + top() { + const noLimit = !this.single.limit && this.single.limit !== 0; + const noOffset = !this.single.offset; + if (noLimit || !noOffset) return ''; + return `top (${this._getValueOrParameterFromAttribute('limit')})`; + } + + limit() { + return ''; + } + + offset() { + const noLimit = !this.single.limit && this.single.limit !== 0; + const noOffset = !this.single.offset; + if (noOffset) return ''; + let offset = `offset ${ + noOffset ? '0' : this._getValueOrParameterFromAttribute('offset') + } rows`; + if (!noLimit) { + offset += ` fetch next ${this._getValueOrParameterFromAttribute( + 'limit' + )} rows only`; + } + return offset; + } + + whereLike(statement) { + return `${this._columnClause( + statement + )} collate SQL_Latin1_General_CP1_CS_AS ${this._not( + statement, + 'like ' + )}${this._valueClause(statement)}`; + } + + whereILike(statement) { + return `${this._columnClause( + statement + )} collate SQL_Latin1_General_CP1_CI_AS ${this._not( + statement, + 'like ' + )}${this._valueClause(statement)}`; + } + + jsonExtract(params) { + // JSON_VALUE return NULL if we query object or array + // JSON_QUERY return NULL if we query literal/single value + return this._jsonExtract( + params.singleValue ? 'JSON_VALUE' : 'JSON_QUERY', + params + ); + } + + jsonSet(params) { + return this._jsonSet('JSON_MODIFY', params); + } + + jsonInsert(params) { + return this._jsonSet('JSON_MODIFY', params); + } + + jsonRemove(params) { + const jsonCol = `JSON_MODIFY(${columnize_( + params.column, + this.builder, + this.client, + this.bindingsHolder + )},${this.client.parameter( + params.path, + this.builder, + this.bindingsHolder + )}, NULL)`; + return params.alias + ? this.client.alias(jsonCol, this.formatter.wrap(params.alias)) + : jsonCol; + } + + whereJsonPath(statement) { + return this._whereJsonPath('JSON_VALUE', statement); + } + + whereJsonSupersetOf(statement) { + throw new Error( + 'Json superset where clause not actually supported by MSSQL' + ); + } + + whereJsonSubsetOf(statement) { + throw new Error('Json subset where clause not actually supported by MSSQL'); + } + + _getExtracts(statement, operator) { + const column = columnize_( + statement.column, + this.builder, + this.client, + this.bindingsHolder + ); + return ( + Array.isArray(statement.values) ? statement.values : [statement.values] + ) + .map(function (value) { + return ( + 'JSON_VALUE(' + + column + + ',' + + this.client.parameter(value, this.builder, this.bindingsHolder) + + ')' + ); + }, this) + .join(operator); + } + + onJsonPathEquals(clause) { + return this._onJsonPathEquals('JSON_VALUE', clause); + } +} + +// Set the QueryBuilder & QueryCompiler on the client object, +// in case anyone wants to modify things to suit their own purposes. +module.exports = QueryCompiler_MSSQL; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-columncompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-columncompiler.js new file mode 100644 index 000000000..5c7bb5881 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-columncompiler.js @@ -0,0 +1,185 @@ +// MSSQL Column Compiler +// ------- +const ColumnCompiler = require('../../../schema/columncompiler'); +const { toNumber } = require('../../../util/helpers'); +const { formatDefault } = require('../../../formatter/formatterUtils'); +const { operator: operator_ } = require('../../../formatter/wrappingFormatter'); + +class ColumnCompiler_MSSQL extends ColumnCompiler { + constructor(client, tableCompiler, columnBuilder) { + super(client, tableCompiler, columnBuilder); + this.modifiers = ['nullable', 'defaultTo', 'first', 'after', 'comment']; + this._addCheckModifiers(); + } + + // Types + // ------ + + double(precision, scale) { + return 'float'; + } + + floating(precision, scale) { + // ignore precicion / scale which is mysql specific stuff + return `float`; + } + + integer() { + // mssql does not support length + return 'int'; + } + + tinyint() { + // mssql does not support length + return 'tinyint'; + } + + varchar(length) { + return `nvarchar(${toNumber(length, 255)})`; + } + + timestamp({ useTz = false } = {}) { + return useTz ? 'datetimeoffset' : 'datetime2'; + } + + bit(length) { + if (length > 1) { + this.client.logger.warn('Bit field is exactly 1 bit length for MSSQL'); + } + return 'bit'; + } + + binary(length) { + return length ? `varbinary(${toNumber(length)})` : 'varbinary(max)'; + } + + // Modifiers + // ------ + + first() { + this.client.logger.warn('Column first modifier not available for MSSQL'); + return ''; + } + + after(column) { + this.client.logger.warn('Column after modifier not available for MSSQL'); + return ''; + } + + defaultTo(value, { constraintName } = {}) { + const formattedValue = formatDefault(value, this.type, this.client); + constraintName = + typeof constraintName !== 'undefined' + ? constraintName + : `${ + this.tableCompiler.tableNameRaw + }_${this.getColumnName()}_default`.toLowerCase(); + if (this.columnBuilder._method === 'alter') { + this.pushAdditional(function () { + this.pushQuery( + `ALTER TABLE ${this.tableCompiler.tableName()} ADD CONSTRAINT ${this.formatter.wrap( + constraintName + )} DEFAULT ${formattedValue} FOR ${this.formatter.wrap( + this.getColumnName() + )}` + ); + }); + return ''; + } + if (!constraintName) { + return `DEFAULT ${formattedValue}`; + } + return `CONSTRAINT ${this.formatter.wrap( + constraintName + )} DEFAULT ${formattedValue}`; + } + + comment(/** @type {string} */ comment) { + if (!comment) { + return; + } + + // XXX: This is a byte limit, not character, so we cannot definitively say they'll exceed the limit without database collation info. + // (Yes, even if the column has its own collation, the sqlvariant still uses the database collation.) + // I'm not sure we even need to raise a warning, as MSSQL will return an error when the limit is exceeded itself. + if (comment && comment.length > 7500 / 2) { + this.client.logger.warn( + 'Your comment might be longer than the max comment length for MSSQL of 7,500 bytes.' + ); + } + + // See: https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-addextendedproperty-transact-sql?view=sql-server-ver15#b-adding-an-extended-property-to-a-column-in-a-table + const value = this.formatter.escapingStringDelimiters(comment); + const level0name = this.tableCompiler.schemaNameRaw || 'dbo'; + const level1name = this.formatter.escapingStringDelimiters( + this.tableCompiler.tableNameRaw + ); + const level2name = this.formatter.escapingStringDelimiters( + this.args[0] || this.defaults('columnName') + ); + + const args = `N'MS_Description', N'${value}', N'Schema', N'${level0name}', N'Table', N'${level1name}', N'Column', N'${level2name}'`; + + this.pushAdditional(function () { + const isAlreadyDefined = `EXISTS(SELECT * FROM sys.fn_listextendedproperty(N'MS_Description', N'Schema', N'${level0name}', N'Table', N'${level1name}', N'Column', N'${level2name}'))`; + this.pushQuery( + `IF ${isAlreadyDefined}\n EXEC sys.sp_updateextendedproperty ${args}\nELSE\n EXEC sys.sp_addextendedproperty ${args}` + ); + }); + return ''; + } + + checkLength(operator, length, constraintName) { + return this._check( + `LEN(${this.formatter.wrap(this.getColumnName())}) ${operator_( + operator, + this.columnBuilder, + this.bindingsHolder + )} ${toNumber(length)}`, + constraintName + ); + } + + checkRegex(regex, constraintName) { + return this._check( + `${this.formatter.wrap( + this.getColumnName() + )} LIKE ${this.client._escapeBinding('%' + regex + '%')}`, + constraintName + ); + } + + increments(options = { primaryKey: true }) { + return ( + 'int identity(1,1) not null' + + (this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '') + ); + } + + bigincrements(options = { primaryKey: true }) { + return ( + 'bigint identity(1,1) not null' + + (this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '') + ); + } +} + +ColumnCompiler_MSSQL.prototype.bigint = 'bigint'; +ColumnCompiler_MSSQL.prototype.mediumint = 'int'; +ColumnCompiler_MSSQL.prototype.smallint = 'smallint'; +ColumnCompiler_MSSQL.prototype.text = 'nvarchar(max)'; +ColumnCompiler_MSSQL.prototype.mediumtext = 'nvarchar(max)'; +ColumnCompiler_MSSQL.prototype.longtext = 'nvarchar(max)'; +ColumnCompiler_MSSQL.prototype.json = ColumnCompiler_MSSQL.prototype.jsonb = + 'nvarchar(max)'; + +// TODO: mssql supports check constraints as of SQL Server 2008 +// so make enu here more like postgres +ColumnCompiler_MSSQL.prototype.enu = 'nvarchar(100)'; +ColumnCompiler_MSSQL.prototype.uuid = ({ useBinaryUuid = false } = {}) => + useBinaryUuid ? 'binary(16)' : 'uniqueidentifier'; + +ColumnCompiler_MSSQL.prototype.datetime = 'datetime2'; +ColumnCompiler_MSSQL.prototype.bool = 'bit'; + +module.exports = ColumnCompiler_MSSQL; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-compiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-compiler.js new file mode 100644 index 000000000..135222af4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-compiler.js @@ -0,0 +1,91 @@ +// MySQL Schema Compiler +// ------- +const SchemaCompiler = require('../../../schema/compiler'); + +class SchemaCompiler_MSSQL extends SchemaCompiler { + constructor(client, builder) { + super(client, builder); + } + + dropTableIfExists(tableName) { + const name = this.formatter.wrap(prefixedTableName(this.schema, tableName)); + this.pushQuery( + `if object_id('${name}', 'U') is not null DROP TABLE ${name}` + ); + } + + dropViewIfExists(viewName) { + const name = this.formatter.wrap(prefixedTableName(this.schema, viewName)); + this.pushQuery( + `if object_id('${name}', 'V') is not null DROP VIEW ${name}` + ); + } + + // Rename a table on the schema. + renameTable(tableName, to) { + this.pushQuery( + `exec sp_rename ${this.client.parameter( + prefixedTableName(this.schema, tableName), + this.builder, + this.bindingsHolder + )}, ${this.client.parameter(to, this.builder, this.bindingsHolder)}` + ); + } + + renameView(viewTable, to) { + this.pushQuery( + `exec sp_rename ${this.client.parameter( + prefixedTableName(this.schema, viewTable), + this.builder, + this.bindingsHolder + )}, ${this.client.parameter(to, this.builder, this.bindingsHolder)}` + ); + } + + // Check whether a table exists on the query. + hasTable(tableName) { + const formattedTable = this.client.parameter( + prefixedTableName(this.schema, tableName), + this.builder, + this.bindingsHolder + ); + const bindings = [tableName]; + let sql = + `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES ` + + `WHERE TABLE_NAME = ${formattedTable}`; + + if (this.schema) { + sql += ' AND TABLE_SCHEMA = ?'; + bindings.push(this.schema); + } + + this.pushQuery({ sql, bindings, output: (resp) => resp.length > 0 }); + } + + // Check whether a column exists on the schema. + hasColumn(tableName, column) { + const formattedColumn = this.client.parameter( + column, + this.builder, + this.bindingsHolder + ); + const formattedTable = this.client.parameter( + this.formatter.wrap(prefixedTableName(this.schema, tableName)), + this.builder, + this.bindingsHolder + ); + const sql = + `select object_id from sys.columns ` + + `where name = ${formattedColumn} ` + + `and object_id = object_id(${formattedTable})`; + this.pushQuery({ sql, output: (resp) => resp.length > 0 }); + } +} + +SchemaCompiler_MSSQL.prototype.dropTablePrefix = 'DROP TABLE '; + +function prefixedTableName(prefix, table) { + return prefix ? `${prefix}.${table}` : table; +} + +module.exports = SchemaCompiler_MSSQL; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-tablecompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-tablecompiler.js new file mode 100644 index 000000000..4802bd71b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-tablecompiler.js @@ -0,0 +1,378 @@ +/* eslint max-len:0 */ + +// MSSQL Table Builder & Compiler +// ------- +const TableCompiler = require('../../../schema/tablecompiler'); +const helpers = require('../../../util/helpers'); +const { isObject } = require('../../../util/is'); + +// Table Compiler +// ------ + +class TableCompiler_MSSQL extends TableCompiler { + constructor(client, tableBuilder) { + super(client, tableBuilder); + } + + createQuery(columns, ifNot, like) { + let createStatement = ifNot + ? `if object_id('${this.tableName()}', 'U') is null ` + : ''; + + if (like) { + // This query copy only columns and not all indexes and keys like other databases. + createStatement += `SELECT * INTO ${this.tableName()} FROM ${this.tableNameLike()} WHERE 0=1`; + } else { + createStatement += + 'CREATE TABLE ' + + this.tableName() + + (this._formatting ? ' (\n ' : ' (') + + columns.sql.join(this._formatting ? ',\n ' : ', ') + + this._addChecks() + + ')'; + } + + this.pushQuery(createStatement); + + if (this.single.comment) { + this.comment(this.single.comment); + } + if (like) { + this.addColumns(columns, this.addColumnsPrefix); + } + } + + comment(/** @type {string} */ comment) { + if (!comment) { + return; + } + + // XXX: This is a byte limit, not character, so we cannot definitively say they'll exceed the limit without server collation info. + // When I checked in SQL Server 2019, the ctext column in sys.syscomments is defined as a varbinary(8000), so it doesn't even have its own defined collation. + if (comment.length > 7500 / 2) { + this.client.logger.warn( + 'Your comment might be longer than the max comment length for MSSQL of 7,500 bytes.' + ); + } + + // See: https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-addextendedproperty-transact-sql?view=sql-server-ver15#f-adding-an-extended-property-to-a-table + const value = this.formatter.escapingStringDelimiters(comment); + const level0name = this.formatter.escapingStringDelimiters( + this.schemaNameRaw || 'dbo' + ); + const level1name = this.formatter.escapingStringDelimiters( + this.tableNameRaw + ); + const args = `N'MS_Description', N'${value}', N'Schema', N'${level0name}', N'Table', N'${level1name}'`; + const isAlreadyDefined = `EXISTS(SELECT * FROM sys.fn_listextendedproperty(N'MS_Description', N'Schema', N'${level0name}', N'Table', N'${level1name}', NULL, NULL))`; + this.pushQuery( + `IF ${isAlreadyDefined}\n EXEC sys.sp_updateextendedproperty ${args}\nELSE\n EXEC sys.sp_addextendedproperty ${args}` + ); + } + + // Compiles column add. Multiple columns need only one ADD clause (not one ADD per column) so core addColumns doesn't work. #1348 + addColumns(columns, prefix) { + prefix = prefix || this.addColumnsPrefix; + + if (columns.sql.length > 0) { + this.pushQuery({ + sql: + (this.lowerCase ? 'alter table ' : 'ALTER TABLE ') + + this.tableName() + + ' ' + + prefix + + columns.sql.join(', '), + bindings: columns.bindings, + }); + } + } + + alterColumns(columns, colBuilder) { + for (let i = 0, l = colBuilder.length; i < l; i++) { + const builder = colBuilder[i]; + if (builder.modified.defaultTo) { + const schema = this.schemaNameRaw || 'dbo'; + const baseQuery = ` + DECLARE @constraint varchar(100) = (SELECT default_constraints.name + FROM sys.all_columns + INNER JOIN sys.tables + ON all_columns.object_id = tables.object_id + INNER JOIN sys.schemas + ON tables.schema_id = schemas.schema_id + INNER JOIN sys.default_constraints + ON all_columns.default_object_id = default_constraints.object_id + WHERE schemas.name = '${schema}' + AND tables.name = '${ + this.tableNameRaw + }' + AND all_columns.name = '${builder.getColumnName()}') + + IF @constraint IS NOT NULL EXEC('ALTER TABLE ${ + this.tableNameRaw + } DROP CONSTRAINT ' + @constraint)`; + this.pushQuery(baseQuery); + } + } + // in SQL server only one column can be altered at a time + columns.sql.forEach((sql) => { + this.pushQuery({ + sql: + (this.lowerCase ? 'alter table ' : 'ALTER TABLE ') + + this.tableName() + + ' ' + + (this.lowerCase + ? this.alterColumnPrefix.toLowerCase() + : this.alterColumnPrefix) + + sql, + bindings: columns.bindings, + }); + }); + } + + // Compiles column drop. Multiple columns need only one DROP clause (not one DROP per column) so core dropColumn doesn't work. #1348 + dropColumn() { + const _this2 = this; + const columns = helpers.normalizeArr.apply(null, arguments); + const columnsArray = Array.isArray(columns) ? columns : [columns]; + const drops = columnsArray.map((column) => _this2.formatter.wrap(column)); + const schema = this.schemaNameRaw || 'dbo'; + + for (const column of columns) { + const baseQuery = ` + DECLARE @constraint varchar(100) = (SELECT default_constraints.name + FROM sys.all_columns + INNER JOIN sys.tables + ON all_columns.object_id = tables.object_id + INNER JOIN sys.schemas + ON tables.schema_id = schemas.schema_id + INNER JOIN sys.default_constraints + ON all_columns.default_object_id = default_constraints.object_id + WHERE schemas.name = '${schema}' + AND tables.name = '${this.tableNameRaw}' + AND all_columns.name = '${column}') + + IF @constraint IS NOT NULL EXEC('ALTER TABLE ${this.tableNameRaw} DROP CONSTRAINT ' + @constraint)`; + this.pushQuery(baseQuery); + } + this.pushQuery( + (this.lowerCase ? 'alter table ' : 'ALTER TABLE ') + + this.tableName() + + ' ' + + this.dropColumnPrefix + + drops.join(', ') + ); + } + + changeType() {} + + // Renames a column on the table. + renameColumn(from, to) { + this.pushQuery( + `exec sp_rename ${this.client.parameter( + this.tableName() + '.' + from, + this.tableBuilder, + this.bindingsHolder + )}, ${this.client.parameter( + to, + this.tableBuilder, + this.bindingsHolder + )}, 'COLUMN'` + ); + } + + dropFKRefs(runner, refs) { + const formatter = this.client.formatter(this.tableBuilder); + return Promise.all( + refs.map(function (ref) { + const constraintName = formatter.wrap(ref.CONSTRAINT_NAME); + const tableName = formatter.wrap(ref.TABLE_NAME); + return runner.query({ + sql: `ALTER TABLE ${tableName} DROP CONSTRAINT ${constraintName}`, + }); + }) + ); + } + + createFKRefs(runner, refs) { + const formatter = this.client.formatter(this.tableBuilder); + + return Promise.all( + refs.map(function (ref) { + const tableName = formatter.wrap(ref.TABLE_NAME); + const keyName = formatter.wrap(ref.CONSTRAINT_NAME); + const column = formatter.columnize(ref.COLUMN_NAME); + const references = formatter.columnize(ref.REFERENCED_COLUMN_NAME); + const inTable = formatter.wrap(ref.REFERENCED_TABLE_NAME); + const onUpdate = ` ON UPDATE ${ref.UPDATE_RULE}`; + const onDelete = ` ON DELETE ${ref.DELETE_RULE}`; + + return runner.query({ + sql: + `ALTER TABLE ${tableName} ADD CONSTRAINT ${keyName}` + + ' FOREIGN KEY (' + + column + + ') REFERENCES ' + + inTable + + ' (' + + references + + ')' + + onUpdate + + onDelete, + }); + }) + ); + } + + index(columns, indexName, options) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('index', this.tableNameRaw, columns); + + let predicate; + if (isObject(options)) { + ({ predicate } = options); + } + const predicateQuery = predicate + ? ' ' + this.client.queryCompiler(predicate).where() + : ''; + this.pushQuery( + `CREATE INDEX ${indexName} ON ${this.tableName()} (${this.formatter.columnize( + columns + )})${predicateQuery}` + ); + } + + /** + * Create a primary key. + * + * @param {undefined | string | string[]} columns + * @param {string | {constraintName: string, deferrable?: 'not deferrable'|'deferred'|'immediate' }} constraintName + */ + primary(columns, constraintName) { + let deferrable; + if (isObject(constraintName)) { + ({ constraintName, deferrable } = constraintName); + } + if (deferrable && deferrable !== 'not deferrable') { + this.client.logger.warn( + `mssql: primary key constraint [${constraintName}] will not be deferrable ${deferrable} because mssql does not support deferred constraints.` + ); + } + constraintName = constraintName + ? this.formatter.wrap(constraintName) + : this.formatter.wrap(`${this.tableNameRaw}_pkey`); + if (!this.forCreate) { + this.pushQuery( + `ALTER TABLE ${this.tableName()} ADD CONSTRAINT ${constraintName} PRIMARY KEY (${this.formatter.columnize( + columns + )})` + ); + } else { + this.pushQuery( + `CONSTRAINT ${constraintName} PRIMARY KEY (${this.formatter.columnize( + columns + )})` + ); + } + } + + /** + * Create a unique index. + * + * @param {string | string[]} columns + * @param {string | {indexName: undefined | string, deferrable?: 'not deferrable'|'deferred'|'immediate', useConstraint?: true|false, predicate?: QueryBuilder }} indexName + */ + unique(columns, indexName) { + /** @type {string | undefined} */ + let deferrable; + let useConstraint = false; + let predicate; + if (isObject(indexName)) { + ({ indexName, deferrable, useConstraint, predicate } = indexName); + } + if (deferrable && deferrable !== 'not deferrable') { + this.client.logger.warn( + `mssql: unique index [${indexName}] will not be deferrable ${deferrable} because mssql does not support deferred constraints.` + ); + } + if (useConstraint && predicate) { + throw new Error('mssql cannot create constraint with predicate'); + } + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('unique', this.tableNameRaw, columns); + + if (!Array.isArray(columns)) { + columns = [columns]; + } + + if (useConstraint) { + // mssql supports unique indexes and unique constraints. + // unique indexes cannot be used with foreign key relationships hence unique constraints are used instead. + this.pushQuery( + `ALTER TABLE ${this.tableName()} ADD CONSTRAINT ${indexName} UNIQUE (${this.formatter.columnize( + columns + )})` + ); + } else { + // default to making unique index that allows null https://stackoverflow.com/a/767702/360060 + // to be more or less compatible with other DBs (if any of the columns is NULL then "duplicates" are allowed) + const predicateQuery = predicate + ? ' ' + this.client.queryCompiler(predicate).where() + : ' WHERE ' + + columns + .map((column) => this.formatter.columnize(column) + ' IS NOT NULL') + .join(' AND '); + this.pushQuery( + `CREATE UNIQUE INDEX ${indexName} ON ${this.tableName()} (${this.formatter.columnize( + columns + )})${predicateQuery}` + ); + } + } + + // Compile a drop index command. + dropIndex(columns, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('index', this.tableNameRaw, columns); + this.pushQuery(`DROP INDEX ${indexName} ON ${this.tableName()}`); + } + + // Compile a drop foreign key command. + dropForeign(columns, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('foreign', this.tableNameRaw, columns); + this.pushQuery( + `ALTER TABLE ${this.tableName()} DROP CONSTRAINT ${indexName}` + ); + } + + // Compile a drop primary key command. + dropPrimary(constraintName) { + constraintName = constraintName + ? this.formatter.wrap(constraintName) + : this.formatter.wrap(`${this.tableNameRaw}_pkey`); + this.pushQuery( + `ALTER TABLE ${this.tableName()} DROP CONSTRAINT ${constraintName}` + ); + } + + // Compile a drop unique key command. + dropUnique(column, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('unique', this.tableNameRaw, column); + this.pushQuery(`DROP INDEX ${indexName} ON ${this.tableName()}`); + } +} + +TableCompiler_MSSQL.prototype.createAlterTableMethods = ['foreign', 'primary']; +TableCompiler_MSSQL.prototype.lowerCase = false; + +TableCompiler_MSSQL.prototype.addColumnsPrefix = 'ADD '; +TableCompiler_MSSQL.prototype.dropColumnPrefix = 'DROP COLUMN '; +TableCompiler_MSSQL.prototype.alterColumnPrefix = 'ALTER COLUMN '; + +module.exports = TableCompiler_MSSQL; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-viewcompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-viewcompiler.js new file mode 100644 index 000000000..981e1b599 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/schema/mssql-viewcompiler.js @@ -0,0 +1,55 @@ +/* eslint max-len: 0 */ + +const ViewCompiler = require('../../../schema/viewcompiler.js'); +const { + columnize: columnize_, +} = require('../../../formatter/wrappingFormatter'); + +class ViewCompiler_MSSQL extends ViewCompiler { + constructor(client, viewCompiler) { + super(client, viewCompiler); + } + + createQuery(columns, selectQuery, materialized, replace) { + const createStatement = 'CREATE ' + (replace ? 'OR ALTER ' : '') + 'VIEW '; + let sql = createStatement + this.viewName(); + + const columnList = columns + ? ' (' + + columnize_( + columns, + this.viewBuilder, + this.client, + this.bindingsHolder + ) + + ')' + : ''; + + sql += columnList; + sql += ' AS '; + sql += selectQuery.toString(); + this.pushQuery({ + sql, + }); + } + + renameColumn(from, to) { + this.pushQuery( + `exec sp_rename ${this.client.parameter( + this.viewName() + '.' + from, + this.viewBuilder, + this.bindingsHolder + )}, ${this.client.parameter( + to, + this.viewBuilder, + this.bindingsHolder + )}, 'COLUMN'` + ); + } + + createOrReplace() { + this.createQuery(this.columns, this.selectQuery, false, true); + } +} + +module.exports = ViewCompiler_MSSQL; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/transaction.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/transaction.js new file mode 100644 index 000000000..52fc0aee8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mssql/transaction.js @@ -0,0 +1,176 @@ +const Transaction = require('../../execution/transaction'); +const debug = require('debug')('knex:tx'); + +class Transaction_MSSQL extends Transaction { + begin(/** @type {import('tedious').Connection} */ conn) { + debug('transaction::begin id=%s', this.txid); + + return new Promise((resolve, reject) => { + conn.beginTransaction( + (err) => { + if (err) { + debug( + 'transaction::begin error id=%s message=%s', + this.txid, + err.message + ); + return reject(err); + } + resolve(); + }, + this.outerTx ? this.txid : undefined, + nameToIsolationLevelEnum(this.isolationLevel) + ); + }).then(this._resolver, this._rejecter); + } + + savepoint(conn) { + debug('transaction::savepoint id=%s', this.txid); + + return new Promise((resolve, reject) => { + conn.saveTransaction( + (err) => { + if (err) { + debug( + 'transaction::savepoint id=%s message=%s', + this.txid, + err.message + ); + return reject(err); + } + + this.trxClient.emit('query', { + __knexUid: this.trxClient.__knexUid, + __knexTxId: this.trxClient.__knexTxId, + autogenerated: true, + sql: this.outerTx + ? `SAVE TRANSACTION [${this.txid}]` + : `SAVE TRANSACTION`, + }); + resolve(); + }, + this.outerTx ? this.txid : undefined + ); + }); + } + + commit(conn, value) { + debug('transaction::commit id=%s', this.txid); + + return new Promise((resolve, reject) => { + conn.commitTransaction( + (err) => { + if (err) { + debug( + 'transaction::commit error id=%s message=%s', + this.txid, + err.message + ); + return reject(err); + } + + this._completed = true; + resolve(value); + }, + this.outerTx ? this.txid : undefined + ); + }).then(() => this._resolver(value), this._rejecter); + } + + release(conn, value) { + return this._resolver(value); + } + + rollback(conn, error) { + this._completed = true; + debug('transaction::rollback id=%s', this.txid); + + return new Promise((_resolve, reject) => { + if (!conn.inTransaction) { + return reject( + error || new Error('Transaction rejected with non-error: undefined') + ); + } + + if (conn.state.name !== 'LoggedIn') { + return reject( + new Error( + "Can't rollback transaction. There is a request in progress" + ) + ); + } + + conn.rollbackTransaction( + (err) => { + if (err) { + debug( + 'transaction::rollback error id=%s message=%s', + this.txid, + err.message + ); + } + + reject( + err || + error || + new Error('Transaction rejected with non-error: undefined') + ); + }, + this.outerTx ? this.txid : undefined + ); + }).catch((err) => { + if (!error && this.doNotRejectOnRollback) { + this._resolver(); + return; + } + if (error) { + try { + err.originalError = error; + } catch (_err) { + // This is to handle https://github.com/knex/knex/issues/4128 + } + } + this._rejecter(err); + }); + } + + rollbackTo(conn, error) { + return this.rollback(conn, error).then( + () => + void this.trxClient.emit('query', { + __knexUid: this.trxClient.__knexUid, + __knexTxId: this.trxClient.__knexTxId, + autogenerated: true, + sql: `ROLLBACK TRANSACTION`, + }) + ); + } +} + +module.exports = Transaction_MSSQL; + +function nameToIsolationLevelEnum(level) { + if (!level) return; + level = level.toUpperCase().replace(' ', '_'); + const knownEnum = isolationEnum[level]; + if (!knownEnum) { + throw new Error( + `Unknown Isolation level, was expecting one of: ${JSON.stringify( + humanReadableKeys + )}` + ); + } + return knownEnum; +} + +// Based on: https://github.com/tediousjs/node-mssql/blob/master/lib/isolationlevel.js +const isolationEnum = { + READ_UNCOMMITTED: 0x01, + READ_COMMITTED: 0x02, + REPEATABLE_READ: 0x03, + SERIALIZABLE: 0x04, + SNAPSHOT: 0x05, +}; +const humanReadableKeys = Object.keys(isolationEnum).map((key) => + key.toLowerCase().replace('_', ' ') +); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/index.js new file mode 100644 index 000000000..fe316c533 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/index.js @@ -0,0 +1,206 @@ +// MySQL Client +// ------- +const defer = require('lodash/defer'); +const map = require('lodash/map'); +const { promisify } = require('util'); +const Client = require('../../client'); + +const Transaction = require('./transaction'); +const QueryBuilder = require('./query/mysql-querybuilder'); +const QueryCompiler = require('./query/mysql-querycompiler'); +const SchemaCompiler = require('./schema/mysql-compiler'); +const TableCompiler = require('./schema/mysql-tablecompiler'); +const ColumnCompiler = require('./schema/mysql-columncompiler'); + +const { makeEscape } = require('../../util/string'); +const ViewCompiler = require('./schema/mysql-viewcompiler'); +const ViewBuilder = require('./schema/mysql-viewbuilder'); + +// Always initialize with the "QueryBuilder" and "QueryCompiler" +// objects, which extend the base 'lib/query/builder' and +// 'lib/query/compiler', respectively. +class Client_MySQL extends Client { + _driver() { + return require('mysql'); + } + + queryBuilder() { + return new QueryBuilder(this); + } + + queryCompiler(builder, formatter) { + return new QueryCompiler(this, builder, formatter); + } + + schemaCompiler() { + return new SchemaCompiler(this, ...arguments); + } + + tableCompiler() { + return new TableCompiler(this, ...arguments); + } + + viewCompiler() { + return new ViewCompiler(this, ...arguments); + } + + viewBuilder() { + return new ViewBuilder(this, ...arguments); + } + + columnCompiler() { + return new ColumnCompiler(this, ...arguments); + } + + transaction() { + return new Transaction(this, ...arguments); + } + + wrapIdentifierImpl(value) { + return value !== '*' ? `\`${value.replace(/`/g, '``')}\`` : '*'; + } + + // Get a raw connection, called by the `pool` whenever a new + // connection needs to be added to the pool. + acquireRawConnection() { + return new Promise((resolver, rejecter) => { + const connection = this.driver.createConnection(this.connectionSettings); + connection.on('error', (err) => { + connection.__knex__disposed = err; + }); + connection.connect((err) => { + if (err) { + // if connection is rejected, remove listener that was registered above... + connection.removeAllListeners(); + return rejecter(err); + } + resolver(connection); + }); + }); + } + + // Used to explicitly close a connection, called internally by the pool + // when a connection times out or the pool is shutdown. + async destroyRawConnection(connection) { + try { + const end = promisify((cb) => connection.end(cb)); + return await end(); + } catch (err) { + connection.__knex__disposed = err; + } finally { + // see discussion https://github.com/knex/knex/pull/3483 + defer(() => connection.removeAllListeners()); + } + } + + validateConnection(connection) { + return ( + connection.state === 'connected' || connection.state === 'authenticated' + ); + } + + // Grab a connection, run the query via the MySQL streaming interface, + // and pass that through to the stream we've sent back to the client. + _stream(connection, obj, stream, options) { + if (!obj.sql) throw new Error('The query is empty'); + + options = options || {}; + const queryOptions = Object.assign({ sql: obj.sql }, obj.options); + return new Promise((resolver, rejecter) => { + stream.on('error', rejecter); + stream.on('end', resolver); + const queryStream = connection + .query(queryOptions, obj.bindings) + .stream(options); + + queryStream.on('error', (err) => { + rejecter(err); + stream.emit('error', err); + }); + + queryStream.pipe(stream); + }); + } + + // Runs the query on the specified connection, providing the bindings + // and any other necessary prep work. + _query(connection, obj) { + if (!obj || typeof obj === 'string') obj = { sql: obj }; + if (!obj.sql) throw new Error('The query is empty'); + + return new Promise(function (resolver, rejecter) { + if (!obj.sql) { + resolver(); + return; + } + const queryOptions = Object.assign({ sql: obj.sql }, obj.options); + connection.query( + queryOptions, + obj.bindings, + function (err, rows, fields) { + if (err) return rejecter(err); + obj.response = [rows, fields]; + resolver(obj); + } + ); + }); + } + + // Process the response as returned from the query. + processResponse(obj, runner) { + if (obj == null) return; + const { response } = obj; + const { method } = obj; + const rows = response[0]; + const fields = response[1]; + if (obj.output) return obj.output.call(runner, rows, fields); + switch (method) { + case 'select': + return rows; + case 'first': + return rows[0]; + case 'pluck': + return map(rows, obj.pluck); + case 'insert': + return [rows.insertId]; + case 'del': + case 'update': + case 'counter': + return rows.affectedRows; + default: + return response; + } + } + + async cancelQuery(connectionToKill) { + const conn = await this.acquireRawConnection(); + try { + return await this._wrappedCancelQueryCall(conn, connectionToKill); + } finally { + await this.destroyRawConnection(conn); + if (conn.__knex__disposed) { + this.logger.warn(`Connection Error: ${conn.__knex__disposed}`); + } + } + } + + _wrappedCancelQueryCall(conn, connectionToKill) { + return this._query(conn, { + sql: 'KILL QUERY ?', + bindings: [connectionToKill.threadId], + options: {}, + }); + } +} + +Object.assign(Client_MySQL.prototype, { + dialect: 'mysql', + + driverName: 'mysql', + + _escapeBinding: makeEscape(), + + canCancelQuery: true, +}); + +module.exports = Client_MySQL; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/query/mysql-querybuilder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/query/mysql-querybuilder.js new file mode 100644 index 000000000..28acd40dd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/query/mysql-querybuilder.js @@ -0,0 +1,14 @@ +const QueryBuilder = require('../../../query/querybuilder'); +const isEmpty = require('lodash/isEmpty'); + +module.exports = class QueryBuilder_MySQL extends QueryBuilder { + upsert(values, returning, options) { + this._method = 'upsert'; + if (!isEmpty(returning)) { + this.returning(returning, options); + } + + this._single.upsert = values; + return this; + } +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/query/mysql-querycompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/query/mysql-querycompiler.js new file mode 100644 index 000000000..e694c9945 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/query/mysql-querycompiler.js @@ -0,0 +1,292 @@ +// MySQL Query Compiler +// ------ +const assert = require('assert'); +const identity = require('lodash/identity'); +const isPlainObject = require('lodash/isPlainObject'); +const isEmpty = require('lodash/isEmpty'); +const QueryCompiler = require('../../../query/querycompiler'); +const { wrapAsIdentifier } = require('../../../formatter/formatterUtils'); +const { + columnize: columnize_, + wrap: wrap_, +} = require('../../../formatter/wrappingFormatter'); + +const isPlainObjectOrArray = (value) => + isPlainObject(value) || Array.isArray(value); + +class QueryCompiler_MySQL extends QueryCompiler { + constructor(client, builder, formatter) { + super(client, builder, formatter); + + const { returning } = this.single; + if (returning) { + this.client.logger.warn( + '.returning() is not supported by mysql and will not have any effect.' + ); + } + + this._emptyInsertValue = '() values ()'; + } + // Compiles an `delete` allowing comments + del() { + const sql = super.del(); + if (sql === '') return sql; + const comments = this.comments(); + return (comments === '' ? '' : comments + ' ') + sql; + } + + // Compiles an `insert` query, allowing for multiple + // inserts using a single query statement. + insert() { + let sql = super.insert(); + if (sql === '') return sql; + const comments = this.comments(); + sql = (comments === '' ? '' : comments + ' ') + sql; + + const { ignore, merge, insert } = this.single; + if (ignore) sql = sql.replace('insert into', 'insert ignore into'); + if (merge) { + sql += this._merge(merge.updates, insert); + const wheres = this.where(); + if (wheres) { + throw new Error( + '.onConflict().merge().where() is not supported for mysql' + ); + } + } + + return sql; + } + + upsert() { + const upsertValues = this.single.upsert || []; + const sql = this.with() + `replace into ${this.tableName} `; + const body = this._insertBody(upsertValues); + return body === '' ? '' : sql + body; + } + + // Compiles merge for onConflict, allowing for different merge strategies + _merge(updates, insert) { + const sql = ' on duplicate key update '; + if (updates && Array.isArray(updates)) { + // update subset of columns + return ( + sql + + updates + .map((column) => + wrapAsIdentifier(column, this.formatter.builder, this.client) + ) + .map((column) => `${column} = values(${column})`) + .join(', ') + ); + } else if (updates && typeof updates === 'object') { + const updateData = this._prepUpdate(updates); + return sql + updateData.join(','); + } else { + const insertData = this._prepInsert(insert); + if (typeof insertData === 'string') { + throw new Error( + 'If using merge with a raw insert query, then updates must be provided' + ); + } + + return ( + sql + + insertData.columns + .map((column) => wrapAsIdentifier(column, this.builder, this.client)) + .map((column) => `${column} = values(${column})`) + .join(', ') + ); + } + } + + // Update method, including joins, wheres, order & limits. + update() { + const comments = this.comments(); + const withSQL = this.with(); + const join = this.join(); + const updates = this._prepUpdate(this.single.update); + const where = this.where(); + const order = this.order(); + const limit = this.limit(); + return ( + (comments === '' ? '' : comments + ' ') + + withSQL + + `update ${this.tableName}` + + (join ? ` ${join}` : '') + + ' set ' + + updates.join(', ') + + (where ? ` ${where}` : '') + + (order ? ` ${order}` : '') + + (limit ? ` ${limit}` : '') + ); + } + + forUpdate() { + return 'for update'; + } + + forShare() { + return 'lock in share mode'; + } + + // Only supported on MySQL 8.0+ + skipLocked() { + return 'skip locked'; + } + + // Supported on MySQL 8.0+ and MariaDB 10.3.0+ + noWait() { + return 'nowait'; + } + + // Compiles a `columnInfo` query. + columnInfo() { + const column = this.single.columnInfo; + + // The user may have specified a custom wrapIdentifier function in the config. We + // need to run the identifiers through that function, but not format them as + // identifiers otherwise. + const table = this.client.customWrapIdentifier(this.single.table, identity); + + return { + sql: 'select * from information_schema.columns where table_name = ? and table_schema = ?', + bindings: [table, this.client.database()], + output(resp) { + const out = resp.reduce(function (columns, val) { + columns[val.COLUMN_NAME] = { + defaultValue: + val.COLUMN_DEFAULT === 'NULL' ? null : val.COLUMN_DEFAULT, + type: val.DATA_TYPE, + maxLength: val.CHARACTER_MAXIMUM_LENGTH, + nullable: val.IS_NULLABLE === 'YES', + }; + return columns; + }, {}); + return (column && out[column]) || out; + }, + }; + } + + limit() { + const noLimit = !this.single.limit && this.single.limit !== 0; + if (noLimit && !this.single.offset) return ''; + + // Workaround for offset only. + // see: http://stackoverflow.com/questions/255517/mysql-offset-infinite-rows + const limit = + this.single.offset && noLimit + ? '18446744073709551615' + : this._getValueOrParameterFromAttribute('limit'); + return `limit ${limit}`; + } + + whereBasic(statement) { + assert( + !isPlainObjectOrArray(statement.value), + 'The values in where clause must not be object or array.' + ); + + return super.whereBasic(statement); + } + + whereRaw(statement) { + assert( + isEmpty(statement.value.bindings) || + !Object.values(statement.value.bindings).some(isPlainObjectOrArray), + 'The values in where clause must not be object or array.' + ); + + return super.whereRaw(statement); + } + + whereLike(statement) { + return `${this._columnClause(statement)} ${this._not( + statement, + 'like ' + )}${this._valueClause(statement)} COLLATE utf8_bin`; + } + + whereILike(statement) { + return `${this._columnClause(statement)} ${this._not( + statement, + 'like ' + )}${this._valueClause(statement)}`; + } + + // Json functions + jsonExtract(params) { + return this._jsonExtract(['json_extract', 'json_unquote'], params); + } + + jsonSet(params) { + return this._jsonSet('json_set', params); + } + + jsonInsert(params) { + return this._jsonSet('json_insert', params); + } + + jsonRemove(params) { + const jsonCol = `json_remove(${columnize_( + params.column, + this.builder, + this.client, + this.bindingsHolder + )},${this.client.parameter( + params.path, + this.builder, + this.bindingsHolder + )})`; + return params.alias + ? this.client.alias(jsonCol, this.formatter.wrap(params.alias)) + : jsonCol; + } + + whereJsonObject(statement) { + return this._not( + statement, + `json_contains(${this._columnClause(statement)}, ${this._jsonValueClause( + statement + )})` + ); + } + + whereJsonPath(statement) { + return this._whereJsonPath('json_extract', statement); + } + + whereJsonSupersetOf(statement) { + return this._not( + statement, + `json_contains(${wrap_( + statement.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + )},${this._jsonValueClause(statement)})` + ); + } + + whereJsonSubsetOf(statement) { + return this._not( + statement, + `json_contains(${this._jsonValueClause(statement)},${wrap_( + statement.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + )})` + ); + } + + onJsonPathEquals(clause) { + return this._onJsonPathEquals('json_extract', clause); + } +} + +// Set the QueryBuilder & QueryCompiler on the client object, +// in case anyone wants to modify things to suit their own purposes. +module.exports = QueryCompiler_MySQL; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-columncompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-columncompiler.js new file mode 100644 index 000000000..c9bd9162f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-columncompiler.js @@ -0,0 +1,193 @@ +// MySQL Column Compiler +// ------- +const ColumnCompiler = require('../../../schema/columncompiler'); +const { isObject } = require('../../../util/is'); +const { toNumber } = require('../../../util/helpers'); + +const commentEscapeRegex = /(? 255) { + this.client.logger.warn( + 'Your comment is longer than the max comment length for MySQL' + ); + } + return comment && `comment '${comment.replace(commentEscapeRegex, "\\'")}'`; + } + + first() { + return 'first'; + } + + after(column) { + return `after ${this.formatter.wrap(column)}`; + } + + collate(collation) { + return collation && `collate '${collation}'`; + } + + checkRegex(regex, constraintName) { + return this._check( + `${this.formatter.wrap( + this.getColumnName() + )} REGEXP ${this.client._escapeBinding(regex)}`, + constraintName + ); + } + + increments(options = { primaryKey: true }) { + return ( + 'int unsigned not null' + + // In MySQL autoincrement are always a primary key. If you already have a primary key, we + // initialize this column as classic int column then modify it later in table compiler + (this.tableCompiler._canBeAddPrimaryKey(options) + ? ' auto_increment primary key' + : '') + ); + } + + bigincrements(options = { primaryKey: true }) { + return ( + 'bigint unsigned not null' + + // In MySQL autoincrement are always a primary key. If you already have a primary key, we + // initialize this column as classic int column then modify it later in table compiler + (this.tableCompiler._canBeAddPrimaryKey(options) + ? ' auto_increment primary key' + : '') + ); + } +} + +ColumnCompiler_MySQL.prototype.bigint = 'bigint'; +ColumnCompiler_MySQL.prototype.mediumint = 'mediumint'; +ColumnCompiler_MySQL.prototype.smallint = 'smallint'; + +module.exports = ColumnCompiler_MySQL; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-compiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-compiler.js new file mode 100644 index 000000000..7b84bacdb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-compiler.js @@ -0,0 +1,60 @@ +// MySQL Schema Compiler +// ------- +const SchemaCompiler = require('../../../schema/compiler'); + +class SchemaCompiler_MySQL extends SchemaCompiler { + constructor(client, builder) { + super(client, builder); + } + + // Rename a table on the schema. + renameTable(tableName, to) { + this.pushQuery( + `rename table ${this.formatter.wrap(tableName)} to ${this.formatter.wrap( + to + )}` + ); + } + + renameView(from, to) { + this.renameTable(from, to); + } + + // Check whether a table exists on the query. + hasTable(tableName) { + let sql = 'select * from information_schema.tables where table_name = ?'; + const bindings = [tableName]; + + if (this.schema) { + sql += ' and table_schema = ?'; + bindings.push(this.schema); + } else { + sql += ' and table_schema = database()'; + } + + this.pushQuery({ + sql, + bindings, + output: function output(resp) { + return resp.length > 0; + }, + }); + } + + // Check whether a column exists on the schema. + hasColumn(tableName, column) { + this.pushQuery({ + sql: `show columns from ${this.formatter.wrap(tableName)}`, + output(resp) { + return resp.some((row) => { + return ( + this.client.wrapIdentifier(row.Field.toLowerCase()) === + this.client.wrapIdentifier(column.toLowerCase()) + ); + }); + }, + }); + } +} + +module.exports = SchemaCompiler_MySQL; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-tablecompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-tablecompiler.js new file mode 100644 index 000000000..5438c9d61 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-tablecompiler.js @@ -0,0 +1,405 @@ +/* eslint max-len:0*/ + +// MySQL Table Builder & Compiler +// ------- +const TableCompiler = require('../../../schema/tablecompiler'); +const { isObject, isString } = require('../../../util/is'); + +// Table Compiler +// ------ + +class TableCompiler_MySQL extends TableCompiler { + constructor(client, tableBuilder) { + super(client, tableBuilder); + } + + createQuery(columns, ifNot, like) { + const createStatement = ifNot + ? 'create table if not exists ' + : 'create table '; + const { client } = this; + let conn = {}; + let columnsSql = ' (' + columns.sql.join(', '); + + columnsSql += this.primaryKeys() || ''; + columnsSql += this._addChecks(); + columnsSql += ')'; + + let sql = + createStatement + + this.tableName() + + (like && this.tableNameLike() + ? ' like ' + this.tableNameLike() + : columnsSql); + + // Check if the connection settings are set. + if (client.connectionSettings) { + conn = client.connectionSettings; + } + + const charset = this.single.charset || conn.charset || ''; + const collation = this.single.collate || conn.collate || ''; + const engine = this.single.engine || ''; + + if (charset && !like) sql += ` default character set ${charset}`; + if (collation) sql += ` collate ${collation}`; + if (engine) sql += ` engine = ${engine}`; + + if (this.single.comment) { + const comment = this.single.comment || ''; + const MAX_COMMENT_LENGTH = 1024; + if (comment.length > MAX_COMMENT_LENGTH) + this.client.logger.warn( + `The max length for a table comment is ${MAX_COMMENT_LENGTH} characters` + ); + sql += ` comment = '${comment}'`; + } + + this.pushQuery(sql); + if (like) { + this.addColumns(columns, this.addColumnsPrefix); + } + } + + // Compiles the comment on the table. + comment(comment) { + this.pushQuery(`alter table ${this.tableName()} comment = '${comment}'`); + } + + changeType() { + // alter table + table + ' modify ' + wrapped + '// type'; + } + + // Renames a column on the table. + renameColumn(from, to) { + const compiler = this; + const table = this.tableName(); + const wrapped = this.formatter.wrap(from) + ' ' + this.formatter.wrap(to); + + this.pushQuery({ + sql: + `show full fields from ${table} where field = ` + + this.client.parameter(from, this.tableBuilder, this.bindingsHolder), + output(resp) { + const column = resp[0]; + const runner = this; + return compiler.getFKRefs(runner).then(([refs]) => + new Promise((resolve, reject) => { + try { + if (!refs.length) { + resolve(); + } + resolve(compiler.dropFKRefs(runner, refs)); + } catch (e) { + reject(e); + } + }) + .then(function () { + let sql = `alter table ${table} change ${wrapped} ${column.Type}`; + + if (String(column.Null).toUpperCase() !== 'YES') { + sql += ` NOT NULL`; + } else { + // This doesn't matter for most cases except Timestamp, where this is important + sql += ` NULL`; + } + if (column.Default !== void 0 && column.Default !== null) { + sql += ` DEFAULT '${column.Default}'`; + } + if (column.Collation !== void 0 && column.Collation !== null) { + sql += ` COLLATE '${column.Collation}'`; + } + // Add back the auto increment if the column it, fix issue #2767 + if (column.Extra == 'auto_increment') { + sql += ` AUTO_INCREMENT`; + } + + return runner.query({ + sql, + }); + }) + .then(function () { + if (!refs.length) { + return; + } + return compiler.createFKRefs( + runner, + refs.map(function (ref) { + if (ref.REFERENCED_COLUMN_NAME === from) { + ref.REFERENCED_COLUMN_NAME = to; + } + if (ref.COLUMN_NAME === from) { + ref.COLUMN_NAME = to; + } + return ref; + }) + ); + }) + ); + }, + }); + } + + primaryKeys() { + const pks = (this.grouped.alterTable || []).filter( + (k) => k.method === 'primary' + ); + if (pks.length > 0 && pks[0].args.length > 0) { + const columns = pks[0].args[0]; + let constraintName = pks[0].args[1] || ''; + if (constraintName) { + constraintName = ' constraint ' + this.formatter.wrap(constraintName); + } + + if (this.grouped.columns) { + const incrementsCols = this._getIncrementsColumnNames(); + if (incrementsCols.length) { + incrementsCols.forEach((c) => { + if (!columns.includes(c)) { + columns.unshift(c); + } + }); + } + const bigIncrementsCols = this._getBigIncrementsColumnNames(); + if (bigIncrementsCols.length) { + bigIncrementsCols.forEach((c) => { + if (!columns.includes(c)) { + columns.unshift(c); + } + }); + } + } + + return `,${constraintName} primary key (${this.formatter.columnize( + columns + )})`; + } + } + + getFKRefs(runner) { + const bindingsHolder = { + bindings: [], + }; + + const sql = + 'SELECT KCU.CONSTRAINT_NAME, KCU.TABLE_NAME, KCU.COLUMN_NAME, ' + + ' KCU.REFERENCED_TABLE_NAME, KCU.REFERENCED_COLUMN_NAME, ' + + ' RC.UPDATE_RULE, RC.DELETE_RULE ' + + 'FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU ' + + 'JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ' + + ' USING(CONSTRAINT_NAME)' + + 'WHERE KCU.REFERENCED_TABLE_NAME = ' + + this.client.parameter( + this.tableNameRaw, + this.tableBuilder, + bindingsHolder + ) + + ' ' + + ' AND KCU.CONSTRAINT_SCHEMA = ' + + this.client.parameter( + this.client.database(), + this.tableBuilder, + bindingsHolder + ) + + ' ' + + ' AND RC.CONSTRAINT_SCHEMA = ' + + this.client.parameter( + this.client.database(), + this.tableBuilder, + bindingsHolder + ); + + return runner.query({ + sql, + bindings: bindingsHolder.bindings, + }); + } + + dropFKRefs(runner, refs) { + const formatter = this.client.formatter(this.tableBuilder); + + return Promise.all( + refs.map(function (ref) { + const constraintName = formatter.wrap(ref.CONSTRAINT_NAME); + const tableName = formatter.wrap(ref.TABLE_NAME); + return runner.query({ + sql: `alter table ${tableName} drop foreign key ${constraintName}`, + }); + }) + ); + } + + createFKRefs(runner, refs) { + const formatter = this.client.formatter(this.tableBuilder); + + return Promise.all( + refs.map(function (ref) { + const tableName = formatter.wrap(ref.TABLE_NAME); + const keyName = formatter.wrap(ref.CONSTRAINT_NAME); + const column = formatter.columnize(ref.COLUMN_NAME); + const references = formatter.columnize(ref.REFERENCED_COLUMN_NAME); + const inTable = formatter.wrap(ref.REFERENCED_TABLE_NAME); + const onUpdate = ` ON UPDATE ${ref.UPDATE_RULE}`; + const onDelete = ` ON DELETE ${ref.DELETE_RULE}`; + + return runner.query({ + sql: + `alter table ${tableName} add constraint ${keyName} ` + + 'foreign key (' + + column + + ') references ' + + inTable + + ' (' + + references + + ')' + + onUpdate + + onDelete, + }); + }) + ); + } + + index(columns, indexName, options) { + let storageEngineIndexType; + let indexType; + + if (isString(options)) { + indexType = options; + } else if (isObject(options)) { + ({ indexType, storageEngineIndexType } = options); + } + + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('index', this.tableNameRaw, columns); + storageEngineIndexType = storageEngineIndexType + ? ` using ${storageEngineIndexType}` + : ''; + this.pushQuery( + `alter table ${this.tableName()} add${ + indexType ? ` ${indexType}` : '' + } index ${indexName}(${this.formatter.columnize( + columns + )})${storageEngineIndexType}` + ); + } + + primary(columns, constraintName) { + let deferrable; + if (isObject(constraintName)) { + ({ constraintName, deferrable } = constraintName); + } + if (deferrable && deferrable !== 'not deferrable') { + this.client.logger.warn( + `mysql: primary key constraint \`${constraintName}\` will not be deferrable ${deferrable} because mysql does not support deferred constraints.` + ); + } + constraintName = constraintName + ? this.formatter.wrap(constraintName) + : this.formatter.wrap(`${this.tableNameRaw}_pkey`); + + const primaryCols = columns; + let incrementsCols = []; + let bigIncrementsCols = []; + if (this.grouped.columns) { + incrementsCols = this._getIncrementsColumnNames(); + if (incrementsCols) { + incrementsCols.forEach((c) => { + if (!primaryCols.includes(c)) { + primaryCols.unshift(c); + } + }); + } + bigIncrementsCols = this._getBigIncrementsColumnNames(); + if (bigIncrementsCols) { + bigIncrementsCols.forEach((c) => { + if (!primaryCols.includes(c)) { + primaryCols.unshift(c); + } + }); + } + } + if (this.method !== 'create' && this.method !== 'createIfNot') { + this.pushQuery( + `alter table ${this.tableName()} add primary key ${constraintName}(${this.formatter.columnize( + primaryCols + )})` + ); + } + if (incrementsCols.length) { + this.pushQuery( + `alter table ${this.tableName()} modify column ${this.formatter.columnize( + incrementsCols + )} int unsigned not null auto_increment` + ); + } + if (bigIncrementsCols.length) { + this.pushQuery( + `alter table ${this.tableName()} modify column ${this.formatter.columnize( + bigIncrementsCols + )} bigint unsigned not null auto_increment` + ); + } + } + + unique(columns, indexName) { + let storageEngineIndexType; + let deferrable; + if (isObject(indexName)) { + ({ indexName, deferrable, storageEngineIndexType } = indexName); + } + if (deferrable && deferrable !== 'not deferrable') { + this.client.logger.warn( + `mysql: unique index \`${indexName}\` will not be deferrable ${deferrable} because mysql does not support deferred constraints.` + ); + } + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('unique', this.tableNameRaw, columns); + storageEngineIndexType = storageEngineIndexType + ? ` using ${storageEngineIndexType}` + : ''; + this.pushQuery( + `alter table ${this.tableName()} add unique ${indexName}(${this.formatter.columnize( + columns + )})${storageEngineIndexType}` + ); + } + + // Compile a drop index command. + dropIndex(columns, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('index', this.tableNameRaw, columns); + this.pushQuery(`alter table ${this.tableName()} drop index ${indexName}`); + } + + // Compile a drop foreign key command. + dropForeign(columns, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('foreign', this.tableNameRaw, columns); + this.pushQuery( + `alter table ${this.tableName()} drop foreign key ${indexName}` + ); + } + + // Compile a drop primary key command. + dropPrimary() { + this.pushQuery(`alter table ${this.tableName()} drop primary key`); + } + + // Compile a drop unique key command. + dropUnique(column, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('unique', this.tableNameRaw, column); + this.pushQuery(`alter table ${this.tableName()} drop index ${indexName}`); + } +} + +TableCompiler_MySQL.prototype.addColumnsPrefix = 'add '; +TableCompiler_MySQL.prototype.alterColumnsPrefix = 'modify '; +TableCompiler_MySQL.prototype.dropColumnPrefix = 'drop '; + +module.exports = TableCompiler_MySQL; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-viewbuilder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-viewbuilder.js new file mode 100644 index 000000000..bfbec27b1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-viewbuilder.js @@ -0,0 +1,21 @@ +const ViewBuilder = require('../../../schema/viewbuilder.js'); + +class ViewBuilder_MySQL extends ViewBuilder { + constructor() { + super(...arguments); + } + + checkOption() { + this._single.checkOption = 'default_option'; + } + + localCheckOption() { + this._single.checkOption = 'local'; + } + + cascadedCheckOption() { + this._single.checkOption = 'cascaded'; + } +} + +module.exports = ViewBuilder_MySQL; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-viewcompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-viewcompiler.js new file mode 100644 index 000000000..60e2ad651 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/schema/mysql-viewcompiler.js @@ -0,0 +1,15 @@ +/* eslint max-len: 0 */ + +const ViewCompiler = require('../../../schema/viewcompiler.js'); + +class ViewCompiler_MySQL extends ViewCompiler { + constructor(client, viewCompiler) { + super(client, viewCompiler); + } + + createOrReplace() { + this.createQuery(this.columns, this.selectQuery, false, true); + } +} + +module.exports = ViewCompiler_MySQL; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/transaction.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/transaction.js new file mode 100644 index 000000000..e5bee580c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql/transaction.js @@ -0,0 +1,46 @@ +const Transaction = require('../../execution/transaction'); +const Debug = require('debug'); + +const debug = Debug('knex:tx'); + +class Transaction_MySQL extends Transaction { + query(conn, sql, status, value) { + const t = this; + const q = this.trxClient + .query(conn, sql) + .catch((err) => { + if (err.errno === 1305) { + this.trxClient.logger.warn( + 'Transaction was implicitly committed, do not mix transactions and ' + + 'DDL with MySQL (#805)' + ); + return; + } + + status = 2; + value = err; + t._completed = true; + debug('%s error running transaction query', t.txid); + }) + .then(function (res) { + if (status === 1) t._resolver(value); + if (status === 2) { + if (value === undefined) { + if (t.doNotRejectOnRollback && /^ROLLBACK\b/i.test(sql)) { + t._resolver(); + return; + } + value = new Error(`Transaction rejected with non-error: ${value}`); + } + t._rejecter(value); + } + return res; + }); + if (status === 1 || status === 2) { + t._completed = true; + } + return q; + } +} + +module.exports = Transaction_MySQL; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql2/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql2/index.js new file mode 100644 index 000000000..a3c713940 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql2/index.js @@ -0,0 +1,53 @@ +// MySQL2 Client +// ------- +const Client_MySQL = require('../mysql'); +const Transaction = require('./transaction'); + +// Always initialize with the "QueryBuilder" and "QueryCompiler" +// objects, which extend the base 'lib/query/builder' and +// 'lib/query/compiler', respectively. +class Client_MySQL2 extends Client_MySQL { + transaction() { + return new Transaction(this, ...arguments); + } + + _driver() { + return require('mysql2'); + } + + initializeDriver() { + try { + this.driver = this._driver(); + } catch (e) { + let message = `Knex: run\n$ npm install ${this.driverName}`; + + const nodeMajorVersion = process.version.replace(/^v/, '').split('.')[0]; + if (nodeMajorVersion <= 12) { + message += `@3.2.0`; + this.logger.error( + 'Mysql2 version 3.2.0 is the latest version to support Node.js 12 or lower.' + ); + } + message += ` --save`; + this.logger.error(`${message}\n${e.message}\n${e.stack}`); + throw new Error(`${message}\n${e.message}`); + } + } + + validateConnection(connection) { + return ( + connection && + !connection._fatalError && + !connection._protocolError && + !connection._closing && + !connection.stream.destroyed + ); + } +} + +Object.assign(Client_MySQL2.prototype, { + // The "dialect", for reference elsewhere. + driverName: 'mysql2', +}); + +module.exports = Client_MySQL2; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql2/transaction.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql2/transaction.js new file mode 100644 index 000000000..2ced4390d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/mysql2/transaction.js @@ -0,0 +1,44 @@ +const Transaction = require('../../execution/transaction'); +const debug = require('debug')('knex:tx'); + +class Transaction_MySQL2 extends Transaction { + query(conn, sql, status, value) { + const t = this; + const q = this.trxClient + .query(conn, sql) + .catch((err) => { + if (err.code === 'ER_SP_DOES_NOT_EXIST') { + this.trxClient.logger.warn( + 'Transaction was implicitly committed, do not mix transactions and ' + + 'DDL with MySQL (#805)' + ); + return; + } + + status = 2; + value = err; + t._completed = true; + debug('%s error running transaction query', t.txid); + }) + .then(function (res) { + if (status === 1) t._resolver(value); + if (status === 2) { + if (value === undefined) { + if (t.doNotRejectOnRollback && /^ROLLBACK\b/i.test(sql)) { + t._resolver(); + return; + } + value = new Error(`Transaction rejected with non-error: ${value}`); + } + t._rejecter(value); + return res; + } + }); + if (status === 1 || status === 2) { + t._completed = true; + } + return q; + } +} + +module.exports = Transaction_MySQL2; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/DEAD_CODE.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/DEAD_CODE.md new file mode 100644 index 000000000..31b83cfcd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/DEAD_CODE.md @@ -0,0 +1,5 @@ +# Warning: Dead Code + +The `oracle` dialect is mostly dead code at this point. However, a handful of its methods are still referenced by the `oracledb` dialect. So, we are in the process of migrating those methods over to the `oracledb` dialect where they belong. Once that task is completed, we will officially remove the `oracle` dialect. + +In short: do not use the `oracle` dialect. Use the `oracledb` dialect instead. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/index.js new file mode 100644 index 000000000..af669f938 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/index.js @@ -0,0 +1,92 @@ +// Oracle Client +// ------- +const { ReturningHelper } = require('./utils'); +const { isConnectionError } = require('./utils'); +const Client = require('../../client'); +const SchemaCompiler = require('./schema/oracle-compiler'); +const ColumnBuilder = require('./schema/oracle-columnbuilder'); +const ColumnCompiler = require('./schema/oracle-columncompiler'); +const TableCompiler = require('./schema/oracle-tablecompiler'); + +// Always initialize with the "QueryBuilder" and "QueryCompiler" +// objects, which extend the base 'lib/query/builder' and +// 'lib/query/compiler', respectively. +class Client_Oracle extends Client { + schemaCompiler() { + return new SchemaCompiler(this, ...arguments); + } + + columnBuilder() { + return new ColumnBuilder(this, ...arguments); + } + + columnCompiler() { + return new ColumnCompiler(this, ...arguments); + } + + tableCompiler() { + return new TableCompiler(this, ...arguments); + } + + // Return the database for the Oracle client. + database() { + return this.connectionSettings.database; + } + + // Position the bindings for the query. + positionBindings(sql) { + let questionCount = 0; + return sql.replace(/\?/g, function () { + questionCount += 1; + return `:${questionCount}`; + }); + } + + _stream(connection, obj, stream, options) { + if (!obj.sql) throw new Error('The query is empty'); + + return new Promise(function (resolver, rejecter) { + stream.on('error', (err) => { + if (isConnectionError(err)) { + connection.__knex__disposed = err; + } + rejecter(err); + }); + stream.on('end', resolver); + const queryStream = connection.queryStream( + obj.sql, + obj.bindings, + options + ); + queryStream.pipe(stream); + queryStream.on('error', function (error) { + rejecter(error); + stream.emit('error', error); + }); + }); + } + + // Formatter part + + alias(first, second) { + return first + ' ' + second; + } + + parameter(value, builder, formatter) { + // Returning helper uses always ROWID as string + if (value instanceof ReturningHelper && this.driver) { + value = new this.driver.OutParam(this.driver.OCCISTRING); + } else if (typeof value === 'boolean') { + value = value ? 1 : 0; + } + return super.parameter(value, builder, formatter); + } +} + +Object.assign(Client_Oracle.prototype, { + dialect: 'oracle', + + driverName: 'oracle', +}); + +module.exports = Client_Oracle; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/query/oracle-querycompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/query/oracle-querycompiler.js new file mode 100644 index 000000000..ee934cb49 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/query/oracle-querycompiler.js @@ -0,0 +1,343 @@ +/* eslint max-len:0 */ + +// Oracle Query Builder & Compiler +// ------ +const compact = require('lodash/compact'); +const identity = require('lodash/identity'); +const isEmpty = require('lodash/isEmpty'); +const isPlainObject = require('lodash/isPlainObject'); +const reduce = require('lodash/reduce'); +const QueryCompiler = require('../../../query/querycompiler'); +const { ReturningHelper } = require('../utils'); +const { isString } = require('../../../util/is'); + +const components = [ + 'comments', + 'columns', + 'join', + 'where', + 'union', + 'group', + 'having', + 'order', + 'lock', +]; + +// Query Compiler +// ------- + +// Set the "Formatter" to use for the queries, +// ensuring that all parameterized values (even across sub-queries) +// are properly built into the same query. +class QueryCompiler_Oracle extends QueryCompiler { + constructor(client, builder, formatter) { + super(client, builder, formatter); + + const { onConflict } = this.single; + if (onConflict) { + throw new Error('.onConflict() is not supported for oracledb.'); + } + + // Compiles the `select` statement, or nested sub-selects + // by calling each of the component compilers, trimming out + // the empties, and returning a generated query string. + this.first = this.select; + } + + // Compiles an "insert" query, allowing for multiple + // inserts using a single query statement. + insert() { + let insertValues = this.single.insert || []; + let { returning } = this.single; + + if (!Array.isArray(insertValues) && isPlainObject(this.single.insert)) { + insertValues = [this.single.insert]; + } + + // always wrap returning argument in array + if (returning && !Array.isArray(returning)) { + returning = [returning]; + } + + if ( + Array.isArray(insertValues) && + insertValues.length === 1 && + isEmpty(insertValues[0]) + ) { + return this._addReturningToSqlAndConvert( + `insert into ${this.tableName} (${this.formatter.wrap( + this.single.returning + )}) values (default)`, + returning, + this.tableName + ); + } + + if ( + isEmpty(this.single.insert) && + typeof this.single.insert !== 'function' + ) { + return ''; + } + + const insertData = this._prepInsert(insertValues); + + const sql = {}; + + if (isString(insertData)) { + return this._addReturningToSqlAndConvert( + `insert into ${this.tableName} ${insertData}`, + returning + ); + } + + if (insertData.values.length === 1) { + return this._addReturningToSqlAndConvert( + `insert into ${this.tableName} (${this.formatter.columnize( + insertData.columns + )}) values (${this.client.parameterize( + insertData.values[0], + undefined, + this.builder, + this.bindingsHolder + )})`, + returning, + this.tableName + ); + } + + const insertDefaultsOnly = insertData.columns.length === 0; + + sql.sql = + 'begin ' + + insertData.values + .map((value) => { + let returningHelper; + const parameterizedValues = !insertDefaultsOnly + ? this.client.parameterize( + value, + this.client.valueForUndefined, + this.builder, + this.bindingsHolder + ) + : ''; + const returningValues = Array.isArray(returning) + ? returning + : [returning]; + let subSql = `insert into ${this.tableName} `; + + if (returning) { + returningHelper = new ReturningHelper(returningValues.join(':')); + sql.outParams = (sql.outParams || []).concat(returningHelper); + } + + if (insertDefaultsOnly) { + // no columns given so only the default value + subSql += `(${this.formatter.wrap( + this.single.returning + )}) values (default)`; + } else { + subSql += `(${this.formatter.columnize( + insertData.columns + )}) values (${parameterizedValues})`; + } + subSql += returning + ? ` returning ROWID into ${this.client.parameter( + returningHelper, + this.builder, + this.bindingsHolder + )}` + : ''; + + // pre bind position because subSql is an execute immediate parameter + // later position binding will only convert the ? params + + subSql = this.formatter.client.positionBindings(subSql); + + const parameterizedValuesWithoutDefault = parameterizedValues + .replace('DEFAULT, ', '') + .replace(', DEFAULT', ''); + return ( + `execute immediate '${subSql.replace(/'/g, "''")}` + + (parameterizedValuesWithoutDefault || returning ? "' using " : '') + + parameterizedValuesWithoutDefault + + (parameterizedValuesWithoutDefault && returning ? ', ' : '') + + (returning ? 'out ?' : '') + + ';' + ); + }) + .join(' ') + + 'end;'; + + if (returning) { + sql.returning = returning; + // generate select statement with special order by to keep the order because 'in (..)' may change the order + sql.returningSql = + `select ${this.formatter.columnize(returning)}` + + ' from ' + + this.tableName + + ' where ROWID in (' + + sql.outParams.map((v, i) => `:${i + 1}`).join(', ') + + ')' + + ' order by case ROWID ' + + sql.outParams + .map((v, i) => `when CHARTOROWID(:${i + 1}) then ${i}`) + .join(' ') + + ' end'; + } + + return sql; + } + + // Update method, including joins, wheres, order & limits. + update() { + const updates = this._prepUpdate(this.single.update); + const where = this.where(); + let { returning } = this.single; + const sql = + `update ${this.tableName}` + + ' set ' + + updates.join(', ') + + (where ? ` ${where}` : ''); + + if (!returning) { + return sql; + } + + // always wrap returning argument in array + if (!Array.isArray(returning)) { + returning = [returning]; + } + + return this._addReturningToSqlAndConvert(sql, returning, this.tableName); + } + + // Compiles a `truncate` query. + truncate() { + return `truncate table ${this.tableName}`; + } + + forUpdate() { + return 'for update'; + } + + forShare() { + // lock for share is not directly supported by oracle + // use LOCK TABLE .. IN SHARE MODE; instead + this.client.logger.warn( + 'lock for share is not supported by oracle dialect' + ); + return ''; + } + + // Compiles a `columnInfo` query. + columnInfo() { + const column = this.single.columnInfo; + + // The user may have specified a custom wrapIdentifier function in the config. We + // need to run the identifiers through that function, but not format them as + // identifiers otherwise. + const table = this.client.customWrapIdentifier(this.single.table, identity); + + // Node oracle drivers doesn't support LONG type (which is data_default type) + const sql = `select * from xmltable( '/ROWSET/ROW' + passing dbms_xmlgen.getXMLType(' + select char_col_decl_length, column_name, data_type, data_default, nullable + from all_tab_columns where table_name = ''${table}'' ') + columns + CHAR_COL_DECL_LENGTH number, COLUMN_NAME varchar2(200), DATA_TYPE varchar2(106), + DATA_DEFAULT clob, NULLABLE varchar2(1))`; + + return { + sql: sql, + output(resp) { + const out = reduce( + resp, + function (columns, val) { + columns[val.COLUMN_NAME] = { + type: val.DATA_TYPE, + defaultValue: val.DATA_DEFAULT, + maxLength: val.CHAR_COL_DECL_LENGTH, + nullable: val.NULLABLE === 'Y', + }; + return columns; + }, + {} + ); + return (column && out[column]) || out; + }, + }; + } + + select() { + let query = this.with(); + const statements = components.map((component) => { + return this[component](); + }); + query += compact(statements).join(' '); + return this._surroundQueryWithLimitAndOffset(query); + } + + aggregate(stmt) { + return this._aggregate(stmt, { aliasSeparator: ' ' }); + } + + // for single commands only + _addReturningToSqlAndConvert(sql, returning, tableName) { + const res = { + sql, + }; + + if (!returning) { + return res; + } + + const returningValues = Array.isArray(returning) ? returning : [returning]; + const returningHelper = new ReturningHelper(returningValues.join(':')); + res.sql = + sql + + ' returning ROWID into ' + + this.client.parameter(returningHelper, this.builder, this.bindingsHolder); + res.returningSql = `select ${this.formatter.columnize( + returning + )} from ${tableName} where ROWID = :1`; + res.outParams = [returningHelper]; + res.returning = returning; + return res; + } + + _surroundQueryWithLimitAndOffset(query) { + let { limit } = this.single; + const { offset } = this.single; + const hasLimit = limit || limit === 0 || limit === '0'; + limit = +limit; + + if (!hasLimit && !offset) return query; + query = query || ''; + + if (hasLimit && !offset) { + return `select * from (${query}) where rownum <= ${this._getValueOrParameterFromAttribute( + 'limit', + limit + )}`; + } + + const endRow = +offset + (hasLimit ? limit : 10000000000000); + + return ( + 'select * from ' + + '(select row_.*, ROWNUM rownum_ from (' + + query + + ') row_ ' + + 'where rownum <= ' + + (this.single.skipBinding['offset'] + ? endRow + : this.client.parameter(endRow, this.builder, this.bindingsHolder)) + + ') ' + + 'where rownum_ > ' + + this._getValueOrParameterFromAttribute('offset', offset) + ); + } +} + +module.exports = QueryCompiler_Oracle; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/internal/incrementUtils.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/internal/incrementUtils.js new file mode 100644 index 000000000..5f583697d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/internal/incrementUtils.js @@ -0,0 +1,22 @@ +const Trigger = require('./trigger'); + +// helper function for pushAdditional in increments() and bigincrements() +function createAutoIncrementTriggerAndSequence(columnCompiler) { + const trigger = new Trigger(columnCompiler.client.version); + + // TODO Add warning that sequence etc is created + columnCompiler.pushAdditional(function () { + const tableName = this.tableCompiler.tableNameRaw; + const schemaName = this.tableCompiler.schemaNameRaw; + const createTriggerSQL = trigger.createAutoIncrementTrigger( + this.client.logger, + tableName, + schemaName + ); + this.pushQuery(createTriggerSQL); + }); +} + +module.exports = { + createAutoIncrementTriggerAndSequence, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/internal/trigger.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/internal/trigger.js new file mode 100644 index 000000000..e906df13e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/internal/trigger.js @@ -0,0 +1,155 @@ +const { NameHelper } = require('../../utils'); + +class Trigger { + constructor(oracleVersion) { + this.nameHelper = new NameHelper(oracleVersion); + } + + renameColumnTrigger(logger, tableName, columnName, to) { + const triggerName = this.nameHelper.generateCombinedName( + logger, + 'autoinc_trg', + tableName + ); + const sequenceName = this.nameHelper.generateCombinedName( + logger, + 'seq', + tableName + ); + return ( + `DECLARE ` + + `PK_NAME VARCHAR(200); ` + + `IS_AUTOINC NUMBER := 0; ` + + `BEGIN` + + ` EXECUTE IMMEDIATE ('ALTER TABLE "${tableName}" RENAME COLUMN "${columnName}" TO "${to}"');` + + ` SELECT COUNT(*) INTO IS_AUTOINC from "USER_TRIGGERS" where trigger_name = '${triggerName}';` + + ` IF (IS_AUTOINC > 0) THEN` + + ` SELECT cols.column_name INTO PK_NAME` + + ` FROM all_constraints cons, all_cons_columns cols` + + ` WHERE cons.constraint_type = 'P'` + + ` AND cons.constraint_name = cols.constraint_name` + + ` AND cons.owner = cols.owner` + + ` AND cols.table_name = '${tableName}';` + + ` IF ('${to}' = PK_NAME) THEN` + + ` EXECUTE IMMEDIATE ('DROP TRIGGER "${triggerName}"');` + + ` EXECUTE IMMEDIATE ('create or replace trigger "${triggerName}"` + + ` BEFORE INSERT on "${tableName}" for each row` + + ` declare` + + ` checking number := 1;` + + ` begin` + + ` if (:new."${to}" is null) then` + + ` while checking >= 1 loop` + + ` select "${sequenceName}".nextval into :new."${to}" from dual;` + + ` select count("${to}") into checking from "${tableName}"` + + ` where "${to}" = :new."${to}";` + + ` end loop;` + + ` end if;` + + ` end;');` + + ` end if;` + + ` end if;` + + `END;` + ); + } + + createAutoIncrementTrigger(logger, tableName, schemaName) { + const tableQuoted = `"${tableName}"`; + const tableUnquoted = tableName; + const schemaQuoted = schemaName ? `"${schemaName}".` : ''; + const constraintOwner = schemaName ? `'${schemaName}'` : 'cols.owner'; + const triggerName = this.nameHelper.generateCombinedName( + logger, + 'autoinc_trg', + tableName + ); + const sequenceNameUnquoted = this.nameHelper.generateCombinedName( + logger, + 'seq', + tableName + ); + const sequenceNameQuoted = `"${sequenceNameUnquoted}"`; + return ( + `DECLARE ` + + `PK_NAME VARCHAR(200); ` + + `BEGIN` + + ` EXECUTE IMMEDIATE ('CREATE SEQUENCE ${schemaQuoted}${sequenceNameQuoted}');` + + ` SELECT cols.column_name INTO PK_NAME` + // TODO : support autoincrement on table with multiple primary keys + ` FROM all_constraints cons, all_cons_columns cols` + + ` WHERE cons.constraint_type = 'P'` + + ` AND cons.constraint_name = cols.constraint_name` + + ` AND cons.owner = ${constraintOwner}` + + ` AND cols.table_name = '${tableUnquoted}';` + + ` execute immediate ('create or replace trigger ${schemaQuoted}"${triggerName}"` + + ` BEFORE INSERT on ${schemaQuoted}${tableQuoted}` + + ` for each row` + + ` declare` + + ` checking number := 1;` + + ` begin` + + ` if (:new."' || PK_NAME || '" is null) then` + + ` while checking >= 1 loop` + + ` select ${schemaQuoted}${sequenceNameQuoted}.nextval into :new."' || PK_NAME || '" from dual;` + + ` select count("' || PK_NAME || '") into checking from ${schemaQuoted}${tableQuoted}` + + ` where "' || PK_NAME || '" = :new."' || PK_NAME || '";` + + ` end loop;` + + ` end if;` + + ` end;'); ` + + `END;` + ); + } + + renameTableAndAutoIncrementTrigger(logger, tableName, to) { + const triggerName = this.nameHelper.generateCombinedName( + logger, + 'autoinc_trg', + tableName + ); + const sequenceName = this.nameHelper.generateCombinedName( + logger, + 'seq', + tableName + ); + const toTriggerName = this.nameHelper.generateCombinedName( + logger, + 'autoinc_trg', + to + ); + const toSequenceName = this.nameHelper.generateCombinedName( + logger, + 'seq', + to + ); + return ( + `DECLARE ` + + `PK_NAME VARCHAR(200); ` + + `IS_AUTOINC NUMBER := 0; ` + + `BEGIN` + + ` EXECUTE IMMEDIATE ('RENAME "${tableName}" TO "${to}"');` + + ` SELECT COUNT(*) INTO IS_AUTOINC from "USER_TRIGGERS" where trigger_name = '${triggerName}';` + + ` IF (IS_AUTOINC > 0) THEN` + + ` EXECUTE IMMEDIATE ('DROP TRIGGER "${triggerName}"');` + + ` EXECUTE IMMEDIATE ('RENAME "${sequenceName}" TO "${toSequenceName}"');` + + ` SELECT cols.column_name INTO PK_NAME` + + ` FROM all_constraints cons, all_cons_columns cols` + + ` WHERE cons.constraint_type = 'P'` + + ` AND cons.constraint_name = cols.constraint_name` + + ` AND cons.owner = cols.owner` + + ` AND cols.table_name = '${to}';` + + ` EXECUTE IMMEDIATE ('create or replace trigger "${toTriggerName}"` + + ` BEFORE INSERT on "${to}" for each row` + + ` declare` + + ` checking number := 1;` + + ` begin` + + ` if (:new."' || PK_NAME || '" is null) then` + + ` while checking >= 1 loop` + + ` select "${toSequenceName}".nextval into :new."' || PK_NAME || '" from dual;` + + ` select count("' || PK_NAME || '") into checking from "${to}"` + + ` where "' || PK_NAME || '" = :new."' || PK_NAME || '";` + + ` end loop;` + + ` end if;` + + ` end;');` + + ` end if;` + + `END;` + ); + } +} + +module.exports = Trigger; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-columnbuilder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-columnbuilder.js new file mode 100644 index 000000000..b248b4088 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-columnbuilder.js @@ -0,0 +1,17 @@ +const ColumnBuilder = require('../../../schema/columnbuilder'); +const toArray = require('lodash/toArray'); + +class ColumnBuilder_Oracle extends ColumnBuilder { + constructor() { + super(...arguments); + } + + // checkIn added to the builder to allow the column compiler to change the + // order via the modifiers ("check" must be after "default") + checkIn() { + this._modifiers.checkIn = toArray(arguments); + return this; + } +} + +module.exports = ColumnBuilder_Oracle; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-columncompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-columncompiler.js new file mode 100644 index 000000000..589301b4e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-columncompiler.js @@ -0,0 +1,126 @@ +const uniq = require('lodash/uniq'); +const Raw = require('../../../raw'); +const ColumnCompiler = require('../../../schema/columncompiler'); +const { + createAutoIncrementTriggerAndSequence, +} = require('./internal/incrementUtils'); +const { toNumber } = require('../../../util/helpers'); + +// Column Compiler +// ------- + +class ColumnCompiler_Oracle extends ColumnCompiler { + constructor() { + super(...arguments); + this.modifiers = ['defaultTo', 'checkIn', 'nullable', 'comment']; + } + + increments(options = { primaryKey: true }) { + createAutoIncrementTriggerAndSequence(this); + return ( + 'integer not null' + + (this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '') + ); + } + + bigincrements(options = { primaryKey: true }) { + createAutoIncrementTriggerAndSequence(this); + return ( + 'number(20, 0) not null' + + (this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '') + ); + } + + floating(precision) { + const parsedPrecision = toNumber(precision, 0); + return `float${parsedPrecision ? `(${parsedPrecision})` : ''}`; + } + + double(precision, scale) { + // if (!precision) return 'number'; // TODO: Check If default is ok + return `number(${toNumber(precision, 8)}, ${toNumber(scale, 2)})`; + } + + decimal(precision, scale) { + if (precision === null) return 'decimal'; + return `decimal(${toNumber(precision, 8)}, ${toNumber(scale, 2)})`; + } + + integer(length) { + return length ? `number(${toNumber(length, 11)})` : 'integer'; + } + + enu(allowed) { + allowed = uniq(allowed); + const maxLength = (allowed || []).reduce( + (maxLength, name) => Math.max(maxLength, String(name).length), + 1 + ); + + // implicitly add the enum values as checked values + this.columnBuilder._modifiers.checkIn = [allowed]; + + return `varchar2(${maxLength})`; + } + + datetime(without) { + return without ? 'timestamp' : 'timestamp with time zone'; + } + + timestamp(without) { + return without ? 'timestamp' : 'timestamp with time zone'; + } + + bool() { + // implicitly add the check for 0 and 1 + this.columnBuilder._modifiers.checkIn = [[0, 1]]; + return 'number(1, 0)'; + } + + varchar(length) { + return `varchar2(${toNumber(length, 255)})`; + } + + // Modifiers + // ------ + + comment(comment) { + const columnName = this.args[0] || this.defaults('columnName'); + + this.pushAdditional(function () { + this.pushQuery( + `comment on column ${this.tableCompiler.tableName()}.` + + this.formatter.wrap(columnName) + + " is '" + + (comment || '') + + "'" + ); + }, comment); + } + + checkIn(value) { + // TODO: Maybe accept arguments also as array + // TODO: value(s) should be escaped properly + if (value === undefined) { + return ''; + } else if (value instanceof Raw) { + value = value.toQuery(); + } else if (Array.isArray(value)) { + value = value.map((v) => `'${v}'`).join(', '); + } else { + value = `'${value}'`; + } + return `check (${this.formatter.wrap(this.args[0])} in (${value}))`; + } +} + +ColumnCompiler_Oracle.prototype.tinyint = 'smallint'; +ColumnCompiler_Oracle.prototype.smallint = 'smallint'; +ColumnCompiler_Oracle.prototype.mediumint = 'integer'; +ColumnCompiler_Oracle.prototype.biginteger = 'number(20, 0)'; +ColumnCompiler_Oracle.prototype.text = 'clob'; +ColumnCompiler_Oracle.prototype.time = 'timestamp with time zone'; +ColumnCompiler_Oracle.prototype.bit = 'clob'; +ColumnCompiler_Oracle.prototype.json = 'clob'; + +module.exports = ColumnCompiler_Oracle; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-compiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-compiler.js new file mode 100644 index 000000000..4509c31a9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-compiler.js @@ -0,0 +1,124 @@ +// Oracle Schema Compiler +// ------- +const SchemaCompiler = require('../../../schema/compiler'); +const utils = require('../utils'); +const Trigger = require('./internal/trigger'); + +class SchemaCompiler_Oracle extends SchemaCompiler { + constructor() { + super(...arguments); + } + + // Rename a table on the schema. + renameTable(tableName, to) { + const trigger = new Trigger(this.client.version); + const renameTable = trigger.renameTableAndAutoIncrementTrigger( + this.client.logger, + tableName, + to + ); + this.pushQuery(renameTable); + } + + // Check whether a table exists on the query. + hasTable(tableName) { + this.pushQuery({ + sql: + 'select TABLE_NAME from USER_TABLES where TABLE_NAME = ' + + this.client.parameter(tableName, this.builder, this.bindingsHolder), + output(resp) { + return resp.length > 0; + }, + }); + } + + // Check whether a column exists on the schema. + hasColumn(tableName, column) { + const sql = + `select COLUMN_NAME from ALL_TAB_COLUMNS ` + + `where TABLE_NAME = ${this.client.parameter( + tableName, + this.builder, + this.bindingsHolder + )} ` + + `and COLUMN_NAME = ${this.client.parameter( + column, + this.builder, + this.bindingsHolder + )}`; + this.pushQuery({ sql, output: (resp) => resp.length > 0 }); + } + + dropSequenceIfExists(sequenceName) { + const prefix = this.schema ? `"${this.schema}".` : ''; + this.pushQuery( + utils.wrapSqlWithCatch( + `drop sequence ${prefix}${this.formatter.wrap(sequenceName)}`, + -2289 + ) + ); + } + + _dropRelatedSequenceIfExists(tableName) { + // removing the sequence that was possibly generated by increments() column + const nameHelper = new utils.NameHelper(this.client.version); + const sequenceName = nameHelper.generateCombinedName( + this.client.logger, + 'seq', + tableName + ); + this.dropSequenceIfExists(sequenceName); + } + + dropTable(tableName) { + const prefix = this.schema ? `"${this.schema}".` : ''; + this.pushQuery(`drop table ${prefix}${this.formatter.wrap(tableName)}`); + + // removing the sequence that was possibly generated by increments() column + this._dropRelatedSequenceIfExists(tableName); + } + + dropTableIfExists(tableName) { + this.dropObject(tableName, 'table'); + } + + dropViewIfExists(viewName) { + this.dropObject(viewName, 'view'); + } + + dropObject(objectName, type) { + const prefix = this.schema ? `"${this.schema}".` : ''; + let errorCode = -942; + if (type === 'materialized view') { + // https://stackoverflow.com/a/1801453 + errorCode = -12003; + } + this.pushQuery( + utils.wrapSqlWithCatch( + `drop ${type} ${prefix}${this.formatter.wrap(objectName)}`, + errorCode + ) + ); + + // removing the sequence that was possibly generated by increments() column + this._dropRelatedSequenceIfExists(objectName); + } + + refreshMaterializedView(viewName) { + return this.pushQuery({ + sql: `BEGIN DBMS_MVIEW.REFRESH('${ + this.schemaNameRaw ? this.schemaNameRaw + '.' : '' + }${viewName}'); END;`, + }); + } + + dropMaterializedView(viewName) { + this._dropView(viewName, false, true); + } + + dropMaterializedViewIfExists(viewName) { + this.dropObject(viewName, 'materialized view'); + } +} + +module.exports = SchemaCompiler_Oracle; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-tablecompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-tablecompiler.js new file mode 100644 index 000000000..b05a3c84f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/schema/oracle-tablecompiler.js @@ -0,0 +1,197 @@ +/* eslint max-len:0 */ + +const utils = require('../utils'); +const TableCompiler = require('../../../schema/tablecompiler'); +const helpers = require('../../../util/helpers'); +const Trigger = require('./internal/trigger'); +const { isObject } = require('../../../util/is'); + +// Table Compiler +// ------ + +class TableCompiler_Oracle extends TableCompiler { + constructor() { + super(...arguments); + } + + addColumns(columns, prefix) { + if (columns.sql.length > 0) { + prefix = prefix || this.addColumnsPrefix; + + const columnSql = columns.sql; + const alter = this.lowerCase ? 'alter table ' : 'ALTER TABLE '; + + let sql = `${alter}${this.tableName()} ${prefix}`; + if (columns.sql.length > 1) { + sql += `(${columnSql.join(', ')})`; + } else { + sql += columnSql.join(', '); + } + + this.pushQuery({ + sql, + bindings: columns.bindings, + }); + } + } + + // Compile a rename column command. + renameColumn(from, to) { + // Remove quotes around tableName + const tableName = this.tableName().slice(1, -1); + const trigger = new Trigger(this.client.version); + return this.pushQuery( + trigger.renameColumnTrigger(this.client.logger, tableName, from, to) + ); + } + + compileAdd(builder) { + const table = this.formatter.wrap(builder); + const columns = this.prefixArray('add column', this.getColumns(builder)); + return this.pushQuery({ + sql: `alter table ${table} ${columns.join(', ')}`, + }); + } + + // Adds the "create" query to the query sequence. + createQuery(columns, ifNot, like) { + const columnsSql = + like && this.tableNameLike() + ? ' as (select * from ' + this.tableNameLike() + ' where 0=1)' + : ' (' + columns.sql.join(', ') + this._addChecks() + ')'; + const sql = `create table ${this.tableName()}${columnsSql}`; + + this.pushQuery({ + // catch "name is already used by an existing object" for workaround for "if not exists" + sql: ifNot ? utils.wrapSqlWithCatch(sql, -955) : sql, + bindings: columns.bindings, + }); + if (this.single.comment) this.comment(this.single.comment); + if (like) { + this.addColumns(columns, this.addColumnsPrefix); + } + } + + // Compiles the comment on the table. + comment(comment) { + this.pushQuery(`comment on table ${this.tableName()} is '${comment}'`); + } + + dropColumn() { + const columns = helpers.normalizeArr.apply(null, arguments); + this.pushQuery( + `alter table ${this.tableName()} drop (${this.formatter.columnize( + columns + )})` + ); + } + + _indexCommand(type, tableName, columns) { + const nameHelper = new utils.NameHelper(this.client.version); + return this.formatter.wrap( + nameHelper.generateCombinedName( + this.client.logger, + type, + tableName, + columns + ) + ); + } + + primary(columns, constraintName) { + let deferrable; + if (isObject(constraintName)) { + ({ constraintName, deferrable } = constraintName); + } + deferrable = deferrable ? ` deferrable initially ${deferrable}` : ''; + constraintName = constraintName + ? this.formatter.wrap(constraintName) + : this.formatter.wrap(`${this.tableNameRaw}_pkey`); + const primaryCols = columns; + let incrementsCols = []; + if (this.grouped.columns) { + incrementsCols = this._getIncrementsColumnNames(); + if (incrementsCols) { + incrementsCols.forEach((c) => { + if (!primaryCols.includes(c)) { + primaryCols.unshift(c); + } + }); + } + } + this.pushQuery( + `alter table ${this.tableName()} add constraint ${constraintName} primary key (${this.formatter.columnize( + primaryCols + )})${deferrable}` + ); + } + + dropPrimary(constraintName) { + constraintName = constraintName + ? this.formatter.wrap(constraintName) + : this.formatter.wrap(this.tableNameRaw + '_pkey'); + this.pushQuery( + `alter table ${this.tableName()} drop constraint ${constraintName}` + ); + } + + index(columns, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('index', this.tableNameRaw, columns); + this.pushQuery( + `create index ${indexName} on ${this.tableName()}` + + ' (' + + this.formatter.columnize(columns) + + ')' + ); + } + + dropIndex(columns, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('index', this.tableNameRaw, columns); + this.pushQuery(`drop index ${indexName}`); + } + + unique(columns, indexName) { + let deferrable; + if (isObject(indexName)) { + ({ indexName, deferrable } = indexName); + } + deferrable = deferrable ? ` deferrable initially ${deferrable}` : ''; + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('unique', this.tableNameRaw, columns); + this.pushQuery( + `alter table ${this.tableName()} add constraint ${indexName}` + + ' unique (' + + this.formatter.columnize(columns) + + ')' + + deferrable + ); + } + + dropUnique(columns, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('unique', this.tableNameRaw, columns); + this.pushQuery( + `alter table ${this.tableName()} drop constraint ${indexName}` + ); + } + + dropForeign(columns, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('foreign', this.tableNameRaw, columns); + this.pushQuery( + `alter table ${this.tableName()} drop constraint ${indexName}` + ); + } +} + +TableCompiler_Oracle.prototype.addColumnsPrefix = 'add '; +TableCompiler_Oracle.prototype.alterColumnsPrefix = 'modify '; + +module.exports = TableCompiler_Oracle; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/utils.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/utils.js new file mode 100644 index 000000000..dee38eb18 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracle/utils.js @@ -0,0 +1,106 @@ +class NameHelper { + constructor(oracleVersion) { + this.oracleVersion = oracleVersion; + + // In oracle versions prior to 12.2, the maximum length for a database + // object name was 30 characters. 12.2 extended this to 128. + const versionParts = oracleVersion + .split('.') + .map((versionPart) => parseInt(versionPart)); + if ( + versionParts[0] > 12 || + (versionParts[0] === 12 && versionParts[1] >= 2) + ) { + this.limit = 128; + } else { + this.limit = 30; + } + } + + generateCombinedName(logger, postfix, name, subNames) { + const crypto = require('crypto'); + if (!Array.isArray(subNames)) subNames = subNames ? [subNames] : []; + const table = name.replace(/\.|-/g, '_'); + const subNamesPart = subNames.join('_'); + let result = `${table}_${ + subNamesPart.length ? subNamesPart + '_' : '' + }${postfix}`.toLowerCase(); + if (result.length > this.limit) { + logger.warn( + `Automatically generated name "${result}" exceeds ${this.limit} character ` + + `limit for Oracle Database ${this.oracleVersion}. Using base64 encoded sha1 of that name instead.` + ); + // generates the sha1 of the name and encode it with base64 + result = crypto + .createHash('sha1') + .update(result) + .digest('base64') + .replace('=', ''); + } + return result; + } +} + +function wrapSqlWithCatch(sql, errorNumberToCatch) { + return ( + `begin execute immediate '${sql.replace(/'/g, "''")}'; ` + + `exception when others then if sqlcode != ${errorNumberToCatch} then raise; ` + + `end if; ` + + `end;` + ); +} + +function ReturningHelper(columnName) { + this.columnName = columnName; +} + +ReturningHelper.prototype.toString = function () { + return `[object ReturningHelper:${this.columnName}]`; +}; + +// If the error is any of these, we'll assume we need to +// mark the connection as failed +function isConnectionError(err) { + return [ + 'DPI-1010', // not connected + 'DPI-1080', // connection was closed by ORA-%d + 'ORA-03114', // not connected to ORACLE + 'ORA-03113', // end-of-file on communication channel + 'ORA-03135', // connection lost contact + 'ORA-12514', // listener does not currently know of service requested in connect descriptor + 'ORA-00022', // invalid session ID; access denied + 'ORA-00028', // your session has been killed + 'ORA-00031', // your session has been marked for kill + 'ORA-00045', // your session has been terminated with no replay + 'ORA-00378', // buffer pools cannot be created as specified + 'ORA-00602', // internal programming exception + 'ORA-00603', // ORACLE server session terminated by fatal error + 'ORA-00609', // could not attach to incoming connection + 'ORA-01012', // not logged on + 'ORA-01041', // internal error. hostdef extension doesn't exist + 'ORA-01043', // user side memory corruption + 'ORA-01089', // immediate shutdown or close in progress + 'ORA-01092', // ORACLE instance terminated. Disconnection forced + 'ORA-02396', // exceeded maximum idle time, please connect again + 'ORA-03122', // attempt to close ORACLE-side window on user side + 'ORA-12153', // TNS'not connected + 'ORA-12537', // TNS'connection closed + 'ORA-12547', // TNS'lost contact + 'ORA-12570', // TNS'packet reader failure + 'ORA-12583', // TNS'no reader + 'ORA-27146', // post/wait initialization failed + 'ORA-28511', // lost RPC connection + 'ORA-56600', // an illegal OCI function call was issued + 'NJS-024', + 'NJS-003', + ].some(function (prefix) { + return err.message.indexOf(prefix) === 0; + }); +} + +module.exports = { + NameHelper, + isConnectionError, + wrapSqlWithCatch, + ReturningHelper, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/index.js new file mode 100644 index 000000000..dc9af90ce --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/index.js @@ -0,0 +1,381 @@ +// Oracledb Client +// ------- +const each = require('lodash/each'); +const flatten = require('lodash/flatten'); +const isEmpty = require('lodash/isEmpty'); +const map = require('lodash/map'); + +const Formatter = require('../../formatter'); +const QueryCompiler = require('./query/oracledb-querycompiler'); +const TableCompiler = require('./schema/oracledb-tablecompiler'); +const ColumnCompiler = require('./schema/oracledb-columncompiler'); +const { + BlobHelper, + ReturningHelper, + monkeyPatchConnection, +} = require('./utils'); +const ViewCompiler = require('./schema/oracledb-viewcompiler'); +const ViewBuilder = require('./schema/oracledb-viewbuilder'); +const Transaction = require('./transaction'); +const Client_Oracle = require('../oracle'); +const { isString } = require('../../util/is'); +const { outputQuery, unwrapRaw } = require('../../formatter/wrappingFormatter'); +const { compileCallback } = require('../../formatter/formatterUtils'); + +class Client_Oracledb extends Client_Oracle { + constructor(config) { + super(config); + + if (this.version) { + // Normalize version format; null bad format + // to trigger fallback to auto-detect. + this.version = parseVersion(this.version); + } + + if (this.driver) { + process.env.UV_THREADPOOL_SIZE = process.env.UV_THREADPOOL_SIZE || 1; + process.env.UV_THREADPOOL_SIZE = + parseInt(process.env.UV_THREADPOOL_SIZE) + this.driver.poolMax; + } + } + + _driver() { + const client = this; + const oracledb = require('oracledb'); + client.fetchAsString = []; + if (this.config.fetchAsString && Array.isArray(this.config.fetchAsString)) { + this.config.fetchAsString.forEach(function (type) { + if (!isString(type)) return; + type = type.toUpperCase(); + if (oracledb[type]) { + if ( + type !== 'NUMBER' && + type !== 'DATE' && + type !== 'CLOB' && + type !== 'BUFFER' + ) { + this.logger.warn( + 'Only "date", "number", "clob" and "buffer" are supported for fetchAsString' + ); + } + client.fetchAsString.push(oracledb[type]); + } + }); + } + return oracledb; + } + + queryCompiler(builder, formatter) { + return new QueryCompiler(this, builder, formatter); + } + + tableCompiler() { + return new TableCompiler(this, ...arguments); + } + + columnCompiler() { + return new ColumnCompiler(this, ...arguments); + } + + viewBuilder() { + return new ViewBuilder(this, ...arguments); + } + + viewCompiler() { + return new ViewCompiler(this, ...arguments); + } + + formatter(builder) { + return new Formatter(this, builder); + } + + transaction() { + return new Transaction(this, ...arguments); + } + + prepBindings(bindings) { + return map(bindings, (value) => { + if (value instanceof BlobHelper && this.driver) { + return { type: this.driver.BLOB, dir: this.driver.BIND_OUT }; + // Returning helper always use ROWID as string + } else if (value instanceof ReturningHelper && this.driver) { + return { type: this.driver.STRING, dir: this.driver.BIND_OUT }; + } else if (typeof value === 'boolean') { + return value ? 1 : 0; + } + return value; + }); + } + + // Checks whether a value is a function... if it is, we compile it + // otherwise we check whether it's a raw + parameter(value, builder, formatter) { + if (typeof value === 'function') { + return outputQuery( + compileCallback(value, undefined, this, formatter), + true, + builder, + this + ); + } else if (value instanceof BlobHelper) { + formatter.bindings.push(value.value); + return '?'; + } + return unwrapRaw(value, true, builder, this, formatter) || '?'; + } + + // Get a raw connection, called by the `pool` whenever a new + // connection needs to be added to the pool. + acquireRawConnection() { + return new Promise((resolver, rejecter) => { + // If external authentication don't have to worry about username/password and + // if not need to set the username and password + const oracleDbConfig = this.connectionSettings.externalAuth + ? { externalAuth: this.connectionSettings.externalAuth } + : { + user: this.connectionSettings.user, + password: this.connectionSettings.password, + }; + + // In the case of external authentication connection string will be given + oracleDbConfig.connectString = resolveConnectString( + this.connectionSettings + ); + + if (this.connectionSettings.prefetchRowCount) { + oracleDbConfig.prefetchRows = this.connectionSettings.prefetchRowCount; + } + + if (this.connectionSettings.stmtCacheSize !== undefined) { + oracleDbConfig.stmtCacheSize = this.connectionSettings.stmtCacheSize; + } + + this.driver.fetchAsString = this.fetchAsString; + + this.driver.getConnection(oracleDbConfig, (err, connection) => { + if (err) { + return rejecter(err); + } + monkeyPatchConnection(connection, this); + + resolver(connection); + }); + }); + } + + // Used to explicitly close a connection, called internally by the pool + // when a connection times out or the pool is shutdown. + destroyRawConnection(connection) { + return connection.release(); + } + + // Handle oracle version resolution on acquiring connection from pool instead of connection creation. + // Must do this here since only the client used to create a connection would be updated with version + // information on creation. Poses a problem when knex instance is cloned since instances share the + // connection pool while having their own client instances. + async acquireConnection() { + const connection = await super.acquireConnection(); + this.checkVersion(connection); + return connection; + } + + // In Oracle, we need to check the version to dynamically determine + // certain limits. If user did not specify a version, get it from the connection. + checkVersion(connection) { + // Already determined version before? + if (this.version) { + return this.version; + } + + const detectedVersion = parseVersion(connection.oracleServerVersionString); + if (!detectedVersion) { + // When original version is set to null, user-provided version was invalid and we fell-back to auto-detect. + // Otherwise, we couldn't auto-detect at all. Set error message accordingly. + throw new Error( + this.version === null + ? 'Invalid Oracledb version number format passed to knex. Unable to successfully auto-detect as fallback. Please specify a valid oracledb version.' + : 'Unable to detect Oracledb version number automatically. Please specify the version in knex configuration.' + ); + } + + this.version = detectedVersion; + return detectedVersion; + } + + // Runs the query on the specified connection, providing the bindings + // and any other necessary prep work. + _query(connection, obj) { + if (!obj.sql) throw new Error('The query is empty'); + + const options = Object.assign({}, obj.options, { autoCommit: false }); + if (obj.method === 'select') { + options.resultSet = true; + } + return connection + .executeAsync(obj.sql, obj.bindings, options) + .then(async function (response) { + // Flatten outBinds + let outBinds = flatten(response.outBinds); + obj.response = response.rows || []; + obj.rowsAffected = response.rows + ? response.rows.rowsAffected + : response.rowsAffected; + + //added for outBind parameter + if (obj.method === 'raw' && outBinds.length > 0) { + return { + response: outBinds, + }; + } + + if (obj.method === 'update') { + const modifiedRowsCount = obj.rowsAffected.length || obj.rowsAffected; + const updatedObjOutBinding = []; + const updatedOutBinds = []; + const updateOutBinds = (i) => + function (value, index) { + const OutBindsOffset = index * modifiedRowsCount; + updatedOutBinds.push(outBinds[i + OutBindsOffset]); + }; + + for (let i = 0; i < modifiedRowsCount; i++) { + updatedObjOutBinding.push(obj.outBinding[0]); + each(obj.outBinding[0], updateOutBinds(i)); + } + outBinds = updatedOutBinds; + obj.outBinding = updatedObjOutBinding; + } + + if (!obj.returning && outBinds.length === 0) { + if (!connection.isTransaction) { + await connection.commitAsync(); + } + return obj; + } + const rowIds = []; + let offset = 0; + + for (let line = 0; line < obj.outBinding.length; line++) { + const ret = obj.outBinding[line]; + + offset = + offset + + (obj.outBinding[line - 1] ? obj.outBinding[line - 1].length : 0); + + for (let index = 0; index < ret.length; index++) { + const out = ret[index]; + + await new Promise(function (bindResolver, bindRejecter) { + if (out instanceof BlobHelper) { + const blob = outBinds[index + offset]; + if (out.returning) { + obj.response[line] = obj.response[line] || {}; + obj.response[line][out.columnName] = out.value; + } + blob.on('error', function (err) { + bindRejecter(err); + }); + blob.on('finish', function () { + bindResolver(); + }); + blob.write(out.value); + blob.end(); + } else if (obj.outBinding[line][index] === 'ROWID') { + rowIds.push(outBinds[index + offset]); + bindResolver(); + } else { + obj.response[line] = obj.response[line] || {}; + obj.response[line][out] = outBinds[index + offset]; + bindResolver(); + } + }); + } + } + if (obj.returningSql) { + const response = await connection.executeAsync( + obj.returningSql(), + rowIds, + { resultSet: true } + ); + obj.response = response.rows; + } + if (connection.isTransaction) { + return obj; + } + await connection.commitAsync(); + return obj; + }); + } + + // Process the response as returned from the query. + processResponse(obj, runner) { + const { response } = obj; + if (obj.output) { + return obj.output.call(runner, response); + } + switch (obj.method) { + case 'select': + return response; + case 'first': + return response[0]; + case 'pluck': + return map(response, obj.pluck); + case 'insert': + case 'del': + case 'update': + case 'counter': + if ((obj.returning && !isEmpty(obj.returning)) || obj.returningSql) { + return response; + } else if (obj.rowsAffected !== undefined) { + return obj.rowsAffected; + } else { + return 1; + } + default: + return response; + } + } + + processPassedConnection(connection) { + this.checkVersion(connection); + monkeyPatchConnection(connection, this); + } +} + +Client_Oracledb.prototype.driverName = 'oracledb'; + +function parseVersion(versionString) { + try { + // We only care about first two version components at most + const versionParts = versionString.split('.').slice(0, 2); + // Strip off any character suffixes in version number (ex. 12c => 12, 12.2c => 12.2) + versionParts.forEach((versionPart, idx) => { + versionParts[idx] = versionPart.replace(/\D$/, ''); + }); + const version = versionParts.join('.'); + return version.match(/^\d+\.?\d*$/) ? version : null; + } catch (err) { + // Non-string versionString passed in. + return null; + } +} + +function resolveConnectString(connectionSettings) { + if (connectionSettings.connectString) { + return connectionSettings.connectString; + } + + if (!connectionSettings.port) { + return connectionSettings.host + '/' + connectionSettings.database; + } + + return ( + connectionSettings.host + + ':' + + connectionSettings.port + + '/' + + connectionSettings.database + ); +} + +module.exports = Client_Oracledb; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/query/oracledb-querycompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/query/oracledb-querycompiler.js new file mode 100644 index 000000000..8c3c04f81 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/query/oracledb-querycompiler.js @@ -0,0 +1,481 @@ +const clone = require('lodash/clone'); +const each = require('lodash/each'); +const isEmpty = require('lodash/isEmpty'); +const isPlainObject = require('lodash/isPlainObject'); +const Oracle_Compiler = require('../../oracle/query/oracle-querycompiler'); +const ReturningHelper = require('../utils').ReturningHelper; +const BlobHelper = require('../utils').BlobHelper; +const { isString } = require('../../../util/is'); +const { + columnize: columnize_, +} = require('../../../formatter/wrappingFormatter'); + +class Oracledb_Compiler extends Oracle_Compiler { + // Compiles an "insert" query, allowing for multiple + // inserts using a single query statement. + insert() { + const self = this; + const outBindPrep = this._prepOutbindings( + this.single.insert, + this.single.returning + ); + const outBinding = outBindPrep.outBinding; + const returning = outBindPrep.returning; + const insertValues = outBindPrep.values; + + if ( + Array.isArray(insertValues) && + insertValues.length === 1 && + isEmpty(insertValues[0]) + ) { + const returningFragment = this.single.returning + ? ' (' + this.formatter.wrap(this.single.returning) + ')' + : ''; + + return this._addReturningToSqlAndConvert( + 'insert into ' + + this.tableName + + returningFragment + + ' values (default)', + outBinding[0], + this.tableName, + returning + ); + } + + if ( + isEmpty(this.single.insert) && + typeof this.single.insert !== 'function' + ) { + return ''; + } + + const insertData = this._prepInsert(insertValues); + + const sql = {}; + + if (isString(insertData)) { + return this._addReturningToSqlAndConvert( + 'insert into ' + this.tableName + ' ' + insertData, + outBinding[0], + this.tableName, + returning + ); + } + + if (insertData.values.length === 1) { + return this._addReturningToSqlAndConvert( + 'insert into ' + + this.tableName + + ' (' + + this.formatter.columnize(insertData.columns) + + ') values (' + + this.client.parameterize( + insertData.values[0], + undefined, + this.builder, + this.bindingsHolder + ) + + ')', + outBinding[0], + this.tableName, + returning + ); + } + + const insertDefaultsOnly = insertData.columns.length === 0; + sql.returning = returning; + sql.sql = + 'begin ' + + insertData.values + .map(function (value, index) { + const parameterizedValues = !insertDefaultsOnly + ? self.client.parameterize( + value, + self.client.valueForUndefined, + self.builder, + self.bindingsHolder + ) + : ''; + let subSql = 'insert into ' + self.tableName; + + if (insertDefaultsOnly) { + // No columns given so only the default value + subSql += + ' (' + + self.formatter.wrap(self.single.returning) + + ') values (default)'; + } else { + subSql += + ' (' + + self.formatter.columnize(insertData.columns) + + ') values (' + + parameterizedValues + + ')'; + } + + let returningClause = ''; + let intoClause = ''; + // ToDo review if this code is still needed or could be dropped + // eslint-disable-next-line no-unused-vars + let usingClause = ''; + let outClause = ''; + + each(value, function (val) { + if (!(val instanceof BlobHelper)) { + usingClause += ' ?,'; + } + }); + // eslint-disable-next-line no-unused-vars + usingClause = usingClause.slice(0, -1); + + // Build returning and into clauses + outBinding[index].forEach(function (ret) { + const columnName = ret.columnName || ret; + returningClause += self.formatter.wrap(columnName) + ','; + intoClause += ' ?,'; + outClause += ' out ?,'; + + // Add Helpers to bindings + if (ret instanceof BlobHelper) { + return self.formatter.bindings.push(ret); + } + self.formatter.bindings.push(new ReturningHelper(columnName)); + }); + + // Strip last comma + returningClause = returningClause.slice(0, -1); + intoClause = intoClause.slice(0, -1); + outClause = outClause.slice(0, -1); + + if (returningClause && intoClause) { + subSql += ' returning ' + returningClause + ' into' + intoClause; + } + + // Pre bind position because subSql is an execute immediate parameter + // later position binding will only convert the ? params + subSql = self.formatter.client.positionBindings(subSql); + const parameterizedValuesWithoutDefaultAndBlob = parameterizedValues + .replace(/DEFAULT, /g, '') + .replace(/, DEFAULT/g, '') + .replace('EMPTY_BLOB(), ', '') + .replace(', EMPTY_BLOB()', ''); + return ( + "execute immediate '" + + subSql.replace(/'/g, "''") + + (parameterizedValuesWithoutDefaultAndBlob || value + ? "' using " + : '') + + parameterizedValuesWithoutDefaultAndBlob + + (parameterizedValuesWithoutDefaultAndBlob && outClause ? ',' : '') + + outClause + + ';' + ); + }) + .join(' ') + + 'end;'; + + sql.outBinding = outBinding; + if (returning[0] === '*') { + // Generate select statement with special order by + // to keep the order because 'in (..)' may change the order + sql.returningSql = function () { + return ( + 'select * from ' + + self.tableName + + ' where ROWID in (' + + this.outBinding + .map(function (v, i) { + return ':' + (i + 1); + }) + .join(', ') + + ')' + + ' order by case ROWID ' + + this.outBinding + .map(function (v, i) { + return 'when CHARTOROWID(:' + (i + 1) + ') then ' + i; + }) + .join(' ') + + ' end' + ); + }; + } + + return sql; + } + + with() { + // WITH RECURSIVE is a syntax error in Oracle SQL. + // So mark all statements as non-recursive, generate the SQL, then restore. + // This approach ensures any changes in base class with() get propagated here. + const undoList = []; + if (this.grouped.with) { + for (const stmt of this.grouped.with) { + if (stmt.recursive) { + undoList.push(stmt); + stmt.recursive = false; + } + } + } + + const result = super.with(); + + // Restore the recursive markings, in case this same query gets cloned and passed to other drivers. + for (const stmt of undoList) { + stmt.recursive = true; + } + return result; + } + + _addReturningToSqlAndConvert(sql, outBinding, tableName, returning) { + const self = this; + const res = { + sql: sql, + }; + + if (!outBinding) { + return res; + } + const returningValues = Array.isArray(outBinding) + ? outBinding + : [outBinding]; + let returningClause = ''; + let intoClause = ''; + // Build returning and into clauses + returningValues.forEach(function (ret) { + const columnName = ret.columnName || ret; + returningClause += self.formatter.wrap(columnName) + ','; + intoClause += '?,'; + + // Add Helpers to bindings + if (ret instanceof BlobHelper) { + return self.formatter.bindings.push(ret); + } + self.formatter.bindings.push(new ReturningHelper(columnName)); + }); + res.sql = sql; + + // Strip last comma + returningClause = returningClause.slice(0, -1); + intoClause = intoClause.slice(0, -1); + if (returningClause && intoClause) { + res.sql += ' returning ' + returningClause + ' into ' + intoClause; + } + res.outBinding = [outBinding]; + if (returning[0] === '*') { + res.returningSql = function () { + return 'select * from ' + self.tableName + ' where ROWID = :1'; + }; + } + res.returning = returning; + + return res; + } + + _prepOutbindings(paramValues, paramReturning) { + const result = {}; + let params = paramValues || []; + let returning = paramReturning || []; + if (!Array.isArray(params) && isPlainObject(paramValues)) { + params = [params]; + } + // Always wrap returning argument in array + if (returning && !Array.isArray(returning)) { + returning = [returning]; + } + + const outBinding = []; + // Handle Buffer value as Blob + each(params, function (values, index) { + if (returning[0] === '*') { + outBinding[index] = ['ROWID']; + } else { + outBinding[index] = clone(returning); + } + each(values, function (value, key) { + if (value instanceof Buffer) { + values[key] = new BlobHelper(key, value); + + // Delete blob duplicate in returning + const blobIndex = outBinding[index].indexOf(key); + if (blobIndex >= 0) { + outBinding[index].splice(blobIndex, 1); + values[key].returning = true; + } + outBinding[index].push(values[key]); + } + if (value === undefined) { + delete params[index][key]; + } + }); + }); + result.returning = returning; + result.outBinding = outBinding; + result.values = params; + return result; + } + + _groupOrder(item, type) { + return super._groupOrderNulls(item, type); + } + + update() { + const self = this; + const sql = {}; + const outBindPrep = this._prepOutbindings( + this.single.update || this.single.counter, + this.single.returning + ); + const outBinding = outBindPrep.outBinding; + const returning = outBindPrep.returning; + + const updates = this._prepUpdate(this.single.update); + const where = this.where(); + + let returningClause = ''; + let intoClause = ''; + + if (isEmpty(updates) && typeof this.single.update !== 'function') { + return ''; + } + + // Build returning and into clauses + outBinding.forEach(function (out) { + out.forEach(function (ret) { + const columnName = ret.columnName || ret; + returningClause += self.formatter.wrap(columnName) + ','; + intoClause += ' ?,'; + + // Add Helpers to bindings + if (ret instanceof BlobHelper) { + return self.formatter.bindings.push(ret); + } + self.formatter.bindings.push(new ReturningHelper(columnName)); + }); + }); + // Strip last comma + returningClause = returningClause.slice(0, -1); + intoClause = intoClause.slice(0, -1); + + sql.outBinding = outBinding; + sql.returning = returning; + sql.sql = + 'update ' + + this.tableName + + ' set ' + + updates.join(', ') + + (where ? ' ' + where : ''); + if (outBinding.length && !isEmpty(outBinding[0])) { + sql.sql += ' returning ' + returningClause + ' into' + intoClause; + } + if (returning[0] === '*') { + sql.returningSql = function () { + let sql = 'select * from ' + self.tableName; + const modifiedRowsCount = this.rowsAffected.length || this.rowsAffected; + let returningSqlIn = ' where ROWID in ('; + let returningSqlOrderBy = ') order by case ROWID '; + + // Needs special order by because in(...) change result order + for (let i = 0; i < modifiedRowsCount; i++) { + if (this.returning[0] === '*') { + returningSqlIn += ':' + (i + 1) + ', '; + returningSqlOrderBy += + 'when CHARTOROWID(:' + (i + 1) + ') then ' + i + ' '; + } + } + if (this.returning[0] === '*') { + this.returning = this.returning.slice(0, -1); + returningSqlIn = returningSqlIn.slice(0, -2); + returningSqlOrderBy = returningSqlOrderBy.slice(0, -1); + } + return (sql += returningSqlIn + returningSqlOrderBy + ' end'); + }; + } + + return sql; + } + + _jsonPathWrap(extraction) { + return `'${extraction.path || extraction[1]}'`; + } + + // Json functions + jsonExtract(params) { + return this._jsonExtract( + params.singleValue ? 'json_value' : 'json_query', + params + ); + } + + jsonSet(params) { + return `json_transform(${columnize_( + params.column, + this.builder, + this.client, + this.bindingsHolder + )}, set ${this.client.parameter( + params.path, + this.builder, + this.bindingsHolder + )} = ${this.client.parameter( + params.value, + this.builder, + this.bindingsHolder + )})`; + } + + jsonInsert(params) { + return `json_transform(${columnize_( + params.column, + this.builder, + this.client, + this.bindingsHolder + )}, insert ${this.client.parameter( + params.path, + this.builder, + this.bindingsHolder + )} = ${this.client.parameter( + params.value, + this.builder, + this.bindingsHolder + )})`; + } + + jsonRemove(params) { + const jsonCol = `json_transform(${columnize_( + params.column, + this.builder, + this.client, + this.bindingsHolder + )}, remove ${this.client.parameter( + params.path, + this.builder, + this.bindingsHolder + )})`; + return params.alias + ? this.client.alias(jsonCol, this.formatter.wrap(params.alias)) + : jsonCol; + } + + whereJsonPath(statement) { + return this._whereJsonPath('json_value', statement); + } + + whereJsonSupersetOf(statement) { + throw new Error( + 'Json superset where clause not actually supported by Oracle' + ); + } + + whereJsonSubsetOf(statement) { + throw new Error( + 'Json subset where clause not actually supported by Oracle' + ); + } + + onJsonPathEquals(clause) { + return this._onJsonPathEquals('json_value', clause); + } +} + +module.exports = Oracledb_Compiler; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-columncompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-columncompiler.js new file mode 100644 index 000000000..df4bb058c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-columncompiler.js @@ -0,0 +1,61 @@ +const ColumnCompiler_Oracle = require('../../oracle/schema/oracle-columncompiler'); +const { isObject } = require('../../../util/is'); + +class ColumnCompiler_Oracledb extends ColumnCompiler_Oracle { + constructor() { + super(...arguments); + this.modifiers = ['defaultTo', 'nullable', 'comment', 'checkJson']; + this._addCheckModifiers(); + } + + datetime(withoutTz) { + let useTz; + if (isObject(withoutTz)) { + ({ useTz } = withoutTz); + } else { + useTz = !withoutTz; + } + return useTz ? 'timestamp with local time zone' : 'timestamp'; + } + + timestamp(withoutTz) { + let useTz; + if (isObject(withoutTz)) { + ({ useTz } = withoutTz); + } else { + useTz = !withoutTz; + } + return useTz ? 'timestamp with local time zone' : 'timestamp'; + } + + checkRegex(regex, constraintName) { + return this._check( + `REGEXP_LIKE(${this.formatter.wrap( + this.getColumnName() + )},${this.client._escapeBinding(regex)})`, + constraintName + ); + } + + json() { + // implicitly add the check for json + this.columnBuilder._modifiers.checkJson = [ + this.formatter.columnize(this.getColumnName()), + ]; + return 'varchar2(4000)'; + } + + jsonb() { + return this.json(); + } + + checkJson(column) { + return `check (${column} is json)`; + } +} + +ColumnCompiler_Oracledb.prototype.time = 'timestamp with local time zone'; +ColumnCompiler_Oracledb.prototype.uuid = ({ useBinaryUuid = false } = {}) => + useBinaryUuid ? 'raw(16)' : 'char(36)'; + +module.exports = ColumnCompiler_Oracledb; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-tablecompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-tablecompiler.js new file mode 100644 index 000000000..4f7d5fa9a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-tablecompiler.js @@ -0,0 +1,19 @@ +const TableCompiler_Oracle = require('../../oracle/schema/oracle-tablecompiler'); + +class TableCompiler_Oracledb extends TableCompiler_Oracle { + constructor(client, tableBuilder) { + super(client, tableBuilder); + } + + _setNullableState(column, isNullable) { + const nullability = isNullable ? 'NULL' : 'NOT NULL'; + const sql = `alter table ${this.tableName()} modify (${this.formatter.wrap( + column + )} ${nullability})`; + return this.pushQuery({ + sql: sql, + }); + } +} + +module.exports = TableCompiler_Oracledb; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-viewbuilder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-viewbuilder.js new file mode 100644 index 000000000..6bd08ec06 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-viewbuilder.js @@ -0,0 +1,13 @@ +const ViewBuilder = require('../../../schema/viewbuilder.js'); + +class ViewBuilder_Oracledb extends ViewBuilder { + constructor() { + super(...arguments); + } + + checkOption() { + this._single.checkOption = 'default_option'; + } +} + +module.exports = ViewBuilder_Oracledb; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-viewcompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-viewcompiler.js new file mode 100644 index 000000000..fd815d24b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/schema/oracledb-viewcompiler.js @@ -0,0 +1,19 @@ +/* eslint max-len: 0 */ + +const ViewCompiler = require('../../../schema/viewcompiler.js'); + +class ViewCompiler_Oracledb extends ViewCompiler { + constructor(client, viewCompiler) { + super(client, viewCompiler); + } + + createOrReplace() { + this.createQuery(this.columns, this.selectQuery, false, true); + } + + createMaterializedView() { + this.createQuery(this.columns, this.selectQuery, true); + } +} + +module.exports = ViewCompiler_Oracledb; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/transaction.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/transaction.js new file mode 100644 index 000000000..9556fb74e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/transaction.js @@ -0,0 +1,98 @@ +const Transaction = require('../../execution/transaction'); +const { timeout, KnexTimeoutError } = require('../../util/timeout'); +const debugTx = require('debug')('knex:tx'); + +// There's also a "read only", but that's not really an "isolationLevel" +const supportedIsolationLevels = ['read committed', 'serializable']; +// Remove this if you make it work and set it to true +const isIsolationLevelEnabled = false; + +module.exports = class Oracle_Transaction extends Transaction { + // disable autocommit to allow correct behavior (default is true) + begin(conn) { + if (this.isolationLevel) { + if (isIsolationLevelEnabled) { + if (!supportedIsolationLevels.includes(this.isolationLevel)) { + this.client.logger.warn( + 'Oracle only supports read committed and serializable transactions, ignoring the isolation level param' + ); + } else { + // I tried this, but it didn't work + // Doc here: https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/SET-TRANSACTION.html + return this.query(conn, `SET TRANSACTION ${this.isolationLevel}`); + } + } else { + this.client.logger.warn( + 'Transaction isolation is not currently supported for Oracle' + ); + } + } + return Promise.resolve(); + } + + async commit(conn, value) { + this._completed = true; + try { + await conn.commitAsync(); + this._resolver(value); + } catch (err) { + this._rejecter(err); + } + } + + release(conn, value) { + return this._resolver(value); + } + + rollback(conn, err) { + this._completed = true; + debugTx('%s: rolling back', this.txid); + return timeout(conn.rollbackAsync(), 5000) + .catch((e) => { + if (!(e instanceof KnexTimeoutError)) { + return Promise.reject(e); + } + this._rejecter(e); + }) + .then(() => { + if (err === undefined) { + if (this.doNotRejectOnRollback) { + this._resolver(); + return; + } + err = new Error(`Transaction rejected with non-error: ${err}`); + } + this._rejecter(err); + }); + } + + savepoint(conn) { + return this.query(conn, `SAVEPOINT ${this.txid}`); + } + + async acquireConnection(config, cb) { + const configConnection = config && config.connection; + + const connection = + configConnection || (await this.client.acquireConnection()); + try { + connection.__knexTxId = this.txid; + connection.isTransaction = true; + return await cb(connection); + } finally { + debugTx('%s: releasing connection', this.txid); + connection.isTransaction = false; + try { + await connection.commitAsync(); + } catch (err) { + this._rejecter(err); + } finally { + if (!configConnection) { + await this.client.releaseConnection(connection); + } else { + debugTx('%s: not releasing external connection', this.txid); + } + } + } + } +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/utils.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/utils.js new file mode 100644 index 000000000..b71ad3f9c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/oracledb/utils.js @@ -0,0 +1,208 @@ +const Utils = require('../oracle/utils'); +const { promisify } = require('util'); +const stream = require('stream'); + +function BlobHelper(columnName, value) { + this.columnName = columnName; + this.value = value; + this.returning = false; +} + +BlobHelper.prototype.toString = function () { + return '[object BlobHelper:' + this.columnName + ']'; +}; + +/** + * @param stream + * @param {'string' | 'buffer'} type + */ +function readStream(stream, type) { + return new Promise((resolve, reject) => { + let data = type === 'string' ? '' : Buffer.alloc(0); + + stream.on('error', function (err) { + reject(err); + }); + stream.on('data', function (chunk) { + if (type === 'string') { + data += chunk; + } else { + data = Buffer.concat([data, chunk]); + } + }); + stream.on('end', function () { + resolve(data); + }); + }); +} + +const lobProcessing = function (stream) { + const oracledb = require('oracledb'); + + /** + * @type 'string' | 'buffer' + */ + let type; + + if (stream.type) { + // v1.2-v4 + if (stream.type === oracledb.BLOB) { + type = 'buffer'; + } else if (stream.type === oracledb.CLOB) { + type = 'string'; + } + } else if (stream.iLob) { + // v1 + if (stream.iLob.type === oracledb.CLOB) { + type = 'string'; + } else if (stream.iLob.type === oracledb.BLOB) { + type = 'buffer'; + } + } else { + throw new Error('Unrecognized oracledb lob stream type'); + } + if (type === 'string') { + stream.setEncoding('utf-8'); + } + return readStream(stream, type); +}; + +function monkeyPatchConnection(connection, client) { + // Connection is already monkey-patched + if (connection.executeAsync) { + return; + } + + connection.commitAsync = function () { + return new Promise((commitResolve, commitReject) => { + this.commit(function (err) { + if (err) { + return commitReject(err); + } + commitResolve(); + }); + }); + }; + connection.rollbackAsync = function () { + return new Promise((rollbackResolve, rollbackReject) => { + this.rollback(function (err) { + if (err) { + return rollbackReject(err); + } + rollbackResolve(); + }); + }); + }; + const fetchAsync = promisify(function (sql, bindParams, options, cb) { + options = options || {}; + options.outFormat = client.driver.OUT_FORMAT_OBJECT || client.driver.OBJECT; + if (!options.outFormat) { + throw new Error('not found oracledb.outFormat constants'); + } + if (options.resultSet) { + connection.execute( + sql, + bindParams || [], + options, + function (err, result) { + if (err) { + if (Utils.isConnectionError(err)) { + connection.close().catch(function (err) {}); + connection.__knex__disposed = err; + } + return cb(err); + } + const fetchResult = { rows: [], resultSet: result.resultSet }; + const numRows = 100; + const fetchRowsFromRS = function (connection, resultSet, numRows) { + resultSet.getRows(numRows, function (err, rows) { + if (err) { + if (Utils.isConnectionError(err)) { + connection.close().catch(function (err) {}); + connection.__knex__disposed = err; + } + resultSet.close(function () { + return cb(err); + }); + } else if (rows.length === 0) { + return cb(null, fetchResult); + } else if (rows.length > 0) { + if (rows.length === numRows) { + fetchResult.rows = fetchResult.rows.concat(rows); + fetchRowsFromRS(connection, resultSet, numRows); + } else { + fetchResult.rows = fetchResult.rows.concat(rows); + return cb(null, fetchResult); + } + } + }); + }; + fetchRowsFromRS(connection, result.resultSet, numRows); + } + ); + } else { + connection.execute( + sql, + bindParams || [], + options, + function (err, result) { + if (err) { + // dispose the connection on connection error + if (Utils.isConnectionError(err)) { + connection.close().catch(function (err) {}); + connection.__knex__disposed = err; + } + return cb(err); + } + + return cb(null, result); + } + ); + } + }); + connection.executeAsync = function (sql, bindParams, options) { + // Read all lob + return fetchAsync(sql, bindParams, options).then(async (results) => { + const closeResultSet = () => { + return results.resultSet + ? promisify(results.resultSet.close).call(results.resultSet) + : Promise.resolve(); + }; + + // Collect LOBs to read + const lobs = []; + if (results.rows) { + if (Array.isArray(results.rows)) { + for (let i = 0; i < results.rows.length; i++) { + // Iterate through the rows + const row = results.rows[i]; + for (const column in row) { + if (row[column] instanceof stream.Readable) { + lobs.push({ index: i, key: column, stream: row[column] }); + } + } + } + } + } + + try { + for (const lob of lobs) { + // todo should be fetchAsString/fetchAsBuffer polyfill only + results.rows[lob.index][lob.key] = await lobProcessing(lob.stream); + } + } catch (e) { + await closeResultSet().catch(() => {}); + + throw e; + } + + await closeResultSet(); + + return results; + }); + }; +} + +Utils.BlobHelper = BlobHelper; +Utils.monkeyPatchConnection = monkeyPatchConnection; +module.exports = Utils; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/pgnative/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/pgnative/index.js new file mode 100644 index 000000000..60ba4fbe1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/pgnative/index.js @@ -0,0 +1,60 @@ +// PostgreSQL Native Driver (pg-native) +// ------- +const Client_PG = require('../postgres'); + +class Client_PgNative extends Client_PG { + constructor(...args) { + super(...args); + this.driverName = 'pgnative'; + this.canCancelQuery = true; + } + + _driver() { + return require('pg').native; + } + + _stream(connection, obj, stream, options) { + if (!obj.sql) throw new Error('The query is empty'); + + const client = this; + return new Promise((resolver, rejecter) => { + stream.on('error', rejecter); + stream.on('end', resolver); + + return client + ._query(connection, obj) + .then((obj) => obj.response) + .then(({ rows }) => rows.forEach((row) => stream.write(row))) + .catch(function (err) { + stream.emit('error', err); + }) + .then(function () { + stream.end(); + }); + }); + } + + async cancelQuery(connectionToKill) { + try { + return await this._wrappedCancelQueryCall(null, connectionToKill); + } catch (err) { + this.logger.warn(`Connection Error: ${err}`); + throw err; + } + } + + _wrappedCancelQueryCall(emptyConnection, connectionToKill) { + return new Promise(function (resolve, reject) { + connectionToKill.native.cancel(function (err) { + if (err) { + reject(err); + return; + } + + resolve(true); + }); + }); + } +} + +module.exports = Client_PgNative; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/execution/pg-transaction.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/execution/pg-transaction.js new file mode 100644 index 000000000..553ada1e6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/execution/pg-transaction.js @@ -0,0 +1,19 @@ +const Transaction = require('../../../execution/transaction'); + +class Transaction_PG extends Transaction { + begin(conn) { + const trxMode = [ + this.isolationLevel ? `ISOLATION LEVEL ${this.isolationLevel}` : '', + this.readOnly ? 'READ ONLY' : '', + ] + .join(' ') + .trim(); + + if (trxMode.length === 0) { + return this.query(conn, 'BEGIN;'); + } + return this.query(conn, `BEGIN TRANSACTION ${trxMode};`); + } +} + +module.exports = Transaction_PG; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/index.js new file mode 100644 index 000000000..8b73cbbd1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/index.js @@ -0,0 +1,361 @@ +// PostgreSQL +// ------- +const extend = require('lodash/extend'); +const map = require('lodash/map'); +const { promisify } = require('util'); +const Client = require('../../client'); + +const Transaction = require('./execution/pg-transaction'); +const QueryCompiler = require('./query/pg-querycompiler'); +const QueryBuilder = require('./query/pg-querybuilder'); +const ColumnCompiler = require('./schema/pg-columncompiler'); +const TableCompiler = require('./schema/pg-tablecompiler'); +const ViewCompiler = require('./schema/pg-viewcompiler'); +const ViewBuilder = require('./schema/pg-viewbuilder'); +const SchemaCompiler = require('./schema/pg-compiler'); +const { makeEscape } = require('../../util/string'); +const { isString } = require('../../util/is'); + +class Client_PG extends Client { + constructor(config) { + super(config); + if (config.returning) { + this.defaultReturning = config.returning; + } + + if (config.searchPath) { + this.searchPath = config.searchPath; + } + } + transaction() { + return new Transaction(this, ...arguments); + } + + queryBuilder() { + return new QueryBuilder(this); + } + + queryCompiler(builder, formatter) { + return new QueryCompiler(this, builder, formatter); + } + + columnCompiler() { + return new ColumnCompiler(this, ...arguments); + } + + schemaCompiler() { + return new SchemaCompiler(this, ...arguments); + } + + tableCompiler() { + return new TableCompiler(this, ...arguments); + } + + viewCompiler() { + return new ViewCompiler(this, ...arguments); + } + + viewBuilder() { + return new ViewBuilder(this, ...arguments); + } + + _driver() { + return require('pg'); + } + + wrapIdentifierImpl(value) { + if (value === '*') return value; + + let arrayAccessor = ''; + const arrayAccessorMatch = value.match(/(.*?)(\[[0-9]+\])/); + + if (arrayAccessorMatch) { + value = arrayAccessorMatch[1]; + arrayAccessor = arrayAccessorMatch[2]; + } + + return `"${value.replace(/"/g, '""')}"${arrayAccessor}`; + } + + _acquireOnlyConnection() { + const connection = new this.driver.Client(this.connectionSettings); + + connection.on('error', (err) => { + connection.__knex__disposed = err; + }); + + connection.on('end', (err) => { + connection.__knex__disposed = err || 'Connection ended unexpectedly'; + }); + + return connection.connect().then(() => connection); + } + + // Get a raw connection, called by the `pool` whenever a new + // connection needs to be added to the pool. + acquireRawConnection() { + const client = this; + + return this._acquireOnlyConnection() + .then(function (connection) { + if (!client.version) { + return client.checkVersion(connection).then(function (version) { + client.version = version; + return connection; + }); + } + + return connection; + }) + .then(async function setSearchPath(connection) { + await client.setSchemaSearchPath(connection); + return connection; + }); + } + + // Used to explicitly close a connection, called internally by the pool + // when a connection times out or the pool is shutdown. + async destroyRawConnection(connection) { + const end = promisify((cb) => connection.end(cb)); + return end(); + } + + // In PostgreSQL, we need to do a version check to do some feature + // checking on the database. + checkVersion(connection) { + return new Promise((resolve, reject) => { + connection.query('select version();', (err, resp) => { + if (err) return reject(err); + resolve(this._parseVersion(resp.rows[0].version)); + }); + }); + } + + _parseVersion(versionString) { + return /^PostgreSQL (.*?)( |$)/.exec(versionString)[1]; + } + + // Position the bindings for the query. The escape sequence for question mark + // is \? (e.g. knex.raw("\\?") since javascript requires '\' to be escaped too...) + positionBindings(sql) { + let questionCount = 0; + return sql.replace(/(\\*)(\?)/g, function (match, escapes) { + if (escapes.length % 2) { + return '?'; + } else { + questionCount++; + return `$${questionCount}`; + } + }); + } + + setSchemaSearchPath(connection, searchPath) { + let path = searchPath || this.searchPath; + + if (!path) return Promise.resolve(true); + + if (!Array.isArray(path) && !isString(path)) { + throw new TypeError( + `knex: Expected searchPath to be Array/String, got: ${typeof path}` + ); + } + + if (isString(path)) { + if (path.includes(',')) { + const parts = path.split(','); + const arraySyntax = `[${parts + .map((searchPath) => `'${searchPath}'`) + .join(', ')}]`; + this.logger.warn( + `Detected comma in searchPath "${path}".` + + `If you are trying to specify multiple schemas, use Array syntax: ${arraySyntax}` + ); + } + path = [path]; + } + + path = path.map((schemaName) => `"${schemaName}"`).join(','); + + return new Promise(function (resolver, rejecter) { + connection.query(`set search_path to ${path}`, function (err) { + if (err) return rejecter(err); + resolver(true); + }); + }); + } + + _stream(connection, obj, stream, options) { + if (!obj.sql) throw new Error('The query is empty'); + + const PGQueryStream = process.browser + ? undefined + : require('pg-query-stream'); + const sql = obj.sql; + + return new Promise(function (resolver, rejecter) { + const queryStream = connection.query( + new PGQueryStream(sql, obj.bindings, options), + (err) => { + rejecter(err); + } + ); + + queryStream.on('error', function (error) { + rejecter(error); + stream.emit('error', error); + }); + + // 'end' IS propagated by .pipe, by default + stream.on('end', resolver); + queryStream.pipe(stream); + }); + } + + // Runs the query on the specified connection, providing the bindings + // and any other necessary prep work. + _query(connection, obj) { + if (!obj.sql) throw new Error('The query is empty'); + + let queryConfig = { + text: obj.sql, + values: obj.bindings || [], + }; + + if (obj.options) { + queryConfig = extend(queryConfig, obj.options); + } + + return new Promise(function (resolver, rejecter) { + connection.query(queryConfig, function (err, response) { + if (err) return rejecter(err); + obj.response = response; + resolver(obj); + }); + }); + } + + // Ensures the response is returned in the same format as other clients. + processResponse(obj, runner) { + const resp = obj.response; + if (obj.output) return obj.output.call(runner, resp); + if (obj.method === 'raw') return resp; + const { returning } = obj; + if (resp.command === 'SELECT') { + if (obj.method === 'first') return resp.rows[0]; + if (obj.method === 'pluck') return map(resp.rows, obj.pluck); + return resp.rows; + } + if (returning) { + const returns = []; + for (let i = 0, l = resp.rows.length; i < l; i++) { + const row = resp.rows[i]; + returns[i] = row; + } + return returns; + } + if (resp.command === 'UPDATE' || resp.command === 'DELETE') { + return resp.rowCount; + } + return resp; + } + + async cancelQuery(connectionToKill) { + const conn = await this.acquireRawConnection(); + + try { + return await this._wrappedCancelQueryCall(conn, connectionToKill); + } finally { + await this.destroyRawConnection(conn).catch((err) => { + this.logger.warn(`Connection Error: ${err}`); + }); + } + } + _wrappedCancelQueryCall(conn, connectionToKill) { + return this._query(conn, { + sql: 'SELECT pg_cancel_backend($1);', + bindings: [connectionToKill.processID], + options: {}, + }); + } + + toPathForJson(jsonPath) { + const PG_PATH_REGEX = /^{.*}$/; + if (jsonPath.match(PG_PATH_REGEX)) { + return jsonPath; + } + return ( + '{' + + jsonPath + .replace(/^(\$\.)/, '') // remove the first dollar + .replace('.', ',') + .replace(/\[([0-9]+)]/, ',$1') + // transform [number] to ,number + '}' + ); + } +} + +Object.assign(Client_PG.prototype, { + dialect: 'postgresql', + + driverName: 'pg', + canCancelQuery: true, + + _escapeBinding: makeEscape({ + escapeArray(val, esc) { + return esc(arrayString(val, esc)); + }, + escapeString(str) { + let hasBackslash = false; + let escaped = "'"; + for (let i = 0; i < str.length; i++) { + const c = str[i]; + if (c === "'") { + escaped += c + c; + } else if (c === '\\') { + escaped += c + c; + hasBackslash = true; + } else { + escaped += c; + } + } + escaped += "'"; + if (hasBackslash === true) { + escaped = 'E' + escaped; + } + return escaped; + }, + escapeObject(val, prepareValue, timezone, seen = []) { + if (val && typeof val.toPostgres === 'function') { + seen = seen || []; + if (seen.indexOf(val) !== -1) { + throw new Error( + `circular reference detected while preparing "${val}" for query` + ); + } + seen.push(val); + return prepareValue(val.toPostgres(prepareValue), seen); + } + return JSON.stringify(val); + }, + }), +}); + +function arrayString(arr, esc) { + let result = '{'; + for (let i = 0; i < arr.length; i++) { + if (i > 0) result += ','; + const val = arr[i]; + if (val === null || typeof val === 'undefined') { + result += 'NULL'; + } else if (Array.isArray(val)) { + result += arrayString(val, esc); + } else if (typeof val === 'number') { + result += val; + } else { + result += JSON.stringify(typeof val === 'string' ? val : esc(val)); + } + } + return result + '}'; +} + +module.exports = Client_PG; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/query/pg-querybuilder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/query/pg-querybuilder.js new file mode 100644 index 000000000..b5bb5b75a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/query/pg-querybuilder.js @@ -0,0 +1,43 @@ +const QueryBuilder = require('../../../query/querybuilder.js'); + +module.exports = class QueryBuilder_PostgreSQL extends QueryBuilder { + updateFrom(name) { + this._single.updateFrom = name; + return this; + } + + using(tables) { + this._single.using = tables; + return this; + } + + withMaterialized(alias, statementOrColumnList, nothingOrStatement) { + this._validateWithArgs( + alias, + statementOrColumnList, + nothingOrStatement, + 'with' + ); + return this.withWrapped( + alias, + statementOrColumnList, + nothingOrStatement, + true + ); + } + + withNotMaterialized(alias, statementOrColumnList, nothingOrStatement) { + this._validateWithArgs( + alias, + statementOrColumnList, + nothingOrStatement, + 'with' + ); + return this.withWrapped( + alias, + statementOrColumnList, + nothingOrStatement, + false + ); + } +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/query/pg-querycompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/query/pg-querycompiler.js new file mode 100644 index 000000000..137486f75 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/query/pg-querycompiler.js @@ -0,0 +1,400 @@ +// PostgreSQL Query Builder & Compiler +// ------ +const identity = require('lodash/identity'); +const reduce = require('lodash/reduce'); + +const QueryCompiler = require('../../../query/querycompiler'); +const { + wrapString, + columnize: columnize_, + operator: operator_, + wrap: wrap_, +} = require('../../../formatter/wrappingFormatter'); + +class QueryCompiler_PG extends QueryCompiler { + constructor(client, builder, formatter) { + super(client, builder, formatter); + this._defaultInsertValue = 'default'; + } + + // Compiles a truncate query. + truncate() { + return `truncate ${this.tableName} restart identity`; + } + + // is used if the an array with multiple empty values supplied + + // Compiles an `insert` query, allowing for multiple + // inserts using a single query statement. + insert() { + let sql = super.insert(); + if (sql === '') return sql; + + const { returning, onConflict, ignore, merge, insert } = this.single; + if (onConflict && ignore) sql += this._ignore(onConflict); + if (onConflict && merge) { + sql += this._merge(merge.updates, onConflict, insert); + const wheres = this.where(); + if (wheres) sql += ` ${wheres}`; + } + if (returning) sql += this._returning(returning); + + return { + sql, + returning, + }; + } + + // Compiles an `update` query, allowing for a return value. + update() { + const withSQL = this.with(); + const updateData = this._prepUpdate(this.single.update); + const wheres = this.where(); + const { returning, updateFrom } = this.single; + return { + sql: + withSQL + + `update ${this.single.only ? 'only ' : ''}${this.tableName} ` + + `set ${updateData.join(', ')}` + + this._updateFrom(updateFrom) + + (wheres ? ` ${wheres}` : '') + + this._returning(returning), + returning, + }; + } + + using() { + const usingTables = this.single.using; + if (!usingTables) return; + let sql = 'using '; + if (Array.isArray(usingTables)) { + sql += usingTables + .map((table) => { + return this.formatter.wrap(table); + }) + .join(','); + } else { + sql += this.formatter.wrap(usingTables); + } + return sql; + } + + // Compiles an `delete` query, allowing for a return value. + del() { + // Make sure tableName is processed by the formatter first. + const { tableName } = this; + const withSQL = this.with(); + let wheres = this.where() || ''; + let using = this.using() || ''; + const joins = this.grouped.join; + + const tableJoins = []; + if (Array.isArray(joins)) { + for (const join of joins) { + tableJoins.push( + wrap_( + this._joinTable(join), + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + ); + + const joinWheres = []; + for (const clause of join.clauses) { + joinWheres.push( + this.whereBasic({ + column: clause.column, + operator: '=', + value: clause.value, + asColumn: true, + }) + ); + } + if (joinWheres.length > 0) { + wheres += (wheres ? ' and ' : 'where ') + joinWheres.join(' and '); + } + } + if (tableJoins.length > 0) { + using += (using ? ',' : 'using ') + tableJoins.join(','); + } + } + + // With 'using' syntax, no tablename between DELETE and FROM. + const sql = + withSQL + + `delete from ${this.single.only ? 'only ' : ''}${tableName}` + + (using ? ` ${using}` : '') + + (wheres ? ` ${wheres}` : ''); + const { returning } = this.single; + return { + sql: sql + this._returning(returning), + returning, + }; + } + + aggregate(stmt) { + return this._aggregate(stmt, { distinctParentheses: true }); + } + + _returning(value) { + return value ? ` returning ${this.formatter.columnize(value)}` : ''; + } + + _updateFrom(name) { + return name ? ` from ${this.formatter.wrap(name)}` : ''; + } + + _ignore(columns) { + if (columns === true) { + return ' on conflict do nothing'; + } + return ` on conflict ${this._onConflictClause(columns)} do nothing`; + } + + _merge(updates, columns, insert) { + let sql = ` on conflict ${this._onConflictClause(columns)} do update set `; + if (updates && Array.isArray(updates)) { + sql += updates + .map((column) => + wrapString( + column.split('.').pop(), + this.formatter.builder, + this.client, + this.formatter + ) + ) + .map((column) => `${column} = excluded.${column}`) + .join(', '); + + return sql; + } else if (updates && typeof updates === 'object') { + const updateData = this._prepUpdate(updates); + if (typeof updateData === 'string') { + sql += updateData; + } else { + sql += updateData.join(','); + } + + return sql; + } else { + const insertData = this._prepInsert(insert); + if (typeof insertData === 'string') { + throw new Error( + 'If using merge with a raw insert query, then updates must be provided' + ); + } + + sql += insertData.columns + .map((column) => + wrapString(column.split('.').pop(), this.builder, this.client) + ) + .map((column) => `${column} = excluded.${column}`) + .join(', '); + + return sql; + } + } + + // Join array of table names and apply default schema. + _tableNames(tables) { + const schemaName = this.single.schema; + const sql = []; + + for (let i = 0; i < tables.length; i++) { + let tableName = tables[i]; + + if (tableName) { + if (schemaName) { + tableName = `${schemaName}.${tableName}`; + } + sql.push(this.formatter.wrap(tableName)); + } + } + + return sql.join(', '); + } + + _lockingClause(lockMode) { + const tables = this.single.lockTables || []; + + return lockMode + (tables.length ? ' of ' + this._tableNames(tables) : ''); + } + + _groupOrder(item, type) { + return super._groupOrderNulls(item, type); + } + + forUpdate() { + return this._lockingClause('for update'); + } + + forShare() { + return this._lockingClause('for share'); + } + + forNoKeyUpdate() { + return this._lockingClause('for no key update'); + } + + forKeyShare() { + return this._lockingClause('for key share'); + } + + skipLocked() { + return 'skip locked'; + } + + noWait() { + return 'nowait'; + } + + // Compiles a columnInfo query + columnInfo() { + const column = this.single.columnInfo; + let schema = this.single.schema; + + // The user may have specified a custom wrapIdentifier function in the config. We + // need to run the identifiers through that function, but not format them as + // identifiers otherwise. + const table = this.client.customWrapIdentifier(this.single.table, identity); + + if (schema) { + schema = this.client.customWrapIdentifier(schema, identity); + } + + const sql = + 'select * from information_schema.columns where table_name = ? and table_catalog = current_database()'; + const bindings = [table]; + + return this._buildColumnInfoQuery(schema, sql, bindings, column); + } + + _buildColumnInfoQuery(schema, sql, bindings, column) { + if (schema) { + sql += ' and table_schema = ?'; + bindings.push(schema); + } else { + sql += ' and table_schema = current_schema()'; + } + + return { + sql, + bindings, + output(resp) { + const out = reduce( + resp.rows, + function (columns, val) { + columns[val.column_name] = { + type: val.data_type, + maxLength: val.character_maximum_length, + nullable: val.is_nullable === 'YES', + defaultValue: val.column_default, + }; + return columns; + }, + {} + ); + return (column && out[column]) || out; + }, + }; + } + + distinctOn(value) { + return 'distinct on (' + this.formatter.columnize(value) + ') '; + } + + // Json functions + jsonExtract(params) { + return this._jsonExtract('jsonb_path_query', params); + } + + jsonSet(params) { + return this._jsonSet( + 'jsonb_set', + Object.assign({}, params, { + path: this.client.toPathForJson(params.path), + }) + ); + } + + jsonInsert(params) { + return this._jsonSet( + 'jsonb_insert', + Object.assign({}, params, { + path: this.client.toPathForJson(params.path), + }) + ); + } + + jsonRemove(params) { + const jsonCol = `${columnize_( + params.column, + this.builder, + this.client, + this.bindingsHolder + )} #- ${this.client.parameter( + this.client.toPathForJson(params.path), + this.builder, + this.bindingsHolder + )}`; + return params.alias + ? this.client.alias(jsonCol, this.formatter.wrap(params.alias)) + : jsonCol; + } + + whereJsonPath(statement) { + let castValue = ''; + if (!isNaN(statement.value) && parseInt(statement.value)) { + castValue = '::int'; + } else if (!isNaN(statement.value) && parseFloat(statement.value)) { + castValue = '::float'; + } else { + castValue = " #>> '{}'"; + } + return `jsonb_path_query_first(${this._columnClause( + statement + )}, ${this.client.parameter( + statement.jsonPath, + this.builder, + this.bindingsHolder + )})${castValue} ${operator_( + statement.operator, + this.builder, + this.client, + this.bindingsHolder + )} ${this._jsonValueClause(statement)}`; + } + + whereJsonSupersetOf(statement) { + return this._not( + statement, + `${wrap_( + statement.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + )} @> ${this._jsonValueClause(statement)}` + ); + } + + whereJsonSubsetOf(statement) { + return this._not( + statement, + `${columnize_( + statement.column, + this.builder, + this.client, + this.bindingsHolder + )} <@ ${this._jsonValueClause(statement)}` + ); + } + + onJsonPathEquals(clause) { + return this._onJsonPathEquals('jsonb_path_query_first', clause); + } +} + +module.exports = QueryCompiler_PG; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-columncompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-columncompiler.js new file mode 100644 index 000000000..443f734b5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-columncompiler.js @@ -0,0 +1,156 @@ +// PostgreSQL Column Compiler +// ------- + +const ColumnCompiler = require('../../../schema/columncompiler'); +const { isObject } = require('../../../util/is'); +const { toNumber } = require('../../../util/helpers'); +const commentEscapeRegex = /(?= 9.2 + ) { + return jsonb ? 'jsonb' : 'json'; + } + return 'text'; +} + +module.exports = ColumnCompiler_PG; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-compiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-compiler.js new file mode 100644 index 000000000..baa41156a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-compiler.js @@ -0,0 +1,138 @@ +// PostgreSQL Schema Compiler +// ------- + +const SchemaCompiler = require('../../../schema/compiler'); + +class SchemaCompiler_PG extends SchemaCompiler { + constructor(client, builder) { + super(client, builder); + } + + // Check whether the current table + hasTable(tableName) { + let sql = 'select * from information_schema.tables where table_name = ?'; + const bindings = [tableName]; + + if (this.schema) { + sql += ' and table_schema = ?'; + bindings.push(this.schema); + } else { + sql += ' and table_schema = current_schema()'; + } + + this.pushQuery({ + sql, + bindings, + output(resp) { + return resp.rows.length > 0; + }, + }); + } + + // Compile the query to determine if a column exists in a table. + hasColumn(tableName, columnName) { + let sql = + 'select * from information_schema.columns where table_name = ? and column_name = ?'; + const bindings = [tableName, columnName]; + + if (this.schema) { + sql += ' and table_schema = ?'; + bindings.push(this.schema); + } else { + sql += ' and table_schema = current_schema()'; + } + + this.pushQuery({ + sql, + bindings, + output(resp) { + return resp.rows.length > 0; + }, + }); + } + + qualifiedTableName(tableName) { + const name = this.schema ? `${this.schema}.${tableName}` : tableName; + return this.formatter.wrap(name); + } + + // Compile a rename table command. + renameTable(from, to) { + this.pushQuery( + `alter table ${this.qualifiedTableName( + from + )} rename to ${this.formatter.wrap(to)}` + ); + } + + createSchema(schemaName) { + this.pushQuery(`create schema ${this.formatter.wrap(schemaName)}`); + } + + createSchemaIfNotExists(schemaName) { + this.pushQuery( + `create schema if not exists ${this.formatter.wrap(schemaName)}` + ); + } + + dropSchema(schemaName, cascade = false) { + this.pushQuery( + `drop schema ${this.formatter.wrap(schemaName)}${ + cascade ? ' cascade' : '' + }` + ); + } + + dropSchemaIfExists(schemaName, cascade = false) { + this.pushQuery( + `drop schema if exists ${this.formatter.wrap(schemaName)}${ + cascade ? ' cascade' : '' + }` + ); + } + + dropExtension(extensionName) { + this.pushQuery(`drop extension ${this.formatter.wrap(extensionName)}`); + } + + dropExtensionIfExists(extensionName) { + this.pushQuery( + `drop extension if exists ${this.formatter.wrap(extensionName)}` + ); + } + + createExtension(extensionName) { + this.pushQuery(`create extension ${this.formatter.wrap(extensionName)}`); + } + + createExtensionIfNotExists(extensionName) { + this.pushQuery( + `create extension if not exists ${this.formatter.wrap(extensionName)}` + ); + } + + renameView(from, to) { + this.pushQuery( + this.alterViewPrefix + + `${this.formatter.wrap(from)} rename to ${this.formatter.wrap(to)}` + ); + } + + refreshMaterializedView(viewName, concurrently = false) { + this.pushQuery({ + sql: `refresh materialized view${ + concurrently ? ' concurrently' : '' + } ${this.formatter.wrap(viewName)}`, + }); + } + + dropMaterializedView(viewName) { + this._dropView(viewName, false, true); + } + + dropMaterializedViewIfExists(viewName) { + this._dropView(viewName, true, true); + } +} + +module.exports = SchemaCompiler_PG; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-tablecompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-tablecompiler.js new file mode 100644 index 000000000..455a339ca --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-tablecompiler.js @@ -0,0 +1,304 @@ +/* eslint max-len: 0 */ + +// PostgreSQL Table Builder & Compiler +// ------- + +const has = require('lodash/has'); +const TableCompiler = require('../../../schema/tablecompiler'); +const { isObject, isString } = require('../../../util/is'); + +class TableCompiler_PG extends TableCompiler { + constructor(client, tableBuilder) { + super(client, tableBuilder); + } + + // Compile a rename column command. + renameColumn(from, to) { + return this.pushQuery({ + sql: `alter table ${this.tableName()} rename ${this.formatter.wrap( + from + )} to ${this.formatter.wrap(to)}`, + }); + } + + _setNullableState(column, isNullable) { + const constraintAction = isNullable ? 'drop not null' : 'set not null'; + const sql = `alter table ${this.tableName()} alter column ${this.formatter.wrap( + column + )} ${constraintAction}`; + return this.pushQuery({ + sql: sql, + }); + } + + compileAdd(builder) { + const table = this.formatter.wrap(builder); + const columns = this.prefixArray('add column', this.getColumns(builder)); + return this.pushQuery({ + sql: `alter table ${table} ${columns.join(', ')}`, + }); + } + + // Adds the "create" query to the query sequence. + createQuery(columns, ifNot, like) { + const createStatement = ifNot + ? 'create table if not exists ' + : 'create table '; + const columnsSql = ` (${columns.sql.join(', ')}${ + this.primaryKeys() || '' + }${this._addChecks()})`; + + let sql = + createStatement + + this.tableName() + + (like && this.tableNameLike() + ? ' (like ' + + this.tableNameLike() + + ' including all' + + (columns.sql.length ? ', ' + columns.sql.join(', ') : '') + + ')' + : columnsSql); + if (this.single.inherits) + sql += ` inherits (${this.formatter.wrap(this.single.inherits)})`; + this.pushQuery({ + sql, + bindings: columns.bindings, + }); + const hasComment = has(this.single, 'comment'); + if (hasComment) this.comment(this.single.comment); + } + + primaryKeys() { + const pks = (this.grouped.alterTable || []).filter( + (k) => k.method === 'primary' + ); + if (pks.length > 0 && pks[0].args.length > 0) { + const columns = pks[0].args[0]; + let constraintName = pks[0].args[1] || ''; + let deferrable; + if (isObject(constraintName)) { + ({ constraintName, deferrable } = constraintName); + } + deferrable = deferrable ? ` deferrable initially ${deferrable}` : ''; + constraintName = constraintName + ? this.formatter.wrap(constraintName) + : this.formatter.wrap(`${this.tableNameRaw}_pkey`); + + return `, constraint ${constraintName} primary key (${this.formatter.columnize( + columns + )})${deferrable}`; + } + } + + addColumns(columns, prefix, colCompilers) { + if (prefix === this.alterColumnsPrefix) { + // alter columns + for (const col of colCompilers) { + this._addColumn(col); + } + } else { + // base class implementation for normal add + super.addColumns(columns, prefix); + } + } + + _addColumn(col) { + const quotedTableName = this.tableName(); + const type = col.getColumnType(); + // We'd prefer to call this.formatter.wrapAsIdentifier here instead, however the context passed to + // `this` instance is not that of the column, but of the table. Thus, we unfortunately have to call + // `wrapIdentifier` here as well (it is already called once on the initial column operation) to give + // our `alter` operation the correct `queryContext`. Refer to issue #2606 and PR #2612. + const colName = this.client.wrapIdentifier( + col.getColumnName(), + col.columnBuilder.queryContext() + ); + + // To alter enum columns they must be cast to text first + const isEnum = col.type === 'enu'; + this.pushQuery({ + sql: `alter table ${quotedTableName} alter column ${colName} drop default`, + bindings: [], + }); + + const alterNullable = col.columnBuilder.alterNullable; + if (alterNullable) { + this.pushQuery({ + sql: `alter table ${quotedTableName} alter column ${colName} drop not null`, + bindings: [], + }); + } + + const alterType = col.columnBuilder.alterType; + if (alterType) { + this.pushQuery({ + sql: `alter table ${quotedTableName} alter column ${colName} type ${type} using (${colName}${ + isEnum ? '::text::' : '::' + }${type})`, + bindings: [], + }); + } + + const defaultTo = col.modified['defaultTo']; + if (defaultTo) { + const modifier = col.defaultTo.apply(col, defaultTo); + this.pushQuery({ + sql: `alter table ${quotedTableName} alter column ${colName} set ${modifier}`, + bindings: [], + }); + } + + if (alterNullable) { + const nullable = col.modified['nullable']; + if (nullable && nullable[0] === false) { + this.pushQuery({ + sql: `alter table ${quotedTableName} alter column ${colName} set not null`, + bindings: [], + }); + } + } + } + + // Compiles the comment on the table. + comment(comment) { + this.pushQuery( + `comment on table ${this.tableName()} is '${this.single.comment}'` + ); + } + + // Indexes: + // ------- + + primary(columns, constraintName) { + let deferrable; + if (isObject(constraintName)) { + ({ constraintName, deferrable } = constraintName); + } + deferrable = deferrable ? ` deferrable initially ${deferrable}` : ''; + constraintName = constraintName + ? this.formatter.wrap(constraintName) + : this.formatter.wrap(`${this.tableNameRaw}_pkey`); + if (this.method !== 'create' && this.method !== 'createIfNot') { + this.pushQuery( + `alter table ${this.tableName()} add constraint ${constraintName} primary key (${this.formatter.columnize( + columns + )})${deferrable}` + ); + } + } + + unique(columns, indexName) { + let deferrable; + let useConstraint = true; + let predicate; + if (isObject(indexName)) { + ({ indexName, deferrable, useConstraint, predicate } = indexName); + if (useConstraint === undefined) { + useConstraint = !!deferrable || !predicate; + } + } + if (!useConstraint && deferrable && deferrable !== 'not deferrable') { + throw new Error('postgres cannot create deferrable index'); + } + if (useConstraint && predicate) { + throw new Error('postgres cannot create constraint with predicate'); + } + deferrable = deferrable ? ` deferrable initially ${deferrable}` : ''; + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('unique', this.tableNameRaw, columns); + + if (useConstraint) { + this.pushQuery( + `alter table ${this.tableName()} add constraint ${indexName}` + + ' unique (' + + this.formatter.columnize(columns) + + ')' + + deferrable + ); + } else { + const predicateQuery = predicate + ? ' ' + this.client.queryCompiler(predicate).where() + : ''; + + this.pushQuery( + `create unique index ${indexName} on ${this.tableName()} (${this.formatter.columnize( + columns + )})${predicateQuery}` + ); + } + } + + index(columns, indexName, options) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('index', this.tableNameRaw, columns); + + let predicate; + let storageEngineIndexType; + let indexType; + + if (isString(options)) { + storageEngineIndexType = options; + } else if (isObject(options)) { + ({ indexType, storageEngineIndexType, predicate } = options); + } + + const predicateQuery = predicate + ? ' ' + this.client.queryCompiler(predicate).where() + : ''; + + this.pushQuery( + `create${ + typeof indexType === 'string' && indexType.toLowerCase() === 'unique' + ? ' unique' + : '' + } index ${indexName} on ${this.tableName()}${ + (storageEngineIndexType && ` using ${storageEngineIndexType}`) || '' + }` + + ' (' + + this.formatter.columnize(columns) + + ')' + + `${predicateQuery}` + ); + } + + dropPrimary(constraintName) { + constraintName = constraintName + ? this.formatter.wrap(constraintName) + : this.formatter.wrap(this.tableNameRaw + '_pkey'); + this.pushQuery( + `alter table ${this.tableName()} drop constraint ${constraintName}` + ); + } + + dropIndex(columns, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('index', this.tableNameRaw, columns); + indexName = this.schemaNameRaw + ? `${this.formatter.wrap(this.schemaNameRaw)}.${indexName}` + : indexName; + this.pushQuery(`drop index ${indexName}`); + } + + dropUnique(columns, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('unique', this.tableNameRaw, columns); + this.pushQuery( + `alter table ${this.tableName()} drop constraint ${indexName}` + ); + } + + dropForeign(columns, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('foreign', this.tableNameRaw, columns); + this.pushQuery( + `alter table ${this.tableName()} drop constraint ${indexName}` + ); + } +} + +module.exports = TableCompiler_PG; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-viewbuilder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-viewbuilder.js new file mode 100644 index 000000000..bb02be005 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-viewbuilder.js @@ -0,0 +1,21 @@ +const ViewBuilder = require('../../../schema/viewbuilder.js'); + +class ViewBuilder_PG extends ViewBuilder { + constructor() { + super(...arguments); + } + + checkOption() { + this._single.checkOption = 'default_option'; + } + + localCheckOption() { + this._single.checkOption = 'local'; + } + + cascadedCheckOption() { + this._single.checkOption = 'cascaded'; + } +} + +module.exports = ViewBuilder_PG; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-viewcompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-viewcompiler.js new file mode 100644 index 000000000..c9a18da2e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/postgres/schema/pg-viewcompiler.js @@ -0,0 +1,35 @@ +/* eslint max-len: 0 */ + +const ViewCompiler = require('../../../schema/viewcompiler.js'); + +class ViewCompiler_PG extends ViewCompiler { + constructor(client, viewCompiler) { + super(client, viewCompiler); + } + + renameColumn(from, to) { + return this.pushQuery({ + sql: `alter view ${this.viewName()} rename ${this.formatter.wrap( + from + )} to ${this.formatter.wrap(to)}`, + }); + } + + defaultTo(column, defaultValue) { + return this.pushQuery({ + sql: `alter view ${this.viewName()} alter ${this.formatter.wrap( + column + )} set default ${defaultValue}`, + }); + } + + createOrReplace() { + this.createQuery(this.columns, this.selectQuery, false, true); + } + + createMaterializedView() { + this.createQuery(this.columns, this.selectQuery, true); + } +} + +module.exports = ViewCompiler_PG; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/index.js new file mode 100644 index 000000000..7b5c41b78 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/index.js @@ -0,0 +1,86 @@ +// Redshift +// ------- +const Client_PG = require('../postgres'); +const map = require('lodash/map'); + +const Transaction = require('./transaction'); +const QueryCompiler = require('./query/redshift-querycompiler'); +const ColumnBuilder = require('./schema/redshift-columnbuilder'); +const ColumnCompiler = require('./schema/redshift-columncompiler'); +const TableCompiler = require('./schema/redshift-tablecompiler'); +const SchemaCompiler = require('./schema/redshift-compiler'); +const ViewCompiler = require('./schema/redshift-viewcompiler'); + +class Client_Redshift extends Client_PG { + transaction() { + return new Transaction(this, ...arguments); + } + + queryCompiler(builder, formatter) { + return new QueryCompiler(this, builder, formatter); + } + + columnBuilder() { + return new ColumnBuilder(this, ...arguments); + } + + columnCompiler() { + return new ColumnCompiler(this, ...arguments); + } + + tableCompiler() { + return new TableCompiler(this, ...arguments); + } + + schemaCompiler() { + return new SchemaCompiler(this, ...arguments); + } + + viewCompiler() { + return new ViewCompiler(this, ...arguments); + } + + _driver() { + return require('pg'); + } + + // Ensures the response is returned in the same format as other clients. + processResponse(obj, runner) { + const resp = obj.response; + if (obj.output) return obj.output.call(runner, resp); + if (obj.method === 'raw') return resp; + if (resp.command === 'SELECT') { + if (obj.method === 'first') return resp.rows[0]; + if (obj.method === 'pluck') return map(resp.rows, obj.pluck); + return resp.rows; + } + if ( + resp.command === 'INSERT' || + resp.command === 'UPDATE' || + resp.command === 'DELETE' + ) { + return resp.rowCount; + } + return resp; + } + + toPathForJson(jsonPath, builder, bindingsHolder) { + return jsonPath + .replace(/^(\$\.)/, '') // remove the first dollar + .split('.') + .map( + function (v) { + return this.parameter(v, builder, bindingsHolder); + }.bind(this) + ) + .join(', '); + } +} + +Object.assign(Client_Redshift.prototype, { + dialect: 'redshift', + + driverName: 'pg-redshift', +}); + +module.exports = Client_Redshift; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/query/redshift-querycompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/query/redshift-querycompiler.js new file mode 100644 index 000000000..6687b80cb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/query/redshift-querycompiler.js @@ -0,0 +1,163 @@ +// Redshift Query Builder & Compiler +// ------ +const QueryCompiler = require('../../../query/querycompiler'); +const QueryCompiler_PG = require('../../postgres/query/pg-querycompiler'); + +const identity = require('lodash/identity'); +const { + columnize: columnize_, +} = require('../../../formatter/wrappingFormatter'); + +class QueryCompiler_Redshift extends QueryCompiler_PG { + truncate() { + return `truncate ${this.tableName.toLowerCase()}`; + } + + // Compiles an `insert` query, allowing for multiple + // inserts using a single query statement. + insert() { + const sql = QueryCompiler.prototype.insert.apply(this, arguments); + if (sql === '') return sql; + this._slightReturn(); + return { + sql, + }; + } + + // Compiles an `update` query, warning on unsupported returning + update() { + const sql = QueryCompiler.prototype.update.apply(this, arguments); + this._slightReturn(); + return { + sql, + }; + } + + // Compiles an `delete` query, warning on unsupported returning + del() { + const sql = QueryCompiler.prototype.del.apply(this, arguments); + this._slightReturn(); + return { + sql, + }; + } + + // simple: if trying to return, warn + _slightReturn() { + if (this.single.isReturning) { + this.client.logger.warn( + 'insert/update/delete returning is not supported by redshift dialect' + ); + } + } + + forUpdate() { + this.client.logger.warn('table lock is not supported by redshift dialect'); + return ''; + } + + forShare() { + this.client.logger.warn( + 'lock for share is not supported by redshift dialect' + ); + return ''; + } + + forNoKeyUpdate() { + this.client.logger.warn('table lock is not supported by redshift dialect'); + return ''; + } + + forKeyShare() { + this.client.logger.warn( + 'lock for share is not supported by redshift dialect' + ); + return ''; + } + + // Compiles a columnInfo query + columnInfo() { + const column = this.single.columnInfo; + let schema = this.single.schema; + + // The user may have specified a custom wrapIdentifier function in the config. We + // need to run the identifiers through that function, but not format them as + // identifiers otherwise. + const table = this.client.customWrapIdentifier(this.single.table, identity); + + if (schema) { + schema = this.client.customWrapIdentifier(schema, identity); + } + + const sql = + 'select * from information_schema.columns where table_name = ? and table_catalog = ?'; + const bindings = [ + table.toLowerCase(), + this.client.database().toLowerCase(), + ]; + + return this._buildColumnInfoQuery(schema, sql, bindings, column); + } + + jsonExtract(params) { + let extractions; + if (Array.isArray(params.column)) { + extractions = params.column; + } else { + extractions = [params]; + } + return extractions + .map((extraction) => { + const jsonCol = `json_extract_path_text(${columnize_( + extraction.column || extraction[0], + this.builder, + this.client, + this.bindingsHolder + )}, ${this.client.toPathForJson( + params.path || extraction[1], + this.builder, + this.bindingsHolder + )})`; + const alias = extraction.alias || extraction[2]; + return alias + ? this.client.alias(jsonCol, this.formatter.wrap(alias)) + : jsonCol; + }) + .join(', '); + } + + jsonSet(params) { + throw new Error('Json set is not supported by Redshift'); + } + + jsonInsert(params) { + throw new Error('Json insert is not supported by Redshift'); + } + + jsonRemove(params) { + throw new Error('Json remove is not supported by Redshift'); + } + + whereJsonPath(statement) { + return this._whereJsonPath( + 'json_extract_path_text', + Object.assign({}, statement, { + path: this.client.toPathForJson(statement.path), + }) + ); + } + + whereJsonSupersetOf(statement) { + throw new Error('Json superset is not supported by Redshift'); + } + + whereJsonSubsetOf(statement) { + throw new Error('Json subset is not supported by Redshift'); + } + + onJsonPathEquals(clause) { + return this._onJsonPathEquals('json_extract_path_text', clause); + } +} + +module.exports = QueryCompiler_Redshift; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-columnbuilder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-columnbuilder.js new file mode 100644 index 000000000..953657d45 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-columnbuilder.js @@ -0,0 +1,22 @@ +const ColumnBuilder = require('../../../schema/columnbuilder'); + +class ColumnBuilder_Redshift extends ColumnBuilder { + constructor() { + super(...arguments); + } + + // primary needs to set not null on non-preexisting columns, or fail + primary() { + this.notNullable(); + return super.primary(...arguments); + } + + index() { + this.client.logger.warn( + 'Redshift does not support the creation of indexes.' + ); + return this; + } +} + +module.exports = ColumnBuilder_Redshift; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-columncompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-columncompiler.js new file mode 100644 index 000000000..405ce4b82 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-columncompiler.js @@ -0,0 +1,67 @@ +// Redshift Column Compiler +// ------- + +const ColumnCompiler_PG = require('../../postgres/schema/pg-columncompiler'); +const ColumnCompiler = require('../../../schema/columncompiler'); + +class ColumnCompiler_Redshift extends ColumnCompiler_PG { + constructor() { + super(...arguments); + } + + // Types: + // ------ + + bit(column) { + return column.length !== false ? `char(${column.length})` : 'char(1)'; + } + + datetime(without) { + return without ? 'timestamp' : 'timestamptz'; + } + + timestamp(without) { + return without ? 'timestamp' : 'timestamptz'; + } + + // Modifiers: + // ------ + comment(comment) { + this.pushAdditional(function () { + this.pushQuery( + `comment on column ${this.tableCompiler.tableName()}.` + + this.formatter.wrap(this.args[0]) + + ' is ' + + (comment ? `'${comment}'` : 'NULL') + ); + }, comment); + } +} + +ColumnCompiler_Redshift.prototype.increments = ({ primaryKey = true } = {}) => + 'integer identity(1,1)' + (primaryKey ? ' primary key' : '') + ' not null'; +ColumnCompiler_Redshift.prototype.bigincrements = ({ + primaryKey = true, +} = {}) => + 'bigint identity(1,1)' + (primaryKey ? ' primary key' : '') + ' not null'; +ColumnCompiler_Redshift.prototype.binary = 'varchar(max)'; +ColumnCompiler_Redshift.prototype.blob = 'varchar(max)'; +ColumnCompiler_Redshift.prototype.enu = 'varchar(255)'; +ColumnCompiler_Redshift.prototype.enum = 'varchar(255)'; +ColumnCompiler_Redshift.prototype.json = 'varchar(max)'; +ColumnCompiler_Redshift.prototype.jsonb = 'varchar(max)'; +ColumnCompiler_Redshift.prototype.longblob = 'varchar(max)'; +ColumnCompiler_Redshift.prototype.mediumblob = 'varchar(16777218)'; +ColumnCompiler_Redshift.prototype.set = 'text'; +ColumnCompiler_Redshift.prototype.text = 'varchar(max)'; +ColumnCompiler_Redshift.prototype.tinyblob = 'varchar(256)'; +ColumnCompiler_Redshift.prototype.uuid = ColumnCompiler.prototype.uuid; +ColumnCompiler_Redshift.prototype.varbinary = 'varchar(max)'; +ColumnCompiler_Redshift.prototype.bigint = 'bigint'; +ColumnCompiler_Redshift.prototype.bool = 'boolean'; +ColumnCompiler_Redshift.prototype.double = 'double precision'; +ColumnCompiler_Redshift.prototype.floating = 'real'; +ColumnCompiler_Redshift.prototype.smallint = 'smallint'; +ColumnCompiler_Redshift.prototype.tinyint = 'smallint'; + +module.exports = ColumnCompiler_Redshift; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-compiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-compiler.js new file mode 100644 index 000000000..03bd41c60 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-compiler.js @@ -0,0 +1,14 @@ +/* eslint max-len: 0 */ + +// Redshift Table Builder & Compiler +// ------- + +const SchemaCompiler_PG = require('../../postgres/schema/pg-compiler'); + +class SchemaCompiler_Redshift extends SchemaCompiler_PG { + constructor() { + super(...arguments); + } +} + +module.exports = SchemaCompiler_Redshift; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-tablecompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-tablecompiler.js new file mode 100644 index 000000000..9ba766421 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-tablecompiler.js @@ -0,0 +1,122 @@ +/* eslint max-len: 0 */ + +// Redshift Table Builder & Compiler +// ------- + +const has = require('lodash/has'); +const TableCompiler_PG = require('../../postgres/schema/pg-tablecompiler'); + +class TableCompiler_Redshift extends TableCompiler_PG { + constructor() { + super(...arguments); + } + + index(columns, indexName, options) { + this.client.logger.warn( + 'Redshift does not support the creation of indexes.' + ); + } + + dropIndex(columns, indexName) { + this.client.logger.warn( + 'Redshift does not support the deletion of indexes.' + ); + } + + // TODO: have to disable setting not null on columns that already exist... + + // Adds the "create" query to the query sequence. + createQuery(columns, ifNot, like) { + const createStatement = ifNot + ? 'create table if not exists ' + : 'create table '; + const columnsSql = ' (' + columns.sql.join(', ') + this._addChecks() + ')'; + let sql = + createStatement + + this.tableName() + + (like && this.tableNameLike() + ? ' (like ' + this.tableNameLike() + ')' + : columnsSql); + if (this.single.inherits) + sql += ` like (${this.formatter.wrap(this.single.inherits)})`; + this.pushQuery({ + sql, + bindings: columns.bindings, + }); + const hasComment = has(this.single, 'comment'); + if (hasComment) this.comment(this.single.comment); + if (like) { + this.addColumns(columns, this.addColumnsPrefix); + } + } + + primary(columns, constraintName) { + const self = this; + constraintName = constraintName + ? self.formatter.wrap(constraintName) + : self.formatter.wrap(`${this.tableNameRaw}_pkey`); + if (columns.constructor !== Array) { + columns = [columns]; + } + const thiscolumns = self.grouped.columns; + + if (thiscolumns) { + for (let i = 0; i < columns.length; i++) { + let exists = thiscolumns.find( + (tcb) => + tcb.grouping === 'columns' && + tcb.builder && + tcb.builder._method === 'add' && + tcb.builder._args && + tcb.builder._args.indexOf(columns[i]) > -1 + ); + if (exists) { + exists = exists.builder; + } + const nullable = !( + exists && + exists._modifiers && + exists._modifiers['nullable'] && + exists._modifiers['nullable'][0] === false + ); + if (nullable) { + if (exists) { + return this.client.logger.warn( + 'Redshift does not allow primary keys to contain nullable columns.' + ); + } else { + return this.client.logger.warn( + 'Redshift does not allow primary keys to contain nonexistent columns.' + ); + } + } + } + } + return self.pushQuery( + `alter table ${self.tableName()} add constraint ${constraintName} primary key (${self.formatter.columnize( + columns + )})` + ); + } + + // Compiles column add. Redshift can only add one column per ALTER TABLE, so core addColumns doesn't work. #2545 + addColumns(columns, prefix, colCompilers) { + if (prefix === this.alterColumnsPrefix) { + super.addColumns(columns, prefix, colCompilers); + } else { + prefix = prefix || this.addColumnsPrefix; + colCompilers = colCompilers || this.getColumns(); + for (const col of colCompilers) { + const quotedTableName = this.tableName(); + const colCompiled = col.compileColumn(); + + this.pushQuery({ + sql: `alter table ${quotedTableName} ${prefix}${colCompiled}`, + bindings: [], + }); + } + } + } +} + +module.exports = TableCompiler_Redshift; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-viewcompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-viewcompiler.js new file mode 100644 index 000000000..53c5f427c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/schema/redshift-viewcompiler.js @@ -0,0 +1,11 @@ +/* eslint max-len: 0 */ + +const ViewCompiler_PG = require('../../postgres/schema/pg-viewcompiler.js'); + +class ViewCompiler_Redshift extends ViewCompiler_PG { + constructor(client, viewCompiler) { + super(client, viewCompiler); + } +} + +module.exports = ViewCompiler_Redshift; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/transaction.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/transaction.js new file mode 100644 index 000000000..10e6ef91c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/redshift/transaction.js @@ -0,0 +1,32 @@ +const Transaction = require('../../execution/transaction'); + +module.exports = class Redshift_Transaction extends Transaction { + begin(conn) { + const trxMode = [ + this.isolationLevel ? `ISOLATION LEVEL ${this.isolationLevel}` : '', + this.readOnly ? 'READ ONLY' : '', + ] + .join(' ') + .trim(); + + if (trxMode.length === 0) { + return this.query(conn, 'BEGIN;'); + } + return this.query(conn, `BEGIN ${trxMode};`); + } + + savepoint(conn) { + this.trxClient.logger('Redshift does not support savepoints.'); + return Promise.resolve(); + } + + release(conn, value) { + this.trxClient.logger('Redshift does not support savepoints.'); + return Promise.resolve(); + } + + rollbackTo(conn, error) { + this.trxClient.logger('Redshift does not support savepoints.'); + return Promise.resolve(); + } +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/execution/sqlite-transaction.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/execution/sqlite-transaction.js new file mode 100644 index 000000000..99a3e7896 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/execution/sqlite-transaction.js @@ -0,0 +1,25 @@ +const Transaction = require('../../../execution/transaction'); + +class Transaction_Sqlite extends Transaction { + begin(conn) { + // SQLite doesn't really support isolation levels, it is serializable by + // default and so we override it to ignore isolation level. + // There is a `PRAGMA read_uncommitted = true;`, but that's probably not + // what the user wants + if (this.isolationLevel) { + this.client.logger.warn( + 'sqlite3 only supports serializable transactions, ignoring the isolation level param' + ); + } + // SQLite infers read vs write transactions from the statement operation + // https://www.sqlite.org/lang_transaction.html#read_transactions_versus_write_transactions + if (this.readOnly) { + this.client.logger.warn( + 'sqlite3 implicitly handles read vs write transactions' + ); + } + return this.query(conn, 'BEGIN;'); + } +} + +module.exports = Transaction_Sqlite; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/index.js new file mode 100644 index 000000000..7524c1c6a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/index.js @@ -0,0 +1,250 @@ +// SQLite3 +// ------- +const defaults = require('lodash/defaults'); +const map = require('lodash/map'); +const { promisify } = require('util'); + +const Client = require('../../client'); + +const Raw = require('../../raw'); +const Transaction = require('./execution/sqlite-transaction'); +const SqliteQueryCompiler = require('./query/sqlite-querycompiler'); +const SchemaCompiler = require('./schema/sqlite-compiler'); +const ColumnCompiler = require('./schema/sqlite-columncompiler'); +const TableCompiler = require('./schema/sqlite-tablecompiler'); +const ViewCompiler = require('./schema/sqlite-viewcompiler'); +const SQLite3_DDL = require('./schema/ddl'); +const Formatter = require('../../formatter'); +const QueryBuilder = require('./query/sqlite-querybuilder'); + +class Client_SQLite3 extends Client { + constructor(config) { + super(config); + + if (config.connection && config.connection.filename === undefined) { + this.logger.warn( + 'Could not find `connection.filename` in config. Please specify ' + + 'the database path and name to avoid errors. ' + + '(see docs https://knexjs.org/guide/#configuration-options)' + ); + } + + if (config.useNullAsDefault === undefined) { + this.logger.warn( + 'sqlite does not support inserting default values. Set the ' + + '`useNullAsDefault` flag to hide this warning. ' + + '(see docs https://knexjs.org/guide/query-builder.html#insert).' + ); + } + } + + _driver() { + return require('sqlite3'); + } + + schemaCompiler() { + return new SchemaCompiler(this, ...arguments); + } + + transaction() { + return new Transaction(this, ...arguments); + } + + queryCompiler(builder, formatter) { + return new SqliteQueryCompiler(this, builder, formatter); + } + + queryBuilder() { + return new QueryBuilder(this); + } + + viewCompiler(builder, formatter) { + return new ViewCompiler(this, builder, formatter); + } + + columnCompiler() { + return new ColumnCompiler(this, ...arguments); + } + + tableCompiler() { + return new TableCompiler(this, ...arguments); + } + + ddl(compiler, pragma, connection) { + return new SQLite3_DDL(this, compiler, pragma, connection); + } + + wrapIdentifierImpl(value) { + return value !== '*' ? `\`${value.replace(/`/g, '``')}\`` : '*'; + } + + // Get a raw connection from the database, returning a promise with the connection object. + acquireRawConnection() { + return new Promise((resolve, reject) => { + // the default mode for sqlite3 + let flags = this.driver.OPEN_READWRITE | this.driver.OPEN_CREATE; + + if (this.connectionSettings.flags) { + if (!Array.isArray(this.connectionSettings.flags)) { + throw new Error(`flags must be an array of strings`); + } + this.connectionSettings.flags.forEach((_flag) => { + if (!_flag.startsWith('OPEN_') || !this.driver[_flag]) { + throw new Error(`flag ${_flag} not supported by node-sqlite3`); + } + flags = flags | this.driver[_flag]; + }); + } + + const db = new this.driver.Database( + this.connectionSettings.filename, + flags, + (err) => { + if (err) { + return reject(err); + } + resolve(db); + } + ); + }); + } + + // Used to explicitly close a connection, called internally by the pool when + // a connection times out or the pool is shutdown. + async destroyRawConnection(connection) { + const close = promisify((cb) => connection.close(cb)); + return close(); + } + + // Runs the query on the specified connection, providing the bindings and any + // other necessary prep work. + _query(connection, obj) { + if (!obj.sql) throw new Error('The query is empty'); + + const { method } = obj; + let callMethod; + switch (method) { + case 'insert': + case 'update': + callMethod = obj.returning ? 'all' : 'run'; + break; + case 'counter': + case 'del': + callMethod = 'run'; + break; + default: + callMethod = 'all'; + } + return new Promise(function (resolver, rejecter) { + if (!connection || !connection[callMethod]) { + return rejecter( + new Error(`Error calling ${callMethod} on connection.`) + ); + } + connection[callMethod](obj.sql, obj.bindings, function (err, response) { + if (err) return rejecter(err); + obj.response = response; + + // We need the context here, as it contains + // the "this.lastID" or "this.changes" + obj.context = this; + + return resolver(obj); + }); + }); + } + + _stream(connection, obj, stream) { + if (!obj.sql) throw new Error('The query is empty'); + + const client = this; + return new Promise(function (resolver, rejecter) { + stream.on('error', rejecter); + stream.on('end', resolver); + + return client + ._query(connection, obj) + .then((obj) => obj.response) + .then((rows) => rows.forEach((row) => stream.write(row))) + .catch(function (err) { + stream.emit('error', err); + }) + .then(function () { + stream.end(); + }); + }); + } + + // Ensures the response is returned in the same format as other clients. + processResponse(obj, runner) { + const ctx = obj.context; + const { response, returning } = obj; + if (obj.output) return obj.output.call(runner, response); + switch (obj.method) { + case 'select': + return response; + case 'first': + return response[0]; + case 'pluck': + return map(response, obj.pluck); + case 'insert': { + if (returning) { + if (response) { + return response; + } + } + return [ctx.lastID]; + } + case 'update': { + if (returning) { + if (response) { + return response; + } + } + return ctx.changes; + } + case 'del': + case 'counter': + return ctx.changes; + default: { + return response; + } + } + } + + poolDefaults() { + return defaults({ min: 1, max: 1 }, super.poolDefaults()); + } + + formatter(builder) { + return new Formatter(this, builder); + } + + values(values, builder, formatter) { + if (Array.isArray(values)) { + if (Array.isArray(values[0])) { + return `( values ${values + .map( + (value) => + `(${this.parameterize(value, undefined, builder, formatter)})` + ) + .join(', ')})`; + } + return `(${this.parameterize(values, undefined, builder, formatter)})`; + } + + if (values instanceof Raw) { + return `(${this.parameter(values, builder, formatter)})`; + } + + return this.parameter(values, builder, formatter); + } +} + +Object.assign(Client_SQLite3.prototype, { + dialect: 'sqlite3', + + driverName: 'sqlite3', +}); + +module.exports = Client_SQLite3; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/query/sqlite-querybuilder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/query/sqlite-querybuilder.js new file mode 100644 index 000000000..08fba898e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/query/sqlite-querybuilder.js @@ -0,0 +1,33 @@ +const QueryBuilder = require('../../../query/querybuilder.js'); + +module.exports = class QueryBuilder_SQLite3 extends QueryBuilder { + withMaterialized(alias, statementOrColumnList, nothingOrStatement) { + this._validateWithArgs( + alias, + statementOrColumnList, + nothingOrStatement, + 'with' + ); + return this.withWrapped( + alias, + statementOrColumnList, + nothingOrStatement, + true + ); + } + + withNotMaterialized(alias, statementOrColumnList, nothingOrStatement) { + this._validateWithArgs( + alias, + statementOrColumnList, + nothingOrStatement, + 'with' + ); + return this.withWrapped( + alias, + statementOrColumnList, + nothingOrStatement, + false + ); + } +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/query/sqlite-querycompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/query/sqlite-querycompiler.js new file mode 100644 index 000000000..47b282eb4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/query/sqlite-querycompiler.js @@ -0,0 +1,334 @@ +// SQLite3 Query Builder & Compiler + +const constant = require('lodash/constant'); +const each = require('lodash/each'); +const identity = require('lodash/identity'); +const isEmpty = require('lodash/isEmpty'); +const reduce = require('lodash/reduce'); + +const QueryCompiler = require('../../../query/querycompiler'); +const noop = require('../../../util/noop'); +const { isString } = require('../../../util/is'); +const { + wrapString, + columnize: columnize_, +} = require('../../../formatter/wrappingFormatter'); + +const emptyStr = constant(''); + +class QueryCompiler_SQLite3 extends QueryCompiler { + constructor(client, builder, formatter) { + super(client, builder, formatter); + + // The locks are not applicable in SQLite3 + this.forShare = emptyStr; + this.forKeyShare = emptyStr; + this.forUpdate = emptyStr; + this.forNoKeyUpdate = emptyStr; + } + + // SQLite requires us to build the multi-row insert as a listing of select with + // unions joining them together. So we'll build out this list of columns and + // then join them all together with select unions to complete the queries. + insert() { + const insertValues = this.single.insert || []; + let sql = this.with() + `insert into ${this.tableName} `; + + if (Array.isArray(insertValues)) { + if (insertValues.length === 0) { + return ''; + } else if ( + insertValues.length === 1 && + insertValues[0] && + isEmpty(insertValues[0]) + ) { + return { + sql: sql + this._emptyInsertValue, + }; + } + } else if (typeof insertValues === 'object' && isEmpty(insertValues)) { + return { + sql: sql + this._emptyInsertValue, + }; + } + + const insertData = this._prepInsert(insertValues); + + if (isString(insertData)) { + return { + sql: sql + insertData, + }; + } + + if (insertData.columns.length === 0) { + return { + sql: '', + }; + } + + sql += `(${this.formatter.columnize(insertData.columns)})`; + + // backwards compatible error + if (this.client.valueForUndefined !== null) { + insertData.values.forEach((bindings) => { + each(bindings, (binding) => { + if (binding === undefined) + throw new TypeError( + '`sqlite` does not support inserting default values. Specify ' + + 'values explicitly or use the `useNullAsDefault` config flag. ' + + '(see docs https://knexjs.org/guide/query-builder.html#insert).' + ); + }); + }); + } + + if (insertData.values.length === 1) { + const parameters = this.client.parameterize( + insertData.values[0], + this.client.valueForUndefined, + this.builder, + this.bindingsHolder + ); + sql += ` values (${parameters})`; + + const { onConflict, ignore, merge } = this.single; + if (onConflict && ignore) sql += this._ignore(onConflict); + else if (onConflict && merge) { + sql += this._merge(merge.updates, onConflict, insertValues); + const wheres = this.where(); + if (wheres) sql += ` ${wheres}`; + } + + const { returning } = this.single; + if (returning) { + sql += this._returning(returning); + } + + return { + sql, + returning, + }; + } + + const blocks = []; + let i = -1; + while (++i < insertData.values.length) { + let i2 = -1; + const block = (blocks[i] = []); + let current = insertData.values[i]; + current = current === undefined ? this.client.valueForUndefined : current; + while (++i2 < insertData.columns.length) { + block.push( + this.client.alias( + this.client.parameter( + current[i2], + this.builder, + this.bindingsHolder + ), + this.formatter.wrap(insertData.columns[i2]) + ) + ); + } + blocks[i] = block.join(', '); + } + sql += ' select ' + blocks.join(' union all select '); + + const { onConflict, ignore, merge } = this.single; + if (onConflict && ignore) sql += ' where true' + this._ignore(onConflict); + else if (onConflict && merge) { + sql += + ' where true' + this._merge(merge.updates, onConflict, insertValues); + } + + const { returning } = this.single; + if (returning) sql += this._returning(returning); + + return { + sql, + returning, + }; + } + + // Compiles an `update` query, allowing for a return value. + update() { + const withSQL = this.with(); + const updateData = this._prepUpdate(this.single.update); + const wheres = this.where(); + const { returning } = this.single; + return { + sql: + withSQL + + `update ${this.single.only ? 'only ' : ''}${this.tableName} ` + + `set ${updateData.join(', ')}` + + (wheres ? ` ${wheres}` : '') + + this._returning(returning), + returning, + }; + } + + _ignore(columns) { + if (columns === true) { + return ' on conflict do nothing'; + } + return ` on conflict ${this._onConflictClause(columns)} do nothing`; + } + + _merge(updates, columns, insert) { + let sql = ` on conflict ${this._onConflictClause(columns)} do update set `; + if (updates && Array.isArray(updates)) { + sql += updates + .map((column) => + wrapString( + column.split('.').pop(), + this.formatter.builder, + this.client, + this.formatter + ) + ) + .map((column) => `${column} = excluded.${column}`) + .join(', '); + + return sql; + } else if (updates && typeof updates === 'object') { + const updateData = this._prepUpdate(updates); + if (typeof updateData === 'string') { + sql += updateData; + } else { + sql += updateData.join(','); + } + + return sql; + } else { + const insertData = this._prepInsert(insert); + if (typeof insertData === 'string') { + throw new Error( + 'If using merge with a raw insert query, then updates must be provided' + ); + } + + sql += insertData.columns + .map((column) => + wrapString(column.split('.').pop(), this.builder, this.client) + ) + .map((column) => `${column} = excluded.${column}`) + .join(', '); + + return sql; + } + } + + _returning(value) { + return value ? ` returning ${this.formatter.columnize(value)}` : ''; + } + + // Compile a truncate table statement into SQL. + truncate() { + const { table } = this.single; + return { + sql: `delete from ${this.tableName}`, + output() { + return this.query({ + sql: `delete from sqlite_sequence where name = '${table}'`, + }).catch(noop); + }, + }; + } + + // Compiles a `columnInfo` query + columnInfo() { + const column = this.single.columnInfo; + + // The user may have specified a custom wrapIdentifier function in the config. We + // need to run the identifiers through that function, but not format them as + // identifiers otherwise. + const table = this.client.customWrapIdentifier(this.single.table, identity); + + return { + sql: `PRAGMA table_info(\`${table}\`)`, + output(resp) { + const maxLengthRegex = /.*\((\d+)\)/; + const out = reduce( + resp, + function (columns, val) { + let { type } = val; + let maxLength = type.match(maxLengthRegex); + if (maxLength) { + maxLength = maxLength[1]; + } + type = maxLength ? type.split('(')[0] : type; + columns[val.name] = { + type: type.toLowerCase(), + maxLength, + nullable: !val.notnull, + defaultValue: val.dflt_value, + }; + return columns; + }, + {} + ); + return (column && out[column]) || out; + }, + }; + } + + limit() { + const noLimit = !this.single.limit && this.single.limit !== 0; + if (noLimit && !this.single.offset) return ''; + + // Workaround for offset only, + // see http://stackoverflow.com/questions/10491492/sqllite-with-skip-offset-only-not-limit + this.single.limit = noLimit ? -1 : this.single.limit; + return `limit ${this._getValueOrParameterFromAttribute('limit')}`; + } + + // Json functions + jsonExtract(params) { + return this._jsonExtract('json_extract', params); + } + + jsonSet(params) { + return this._jsonSet('json_set', params); + } + + jsonInsert(params) { + return this._jsonSet('json_insert', params); + } + + jsonRemove(params) { + const jsonCol = `json_remove(${columnize_( + params.column, + this.builder, + this.client, + this.bindingsHolder + )},${this.client.parameter( + params.path, + this.builder, + this.bindingsHolder + )})`; + return params.alias + ? this.client.alias(jsonCol, this.formatter.wrap(params.alias)) + : jsonCol; + } + + whereJsonPath(statement) { + return this._whereJsonPath('json_extract', statement); + } + + whereJsonSupersetOf(statement) { + throw new Error( + 'Json superset where clause not actually supported by SQLite' + ); + } + + whereJsonSubsetOf(statement) { + throw new Error( + 'Json subset where clause not actually supported by SQLite' + ); + } + + onJsonPathEquals(clause) { + return this._onJsonPathEquals('json_extract', clause); + } +} + +module.exports = QueryCompiler_SQLite3; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/ddl.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/ddl.js new file mode 100644 index 000000000..5bec4d48c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/ddl.js @@ -0,0 +1,400 @@ +// SQLite3_DDL +// +// All of the SQLite3 specific DDL helpers for renaming/dropping +// columns and changing datatypes. +// ------- + +const identity = require('lodash/identity'); +const { nanonum } = require('../../../util/nanoid'); +const { + copyData, + dropOriginal, + renameTable, + getTableSql, + isForeignCheckEnabled, + setForeignCheck, + executeForeignCheck, +} = require('./internal/sqlite-ddl-operations'); +const { parseCreateTable, parseCreateIndex } = require('./internal/parser'); +const { + compileCreateTable, + compileCreateIndex, +} = require('./internal/compiler'); +const { isEqualId, includesId } = require('./internal/utils'); + +// So altering the schema in SQLite3 is a major pain. +// We have our own object to deal with the renaming and altering the types +// for sqlite3 things. +class SQLite3_DDL { + constructor(client, tableCompiler, pragma, connection) { + this.client = client; + this.tableCompiler = tableCompiler; + this.pragma = pragma; + this.tableNameRaw = this.tableCompiler.tableNameRaw; + this.alteredName = `_knex_temp_alter${nanonum(3)}`; + this.connection = connection; + this.formatter = (value) => + this.client.customWrapIdentifier(value, identity); + this.wrap = (value) => this.client.wrapIdentifierImpl(value); + } + + tableName() { + return this.formatter(this.tableNameRaw); + } + + getTableSql() { + const tableName = this.tableName(); + + return this.client.transaction( + async (trx) => { + trx.disableProcessing(); + const result = await trx.raw(getTableSql(tableName)); + trx.enableProcessing(); + + return { + createTable: result.filter((create) => create.type === 'table')[0] + .sql, + createIndices: result + .filter((create) => create.type === 'index') + .map((create) => create.sql), + }; + }, + { connection: this.connection } + ); + } + + async isForeignCheckEnabled() { + const result = await this.client + .raw(isForeignCheckEnabled()) + .connection(this.connection); + + return result[0].foreign_keys === 1; + } + + async setForeignCheck(enable) { + await this.client.raw(setForeignCheck(enable)).connection(this.connection); + } + + renameTable(trx) { + return trx.raw(renameTable(this.alteredName, this.tableName())); + } + + dropOriginal(trx) { + return trx.raw(dropOriginal(this.tableName())); + } + + copyData(trx, columns) { + return trx.raw(copyData(this.tableName(), this.alteredName, columns)); + } + + async alterColumn(columns) { + const { createTable, createIndices } = await this.getTableSql(); + + const parsedTable = parseCreateTable(createTable); + parsedTable.table = this.alteredName; + + parsedTable.columns = parsedTable.columns.map((column) => { + const newColumnInfo = columns.find((c) => isEqualId(c.name, column.name)); + + if (newColumnInfo) { + column.type = newColumnInfo.type; + + column.constraints.default = + newColumnInfo.defaultTo !== null + ? { + name: null, + value: newColumnInfo.defaultTo, + expression: false, + } + : null; + + column.constraints.notnull = newColumnInfo.notNull + ? { name: null, conflict: null } + : null; + + column.constraints.null = newColumnInfo.notNull + ? null + : column.constraints.null; + } + + return column; + }); + + const newTable = compileCreateTable(parsedTable, this.wrap); + + return this.generateAlterCommands(newTable, createIndices); + } + + async dropColumn(columns) { + const { createTable, createIndices } = await this.getTableSql(); + + const parsedTable = parseCreateTable(createTable); + parsedTable.table = this.alteredName; + + parsedTable.columns = parsedTable.columns.filter( + (parsedColumn) => + parsedColumn.expression || !includesId(columns, parsedColumn.name) + ); + + if (parsedTable.columns.length === 0) { + throw new Error('Unable to drop last column from table'); + } + + parsedTable.constraints = parsedTable.constraints.filter((constraint) => { + if (constraint.type === 'PRIMARY KEY' || constraint.type === 'UNIQUE') { + return constraint.columns.every( + (constraintColumn) => + constraintColumn.expression || + !includesId(columns, constraintColumn.name) + ); + } else if (constraint.type === 'FOREIGN KEY') { + return ( + constraint.columns.every( + (constraintColumnName) => !includesId(columns, constraintColumnName) + ) && + (constraint.references.table !== parsedTable.table || + constraint.references.columns.every( + (referenceColumnName) => !includesId(columns, referenceColumnName) + )) + ); + } else { + return true; + } + }); + + const newColumns = parsedTable.columns.map((column) => column.name); + + const newTable = compileCreateTable(parsedTable, this.wrap); + + const newIndices = []; + for (const createIndex of createIndices) { + const parsedIndex = parseCreateIndex(createIndex); + + parsedIndex.columns = parsedIndex.columns.filter( + (parsedColumn) => + parsedColumn.expression || !includesId(columns, parsedColumn.name) + ); + + if (parsedIndex.columns.length > 0) { + newIndices.push(compileCreateIndex(parsedIndex, this.wrap)); + } + } + + return this.alter(newTable, newIndices, newColumns); + } + + async dropForeign(columns, foreignKeyName) { + const { createTable, createIndices } = await this.getTableSql(); + + const parsedTable = parseCreateTable(createTable); + parsedTable.table = this.alteredName; + + if (!foreignKeyName) { + parsedTable.columns = parsedTable.columns.map((column) => ({ + ...column, + references: includesId(columns, column.name) ? null : column.references, + })); + } + + parsedTable.constraints = parsedTable.constraints.filter((constraint) => { + if (constraint.type === 'FOREIGN KEY') { + if (foreignKeyName) { + return ( + !constraint.name || !isEqualId(constraint.name, foreignKeyName) + ); + } + + return constraint.columns.every( + (constraintColumnName) => !includesId(columns, constraintColumnName) + ); + } else { + return true; + } + }); + + const newTable = compileCreateTable(parsedTable, this.wrap); + + return this.alter(newTable, createIndices); + } + + async dropPrimary(constraintName) { + const { createTable, createIndices } = await this.getTableSql(); + + const parsedTable = parseCreateTable(createTable); + parsedTable.table = this.alteredName; + + parsedTable.columns = parsedTable.columns.map((column) => ({ + ...column, + primary: null, + })); + + parsedTable.constraints = parsedTable.constraints.filter((constraint) => { + if (constraint.type === 'PRIMARY KEY') { + if (constraintName) { + return ( + !constraint.name || !isEqualId(constraint.name, constraintName) + ); + } else { + return false; + } + } else { + return true; + } + }); + + const newTable = compileCreateTable(parsedTable, this.wrap); + + return this.alter(newTable, createIndices); + } + + async primary(columns, constraintName) { + const { createTable, createIndices } = await this.getTableSql(); + + const parsedTable = parseCreateTable(createTable); + parsedTable.table = this.alteredName; + + parsedTable.columns = parsedTable.columns.map((column) => ({ + ...column, + primary: null, + })); + + parsedTable.constraints = parsedTable.constraints.filter( + (constraint) => constraint.type !== 'PRIMARY KEY' + ); + + parsedTable.constraints.push({ + type: 'PRIMARY KEY', + name: constraintName || null, + columns: columns.map((column) => ({ + name: column, + expression: false, + collation: null, + order: null, + })), + conflict: null, + }); + + const newTable = compileCreateTable(parsedTable, this.wrap); + + return this.alter(newTable, createIndices); + } + + async foreign(foreignInfo) { + const { createTable, createIndices } = await this.getTableSql(); + + const parsedTable = parseCreateTable(createTable); + parsedTable.table = this.alteredName; + + parsedTable.constraints.push({ + type: 'FOREIGN KEY', + name: foreignInfo.keyName || null, + columns: foreignInfo.column, + references: { + table: foreignInfo.inTable, + columns: foreignInfo.references, + delete: foreignInfo.onDelete || null, + update: foreignInfo.onUpdate || null, + match: null, + deferrable: null, + }, + }); + + const newTable = compileCreateTable(parsedTable, this.wrap); + + return this.generateAlterCommands(newTable, createIndices); + } + + async setNullable(column, isNullable) { + const { createTable, createIndices } = await this.getTableSql(); + + const parsedTable = parseCreateTable(createTable); + parsedTable.table = this.alteredName; + + const parsedColumn = parsedTable.columns.find((c) => + isEqualId(column, c.name) + ); + + if (!parsedColumn) { + throw new Error( + `.setNullable: Column ${column} does not exist in table ${this.tableName()}.` + ); + } + + parsedColumn.constraints.notnull = isNullable + ? null + : { name: null, conflict: null }; + + parsedColumn.constraints.null = isNullable + ? parsedColumn.constraints.null + : null; + + const newTable = compileCreateTable(parsedTable, this.wrap); + + return this.generateAlterCommands(newTable, createIndices); + } + + async alter(newSql, createIndices, columns) { + const wasForeignCheckEnabled = await this.isForeignCheckEnabled(); + + if (wasForeignCheckEnabled) { + await this.setForeignCheck(false); + } + + try { + await this.client.transaction( + async (trx) => { + await trx.raw(newSql); + await this.copyData(trx, columns); + await this.dropOriginal(trx); + await this.renameTable(trx); + + for (const createIndex of createIndices) { + await trx.raw(createIndex); + } + + if (wasForeignCheckEnabled) { + const foreignViolations = await trx.raw(executeForeignCheck()); + + if (foreignViolations.length > 0) { + throw new Error('FOREIGN KEY constraint failed'); + } + } + }, + { connection: this.connection } + ); + } finally { + if (wasForeignCheckEnabled) { + await this.setForeignCheck(true); + } + } + } + + async generateAlterCommands(newSql, createIndices, columns) { + const sql = []; + const pre = []; + const post = []; + let check = null; + + sql.push(newSql); + sql.push(copyData(this.tableName(), this.alteredName, columns)); + sql.push(dropOriginal(this.tableName())); + sql.push(renameTable(this.alteredName, this.tableName())); + + for (const createIndex of createIndices) { + sql.push(createIndex); + } + + const isForeignCheckEnabled = await this.isForeignCheckEnabled(); + + if (isForeignCheckEnabled) { + pre.push(setForeignCheck(false)); + post.push(setForeignCheck(true)); + + check = executeForeignCheck(); + } + + return { pre, sql, check, post }; + } +} + +module.exports = SQLite3_DDL; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/compiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/compiler.js new file mode 100644 index 000000000..cb8c694be --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/compiler.js @@ -0,0 +1,327 @@ +function compileCreateTable(ast, wrap = (v) => v) { + return createTable(ast, wrap); +} + +function compileCreateIndex(ast, wrap = (v) => v) { + return createIndex(ast, wrap); +} + +function createTable(ast, wrap) { + return `CREATE${temporary(ast, wrap)} TABLE${exists(ast, wrap)} ${schema( + ast, + wrap + )}${table(ast, wrap)} (${columnDefinitionList( + ast, + wrap + )}${tableConstraintList(ast, wrap)})${rowid(ast, wrap)}`; +} + +function temporary(ast, wrap) { + return ast.temporary ? ' TEMP' : ''; +} + +function rowid(ast, wrap) { + return ast.rowid ? ' WITHOUT ROWID' : ''; +} + +function columnDefinitionList(ast, wrap) { + return ast.columns.map((column) => columnDefinition(column, wrap)).join(', '); +} + +function columnDefinition(ast, wrap) { + return `${identifier(ast.name, wrap)}${typeName( + ast, + wrap + )}${columnConstraintList(ast.constraints, wrap)}`; +} + +function typeName(ast, wrap) { + return ast.type !== null ? ` ${ast.type}` : ''; +} + +function columnConstraintList(ast, wrap) { + return `${primaryColumnConstraint(ast, wrap)}${notnullColumnConstraint( + ast, + wrap + )}${nullColumnConstraint(ast, wrap)}${uniqueColumnConstraint( + ast, + wrap + )}${checkColumnConstraint(ast, wrap)}${defaultColumnConstraint( + ast, + wrap + )}${collateColumnConstraint(ast, wrap)}${referencesColumnConstraint( + ast, + wrap + )}${asColumnConstraint(ast, wrap)}`; +} + +function primaryColumnConstraint(ast, wrap) { + return ast.primary !== null + ? ` ${constraintName(ast.primary, wrap)}PRIMARY KEY${order( + ast.primary, + wrap + )}${conflictClause(ast.primary, wrap)}${autoincrement(ast.primary, wrap)}` + : ''; +} + +function autoincrement(ast, wrap) { + return ast.autoincrement ? ' AUTOINCREMENT' : ''; +} + +function notnullColumnConstraint(ast, wrap) { + return ast.notnull !== null + ? ` ${constraintName(ast.notnull, wrap)}NOT NULL${conflictClause( + ast.notnull, + wrap + )}` + : ''; +} + +function nullColumnConstraint(ast, wrap) { + return ast.null !== null + ? ` ${constraintName(ast.null, wrap)}NULL${conflictClause(ast.null, wrap)}` + : ''; +} + +function uniqueColumnConstraint(ast, wrap) { + return ast.unique !== null + ? ` ${constraintName(ast.unique, wrap)}UNIQUE${conflictClause( + ast.unique, + wrap + )}` + : ''; +} + +function checkColumnConstraint(ast, wrap) { + return ast.check !== null + ? ` ${constraintName(ast.check, wrap)}CHECK (${expression( + ast.check.expression, + wrap + )})` + : ''; +} + +function defaultColumnConstraint(ast, wrap) { + return ast.default !== null + ? ` ${constraintName(ast.default, wrap)}DEFAULT ${ + !ast.default.expression + ? ast.default.value + : `(${expression(ast.default.value, wrap)})` + }` + : ''; +} + +function collateColumnConstraint(ast, wrap) { + return ast.collate !== null + ? ` ${constraintName(ast.collate, wrap)}COLLATE ${ast.collate.collation}` + : ''; +} + +function referencesColumnConstraint(ast, wrap) { + return ast.references !== null + ? ` ${constraintName(ast.references, wrap)}${foreignKeyClause( + ast.references, + wrap + )}` + : ''; +} + +function asColumnConstraint(ast, wrap) { + return ast.as !== null + ? ` ${constraintName(ast.as, wrap)}${ + ast.as.generated ? 'GENERATED ALWAYS ' : '' + }AS (${expression(ast.as.expression, wrap)})${ + ast.as.mode !== null ? ` ${ast.as.mode}` : '' + }` + : ''; +} + +function tableConstraintList(ast, wrap) { + return ast.constraints.reduce( + (constraintList, constraint) => + `${constraintList}, ${tableConstraint(constraint, wrap)}`, + '' + ); +} + +function tableConstraint(ast, wrap) { + switch (ast.type) { + case 'PRIMARY KEY': + return primaryTableConstraint(ast, wrap); + case 'UNIQUE': + return uniqueTableConstraint(ast, wrap); + case 'CHECK': + return checkTableConstraint(ast, wrap); + case 'FOREIGN KEY': + return foreignTableConstraint(ast, wrap); + } +} + +function primaryTableConstraint(ast, wrap) { + return `${constraintName(ast, wrap)}PRIMARY KEY (${indexedColumnList( + ast, + wrap + )})${conflictClause(ast, wrap)}`; +} + +function uniqueTableConstraint(ast, wrap) { + return `${constraintName(ast, wrap)}UNIQUE (${indexedColumnList( + ast, + wrap + )})${conflictClause(ast, wrap)}`; +} + +function conflictClause(ast, wrap) { + return ast.conflict !== null ? ` ON CONFLICT ${ast.conflict}` : ''; +} + +function checkTableConstraint(ast, wrap) { + return `${constraintName(ast, wrap)}CHECK (${expression( + ast.expression, + wrap + )})`; +} + +function foreignTableConstraint(ast, wrap) { + return `${constraintName(ast, wrap)}FOREIGN KEY (${columnNameList( + ast, + wrap + )}) ${foreignKeyClause(ast.references, wrap)}`; +} + +function foreignKeyClause(ast, wrap) { + return `REFERENCES ${table(ast, wrap)}${columnNameListOptional( + ast, + wrap + )}${deleteUpdateMatchList(ast, wrap)}${deferrable(ast.deferrable, wrap)}`; +} + +function columnNameListOptional(ast, wrap) { + return ast.columns.length > 0 ? ` (${columnNameList(ast, wrap)})` : ''; +} + +function columnNameList(ast, wrap) { + return ast.columns.map((column) => identifier(column, wrap)).join(', '); +} + +function deleteUpdateMatchList(ast, wrap) { + return `${deleteReference(ast, wrap)}${updateReference( + ast, + wrap + )}${matchReference(ast, wrap)}`; +} + +function deleteReference(ast, wrap) { + return ast.delete !== null ? ` ON DELETE ${ast.delete}` : ''; +} + +function updateReference(ast, wrap) { + return ast.update !== null ? ` ON UPDATE ${ast.update}` : ''; +} + +function matchReference(ast, wrap) { + return ast.match !== null ? ` MATCH ${ast.match}` : ''; +} + +function deferrable(ast, wrap) { + return ast !== null + ? ` ${ast.not ? 'NOT ' : ''}DEFERRABLE${ + ast.initially !== null ? ` INITIALLY ${ast.initially}` : '' + }` + : ''; +} + +function constraintName(ast, wrap) { + return ast.name !== null ? `CONSTRAINT ${identifier(ast.name, wrap)} ` : ''; +} + +function createIndex(ast, wrap) { + return `CREATE${unique(ast, wrap)} INDEX${exists(ast, wrap)} ${schema( + ast, + wrap + )}${index(ast, wrap)} on ${table(ast, wrap)} (${indexedColumnList( + ast, + wrap + )})${where(ast, wrap)}`; +} + +function unique(ast, wrap) { + return ast.unique ? ' UNIQUE' : ''; +} + +function exists(ast, wrap) { + return ast.exists ? ' IF NOT EXISTS' : ''; +} + +function schema(ast, wrap) { + return ast.schema !== null ? `${identifier(ast.schema, wrap)}.` : ''; +} + +function index(ast, wrap) { + return identifier(ast.index, wrap); +} + +function table(ast, wrap) { + return identifier(ast.table, wrap); +} + +function where(ast, wrap) { + return ast.where !== null ? ` where ${expression(ast.where)}` : ''; +} + +function indexedColumnList(ast, wrap) { + return ast.columns + .map((column) => + !column.expression + ? indexedColumn(column, wrap) + : indexedColumnExpression(column, wrap) + ) + .join(', '); +} + +function indexedColumn(ast, wrap) { + return `${identifier(ast.name, wrap)}${collation(ast, wrap)}${order( + ast, + wrap + )}`; +} + +function indexedColumnExpression(ast, wrap) { + return `${indexedExpression(ast.name, wrap)}${collation(ast, wrap)}${order( + ast, + wrap + )}`; +} + +function collation(ast, wrap) { + return ast.collation !== null ? ` COLLATE ${ast.collation}` : ''; +} + +function order(ast, wrap) { + return ast.order !== null ? ` ${ast.order}` : ''; +} + +function indexedExpression(ast, wrap) { + return expression(ast, wrap); +} + +function expression(ast, wrap) { + return ast.reduce( + (expr, e) => + Array.isArray(e) + ? `${expr}(${expression(e)})` + : !expr + ? e + : `${expr} ${e}`, + '' + ); +} + +function identifier(ast, wrap) { + return wrap(ast); +} + +module.exports = { + compileCreateTable, + compileCreateIndex, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/parser-combinator.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/parser-combinator.js new file mode 100644 index 000000000..024dafcd2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/parser-combinator.js @@ -0,0 +1,161 @@ +// Sequence parser combinator +function s(sequence, post = (v) => v) { + return function ({ index = 0, input }) { + let position = index; + const ast = []; + + for (const parser of sequence) { + const result = parser({ index: position, input }); + + if (result.success) { + position = result.index; + ast.push(result.ast); + } else { + return result; + } + } + + return { success: true, ast: post(ast), index: position, input }; + }; +} + +// Alternative parser combinator +function a(alternative, post = (v) => v) { + return function ({ index = 0, input }) { + for (const parser of alternative) { + const result = parser({ index, input }); + + if (result.success) { + return { + success: true, + ast: post(result.ast), + index: result.index, + input, + }; + } + } + + return { success: false, ast: null, index, input }; + }; +} + +// Many parser combinator +function m(many, post = (v) => v) { + return function ({ index = 0, input }) { + let result = {}; + let position = index; + const ast = []; + + do { + result = many({ index: position, input }); + + if (result.success) { + position = result.index; + ast.push(result.ast); + } + } while (result.success); + + if (ast.length > 0) { + return { success: true, ast: post(ast), index: position, input }; + } else { + return { success: false, ast: null, index: position, input }; + } + }; +} + +// Optional parser combinator +function o(optional, post = (v) => v) { + return function ({ index = 0, input }) { + const result = optional({ index, input }); + + if (result.success) { + return { + success: true, + ast: post(result.ast), + index: result.index, + input, + }; + } else { + return { success: true, ast: post(null), index, input }; + } + }; +} + +// Lookahead parser combinator +function l(lookahead, post = (v) => v) { + return function ({ index = 0, input }) { + const result = lookahead.do({ index, input }); + + if (result.success) { + const resultNext = lookahead.next({ index: result.index, input }); + + if (resultNext.success) { + return { + success: true, + ast: post(result.ast), + index: result.index, + input, + }; + } + } + + return { success: false, ast: null, index, input }; + }; +} + +// Negative parser combinator +function n(negative, post = (v) => v) { + return function ({ index = 0, input }) { + const result = negative.do({ index, input }); + + if (result.success) { + const resultNot = negative.not({ index, input }); + + if (!resultNot.success) { + return { + success: true, + ast: post(result.ast), + index: result.index, + input, + }; + } + } + + return { success: false, ast: null, index, input }; + }; +} + +// Token parser combinator +function t(token, post = (v) => v.text) { + return function ({ index = 0, input }) { + const result = input[index]; + + if ( + result !== undefined && + (token.type === undefined || token.type === result.type) && + (token.text === undefined || + token.text.toUpperCase() === result.text.toUpperCase()) + ) { + return { + success: true, + ast: post(result), + index: index + 1, + input, + }; + } else { + return { success: false, ast: null, index, input }; + } + }; +} + +// Empty parser constant +const e = function ({ index = 0, input }) { + return { success: true, ast: null, index, input }; +}; + +// Finish parser constant +const f = function ({ index = 0, input }) { + return { success: index === input.length, ast: null, index, input }; +}; + +module.exports = { s, a, m, o, l, n, t, e, f }; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/parser.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/parser.js new file mode 100644 index 000000000..535faf7b3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/parser.js @@ -0,0 +1,638 @@ +const { tokenize } = require('./tokenizer'); +const { s, a, m, o, l, n, t, e, f } = require('./parser-combinator'); + +const TOKENS = { + keyword: + /(?:ABORT|ACTION|ADD|AFTER|ALL|ALTER|ALWAYS|ANALYZE|AND|AS|ASC|ATTACH|AUTOINCREMENT|BEFORE|BEGIN|BETWEEN|BY|CASCADE|CASE|CAST|CHECK|COLLATE|COLUMN|COMMIT|CONFLICT|CONSTRAINT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|DATABASE|DEFAULT|DEFERRED|DEFERRABLE|DELETE|DESC|DETACH|DISTINCT|DO|DROP|END|EACH|ELSE|ESCAPE|EXCEPT|EXCLUSIVE|EXCLUDE|EXISTS|EXPLAIN|FAIL|FILTER|FIRST|FOLLOWING|FOR|FOREIGN|FROM|FULL|GENERATED|GLOB|GROUP|GROUPS|HAVING|IF|IGNORE|IMMEDIATE|IN|INDEX|INDEXED|INITIALLY|INNER|INSERT|INSTEAD|INTERSECT|INTO|IS|ISNULL|JOIN|KEY|LAST|LEFT|LIKE|LIMIT|MATCH|MATERIALIZED|NATURAL|NO|NOT|NOTHING|NOTNULL|NULL|NULLS|OF|OFFSET|ON|OR|ORDER|OTHERS|OUTER|OVER|PARTITION|PLAN|PRAGMA|PRECEDING|PRIMARY|QUERY|RAISE|RANGE|RECURSIVE|REFERENCES|REGEXP|REINDEX|RELEASE|RENAME|REPLACE|RESTRICT|RETURNING|RIGHT|ROLLBACK|ROW|ROWS|SAVEPOINT|SELECT|SET|TABLE|TEMP|TEMPORARY|THEN|TIES|TO|TRANSACTION|TRIGGER|UNBOUNDED|UNION|UNIQUE|UPDATE|USING|VACUUM|VALUES|VIEW|VIRTUAL|WHEN|WHERE|WINDOW|WITH|WITHOUT)(?=\s+|-|\(|\)|;|\+|\*|\/|%|==|=|<=|<>|<<|<|>=|>>|>|!=|,|&|~|\|\||\||\.)/, + id: /"[^"]*(?:""[^"]*)*"|`[^`]*(?:``[^`]*)*`|\[[^[\]]*\]|[a-z_][a-z0-9_$]*/, + string: /'[^']*(?:''[^']*)*'/, + blob: /x'(?:[0-9a-f][0-9a-f])+'/, + numeric: /(?:\d+(?:\.\d*)?|\.\d+)(?:e(?:\+|-)?\d+)?|0x[0-9a-f]+/, + variable: /\?\d*|[@$:][a-z0-9_$]+/, + operator: /-|\(|\)|;|\+|\*|\/|%|==|=|<=|<>|<<|<|>=|>>|>|!=|,|&|~|\|\||\||\./, + _ws: /\s+/, +}; + +function parseCreateTable(sql) { + const result = createTable({ input: tokenize(sql, TOKENS) }); + + if (!result.success) { + throw new Error( + `Parsing CREATE TABLE failed at [${result.input + .slice(result.index) + .map((t) => t.text) + .join(' ')}] of "${sql}"` + ); + } + + return result.ast; +} + +function parseCreateIndex(sql) { + const result = createIndex({ input: tokenize(sql, TOKENS) }); + + if (!result.success) { + throw new Error( + `Parsing CREATE INDEX failed at [${result.input + .slice(result.index) + .map((t) => t.text) + .join(' ')}] of "${sql}"` + ); + } + + return result.ast; +} + +function createTable(ctx) { + return s( + [ + t({ text: 'CREATE' }, (v) => null), + temporary, + t({ text: 'TABLE' }, (v) => null), + exists, + schema, + table, + t({ text: '(' }, (v) => null), + columnDefinitionList, + tableConstraintList, + t({ text: ')' }, (v) => null), + rowid, + f, + ], + (v) => Object.assign({}, ...v.filter((x) => x !== null)) + )(ctx); +} + +function temporary(ctx) { + return a([t({ text: 'TEMP' }), t({ text: 'TEMPORARY' }), e], (v) => ({ + temporary: v !== null, + }))(ctx); +} + +function rowid(ctx) { + return o(s([t({ text: 'WITHOUT' }), t({ text: 'ROWID' })]), (v) => ({ + rowid: v !== null, + }))(ctx); +} + +function columnDefinitionList(ctx) { + return a([ + s([columnDefinition, t({ text: ',' }), columnDefinitionList], (v) => ({ + columns: [v[0]].concat(v[2].columns), + })), + s([columnDefinition], (v) => ({ columns: [v[0]] })), + ])(ctx); +} + +function columnDefinition(ctx) { + return s( + [s([identifier], (v) => ({ name: v[0] })), typeName, columnConstraintList], + (v) => Object.assign({}, ...v) + )(ctx); +} + +function typeName(ctx) { + return o( + s( + [ + m(t({ type: 'id' })), + a([ + s( + [ + t({ text: '(' }), + signedNumber, + t({ text: ',' }), + signedNumber, + t({ text: ')' }), + ], + (v) => `(${v[1]}, ${v[3]})` + ), + s( + [t({ text: '(' }), signedNumber, t({ text: ')' })], + (v) => `(${v[1]})` + ), + e, + ]), + ], + (v) => `${v[0].join(' ')}${v[1] || ''}` + ), + (v) => ({ type: v }) + )(ctx); +} + +function columnConstraintList(ctx) { + return o(m(columnConstraint), (v) => ({ + constraints: Object.assign( + { + primary: null, + notnull: null, + null: null, + unique: null, + check: null, + default: null, + collate: null, + references: null, + as: null, + }, + ...(v || []) + ), + }))(ctx); +} + +function columnConstraint(ctx) { + return a([ + primaryColumnConstraint, + notnullColumnConstraint, + nullColumnConstraint, + uniqueColumnConstraint, + checkColumnConstraint, + defaultColumnConstraint, + collateColumnConstraint, + referencesColumnConstraint, + asColumnConstraint, + ])(ctx); +} + +function primaryColumnConstraint(ctx) { + return s( + [ + constraintName, + t({ text: 'PRIMARY' }, (v) => null), + t({ text: 'KEY' }, (v) => null), + order, + conflictClause, + autoincrement, + ], + (v) => ({ primary: Object.assign({}, ...v.filter((x) => x !== null)) }) + )(ctx); +} + +function autoincrement(ctx) { + return o(t({ text: 'AUTOINCREMENT' }), (v) => ({ + autoincrement: v !== null, + }))(ctx); +} + +function notnullColumnConstraint(ctx) { + return s( + [ + constraintName, + t({ text: 'NOT' }, (v) => null), + t({ text: 'NULL' }, (v) => null), + conflictClause, + ], + (v) => ({ notnull: Object.assign({}, ...v.filter((x) => x !== null)) }) + )(ctx); +} + +function nullColumnConstraint(ctx) { + return s( + [constraintName, t({ text: 'NULL' }, (v) => null), conflictClause], + (v) => ({ null: Object.assign({}, ...v.filter((x) => x !== null)) }) + )(ctx); +} + +function uniqueColumnConstraint(ctx) { + return s( + [constraintName, t({ text: 'UNIQUE' }, (v) => null), conflictClause], + (v) => ({ unique: Object.assign({}, ...v.filter((x) => x !== null)) }) + )(ctx); +} + +function checkColumnConstraint(ctx) { + return s( + [ + constraintName, + t({ text: 'CHECK' }, (v) => null), + t({ text: '(' }, (v) => null), + s([expression], (v) => ({ expression: v[0] })), + t({ text: ')' }, (v) => null), + ], + (v) => ({ check: Object.assign({}, ...v.filter((x) => x !== null)) }) + )(ctx); +} + +function defaultColumnConstraint(ctx) { + return s( + [ + constraintName, + t({ text: 'DEFAULT' }, (v) => null), + a([ + s([t({ text: '(' }), expression, t({ text: ')' })], (v) => ({ + value: v[1], + expression: true, + })), + s([literalValue], (v) => ({ value: v[0], expression: false })), + s([signedNumber], (v) => ({ value: v[0], expression: false })), + ]), + ], + (v) => ({ default: Object.assign({}, ...v.filter((x) => x !== null)) }) + )(ctx); +} + +function collateColumnConstraint(ctx) { + return s( + [ + constraintName, + t({ text: 'COLLATE' }, (v) => null), + t({ type: 'id' }, (v) => ({ collation: v.text })), + ], + (v) => ({ collate: Object.assign({}, ...v.filter((x) => x !== null)) }) + )(ctx); +} + +function referencesColumnConstraint(ctx) { + return s( + [constraintName, s([foreignKeyClause], (v) => v[0].references)], + (v) => ({ + references: Object.assign({}, ...v.filter((x) => x !== null)), + }) + )(ctx); +} + +function asColumnConstraint(ctx) { + return s( + [ + constraintName, + o(s([t({ text: 'GENERATED' }), t({ text: 'ALWAYS' })]), (v) => ({ + generated: v !== null, + })), + t({ text: 'AS' }, (v) => null), + t({ text: '(' }, (v) => null), + s([expression], (v) => ({ expression: v[0] })), + t({ text: ')' }, (v) => null), + a([t({ text: 'STORED' }), t({ text: 'VIRTUAL' }), e], (v) => ({ + mode: v ? v.toUpperCase() : null, + })), + ], + (v) => ({ as: Object.assign({}, ...v.filter((x) => x !== null)) }) + )(ctx); +} + +function tableConstraintList(ctx) { + return o(m(s([t({ text: ',' }), tableConstraint], (v) => v[1])), (v) => ({ + constraints: v || [], + }))(ctx); +} + +function tableConstraint(ctx) { + return a([ + primaryTableConstraint, + uniqueTableConstraint, + checkTableConstraint, + foreignTableConstraint, + ])(ctx); +} + +function primaryTableConstraint(ctx) { + return s( + [ + constraintName, + t({ text: 'PRIMARY' }, (v) => null), + t({ text: 'KEY' }, (v) => null), + t({ text: '(' }, (v) => null), + indexedColumnList, + t({ text: ')' }, (v) => null), + conflictClause, + ], + (v) => + Object.assign({ type: 'PRIMARY KEY' }, ...v.filter((x) => x !== null)) + )(ctx); +} + +function uniqueTableConstraint(ctx) { + return s( + [ + constraintName, + t({ text: 'UNIQUE' }, (v) => null), + t({ text: '(' }, (v) => null), + indexedColumnList, + t({ text: ')' }, (v) => null), + conflictClause, + ], + (v) => Object.assign({ type: 'UNIQUE' }, ...v.filter((x) => x !== null)) + )(ctx); +} + +function conflictClause(ctx) { + return o( + s( + [ + t({ text: 'ON' }), + t({ text: 'CONFLICT' }), + a([ + t({ text: 'ROLLBACK' }), + t({ text: 'ABORT' }), + t({ text: 'FAIL' }), + t({ text: 'IGNORE' }), + t({ text: 'REPLACE' }), + ]), + ], + (v) => v[2] + ), + (v) => ({ conflict: v ? v.toUpperCase() : null }) + )(ctx); +} + +function checkTableConstraint(ctx) { + return s( + [ + constraintName, + t({ text: 'CHECK' }, (v) => null), + t({ text: '(' }, (v) => null), + s([expression], (v) => ({ expression: v[0] })), + t({ text: ')' }, (v) => null), + ], + (v) => Object.assign({ type: 'CHECK' }, ...v.filter((x) => x !== null)) + )(ctx); +} + +function foreignTableConstraint(ctx) { + return s( + [ + constraintName, + t({ text: 'FOREIGN' }, (v) => null), + t({ text: 'KEY' }, (v) => null), + t({ text: '(' }, (v) => null), + columnNameList, + t({ text: ')' }, (v) => null), + foreignKeyClause, + ], + (v) => + Object.assign({ type: 'FOREIGN KEY' }, ...v.filter((x) => x !== null)) + )(ctx); +} + +function foreignKeyClause(ctx) { + return s( + [ + t({ text: 'REFERENCES' }, (v) => null), + table, + columnNameListOptional, + o(m(a([deleteReference, updateReference, matchReference])), (v) => + Object.assign({ delete: null, update: null, match: null }, ...(v || [])) + ), + deferrable, + ], + (v) => ({ references: Object.assign({}, ...v.filter((x) => x !== null)) }) + )(ctx); +} + +function columnNameListOptional(ctx) { + return o( + s([t({ text: '(' }), columnNameList, t({ text: ')' })], (v) => v[1]), + (v) => ({ columns: v ? v.columns : [] }) + )(ctx); +} + +function columnNameList(ctx) { + return s( + [ + o(m(s([identifier, t({ text: ',' })], (v) => v[0])), (v) => + v !== null ? v : [] + ), + identifier, + ], + (v) => ({ columns: v[0].concat([v[1]]) }) + )(ctx); +} + +function deleteReference(ctx) { + return s([t({ text: 'ON' }), t({ text: 'DELETE' }), onAction], (v) => ({ + delete: v[2], + }))(ctx); +} + +function updateReference(ctx) { + return s([t({ text: 'ON' }), t({ text: 'UPDATE' }), onAction], (v) => ({ + update: v[2], + }))(ctx); +} + +function matchReference(ctx) { + return s( + [t({ text: 'MATCH' }), a([t({ type: 'keyword' }), t({ type: 'id' })])], + (v) => ({ match: v[1] }) + )(ctx); +} + +function deferrable(ctx) { + return o( + s([ + o(t({ text: 'NOT' })), + t({ text: 'DEFERRABLE' }), + o( + s( + [ + t({ text: 'INITIALLY' }), + a([t({ text: 'DEFERRED' }), t({ text: 'IMMEDIATE' })]), + ], + (v) => v[1].toUpperCase() + ) + ), + ]), + (v) => ({ deferrable: v ? { not: v[0] !== null, initially: v[2] } : null }) + )(ctx); +} + +function constraintName(ctx) { + return o( + s([t({ text: 'CONSTRAINT' }), identifier], (v) => v[1]), + (v) => ({ name: v }) + )(ctx); +} + +function createIndex(ctx) { + return s( + [ + t({ text: 'CREATE' }, (v) => null), + unique, + t({ text: 'INDEX' }, (v) => null), + exists, + schema, + index, + t({ text: 'ON' }, (v) => null), + table, + t({ text: '(' }, (v) => null), + indexedColumnList, + t({ text: ')' }, (v) => null), + where, + f, + ], + (v) => Object.assign({}, ...v.filter((x) => x !== null)) + )(ctx); +} + +function unique(ctx) { + return o(t({ text: 'UNIQUE' }), (v) => ({ unique: v !== null }))(ctx); +} + +function exists(ctx) { + return o( + s([t({ text: 'IF' }), t({ text: 'NOT' }), t({ text: 'EXISTS' })]), + (v) => ({ exists: v !== null }) + )(ctx); +} + +function schema(ctx) { + return o( + s([identifier, t({ text: '.' })], (v) => v[0]), + (v) => ({ schema: v }) + )(ctx); +} + +function index(ctx) { + return s([identifier], (v) => ({ index: v[0] }))(ctx); +} + +function table(ctx) { + return s([identifier], (v) => ({ table: v[0] }))(ctx); +} + +function where(ctx) { + return o( + s([t({ text: 'WHERE' }), expression], (v) => v[1]), + (v) => ({ where: v }) + )(ctx); +} + +function indexedColumnList(ctx) { + return a([ + s([indexedColumn, t({ text: ',' }), indexedColumnList], (v) => ({ + columns: [v[0]].concat(v[2].columns), + })), + s([indexedColumnExpression, t({ text: ',' }), indexedColumnList], (v) => ({ + columns: [v[0]].concat(v[2].columns), + })), + l({ do: indexedColumn, next: t({ text: ')' }) }, (v) => ({ + columns: [v], + })), + l({ do: indexedColumnExpression, next: t({ text: ')' }) }, (v) => ({ + columns: [v], + })), + ])(ctx); +} + +function indexedColumn(ctx) { + return s( + [ + s([identifier], (v) => ({ name: v[0], expression: false })), + collation, + order, + ], + (v) => Object.assign({}, ...v.filter((x) => x !== null)) + )(ctx); +} + +function indexedColumnExpression(ctx) { + return s( + [ + s([indexedExpression], (v) => ({ name: v[0], expression: true })), + collation, + order, + ], + (v) => Object.assign({}, ...v.filter((x) => x !== null)) + )(ctx); +} + +function collation(ctx) { + return o( + s([t({ text: 'COLLATE' }), t({ type: 'id' })], (v) => v[1]), + (v) => ({ collation: v }) + )(ctx); +} + +function order(ctx) { + return a([t({ text: 'ASC' }), t({ text: 'DESC' }), e], (v) => ({ + order: v ? v.toUpperCase() : null, + }))(ctx); +} + +function indexedExpression(ctx) { + return m( + a([ + n({ + do: t({ type: 'keyword' }), + not: a([ + t({ text: 'COLLATE' }), + t({ text: 'ASC' }), + t({ text: 'DESC' }), + ]), + }), + t({ type: 'id' }), + t({ type: 'string' }), + t({ type: 'blob' }), + t({ type: 'numeric' }), + t({ type: 'variable' }), + n({ + do: t({ type: 'operator' }), + not: a([t({ text: '(' }), t({ text: ')' }), t({ text: ',' })]), + }), + s([t({ text: '(' }), o(expression), t({ text: ')' })], (v) => v[1] || []), + ]) + )(ctx); +} + +function expression(ctx) { + return m( + a([ + t({ type: 'keyword' }), + t({ type: 'id' }), + t({ type: 'string' }), + t({ type: 'blob' }), + t({ type: 'numeric' }), + t({ type: 'variable' }), + n({ + do: t({ type: 'operator' }), + not: a([t({ text: '(' }), t({ text: ')' })]), + }), + s([t({ text: '(' }), o(expression), t({ text: ')' })], (v) => v[1] || []), + ]) + )(ctx); +} + +function identifier(ctx) { + return a([t({ type: 'id' }), t({ type: 'string' })], (v) => + /^["`['][^]*["`\]']$/.test(v) ? v.substring(1, v.length - 1) : v + )(ctx); +} + +function onAction(ctx) { + return a( + [ + s([t({ text: 'SET' }), t({ text: 'NULL' })], (v) => `${v[0]} ${v[1]}`), + s([t({ text: 'SET' }), t({ text: 'DEFAULT' })], (v) => `${v[0]} ${v[1]}`), + t({ text: 'CASCADE' }), + t({ text: 'RESTRICT' }), + s([t({ text: 'NO' }), t({ text: 'ACTION' })], (v) => `${v[0]} ${v[1]}`), + ], + (v) => v.toUpperCase() + )(ctx); +} + +function literalValue(ctx) { + return a([ + t({ type: 'numeric' }), + t({ type: 'string' }), + t({ type: 'id' }), + t({ type: 'blob' }), + t({ text: 'NULL' }), + t({ text: 'TRUE' }), + t({ text: 'FALSE' }), + t({ text: 'CURRENT_TIME' }), + t({ text: 'CURRENT_DATE' }), + t({ text: 'CURRENT_TIMESTAMP' }), + ])(ctx); +} + +function signedNumber(ctx) { + return s( + [a([t({ text: '+' }), t({ text: '-' }), e]), t({ type: 'numeric' })], + (v) => `${v[0] || ''}${v[1]}` + )(ctx); +} + +module.exports = { + parseCreateTable, + parseCreateIndex, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js new file mode 100644 index 000000000..73371cf02 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/sqlite-ddl-operations.js @@ -0,0 +1,41 @@ +function copyData(sourceTable, targetTable, columns) { + return `INSERT INTO "${targetTable}" SELECT ${ + columns === undefined + ? '*' + : columns.map((column) => `"${column}"`).join(', ') + } FROM "${sourceTable}";`; +} + +function dropOriginal(tableName) { + return `DROP TABLE "${tableName}"`; +} + +function renameTable(tableName, alteredName) { + return `ALTER TABLE "${tableName}" RENAME TO "${alteredName}"`; +} + +function getTableSql(tableName) { + return `SELECT type, sql FROM sqlite_master WHERE (type='table' OR (type='index' AND sql IS NOT NULL)) AND lower(tbl_name)='${tableName.toLowerCase()}'`; +} + +function isForeignCheckEnabled() { + return `PRAGMA foreign_keys`; +} + +function setForeignCheck(enable) { + return `PRAGMA foreign_keys = ${enable ? 'ON' : 'OFF'}`; +} + +function executeForeignCheck() { + return `PRAGMA foreign_key_check`; +} + +module.exports = { + copyData, + dropOriginal, + renameTable, + getTableSql, + isForeignCheckEnabled, + setForeignCheck, + executeForeignCheck, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/tokenizer.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/tokenizer.js new file mode 100644 index 000000000..30eb74758 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/tokenizer.js @@ -0,0 +1,38 @@ +function tokenize(text, tokens) { + const compiledRegex = new RegExp( + Object.entries(tokens) + .map(([type, regex]) => `(?<${type}>${regex.source})`) + .join('|'), + 'yi' + ); + + let index = 0; + const ast = []; + + while (index < text.length) { + compiledRegex.lastIndex = index; + const result = text.match(compiledRegex); + + if (result !== null) { + const [type, text] = Object.entries(result.groups).find( + ([name, group]) => group !== undefined + ); + + index += text.length; + + if (!type.startsWith('_')) { + ast.push({ type, text }); + } + } else { + throw new Error( + `No matching tokenizer rule found at: [${text.substring(index)}]` + ); + } + } + + return ast; +} + +module.exports = { + tokenize, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/utils.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/utils.js new file mode 100644 index 000000000..ff6774b8e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/internal/utils.js @@ -0,0 +1,12 @@ +function isEqualId(first, second) { + return first.toLowerCase() === second.toLowerCase(); +} + +function includesId(list, id) { + return list.some((item) => isEqualId(item, id)); +} + +module.exports = { + isEqualId, + includesId, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-columncompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-columncompiler.js new file mode 100644 index 000000000..0ef4394d5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-columncompiler.js @@ -0,0 +1,50 @@ +const ColumnCompiler = require('../../../schema/columncompiler'); + +// Column Compiler +// ------- + +class ColumnCompiler_SQLite3 extends ColumnCompiler { + constructor() { + super(...arguments); + this.modifiers = ['nullable', 'defaultTo']; + this._addCheckModifiers(); + } + + // Types + // ------- + + enu(allowed) { + return `text check (${this.formatter.wrap( + this.args[0] + )} in ('${allowed.join("', '")}'))`; + } + + _pushAlterCheckQuery(checkPredicate, constraintName) { + throw new Error( + `Alter table with to add constraints is not permitted in SQLite` + ); + } + + checkRegex(regexes, constraintName) { + return this._check( + `${this.formatter.wrap( + this.getColumnName() + )} REGEXP ${this.client._escapeBinding(regexes)}`, + constraintName + ); + } +} + +ColumnCompiler_SQLite3.prototype.json = 'json'; +ColumnCompiler_SQLite3.prototype.jsonb = 'json'; +ColumnCompiler_SQLite3.prototype.double = + ColumnCompiler_SQLite3.prototype.decimal = + ColumnCompiler_SQLite3.prototype.floating = + 'float'; +ColumnCompiler_SQLite3.prototype.timestamp = 'datetime'; +// autoincrement without primary key is a syntax error in SQLite, so it's necessary +ColumnCompiler_SQLite3.prototype.increments = + ColumnCompiler_SQLite3.prototype.bigincrements = + 'integer not null primary key autoincrement'; + +module.exports = ColumnCompiler_SQLite3; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-compiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-compiler.js new file mode 100644 index 000000000..282ca01f6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-compiler.js @@ -0,0 +1,80 @@ +// SQLite3: Column Builder & Compiler +// ------- +const SchemaCompiler = require('../../../schema/compiler'); + +const some = require('lodash/some'); + +// Schema Compiler +// ------- + +class SchemaCompiler_SQLite3 extends SchemaCompiler { + constructor(client, builder) { + super(client, builder); + } + + // Compile the query to determine if a table exists. + hasTable(tableName) { + const sql = + `select * from sqlite_master ` + + `where type = 'table' and name = ${this.client.parameter( + this.formatter.wrap(tableName).replace(/`/g, ''), + this.builder, + this.bindingsHolder + )}`; + this.pushQuery({ sql, output: (resp) => resp.length > 0 }); + } + + // Compile the query to determine if a column exists. + hasColumn(tableName, column) { + this.pushQuery({ + sql: `PRAGMA table_info(${this.formatter.wrap(tableName)})`, + output(resp) { + return some(resp, (col) => { + return ( + this.client.wrapIdentifier(col.name.toLowerCase()) === + this.client.wrapIdentifier(column.toLowerCase()) + ); + }); + }, + }); + } + + // Compile a rename table command. + renameTable(from, to) { + this.pushQuery( + `alter table ${this.formatter.wrap(from)} rename to ${this.formatter.wrap( + to + )}` + ); + } + + async generateDdlCommands() { + const sequence = this.builder._sequence; + for (let i = 0, l = sequence.length; i < l; i++) { + const query = sequence[i]; + this[query.method].apply(this, query.args); + } + + const commandSources = this.sequence; + + if (commandSources.length === 1 && commandSources[0].statementsProducer) { + return commandSources[0].statementsProducer(); + } else { + const result = []; + + for (const commandSource of commandSources) { + const command = commandSource.sql; + + if (Array.isArray(command)) { + result.push(...command); + } else { + result.push(command); + } + } + + return { pre: [], sql: result, check: null, post: [] }; + } + } +} + +module.exports = SchemaCompiler_SQLite3; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js new file mode 100644 index 000000000..5e1a9b2b3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-tablecompiler.js @@ -0,0 +1,347 @@ +const filter = require('lodash/filter'); +const values = require('lodash/values'); +const identity = require('lodash/identity'); +const { isObject } = require('../../../util/is'); + +const TableCompiler = require('../../../schema/tablecompiler'); +const { formatDefault } = require('../../../formatter/formatterUtils'); + +class TableCompiler_SQLite3 extends TableCompiler { + constructor() { + super(...arguments); + } + + // Create a new table. + createQuery(columns, ifNot, like) { + const createStatement = ifNot + ? 'create table if not exists ' + : 'create table '; + + let sql = createStatement + this.tableName(); + + if (like && this.tableNameLike()) { + sql += ' as select * from ' + this.tableNameLike() + ' where 0=1'; + } else { + // so we will need to check for a primary key commands and add the columns + // to the table's declaration here so they can be created on the tables. + sql += ' (' + columns.sql.join(', '); + sql += this.foreignKeys() || ''; + sql += this.primaryKeys() || ''; + sql += this._addChecks(); + sql += ')'; + } + this.pushQuery(sql); + + if (like) { + this.addColumns(columns, this.addColumnsPrefix); + } + } + + addColumns(columns, prefix, colCompilers) { + if (prefix === this.alterColumnsPrefix) { + const compiler = this; + + const columnsInfo = colCompilers.map((col) => { + const name = this.client.customWrapIdentifier( + col.getColumnName(), + identity, + col.columnBuilder.queryContext() + ); + + const type = col.getColumnType(); + + const defaultTo = col.modified['defaultTo'] + ? formatDefault(col.modified['defaultTo'][0], col.type, this.client) + : null; + + const notNull = + col.modified['nullable'] && col.modified['nullable'][0] === false; + + return { name, type, defaultTo, notNull }; + }); + + this.pushQuery({ + sql: `PRAGMA table_info(${this.tableName()})`, + statementsProducer(pragma, connection) { + return compiler.client + .ddl(compiler, pragma, connection) + .alterColumn(columnsInfo); + }, + }); + } else { + for (let i = 0, l = columns.sql.length; i < l; i++) { + this.pushQuery({ + sql: `alter table ${this.tableName()} add column ${columns.sql[i]}`, + bindings: columns.bindings[i], + }); + } + } + } + + // Compile a drop unique key command. + dropUnique(columns, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('unique', this.tableNameRaw, columns); + this.pushQuery(`drop index ${indexName}`); + } + + // Compile a drop foreign key command. + dropForeign(columns, indexName) { + const compiler = this; + + columns = Array.isArray(columns) ? columns : [columns]; + columns = columns.map((column) => + this.client.customWrapIdentifier(column, identity) + ); + indexName = this.client.customWrapIdentifier(indexName, identity); + + this.pushQuery({ + sql: `PRAGMA table_info(${this.tableName()})`, + output(pragma) { + return compiler.client + .ddl(compiler, pragma, this.connection) + .dropForeign(columns, indexName); + }, + }); + } + + // Compile a drop primary key command. + dropPrimary(constraintName) { + const compiler = this; + + constraintName = this.client.customWrapIdentifier(constraintName, identity); + + this.pushQuery({ + sql: `PRAGMA table_info(${this.tableName()})`, + output(pragma) { + return compiler.client + .ddl(compiler, pragma, this.connection) + .dropPrimary(constraintName); + }, + }); + } + + dropIndex(columns, indexName) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('index', this.tableNameRaw, columns); + this.pushQuery(`drop index ${indexName}`); + } + + // Compile a unique key command. + unique(columns, indexName) { + let deferrable; + let predicate; + if (isObject(indexName)) { + ({ indexName, deferrable, predicate } = indexName); + } + if (deferrable && deferrable !== 'not deferrable') { + this.client.logger.warn( + `sqlite3: unique index \`${indexName}\` will not be deferrable ${deferrable} because sqlite3 does not support deferred constraints.` + ); + } + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('unique', this.tableNameRaw, columns); + columns = this.formatter.columnize(columns); + + const predicateQuery = predicate + ? ' ' + this.client.queryCompiler(predicate).where() + : ''; + + this.pushQuery( + `create unique index ${indexName} on ${this.tableName()} (${columns})${predicateQuery}` + ); + } + + // Compile a plain index key command. + index(columns, indexName, options) { + indexName = indexName + ? this.formatter.wrap(indexName) + : this._indexCommand('index', this.tableNameRaw, columns); + columns = this.formatter.columnize(columns); + + let predicate; + if (isObject(options)) { + ({ predicate } = options); + } + const predicateQuery = predicate + ? ' ' + this.client.queryCompiler(predicate).where() + : ''; + this.pushQuery( + `create index ${indexName} on ${this.tableName()} (${columns})${predicateQuery}` + ); + } + + /** + * Add a primary key to an existing table. + * + * @NOTE The `createQuery` method above handles table creation. Don't do anything regarding table + * creation in this method + * + * @param {string | string[]} columns - Column name(s) to assign as primary keys + * @param {string} [constraintName] - Custom name for the PK constraint + */ + primary(columns, constraintName) { + const compiler = this; + + columns = Array.isArray(columns) ? columns : [columns]; + columns = columns.map((column) => + this.client.customWrapIdentifier(column, identity) + ); + + let deferrable; + if (isObject(constraintName)) { + ({ constraintName, deferrable } = constraintName); + } + if (deferrable && deferrable !== 'not deferrable') { + this.client.logger.warn( + `sqlite3: primary key constraint \`${constraintName}\` will not be deferrable ${deferrable} because sqlite3 does not support deferred constraints.` + ); + } + constraintName = this.client.customWrapIdentifier(constraintName, identity); + + if (this.method !== 'create' && this.method !== 'createIfNot') { + this.pushQuery({ + sql: `PRAGMA table_info(${this.tableName()})`, + output(pragma) { + return compiler.client + .ddl(compiler, pragma, this.connection) + .primary(columns, constraintName); + }, + }); + } + } + + /** + * Add a foreign key constraint to an existing table + * + * @NOTE The `createQuery` method above handles foreign key constraints on table creation. Don't do + * anything regarding table creation in this method + * + * @param {object} foreignInfo - Information about the current column foreign setup + * @param {string | string[]} [foreignInfo.column] - Column in the current constraint + * @param {string | undefined} foreignInfo.keyName - Name of the foreign key constraint + * @param {string | string[]} foreignInfo.references - What column it references in the other table + * @param {string} foreignInfo.inTable - What table is referenced in this constraint + * @param {string} [foreignInfo.onUpdate] - What to do on updates + * @param {string} [foreignInfo.onDelete] - What to do on deletions + */ + foreign(foreignInfo) { + const compiler = this; + + if (this.method !== 'create' && this.method !== 'createIfNot') { + foreignInfo.column = Array.isArray(foreignInfo.column) + ? foreignInfo.column + : [foreignInfo.column]; + foreignInfo.column = foreignInfo.column.map((column) => + this.client.customWrapIdentifier(column, identity) + ); + foreignInfo.inTable = this.client.customWrapIdentifier( + foreignInfo.inTable, + identity + ); + foreignInfo.references = Array.isArray(foreignInfo.references) + ? foreignInfo.references + : [foreignInfo.references]; + foreignInfo.references = foreignInfo.references.map((column) => + this.client.customWrapIdentifier(column, identity) + ); + + this.pushQuery({ + sql: `PRAGMA table_info(${this.tableName()})`, + statementsProducer(pragma, connection) { + return compiler.client + .ddl(compiler, pragma, connection) + .foreign(foreignInfo); + }, + }); + } + } + + primaryKeys() { + const pks = filter(this.grouped.alterTable || [], { method: 'primary' }); + if (pks.length > 0 && pks[0].args.length > 0) { + const columns = pks[0].args[0]; + let constraintName = pks[0].args[1] || ''; + if (constraintName) { + constraintName = ' constraint ' + this.formatter.wrap(constraintName); + } + const needUniqueCols = + this.grouped.columns.filter((t) => t.builder._type === 'increments') + .length > 0; + // SQLite dont support autoincrement columns and composite primary keys (autoincrement is always primary key). + // You need to add unique index instead when you have autoincrement columns (https://stackoverflow.com/a/6154876/1535159) + return `,${constraintName} ${ + needUniqueCols ? 'unique' : 'primary key' + } (${this.formatter.columnize(columns)})`; + } + } + + foreignKeys() { + let sql = ''; + const foreignKeys = filter(this.grouped.alterTable || [], { + method: 'foreign', + }); + for (let i = 0, l = foreignKeys.length; i < l; i++) { + const foreign = foreignKeys[i].args[0]; + const column = this.formatter.columnize(foreign.column); + const references = this.formatter.columnize(foreign.references); + const foreignTable = this.formatter.wrap(foreign.inTable); + let constraintName = foreign.keyName || ''; + if (constraintName) { + constraintName = ' constraint ' + this.formatter.wrap(constraintName); + } + sql += `,${constraintName} foreign key(${column}) references ${foreignTable}(${references})`; + if (foreign.onDelete) sql += ` on delete ${foreign.onDelete}`; + if (foreign.onUpdate) sql += ` on update ${foreign.onUpdate}`; + } + return sql; + } + + createTableBlock() { + return this.getColumns().concat().join(','); + } + + renameColumn(from, to) { + this.pushQuery({ + sql: `alter table ${this.tableName()} rename ${this.formatter.wrap( + from + )} to ${this.formatter.wrap(to)}`, + }); + } + + _setNullableState(column, isNullable) { + const compiler = this; + + this.pushQuery({ + sql: `PRAGMA table_info(${this.tableName()})`, + statementsProducer(pragma, connection) { + return compiler.client + .ddl(compiler, pragma, connection) + .setNullable(column, isNullable); + }, + }); + } + + dropColumn() { + const compiler = this; + const columns = values(arguments); + + const columnsWrapped = columns.map((column) => + this.client.customWrapIdentifier(column, identity) + ); + + this.pushQuery({ + sql: `PRAGMA table_info(${this.tableName()})`, + output(pragma) { + return compiler.client + .ddl(compiler, pragma, this.connection) + .dropColumn(columnsWrapped); + }, + }); + } +} + +module.exports = TableCompiler_SQLite3; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js new file mode 100644 index 000000000..77f42244e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/dialects/sqlite3/schema/sqlite-viewcompiler.js @@ -0,0 +1,40 @@ +/* eslint max-len: 0 */ + +const ViewCompiler = require('../../../schema/viewcompiler.js'); +const { + columnize: columnize_, +} = require('../../../formatter/wrappingFormatter'); + +class ViewCompiler_SQLite3 extends ViewCompiler { + constructor(client, viewCompiler) { + super(client, viewCompiler); + } + createOrReplace() { + const columns = this.columns; + const selectQuery = this.selectQuery.toString(); + const viewName = this.viewName(); + + const columnList = columns + ? ' (' + + columnize_( + columns, + this.viewBuilder, + this.client, + this.bindingsHolder + ) + + ')' + : ''; + + const dropSql = `drop view if exists ${viewName}`; + const createSql = `create view ${viewName}${columnList} as ${selectQuery}`; + + this.pushQuery({ + sql: dropSql, + }); + this.pushQuery({ + sql: createSql, + }); + } +} + +module.exports = ViewCompiler_SQLite3; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/batch-insert.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/batch-insert.js new file mode 100644 index 000000000..fbd4e2a8d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/batch-insert.js @@ -0,0 +1,51 @@ +const chunk = require('lodash/chunk'); +const flatten = require('lodash/flatten'); +const delay = require('./internal/delay'); +const { isNumber } = require('../util/is'); + +function batchInsert(client, tableName, batch, chunkSize = 1000) { + let returning = undefined; + let transaction = null; + if (!isNumber(chunkSize) || chunkSize < 1) { + throw new TypeError(`Invalid chunkSize: ${chunkSize}`); + } + if (!Array.isArray(batch)) { + throw new TypeError(`Invalid batch: Expected array, got ${typeof batch}`); + } + const chunks = chunk(batch, chunkSize); + + const runInTransaction = (cb) => { + if (transaction) { + return cb(transaction); + } + return client.transaction(cb); + }; + + return Object.assign( + Promise.resolve().then(async () => { + //Next tick to ensure wrapper functions are called if needed + await delay(1); + return runInTransaction(async (tr) => { + const chunksResults = []; + for (const items of chunks) { + chunksResults.push(await tr(tableName).insert(items, returning)); + } + return flatten(chunksResults); + }); + }), + { + returning(columns) { + returning = columns; + + return this; + }, + transacting(tr) { + transaction = tr; + + return this; + }, + } + ); +} + +module.exports = batchInsert; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/internal/delay.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/internal/delay.js new file mode 100644 index 000000000..bd49afe06 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/internal/delay.js @@ -0,0 +1,6 @@ +/** + * @param {number} delay + * @returns {Promise} + */ +module.exports = (delay) => + new Promise((resolve) => setTimeout(resolve, delay)); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/internal/ensure-connection-callback.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/internal/ensure-connection-callback.js new file mode 100644 index 000000000..1bb96e59f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/internal/ensure-connection-callback.js @@ -0,0 +1,41 @@ +function ensureConnectionCallback(runner) { + runner.client.emit('start', runner.builder); + runner.builder.emit('start', runner.builder); + const sql = runner.builder.toSQL(); + + if (runner.builder._debug) { + runner.client.logger.debug(sql); + } + + if (Array.isArray(sql)) { + return runner.queryArray(sql); + } + return runner.query(sql); +} + +function ensureConnectionStreamCallback(runner, params) { + try { + const sql = runner.builder.toSQL(); + + if (Array.isArray(sql) && params.hasHandler) { + throw new Error( + 'The stream may only be used with a single query statement.' + ); + } + + return runner.client.stream( + runner.connection, + sql, + params.stream, + params.options + ); + } catch (e) { + params.stream.emit('error', e); + throw e; + } +} + +module.exports = { + ensureConnectionCallback, + ensureConnectionStreamCallback, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/internal/query-executioner.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/internal/query-executioner.js new file mode 100644 index 000000000..8ca978433 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/internal/query-executioner.js @@ -0,0 +1,62 @@ +const _debugQuery = require('debug')('knex:query'); +const debugBindings = require('debug')('knex:bindings'); +const debugQuery = (sql, txId) => _debugQuery(sql.replace(/%/g, '%%'), txId); +const { isString } = require('../../util/is'); + +function formatQuery(sql, bindings, timeZone, client) { + bindings = bindings == null ? [] : [].concat(bindings); + let index = 0; + return sql.replace(/\\?\?/g, (match) => { + if (match === '\\?') { + return '?'; + } + if (index === bindings.length) { + return match; + } + const value = bindings[index++]; + return client._escapeBinding(value, { timeZone }); + }); +} + +function enrichQueryObject(connection, queryParam, client) { + const queryObject = isString(queryParam) ? { sql: queryParam } : queryParam; + + queryObject.bindings = client.prepBindings(queryObject.bindings); + queryObject.sql = client.positionBindings(queryObject.sql); + + const { __knexUid, __knexTxId } = connection; + + client.emit('query', Object.assign({ __knexUid, __knexTxId }, queryObject)); + debugQuery(queryObject.sql, __knexTxId); + debugBindings(queryObject.bindings, __knexTxId); + + return queryObject; +} + +function executeQuery(connection, queryObject, client) { + return client._query(connection, queryObject).catch((err) => { + if (client.config && client.config.compileSqlOnError === false) { + err.message = queryObject.sql + ' - ' + err.message; + } else { + err.message = + formatQuery(queryObject.sql, queryObject.bindings, undefined, client) + + ' - ' + + err.message; + } + client.emit( + 'query-error', + err, + Object.assign( + { __knexUid: connection.__knexUid, __knexTxId: connection.__knexUid }, + queryObject + ) + ); + throw err; + }); +} + +module.exports = { + enrichQueryObject, + executeQuery, + formatQuery, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/runner.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/runner.js new file mode 100644 index 000000000..ed0165292 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/runner.js @@ -0,0 +1,325 @@ +const { KnexTimeoutError } = require('../util/timeout'); +const { timeout } = require('../util/timeout'); +const { + ensureConnectionCallback, + ensureConnectionStreamCallback, +} = require('./internal/ensure-connection-callback'); + +let Transform; + +// The "Runner" constructor takes a "builder" (query, schema, or raw) +// and runs through each of the query statements, calling any additional +// "output" method provided alongside the query and bindings. +class Runner { + constructor(client, builder) { + this.client = client; + this.builder = builder; + this.queries = []; + + // The "connection" object is set on the runner when + // "run" is called. + this.connection = undefined; + } + + // "Run" the target, calling "toSQL" on the builder, returning + // an object or array of queries to run, each of which are run on + // a single connection. + async run() { + const runner = this; + try { + const res = await this.ensureConnection(ensureConnectionCallback); + + // Fire a single "end" event on the builder when + // all queries have successfully completed. + runner.builder.emit('end'); + return res; + + // If there are any "error" listeners, we fire an error event + // and then re-throw the error to be eventually handled by + // the promise chain. Useful if you're wrapping in a custom `Promise`. + } catch (err) { + if (runner.builder._events && runner.builder._events.error) { + runner.builder.emit('error', err); + } + throw err; + } + } + + // Stream the result set, by passing through to the dialect's streaming + // capabilities. If the options are + stream(optionsOrHandler, handlerOrNil) { + const firstOptionIsHandler = + typeof optionsOrHandler === 'function' && arguments.length === 1; + + const options = firstOptionIsHandler ? {} : optionsOrHandler; + const handler = firstOptionIsHandler ? optionsOrHandler : handlerOrNil; + + // Determines whether we emit an error or throw here. + const hasHandler = typeof handler === 'function'; + + // Lazy-load the "Transform" dependency. + Transform = Transform || require('stream').Transform; + + const queryContext = this.builder.queryContext(); + + const stream = new Transform({ + objectMode: true, + transform: (chunk, _, callback) => { + callback(null, this.client.postProcessResponse(chunk, queryContext)); + }, + }); + stream.on('close', () => { + this.client.releaseConnection(this.connection); + }); + + // If the stream is manually destroyed, the close event is not + // propagated to the top of the pipe chain. We need to manually verify + // that the source stream is closed and if not, manually destroy it. + stream.on('pipe', (sourceStream) => { + const cleanSourceStream = () => { + if (!sourceStream.closed) { + sourceStream.destroy(); + } + }; + + // Stream already closed, cleanup immediately + if (stream.closed) { + cleanSourceStream(); + } else { + stream.on('close', cleanSourceStream); + } + }); + + const connectionAcquirePromise = this.ensureConnection( + ensureConnectionStreamCallback, + { + options, + hasHandler, + stream, + } + ) + // Emit errors on the stream if the error occurred before a connection + // could be acquired. + // If the connection was acquired, assume the error occurred in the client + // code and has already been emitted on the stream. Don't emit it twice. + .catch((err) => { + if (!this.connection) { + stream.emit('error', err); + } + }); + + // If a function is passed to handle the stream, send the stream + // there and return the promise, otherwise just return the stream + // and the promise will take care of itself. + if (hasHandler) { + handler(stream); + return connectionAcquirePromise; + } + return stream; + } + + // Allow you to pipe the stream to a writable stream. + pipe(writable, options) { + return this.stream(options).pipe(writable); + } + + // "Runs" a query, returning a promise. All queries specified by the builder are guaranteed + // to run in sequence, and on the same connection, especially helpful when schema building + // and dealing with foreign key constraints, etc. + async query(obj) { + const { __knexUid, __knexTxId } = this.connection; + + this.builder.emit('query', Object.assign({ __knexUid, __knexTxId }, obj)); + + const runner = this; + const queryContext = this.builder.queryContext(); + // query-error events are emitted before the queryPromise continuations. + // pass queryContext into client.query so it can be raised properly. + if (obj !== null && typeof obj === 'object') { + obj.queryContext = queryContext; + } + let queryPromise = this.client.query(this.connection, obj); + + if (obj.timeout) { + queryPromise = timeout(queryPromise, obj.timeout); + } + + // Await the return value of client.processResponse; in the case of sqlite3's + // dropColumn()/renameColumn(), it will be a Promise for the transaction + // containing the complete rename procedure. + return queryPromise + .then((resp) => this.client.processResponse(resp, runner)) + .then((processedResponse) => { + const postProcessedResponse = this.client.postProcessResponse( + processedResponse, + queryContext + ); + + this.builder.emit( + 'query-response', + postProcessedResponse, + Object.assign({ __knexUid, __knexTxId }, obj), + this.builder + ); + + this.client.emit( + 'query-response', + postProcessedResponse, + Object.assign({ __knexUid, __knexTxId }, obj), + this.builder + ); + + return postProcessedResponse; + }) + .catch((error) => { + if (!(error instanceof KnexTimeoutError)) { + return Promise.reject(error); + } + const { timeout, sql, bindings } = obj; + + let cancelQuery; + if (obj.cancelOnTimeout) { + cancelQuery = this.client.cancelQuery(this.connection); + } else { + // If we don't cancel the query, we need to mark the connection as disposed so that + // it gets destroyed by the pool and is never used again. If we don't do this and + // return the connection to the pool, it will be useless until the current operation + // that timed out, finally finishes. + this.connection.__knex__disposed = error; + cancelQuery = Promise.resolve(); + } + + return cancelQuery + .catch((cancelError) => { + // If the cancellation failed, we need to mark the connection as disposed so that + // it gets destroyed by the pool and is never used again. If we don't do this and + // return the connection to the pool, it will be useless until the current operation + // that timed out, finally finishes. + this.connection.__knex__disposed = error; + + // cancellation failed + throw Object.assign(cancelError, { + message: `After query timeout of ${timeout}ms exceeded, cancelling of query failed.`, + sql, + bindings, + timeout, + }); + }) + .then(() => { + // cancellation succeeded, rethrow timeout error + throw Object.assign(error, { + message: `Defined query timeout of ${timeout}ms exceeded when running query.`, + sql, + bindings, + timeout, + }); + }); + }) + .catch((error) => { + this.builder.emit( + 'query-error', + error, + Object.assign({ __knexUid, __knexTxId, queryContext }, obj) + ); + throw error; + }); + } + + // In the case of the "schema builder" we call `queryArray`, which runs each + // of the queries in sequence. + async queryArray(queries) { + if (queries.length === 1) { + const query = queries[0]; + + if (!query.statementsProducer) { + return this.query(query); + } + + const statements = await query.statementsProducer( + undefined, + this.connection + ); + + const sqlQueryObjects = statements.sql.map((statement) => ({ + sql: statement, + bindings: query.bindings, + })); + const preQueryObjects = statements.pre.map((statement) => ({ + sql: statement, + bindings: query.bindings, + })); + const postQueryObjects = statements.post.map((statement) => ({ + sql: statement, + bindings: query.bindings, + })); + + let results = []; + + await this.queryArray(preQueryObjects); + + try { + await this.client.transaction( + async (trx) => { + const transactionRunner = new Runner(trx.client, this.builder); + transactionRunner.connection = this.connection; + + results = await transactionRunner.queryArray(sqlQueryObjects); + + if (statements.check) { + const foreignViolations = await trx.raw(statements.check); + + if (foreignViolations.length > 0) { + throw new Error('FOREIGN KEY constraint failed'); + } + } + }, + { connection: this.connection } + ); + } finally { + await this.queryArray(postQueryObjects); + } + + return results; + } + + const results = []; + for (const query of queries) { + results.push(await this.queryArray([query])); + } + return results; + } + + // Check whether there's a transaction flag, and that it has a connection. + async ensureConnection(cb, cbParams) { + // Use override from a builder if passed + if (this.builder._connection) { + this.connection = this.builder._connection; + } + + if (this.connection) { + return cb(this, cbParams); + } + + let acquiredConnection; + try { + acquiredConnection = await this.client.acquireConnection(); + } catch (error) { + if (!(error instanceof KnexTimeoutError)) { + return Promise.reject(error); + } + if (this.builder) { + error.sql = this.builder.sql; + error.bindings = this.builder.bindings; + } + throw error; + } + try { + this.connection = acquiredConnection; + return await cb(this, cbParams); + } finally { + await this.client.releaseConnection(acquiredConnection); + } + } +} + +module.exports = Runner; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/transaction.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/transaction.js new file mode 100644 index 000000000..c5a60ce3e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/execution/transaction.js @@ -0,0 +1,413 @@ +// Transaction +// ------- +const { EventEmitter } = require('events'); +const Debug = require('debug'); +const uniqueId = require('lodash/uniqueId'); +const { callbackify } = require('util'); + +const makeKnex = require('../knex-builder/make-knex'); +const { timeout, KnexTimeoutError } = require('../util/timeout'); +const finallyMixin = require('../util/finally-mixin'); + +const debug = Debug('knex:tx'); + +// FYI: This is defined as a function instead of a constant so that +// each Transactor can have its own copy of the default config. +// This will minimize the impact of bugs that might be introduced +// if a Transactor ever mutates its config. +function DEFAULT_CONFIG() { + return { + userParams: {}, + doNotRejectOnRollback: true, + }; +} +// These aren't supported in sqlite3 which is serialized already so it's as +// safe as reasonable, except for a special read_uncommitted pragma +const validIsolationLevels = [ + // Doesn't really work in postgres, it treats it as read committed + 'read uncommitted', + 'read committed', + 'snapshot', + // snapshot and repeatable read are basically the same, most "repeatable + // read" implementations are actually "snapshot" also known as Multi Version + // Concurrency Control (MVCC). Mssql's repeatable read doesn't stop + // repeated reads for inserts as it uses a pessimistic locking system so + // you should probably use 'snapshot' to stop read skew. + 'repeatable read', + // mysql pretends to have serializable, but it is not + 'serializable', +]; + +// Acts as a facade for a Promise, keeping the internal state +// and managing any child transactions. +class Transaction extends EventEmitter { + constructor(client, container, config = DEFAULT_CONFIG(), outerTx = null) { + super(); + this.userParams = config.userParams; + this.doNotRejectOnRollback = config.doNotRejectOnRollback; + + const txid = (this.txid = uniqueId('trx')); + + this.client = client; + this.logger = client.logger; + this.outerTx = outerTx; + this.trxClient = undefined; + this._completed = false; + this._debug = client.config && client.config.debug; + + this.readOnly = config.readOnly; + if (config.isolationLevel) { + this.setIsolationLevel(config.isolationLevel); + } + + debug( + '%s: Starting %s transaction', + txid, + outerTx ? 'nested' : 'top level' + ); + + // `this` can potentially serve as an `outerTx` for another + // Transaction. So, go ahead and establish `_lastChild` now. + this._lastChild = Promise.resolve(); + + const _previousSibling = outerTx ? outerTx._lastChild : Promise.resolve(); + + // FYI: As you will see in a moment, this Promise will be used to construct + // 2 separate Promise Chains. This ensures that each Promise Chain + // can establish its error-handling semantics without interfering + // with the other Promise Chain. + const basePromise = _previousSibling.then(() => + this._evaluateContainer(config, container) + ); + + // FYI: This is the Promise Chain for EXTERNAL use. It ensures that the + // caller must handle any exceptions that result from `basePromise`. + this._promise = basePromise.then((x) => x); + + if (outerTx) { + // FYI: This is the Promise Chain for INTERNAL use. It serves as a signal + // for when the next sibling should begin its execution. Therefore, + // exceptions are caught and ignored. + outerTx._lastChild = basePromise.catch(() => {}); + } + } + + isCompleted() { + return ( + this._completed || (this.outerTx && this.outerTx.isCompleted()) || false + ); + } + + begin(conn) { + const trxMode = [ + this.isolationLevel ? `ISOLATION LEVEL ${this.isolationLevel}` : '', + this.readOnly ? 'READ ONLY' : '', + ] + .join(' ') + .trim(); + + if (trxMode.length === 0) { + return this.query(conn, 'BEGIN;'); + } + + return this.query(conn, `SET TRANSACTION ${trxMode};`).then(() => + this.query(conn, 'BEGIN;') + ); + } + + savepoint(conn) { + return this.query(conn, `SAVEPOINT ${this.txid};`); + } + + commit(conn, value) { + return this.query(conn, 'COMMIT;', 1, value); + } + + release(conn, value) { + return this.query(conn, `RELEASE SAVEPOINT ${this.txid};`, 1, value); + } + + setIsolationLevel(isolationLevel) { + if (!validIsolationLevels.includes(isolationLevel)) { + throw new Error( + `Invalid isolationLevel, supported isolation levels are: ${JSON.stringify( + validIsolationLevels + )}` + ); + } + this.isolationLevel = isolationLevel; + return this; + } + + rollback(conn, error) { + return timeout(this.query(conn, 'ROLLBACK', 2, error), 5000).catch( + (err) => { + if (!(err instanceof KnexTimeoutError)) { + return Promise.reject(err); + } + this._rejecter(error); + } + ); + } + + rollbackTo(conn, error) { + return timeout( + this.query(conn, `ROLLBACK TO SAVEPOINT ${this.txid}`, 2, error), + 5000 + ).catch((err) => { + if (!(err instanceof KnexTimeoutError)) { + return Promise.reject(err); + } + this._rejecter(error); + }); + } + + query(conn, sql, status, value) { + const q = this.trxClient + .query(conn, sql) + .catch((err) => { + status = 2; + value = err; + this._completed = true; + debug('%s error running transaction query', this.txid); + }) + .then((res) => { + if (status === 1) { + this._resolver(value); + } + if (status === 2) { + if (value === undefined) { + if (this.doNotRejectOnRollback && /^ROLLBACK\b/i.test(sql)) { + this._resolver(); + return; + } + + value = new Error(`Transaction rejected with non-error: ${value}`); + } + this._rejecter(value); + } + return res; + }); + if (status === 1 || status === 2) { + this._completed = true; + } + return q; + } + + debug(enabled) { + this._debug = arguments.length ? enabled : true; + return this; + } + + async _evaluateContainer(config, container) { + return this.acquireConnection(config, (connection) => { + const trxClient = (this.trxClient = makeTxClient( + this, + this.client, + connection + )); + const init = this.client.transacting + ? this.savepoint(connection) + : this.begin(connection); + const executionPromise = new Promise((resolver, rejecter) => { + this._resolver = resolver; + this._rejecter = rejecter; + }); + + init + .then(() => { + return makeTransactor(this, connection, trxClient); + }) + .then((transactor) => { + this.transactor = transactor; + if (this.outerTx) { + transactor.parentTransaction = this.outerTx.transactor; + } + transactor.executionPromise = executionPromise; + + // If we've returned a "thenable" from the transaction container, assume + // the rollback and commit are chained to this object's success / failure. + // Directly thrown errors are treated as automatic rollbacks. + let result; + try { + result = container(transactor); + } catch (err) { + result = Promise.reject(err); + } + if (result && result.then && typeof result.then === 'function') { + result + .then((val) => { + return transactor.commit(val); + }) + .catch((err) => { + return transactor.rollback(err); + }); + } + return null; + }) + .catch((e) => { + return this._rejecter(e); + }); + + return executionPromise; + }); + } + + // Acquire a connection and create a disposer - either using the one passed + // via config or getting one off the client. The disposer will be called once + // the original promise is marked completed. + async acquireConnection(config, cb) { + const configConnection = config && config.connection; + const connection = + configConnection || (await this.client.acquireConnection()); + + try { + connection.__knexTxId = this.txid; + return await cb(connection); + } finally { + if (!configConnection) { + debug('%s: releasing connection', this.txid); + this.client.releaseConnection(connection); + } else { + debug('%s: not releasing external connection', this.txid); + } + } + } + + then(onResolve, onReject) { + return this._promise.then(onResolve, onReject); + } + + catch(...args) { + return this._promise.catch(...args); + } + + asCallback(cb) { + callbackify(() => this._promise)(cb); + return this._promise; + } +} +finallyMixin(Transaction.prototype); + +// The transactor is a full featured knex object, with a "commit", a "rollback" +// and a "savepoint" function. The "savepoint" is just sugar for creating a new +// transaction. If the rollback is run inside a savepoint, it rolls back to the +// last savepoint - otherwise it rolls back the transaction. +function makeTransactor(trx, connection, trxClient) { + const transactor = makeKnex(trxClient); + + transactor.context.withUserParams = () => { + throw new Error( + 'Cannot set user params on a transaction - it can only inherit params from main knex instance' + ); + }; + + transactor.isTransaction = true; + transactor.userParams = trx.userParams || {}; + + transactor.context.transaction = function (container, options) { + if (!options) { + options = { doNotRejectOnRollback: true }; + } else if (options.doNotRejectOnRollback === undefined) { + options.doNotRejectOnRollback = true; + } + + return this._transaction(container, options, trx); + }; + + transactor.savepoint = function (container, options) { + return transactor.transaction(container, options); + }; + + if (trx.client.transacting) { + transactor.commit = (value) => trx.release(connection, value); + transactor.rollback = (error) => trx.rollbackTo(connection, error); + } else { + transactor.commit = (value) => trx.commit(connection, value); + transactor.rollback = (error) => trx.rollback(connection, error); + } + + transactor.isCompleted = () => trx.isCompleted(); + + return transactor; +} + +// We need to make a client object which always acquires the same +// connection and does not release back into the pool. +function makeTxClient(trx, client, connection) { + const trxClient = Object.create(client.constructor.prototype); + trxClient.version = client.version; + trxClient.config = client.config; + trxClient.driver = client.driver; + trxClient.connectionSettings = client.connectionSettings; + trxClient.transacting = true; + trxClient.valueForUndefined = client.valueForUndefined; + trxClient.logger = client.logger; + + trxClient.on('start', function (arg) { + trx.emit('start', arg); + client.emit('start', arg); + }); + + trxClient.on('query', function (arg) { + trx.emit('query', arg); + client.emit('query', arg); + }); + + trxClient.on('query-error', function (err, obj) { + trx.emit('query-error', err, obj); + client.emit('query-error', err, obj); + }); + + trxClient.on('query-response', function (response, obj, builder) { + trx.emit('query-response', response, obj, builder); + client.emit('query-response', response, obj, builder); + }); + + const _query = trxClient.query; + trxClient.query = function (conn, obj) { + const completed = trx.isCompleted(); + return new Promise(function (resolve, reject) { + try { + if (conn !== connection) + throw new Error('Invalid connection for transaction query.'); + if (completed) completedError(trx, obj); + resolve(_query.call(trxClient, conn, obj)); + } catch (e) { + reject(e); + } + }); + }; + const _stream = trxClient.stream; + trxClient.stream = function (conn, obj, stream, options) { + const completed = trx.isCompleted(); + return new Promise(function (resolve, reject) { + try { + if (conn !== connection) + throw new Error('Invalid connection for transaction query.'); + if (completed) completedError(trx, obj); + resolve(_stream.call(trxClient, conn, obj, stream, options)); + } catch (e) { + reject(e); + } + }); + }; + trxClient.acquireConnection = function () { + return Promise.resolve(connection); + }; + trxClient.releaseConnection = function () { + return Promise.resolve(); + }; + + return trxClient; +} + +function completedError(trx, obj) { + const sql = typeof obj === 'string' ? obj : obj && obj.sql; + debug('%s: Transaction completed: %s', trx.txid, sql); + throw new Error( + 'Transaction query already complete, run with DEBUG=knex:tx for more info' + ); +} + +module.exports = Transaction; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter.js new file mode 100644 index 000000000..bd398e7d4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter.js @@ -0,0 +1,25 @@ +const { + columnize: columnize_, + wrap: wrap_, +} = require('./formatter/wrappingFormatter'); + +class Formatter { + constructor(client, builder) { + this.client = client; + this.builder = builder; + this.bindings = []; + } + + // Accepts a string or array of columns to wrap as appropriate. + columnize(target) { + return columnize_(target, this.builder, this.client, this); + } + + // Puts the appropriate wrapper around a value depending on the database + // engine, unless it's a knex.raw value, in which case it's left alone. + wrap(value, isParameter) { + return wrap_(value, isParameter, this.builder, this.client, this); + } +} + +module.exports = Formatter; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter/formatterUtils.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter/formatterUtils.js new file mode 100644 index 000000000..d6e54af54 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter/formatterUtils.js @@ -0,0 +1,42 @@ +const { isObject } = require('../util/is'); + +// Compiles a callback using the query builder. +function compileCallback(callback, method, client, bindingsHolder) { + // Build the callback + const builder = client.queryBuilder(); + callback.call(builder, builder); + + // Compile the callback, using the current formatter (to track all bindings). + const compiler = client.queryCompiler(builder, bindingsHolder.bindings); + + // Return the compiled & parameterized sql. + return compiler.toSQL(method || builder._method || 'select'); +} + +function wrapAsIdentifier(value, builder, client) { + const queryContext = builder.queryContext(); + return client.wrapIdentifier((value || '').trim(), queryContext); +} + +function formatDefault(value, type, client) { + if (value === void 0) { + return ''; + } else if (value === null) { + return 'null'; + } else if (value && value.isRawInstance) { + return value.toQuery(); + } else if (type === 'bool') { + if (value === 'false') value = 0; + return `'${value ? 1 : 0}'`; + } else if ((type === 'json' || type === 'jsonb') && isObject(value)) { + return `'${JSON.stringify(value)}'`; + } else { + return client._escapeBinding(value.toString()); + } +} + +module.exports = { + compileCallback, + wrapAsIdentifier, + formatDefault, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter/rawFormatter.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter/rawFormatter.js new file mode 100644 index 000000000..800fcbfc5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter/rawFormatter.js @@ -0,0 +1,84 @@ +const { columnize } = require('./wrappingFormatter'); + +function replaceRawArrBindings(raw, client) { + const bindingsHolder = { + bindings: [], + }; + const builder = raw; + + const expectedBindings = raw.bindings.length; + const values = raw.bindings; + let index = 0; + + const sql = raw.sql.replace(/\\?\?\??/g, function (match) { + if (match === '\\?') { + return match; + } + + const value = values[index++]; + + if (match === '??') { + return columnize(value, builder, client, bindingsHolder); + } + return client.parameter(value, builder, bindingsHolder); + }); + + if (expectedBindings !== index) { + throw new Error(`Expected ${expectedBindings} bindings, saw ${index}`); + } + + return { + method: 'raw', + sql, + bindings: bindingsHolder.bindings, + }; +} + +function replaceKeyBindings(raw, client) { + const bindingsHolder = { + bindings: [], + }; + const builder = raw; + + const values = raw.bindings; + const regex = /\\?(:(\w+):(?=::)|:(\w+):(?!:)|:(\w+))/g; + + const sql = raw.sql.replace(regex, function (match, p1, p2, p3, p4) { + if (match !== p1) { + return p1; + } + + const part = p2 || p3 || p4; + const key = match.trim(); + const isIdentifier = key[key.length - 1] === ':'; + const value = values[part]; + + if (value === undefined) { + if (Object.prototype.hasOwnProperty.call(values, part)) { + bindingsHolder.bindings.push(value); + } + + return match; + } + + if (isIdentifier) { + return match.replace( + p1, + columnize(value, builder, client, bindingsHolder) + ); + } + + return match.replace(p1, client.parameter(value, builder, bindingsHolder)); + }); + + return { + method: 'raw', + sql, + bindings: bindingsHolder.bindings, + }; +} + +module.exports = { + replaceKeyBindings, + replaceRawArrBindings, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter/wrappingFormatter.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter/wrappingFormatter.js new file mode 100644 index 000000000..c9fe7ecfc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/formatter/wrappingFormatter.js @@ -0,0 +1,250 @@ +const transform = require('lodash/transform'); +const QueryBuilder = require('../query/querybuilder'); +const { compileCallback, wrapAsIdentifier } = require('./formatterUtils'); + +// Valid values for the `order by` clause generation. +const orderBys = ['asc', 'desc']; + +// Turn this into a lookup map +const operators = transform( + [ + '=', + '<', + '>', + '<=', + '>=', + '<>', + '!=', + 'like', + 'not like', + 'between', + 'not between', + 'ilike', + 'not ilike', + 'exists', + 'not exist', + 'rlike', + 'not rlike', + 'regexp', + 'not regexp', + 'match', + '&', + '|', + '^', + '<<', + '>>', + '~', + '~=', + '~*', + '!~', + '!~*', + '#', + '&&', + '@>', + '<@', + '||', + '&<', + '&>', + '-|-', + '@@', + '!!', + ['?', '\\?'], + ['?|', '\\?|'], + ['?&', '\\?&'], + ], + (result, key) => { + if (Array.isArray(key)) { + result[key[0]] = key[1]; + } else { + result[key] = key; + } + }, + {} +); + +// Accepts a string or array of columns to wrap as appropriate. Column can be raw +function columnize(target, builder, client, bindingHolder) { + const columns = Array.isArray(target) ? target : [target]; + let str = '', + i = -1; + while (++i < columns.length) { + if (i > 0) str += ', '; + str += wrap(columns[i], undefined, builder, client, bindingHolder); + } + return str; +} + +// Puts the appropriate wrapper around a value depending on the database +// engine, unless it's a knex.raw value, in which case it's left alone. +function wrap(value, isParameter, builder, client, bindingHolder) { + const raw = unwrapRaw(value, isParameter, builder, client, bindingHolder); + if (raw) return raw; + switch (typeof value) { + case 'function': + return outputQuery( + compileCallback(value, undefined, client, bindingHolder), + true, + builder, + client + ); + case 'object': + return parseObject(value, builder, client, bindingHolder); + case 'number': + return value; + default: + return wrapString(value + '', builder, client); + } +} + +function unwrapRaw(value, isParameter, builder, client, bindingsHolder) { + let query; + if (value instanceof QueryBuilder) { + query = client.queryCompiler(value).toSQL(); + if (query.bindings) { + bindingsHolder.bindings.push(...query.bindings); + } + return outputQuery(query, isParameter, builder, client); + } + if (value && value.isRawInstance) { + value.client = client; + if (builder._queryContext) { + value.queryContext = () => { + return builder._queryContext; + }; + } + + query = value.toSQL(); + if (query.bindings) { + bindingsHolder.bindings.push(...query.bindings); + } + return query.sql; + } + if (isParameter) { + bindingsHolder.bindings.push(value); + } +} + +function operator(value, builder, client, bindingsHolder) { + const raw = unwrapRaw(value, undefined, builder, client, bindingsHolder); + if (raw) return raw; + const operator = operators[(value || '').toLowerCase()]; + if (!operator) { + throw new TypeError(`The operator "${value}" is not permitted`); + } + return operator; +} + +// Coerce to string to prevent strange errors when it's not a string. +function wrapString(value, builder, client) { + const asIndex = value.toLowerCase().indexOf(' as '); + if (asIndex !== -1) { + const first = value.slice(0, asIndex); + const second = value.slice(asIndex + 4); + return client.alias( + wrapString(first, builder, client), + wrapAsIdentifier(second, builder, client) + ); + } + const wrapped = []; + let i = -1; + const segments = value.split('.'); + while (++i < segments.length) { + value = segments[i]; + if (i === 0 && segments.length > 1) { + wrapped.push(wrapString((value || '').trim(), builder, client)); + } else { + wrapped.push(wrapAsIdentifier(value, builder, client)); + } + } + return wrapped.join('.'); +} + +// Key-value notation for alias +function parseObject(obj, builder, client, formatter) { + const ret = []; + for (const alias in obj) { + const queryOrIdentifier = obj[alias]; + // Avoids double aliasing for subqueries + if (typeof queryOrIdentifier === 'function') { + const compiled = compileCallback( + queryOrIdentifier, + undefined, + client, + formatter + ); + compiled.as = alias; // enforces the object's alias + ret.push(outputQuery(compiled, true, builder, client)); + } else if (queryOrIdentifier instanceof QueryBuilder) { + ret.push( + client.alias( + `(${wrap(queryOrIdentifier, undefined, builder, client, formatter)})`, + wrapAsIdentifier(alias, builder, client) + ) + ); + } else { + ret.push( + client.alias( + wrap(queryOrIdentifier, undefined, builder, client, formatter), + wrapAsIdentifier(alias, builder, client) + ) + ); + } + } + return ret.join(', '); +} + +// Ensures the query is aliased if necessary. +function outputQuery(compiled, isParameter, builder, client) { + let sql = compiled.sql || ''; + if (sql) { + if ( + (compiled.method === 'select' || compiled.method === 'first') && + (isParameter || compiled.as) + ) { + sql = `(${sql})`; + if (compiled.as) + return client.alias(sql, wrapString(compiled.as, builder, client)); + } + } + return sql; +} + +/** + * Creates SQL for a parameter, which might be passed to where() or .with() or + * pretty much anywhere in API. + * + * @param value + * @param method Optional at least 'select' or 'update' are valid + * @param builder + * @param client + * @param bindingHolder + */ +function rawOrFn(value, method, builder, client, bindingHolder) { + if (typeof value === 'function') { + return outputQuery( + compileCallback(value, method, client, bindingHolder), + undefined, + builder, + client + ); + } + return unwrapRaw(value, undefined, builder, client, bindingHolder) || ''; +} + +// Specify the direction of the ordering. +function direction(value, builder, client, bindingsHolder) { + const raw = unwrapRaw(value, undefined, builder, client, bindingsHolder); + if (raw) return raw; + return orderBys.indexOf((value || '').toLowerCase()) !== -1 ? value : 'asc'; +} + +module.exports = { + columnize, + direction, + operator, + outputQuery, + rawOrFn, + unwrapRaw, + wrap, + wrapString, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/index.js new file mode 100644 index 000000000..f8cc6acbe --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/index.js @@ -0,0 +1,3 @@ +const Knex = require('./knex-builder/Knex'); + +module.exports = Knex; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/FunctionHelper.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/FunctionHelper.js new file mode 100644 index 000000000..74abf94f3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/FunctionHelper.js @@ -0,0 +1,80 @@ +// FunctionHelper +// ------- +// Used for adding functions from the builder +// Example usage: table.dateTime('datetime_to_date').notNull().defaultTo(knex.fn.now()); +class FunctionHelper { + constructor(client) { + this.client = client; + } + + now(precision) { + if (typeof precision === 'number') { + return this.client.raw(`CURRENT_TIMESTAMP(${precision})`); + } + return this.client.raw('CURRENT_TIMESTAMP'); + } + + uuid() { + switch (this.client.driverName) { + case 'sqlite3': + case 'better-sqlite3': + return this.client.raw( + "(lower(hex(randomblob(4))) || '-' || lower(hex(randomblob(2))) || '-4' || substr(lower(hex(randomblob(2))),2) || '-' || substr('89ab',abs(random()) % 4 + 1, 1) || substr(lower(hex(randomblob(2))),2) || '-' || lower(hex(randomblob(6))))" + ); + case 'mssql': + return this.client.raw('(NEWID())'); + case 'pg': + case 'pgnative': + case 'cockroachdb': + return this.client.raw('(gen_random_uuid())'); + case 'oracle': + case 'oracledb': + return this.client.raw('(random_uuid())'); + case 'mysql': + case 'mysql2': + return this.client.raw('(UUID())'); + default: + throw new Error( + `${this.client.driverName} does not have a uuid function` + ); + } + } + + uuidToBin(uuid, ordered = true) { + const buf = Buffer.from(uuid.replace(/-/g, ''), 'hex'); + return ordered + ? Buffer.concat([ + buf.slice(6, 8), + buf.slice(4, 6), + buf.slice(0, 4), + buf.slice(8, 16), + ]) + : Buffer.concat([ + buf.slice(0, 4), + buf.slice(4, 6), + buf.slice(6, 8), + buf.slice(8, 16), + ]); + } + + binToUuid(bin, ordered = true) { + const buf = Buffer.from(bin, 'hex'); + return ordered + ? [ + buf.toString('hex', 4, 8), + buf.toString('hex', 2, 4), + buf.toString('hex', 0, 2), + buf.toString('hex', 8, 10), + buf.toString('hex', 10, 16), + ].join('-') + : [ + buf.toString('hex', 0, 4), + buf.toString('hex', 4, 6), + buf.toString('hex', 6, 8), + buf.toString('hex', 8, 10), + buf.toString('hex', 10, 16), + ].join('-'); + } +} + +module.exports = FunctionHelper; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/Knex.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/Knex.js new file mode 100644 index 000000000..dad1077f0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/Knex.js @@ -0,0 +1,59 @@ +const Client = require('../client'); +const QueryBuilder = require('../query/querybuilder'); +const QueryInterface = require('../query/method-constants'); + +const makeKnex = require('./make-knex'); +const { KnexTimeoutError } = require('../util/timeout'); +const { resolveConfig } = require('./internal/config-resolver'); +const SchemaBuilder = require('../schema/builder'); +const ViewBuilder = require('../schema/viewbuilder'); +const ColumnBuilder = require('../schema/columnbuilder'); +const TableBuilder = require('../schema/tablebuilder'); + +function knex(config) { + const { resolvedConfig, Dialect } = resolveConfig(...arguments); + + const newKnex = makeKnex(new Dialect(resolvedConfig)); + if (resolvedConfig.userParams) { + newKnex.userParams = resolvedConfig.userParams; + } + return newKnex; +} + +// Expose Client on the main Knex namespace. +knex.Client = Client; + +knex.KnexTimeoutError = KnexTimeoutError; + +knex.QueryBuilder = { + extend: function (methodName, fn) { + QueryBuilder.extend(methodName, fn); + QueryInterface.push(methodName); + }, +}; + +knex.SchemaBuilder = { + extend: function (methodName, fn) { + SchemaBuilder.extend(methodName, fn); + }, +}; + +knex.ViewBuilder = { + extend: function (methodName, fn) { + ViewBuilder.extend(methodName, fn); + }, +}; + +knex.ColumnBuilder = { + extend: function (methodName, fn) { + ColumnBuilder.extend(methodName, fn); + }, +}; + +knex.TableBuilder = { + extend: function (methodName, fn) { + TableBuilder.extend(methodName, fn); + }, +}; + +module.exports = knex; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/internal/config-resolver.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/internal/config-resolver.js new file mode 100644 index 000000000..a8ad65774 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/internal/config-resolver.js @@ -0,0 +1,57 @@ +const Client = require('../../client'); +const { SUPPORTED_CLIENTS } = require('../../constants'); + +const parseConnection = require('./parse-connection'); +const { getDialectByNameOrAlias } = require('../../dialects'); + +function resolveConfig(config) { + let Dialect; + let resolvedConfig; + + // If config is a string, try to parse it + const parsedConfig = + typeof config === 'string' + ? Object.assign(parseConnection(config), arguments[2]) + : config; + + // If user provided no relevant parameters, use generic client + if ( + arguments.length === 0 || + (!parsedConfig.client && !parsedConfig.dialect) + ) { + Dialect = Client; + } + // If user provided Client constructor as a parameter, use it + else if (typeof parsedConfig.client === 'function') { + Dialect = parsedConfig.client; + } + // If neither applies, let's assume user specified name of a client or dialect as a string + else { + const clientName = parsedConfig.client || parsedConfig.dialect; + if (!SUPPORTED_CLIENTS.includes(clientName)) { + throw new Error( + `knex: Unknown configuration option 'client' value ${clientName}. Note that it is case-sensitive, check documentation for supported values.` + ); + } + + Dialect = getDialectByNameOrAlias(clientName); + } + + // If config connection parameter is passed as string, try to parse it + if (typeof parsedConfig.connection === 'string') { + resolvedConfig = Object.assign({}, parsedConfig, { + connection: parseConnection(parsedConfig.connection).connection, + }); + } else { + resolvedConfig = Object.assign({}, parsedConfig); + } + + return { + resolvedConfig, + Dialect, + }; +} + +module.exports = { + resolveConfig, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/internal/parse-connection.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/internal/parse-connection.js new file mode 100644 index 000000000..72671272f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/internal/parse-connection.js @@ -0,0 +1,87 @@ +const { parse } = require('pg-connection-string'); +const parsePG = parse; +const isWindows = process && process.platform && process.platform === 'win32'; + +/** + * @param str + * @returns {URL} + */ +function tryParse(str) { + try { + return new URL(str); + } catch (e) { + return null; + } +} + +module.exports = function parseConnectionString(str) { + const parsed = tryParse(str); + const isDriveLetter = isWindows && parsed && parsed.protocol.length === 2; + if (!parsed || isDriveLetter) { + return { + client: 'sqlite3', + connection: { + filename: str, + }, + }; + } + let { protocol } = parsed; + if (protocol.slice(-1) === ':') { + protocol = protocol.slice(0, -1); + } + + const isPG = ['postgresql', 'postgres'].includes(protocol); + + return { + client: protocol, + connection: isPG ? parsePG(str) : connectionObject(parsed), + }; +}; + +/** + * @param {URL} parsed + * @returns {{}} + */ +function connectionObject(parsed) { + const connection = {}; + let db = parsed.pathname; + if (db[0] === '/') { + db = db.slice(1); + } + + connection.database = db; + + if (parsed.hostname) { + if (parsed.protocol.indexOf('mssql') === 0) { + connection.server = parsed.hostname; + } else { + connection.host = parsed.hostname; + } + } + if (parsed.port) { + connection.port = parsed.port; + } + if (parsed.username || parsed.password) { + connection.user = decodeURIComponent(parsed.username); + } + if (parsed.password) { + connection.password = decodeURIComponent(parsed.password); + } + if (parsed.searchParams) { + for (const [key, value] of parsed.searchParams.entries()) { + const isNestedConfigSupported = ['mysql:', 'mariadb:', 'mssql:'].includes( + parsed.protocol + ); + if (isNestedConfigSupported) { + try { + connection[key] = JSON.parse(value); + } catch (err) { + connection[key] = value; + } + } else { + connection[key] = value; + } + } + } + return connection; +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/make-knex.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/make-knex.js new file mode 100644 index 000000000..7345708c3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/knex-builder/make-knex.js @@ -0,0 +1,345 @@ +const { EventEmitter } = require('events'); + +const { Migrator } = require('../migrations/migrate/Migrator'); +const Seeder = require('../migrations/seed/Seeder'); +const FunctionHelper = require('./FunctionHelper'); +const QueryInterface = require('../query/method-constants'); +const merge = require('lodash/merge'); +const batchInsert = require('../execution/batch-insert'); +const { isObject } = require('../util/is'); +const { setHiddenProperty } = require('../util/security'); + +// Javascript does not officially support "callable objects". Instead, +// you must create a regular Function and inject properties/methods +// into it. In other words: you can't leverage Prototype Inheritance +// to share the property/method definitions. +// +// To work around this, we're creating an Object Property Definition. +// This allow us to quickly inject everything into the `knex` function +// via the `Object.defineProperties(..)` function. More importantly, +// it allows the same definitions to be shared across `knex` instances. +const KNEX_PROPERTY_DEFINITIONS = { + client: { + get() { + return this.context.client; + }, + set(client) { + this.context.client = client; + }, + configurable: true, + }, + + userParams: { + get() { + return this.context.userParams; + }, + set(userParams) { + this.context.userParams = userParams; + }, + configurable: true, + }, + + schema: { + get() { + return this.client.schemaBuilder(); + }, + configurable: true, + }, + + migrate: { + get() { + return new Migrator(this); + }, + configurable: true, + }, + + seed: { + get() { + return new Seeder(this); + }, + configurable: true, + }, + + fn: { + get() { + return new FunctionHelper(this.client); + }, + configurable: true, + }, +}; + +// `knex` instances serve as proxies around `context` objects. So, calling +// any of these methods on the `knex` instance will forward the call to +// the `knex.context` object. This ensures that `this` will correctly refer +// to `context` within each of these methods. +const CONTEXT_METHODS = [ + 'raw', + 'batchInsert', + 'transaction', + 'transactionProvider', + 'initialize', + 'destroy', + 'ref', + 'withUserParams', + 'queryBuilder', + 'disableProcessing', + 'enableProcessing', +]; + +for (const m of CONTEXT_METHODS) { + KNEX_PROPERTY_DEFINITIONS[m] = { + value: function (...args) { + return this.context[m](...args); + }, + configurable: true, + }; +} + +function makeKnex(client) { + // The object we're potentially using to kick off an initial chain. + function knex(tableName, options) { + return createQueryBuilder(knex.context, tableName, options); + } + + redefineProperties(knex, client); + return knex; +} + +function initContext(knexFn) { + const knexContext = knexFn.context || {}; + Object.assign(knexContext, { + queryBuilder() { + return this.client.queryBuilder(); + }, + + raw() { + return this.client.raw.apply(this.client, arguments); + }, + + batchInsert(table, batch, chunkSize = 1000) { + return batchInsert(this, table, batch, chunkSize); + }, + + // Creates a new transaction. + // If container is provided, returns a promise for when the transaction is resolved. + // If container is not provided, returns a promise with a transaction that is resolved + // when transaction is ready to be used. + transaction(container, _config) { + // Overload support of `transaction(config)` + if (!_config && isObject(container)) { + _config = container; + container = null; + } + + const config = Object.assign({}, _config); + config.userParams = this.userParams || {}; + if (config.doNotRejectOnRollback === undefined) { + config.doNotRejectOnRollback = true; + } + + return this._transaction(container, config); + }, + + // Internal method that actually establishes the Transaction. It makes no assumptions + // about the `config` or `outerTx`, and expects the caller to handle these details. + _transaction(container, config, outerTx = null) { + if (container) { + const trx = this.client.transaction(container, config, outerTx); + return trx; + } else { + return new Promise((resolve, reject) => { + this.client.transaction(resolve, config, outerTx).catch(reject); + }); + } + }, + + transactionProvider(config) { + let trx; + return () => { + if (!trx) { + trx = this.transaction(undefined, config); + } + return trx; + }; + }, + + // Typically never needed, initializes the pool for a knex client. + initialize(config) { + return this.client.initializePool(config); + }, + + // Convenience method for tearing down the pool. + destroy(callback) { + return this.client.destroy(callback); + }, + + ref(ref) { + return this.client.ref(ref); + }, + + // Do not document this as public API until naming and API is improved for general consumption + // This method exists to disable processing of internal queries in migrations + disableProcessing() { + if (this.userParams.isProcessingDisabled) { + return; + } + this.userParams.wrapIdentifier = this.client.config.wrapIdentifier; + this.userParams.postProcessResponse = + this.client.config.postProcessResponse; + this.client.config.wrapIdentifier = null; + this.client.config.postProcessResponse = null; + this.userParams.isProcessingDisabled = true; + }, + + // Do not document this as public API until naming and API is improved for general consumption + // This method exists to enable execution of non-internal queries with consistent identifier naming in migrations + enableProcessing() { + if (!this.userParams.isProcessingDisabled) { + return; + } + this.client.config.wrapIdentifier = this.userParams.wrapIdentifier; + this.client.config.postProcessResponse = + this.userParams.postProcessResponse; + this.userParams.isProcessingDisabled = false; + }, + + withUserParams(params) { + const knexClone = shallowCloneFunction(knexFn); // We need to include getters in our clone + if (this.client) { + knexClone.client = Object.create(this.client.constructor.prototype); // Clone client to avoid leaking listeners that are set on it + merge(knexClone.client, this.client); + knexClone.client.config = Object.assign({}, this.client.config); // Clone client config to make sure they can be modified independently + + if (this.client.config.password) { + setHiddenProperty(knexClone.client.config, this.client.config); + } + } + + redefineProperties(knexClone, knexClone.client); + _copyEventListeners('query', knexFn, knexClone); + _copyEventListeners('query-error', knexFn, knexClone); + _copyEventListeners('query-response', knexFn, knexClone); + _copyEventListeners('start', knexFn, knexClone); + knexClone.userParams = params; + return knexClone; + }, + }); + + if (!knexFn.context) { + knexFn.context = knexContext; + } +} + +function _copyEventListeners(eventName, sourceKnex, targetKnex) { + const listeners = sourceKnex.listeners(eventName); + listeners.forEach((listener) => { + targetKnex.on(eventName, listener); + }); +} + +function redefineProperties(knex, client) { + // Allow chaining methods from the root object, before + // any other information is specified. + // + // TODO: `QueryBuilder.extend(..)` allows new QueryBuilder + // methods to be introduced via external components. + // As a side-effect, it also pushes the new method names + // into the `QueryInterface` array. + // + // The Problem: due to the way the code is currently + // structured, these new methods cannot be retroactively + // injected into existing `knex` instances! As a result, + // some `knex` instances will support the methods, and + // others will not. + // + // We should revisit this once we figure out the desired + // behavior / usage. For instance: do we really want to + // allow external components to directly manipulate `knex` + // data structures? Or, should we come up w/ a different + // approach that avoids side-effects / mutation? + // + // (FYI: I noticed this issue because I attempted to integrate + // this logic directly into the `KNEX_PROPERTY_DEFINITIONS` + // construction. However, `KNEX_PROPERTY_DEFINITIONS` is + // constructed before any `knex` instances are created. + // As a result, the method extensions were missing from all + // `knex` instances.) + for (let i = 0; i < QueryInterface.length; i++) { + const method = QueryInterface[i]; + knex[method] = function () { + const builder = this.queryBuilder(); + return builder[method].apply(builder, arguments); + }; + } + + Object.defineProperties(knex, KNEX_PROPERTY_DEFINITIONS); + + initContext(knex); + knex.client = client; + knex.userParams = {}; + + // Hook up the "knex" object as an EventEmitter. + const ee = new EventEmitter(); + for (const key in ee) { + knex[key] = ee[key]; + } + + // Unfortunately, something seems to be broken in Node 6 and removing events from a clone also mutates original Knex, + // which is highly undesirable + if (knex._internalListeners) { + knex._internalListeners.forEach(({ eventName, listener }) => { + knex.client.removeListener(eventName, listener); // Remove duplicates for copies + }); + } + knex._internalListeners = []; + + // Passthrough all "start" and "query" events to the knex object. + _addInternalListener(knex, 'start', (obj) => { + knex.emit('start', obj); + }); + _addInternalListener(knex, 'query', (obj) => { + knex.emit('query', obj); + }); + _addInternalListener(knex, 'query-error', (err, obj) => { + knex.emit('query-error', err, obj); + }); + _addInternalListener(knex, 'query-response', (response, obj, builder) => { + knex.emit('query-response', response, obj, builder); + }); +} + +function _addInternalListener(knex, eventName, listener) { + knex.client.on(eventName, listener); + knex._internalListeners.push({ + eventName, + listener, + }); +} + +function createQueryBuilder(knexContext, tableName, options) { + const qb = knexContext.queryBuilder(); + if (!tableName) + knexContext.client.logger.warn( + 'calling knex without a tableName is deprecated. Use knex.queryBuilder() instead.' + ); + return tableName ? qb.table(tableName, options) : qb; +} + +function shallowCloneFunction(originalFunction) { + const fnContext = Object.create( + Object.getPrototypeOf(originalFunction), + Object.getOwnPropertyDescriptors(originalFunction) + ); + + const knexContext = {}; + const knexFnWrapper = (tableName, options) => { + return createQueryBuilder(knexContext, tableName, options); + }; + + const clonedFunction = knexFnWrapper.bind(fnContext); + Object.assign(clonedFunction, originalFunction); + clonedFunction.context = knexContext; + return clonedFunction; +} + +module.exports = makeKnex; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/logger.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/logger.js new file mode 100644 index 000000000..f730f7381 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/logger.js @@ -0,0 +1,76 @@ +const color = require('colorette'); +const { inspect } = require('util'); +const { isString, isFunction } = require('./util/is'); + +class Logger { + constructor(config = {}) { + const { + log: { + debug, + warn, + error, + deprecate, + inspectionDepth, + enableColors, + } = {}, + } = config; + this._inspectionDepth = inspectionDepth || 5; + this._enableColors = resolveIsEnabledColors(enableColors); + this._debug = debug; + this._warn = warn; + this._error = error; + this._deprecate = deprecate; + } + + _log(message, userFn, colorFn) { + if (userFn != null && !isFunction(userFn)) { + throw new TypeError('Extensions to knex logger must be functions!'); + } + + if (isFunction(userFn)) { + userFn(message); + return; + } + + if (!isString(message)) { + message = inspect(message, { + depth: this._inspectionDepth, + colors: this._enableColors, + }); + } + + console.log(colorFn ? colorFn(message) : message); + } + + debug(message) { + this._log(message, this._debug); + } + + warn(message) { + this._log(message, this._warn, color.yellow); + } + + error(message) { + this._log(message, this._error, color.red); + } + + deprecate(method, alternative) { + const message = `${method} is deprecated, please use ${alternative}`; + + this._log(message, this._deprecate, color.yellow); + } +} + +function resolveIsEnabledColors(enableColorsParam) { + if (enableColorsParam != null) { + return enableColorsParam; + } + + if (process && process.stdout) { + return process.stdout.isTTY; + } + + return false; +} + +module.exports = Logger; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/common/MigrationsLoader.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/common/MigrationsLoader.js new file mode 100644 index 000000000..b89999f9a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/common/MigrationsLoader.js @@ -0,0 +1,36 @@ +const path = require('path'); +const DEFAULT_LOAD_EXTENSIONS = Object.freeze([ + '.co', + '.coffee', + '.eg', + '.iced', + '.js', + '.cjs', + '.litcoffee', + '.ls', + '.ts', +]); + +class AbstractMigrationsLoader { + constructor(migrationDirectories, sortDirsSeparately, loadExtensions) { + this.sortDirsSeparately = sortDirsSeparately; + + if (!Array.isArray(migrationDirectories)) { + migrationDirectories = [migrationDirectories]; + } + this.migrationsPaths = migrationDirectories; + this.loadExtensions = loadExtensions || DEFAULT_LOAD_EXTENSIONS; + } + + getFile(migrationsInfo) { + const absoluteDir = path.resolve(process.cwd(), migrationsInfo.directory); + const _path = path.join(absoluteDir, migrationsInfo.file); + const importFile = require('../util/import-file'); // late import + return importFile(_path); + } +} + +module.exports = { + DEFAULT_LOAD_EXTENSIONS, + AbstractMigrationsLoader, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/MigrationGenerator.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/MigrationGenerator.js new file mode 100644 index 000000000..bbab2e5fc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/MigrationGenerator.js @@ -0,0 +1,84 @@ +const path = require('path'); +const { writeJsFileUsingTemplate } = require('../util/template'); +const { getMergedConfig } = require('./migrator-configuration-merger'); +const { ensureDirectoryExists } = require('../util/fs'); +const { yyyymmddhhmmss } = require('../util/timestamp'); + +class MigrationGenerator { + constructor(migrationConfig, logger) { + this.config = getMergedConfig(migrationConfig, undefined, logger); + } + + // Creates a new migration, with a given name. + async make(name, config, logger) { + this.config = getMergedConfig(config, this.config, logger); + if (!name) { + return Promise.reject( + new Error('A name must be specified for the generated migration') + ); + } + await this._ensureFolder(); + const createdMigrationFilePath = await this._writeNewMigration(name); + return createdMigrationFilePath; + } + + // Ensures a folder for the migrations exist, dependent on the migration + // config settings. + _ensureFolder() { + const dirs = this._absoluteConfigDirs(); + + const promises = dirs.map(ensureDirectoryExists); + + return Promise.all(promises); + } + + _getStubPath() { + return ( + this.config.stub || + path.join(__dirname, 'stub', this.config.extension + '.stub') + ); + } + + _getNewMigrationName(name) { + if (name[0] === '-') name = name.slice(1); + return ( + yyyymmddhhmmss() + '_' + name + '.' + this.config.extension.split('-')[0] + ); + } + + _getNewMigrationPath(name) { + const fileName = this._getNewMigrationName(name); + const dirs = this._absoluteConfigDirs(); + const dir = dirs.slice(-1)[0]; // Get last specified directory + return path.join(dir, fileName); + } + + // Write a new migration to disk, using the config and generated filename, + // passing any `variables` given in the config to the template. + async _writeNewMigration(name) { + const migrationPath = this._getNewMigrationPath(name); + await writeJsFileUsingTemplate( + migrationPath, + this._getStubPath(), + { variable: 'd' }, + this.config.variables || {} + ); + return migrationPath; + } + + _absoluteConfigDirs() { + const directories = Array.isArray(this.config.directory) + ? this.config.directory + : [this.config.directory]; + return directories.map((directory) => { + if (!directory) { + console.warn( + 'Failed to resolve config file, knex cannot determine where to generate migrations' + ); + } + return path.resolve(process.cwd(), directory); + }); + } +} + +module.exports = MigrationGenerator; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/Migrator.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/Migrator.js new file mode 100644 index 000000000..10b27a487 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/Migrator.js @@ -0,0 +1,599 @@ +// Migrator +// ------- +const differenceWith = require('lodash/differenceWith'); +const get = require('lodash/get'); +const isEmpty = require('lodash/isEmpty'); +const max = require('lodash/max'); +const { + getLockTableName, + getTable, + getTableName, +} = require('./table-resolver'); +const { getSchemaBuilder } = require('./table-creator'); +const migrationListResolver = require('./migration-list-resolver'); +const MigrationGenerator = require('./MigrationGenerator'); +const { getMergedConfig } = require('./migrator-configuration-merger'); +const { isBoolean, isFunction } = require('../../util/is'); + +class LockError extends Error { + constructor(msg) { + super(msg); + this.name = 'MigrationLocked'; + } +} + +// The new migration we're performing, typically called from the `knex.migrate` +// interface on the main `knex` object. Passes the `knex` instance performing +// the migration. +class Migrator { + constructor(knex) { + // Clone knex instance and remove post-processing that is unnecessary for internal queries from a cloned config + if (isFunction(knex)) { + if (!knex.isTransaction) { + this.knex = knex.withUserParams({ + ...knex.userParams, + }); + } else { + this.knex = knex; + } + } else { + this.knex = Object.assign({}, knex); + this.knex.userParams = this.knex.userParams || {}; + } + + this.config = getMergedConfig( + this.knex.client.config.migrations, + undefined, + this.knex.client.logger + ); + this.generator = new MigrationGenerator( + this.knex.client.config.migrations, + this.knex.client.logger + ); + this._activeMigration = { + fileName: null, + }; + } + + // Migrators to the latest configuration. + async latest(config) { + this._disableProcessing(); + this.config = getMergedConfig(config, this.config, this.knex.client.logger); + + const allAndCompleted = await migrationListResolver.listAllAndCompleted( + this.config, + this.knex + ); + + if (!this.config.disableMigrationsListValidation) { + validateMigrationList(this.config.migrationSource, allAndCompleted); + } + + const [all, completed] = allAndCompleted; + + const migrations = getNewMigrations( + this.config.migrationSource, + all, + completed + ); + + const transactionForAll = + !this.config.disableTransactions && + !( + await Promise.all( + migrations.map(async (migration) => { + const migrationContents = + await this.config.migrationSource.getMigration(migration); + return !this._useTransaction(migrationContents); + }) + ) + ).some((isTransactionUsed) => isTransactionUsed); + + if (transactionForAll) { + return this.knex.transaction((trx) => { + return this._runBatch(migrations, 'up', trx); + }); + } else { + return this._runBatch(migrations, 'up'); + } + } + + // Runs the next migration that has not yet been run + async up(config) { + this._disableProcessing(); + this.config = getMergedConfig(config, this.config, this.knex.client.logger); + + const allAndCompleted = await migrationListResolver.listAllAndCompleted( + this.config, + this.knex + ); + + if (!this.config.disableMigrationsListValidation) { + validateMigrationList(this.config.migrationSource, allAndCompleted); + } + const [all, completed] = allAndCompleted; + + const newMigrations = getNewMigrations( + this.config.migrationSource, + all, + completed + ); + + let migrationToRun; + const name = this.config.name; + if (name) { + if (!completed.includes(name)) { + migrationToRun = newMigrations.find((migration) => { + return ( + this.config.migrationSource.getMigrationName(migration) === name + ); + }); + if (!migrationToRun) { + throw new Error(`Migration "${name}" not found.`); + } + } + } else { + migrationToRun = newMigrations[0]; + } + + const useTransaction = + !migrationToRun || + this._useTransaction( + await this.config.migrationSource.getMigration(migrationToRun) + ); + + const migrationsToRun = []; + if (migrationToRun) { + migrationsToRun.push(migrationToRun); + } + + const transactionForAll = + !this.config.disableTransactions && (!migrationToRun || useTransaction); + + if (transactionForAll) { + return await this.knex.transaction((trx) => { + return this._runBatch(migrationsToRun, 'up', trx); + }); + } else { + return await this._runBatch(migrationsToRun, 'up'); + } + } + + // Rollback the last "batch", or all, of migrations that were run. + rollback(config, all = false) { + this._disableProcessing(); + return new Promise((resolve, reject) => { + try { + this.config = getMergedConfig( + config, + this.config, + this.knex.client.logger + ); + } catch (e) { + reject(e); + } + migrationListResolver + .listAllAndCompleted(this.config, this.knex) + .then((value) => { + if (!this.config.disableMigrationsListValidation) { + validateMigrationList(this.config.migrationSource, value); + } + return value; + }) + .then((val) => { + const [allMigrations, completedMigrations] = val; + + return all + ? allMigrations + .filter((migration) => { + return completedMigrations + .map((migration) => migration.name) + .includes( + this.config.migrationSource.getMigrationName(migration) + ); + }) + .reverse() + : this._getLastBatch(val); + }) + .then((migrations) => { + return this._runBatch(migrations, 'down'); + }) + .then(resolve, reject); + }); + } + + down(config) { + this._disableProcessing(); + this.config = getMergedConfig(config, this.config, this.knex.client.logger); + + return migrationListResolver + .listAllAndCompleted(this.config, this.knex) + .then((value) => { + if (!this.config.disableMigrationsListValidation) { + validateMigrationList(this.config.migrationSource, value); + } + return value; + }) + .then(([all, completed]) => { + const completedMigrations = all.filter((migration) => { + return completed + .map((migration) => migration.name) + .includes(this.config.migrationSource.getMigrationName(migration)); + }); + + let migrationToRun; + const name = this.config.name; + if (name) { + migrationToRun = completedMigrations.find((migration) => { + return ( + this.config.migrationSource.getMigrationName(migration) === name + ); + }); + if (!migrationToRun) { + throw new Error(`Migration "${name}" was not run.`); + } + } else { + migrationToRun = completedMigrations[completedMigrations.length - 1]; + } + + const migrationsToRun = []; + if (migrationToRun) { + migrationsToRun.push(migrationToRun); + } + + return this._runBatch(migrationsToRun, 'down'); + }); + } + + status(config) { + this._disableProcessing(); + this.config = getMergedConfig(config, this.config, this.knex.client.logger); + + return Promise.all([ + getTable(this.knex, this.config.tableName, this.config.schemaName).select( + '*' + ), + migrationListResolver.listAll(this.config.migrationSource), + ]).then(([db, code]) => db.length - code.length); + } + + // Retrieves and returns the current migration version we're on, as a promise. + // If no migrations have been run yet, return "none". + currentVersion(config) { + this._disableProcessing(); + this.config = getMergedConfig(config, this.config, this.knex.client.logger); + + return migrationListResolver + .listCompleted(this.config.tableName, this.config.schemaName, this.knex) + .then((completed) => { + const val = max(completed.map((value) => value.name.split('_')[0])); + return val === undefined ? 'none' : val; + }); + } + + // list all migrations + async list(config) { + this._disableProcessing(); + this.config = getMergedConfig(config, this.config, this.knex.client.logger); + + const [all, completed] = await migrationListResolver.listAllAndCompleted( + this.config, + this.knex + ); + + if (!this.config.disableMigrationsListValidation) { + validateMigrationList(this.config.migrationSource, [all, completed]); + } + + const newMigrations = getNewMigrations( + this.config.migrationSource, + all, + completed + ); + return [completed, newMigrations]; + } + + async forceFreeMigrationsLock(config) { + this._disableProcessing(); + this.config = getMergedConfig(config, this.config, this.knex.client.logger); + const { schemaName, tableName } = this.config; + const lockTableName = getLockTableName(tableName); + const { knex } = this; + const getLockTable = () => getTable(knex, lockTableName, schemaName); + const tableExists = await getSchemaBuilder(knex, schemaName).hasTable( + lockTableName + ); + if (tableExists) { + await getLockTable().del(); + await getLockTable().insert({ + is_locked: 0, + }); + } + } + + // Creates a new migration, with a given name. + make(name, config) { + return this.generator.make(name, config, this.knex.client.logger); + } + + _disableProcessing() { + if (this.knex.disableProcessing) { + this.knex.disableProcessing(); + } + } + + _lockMigrations(trx) { + const tableName = getLockTableName(this.config.tableName); + return getTable(this.knex, tableName, this.config.schemaName) + .transacting(trx) + .where('is_locked', '=', 0) + .update({ is_locked: 1 }) + .then((rowCount) => { + if (rowCount !== 1) { + throw new Error('Migration table is already locked'); + } + }); + } + + _getLock(trx) { + const transact = trx ? (fn) => fn(trx) : (fn) => this.knex.transaction(fn); + return transact((trx) => { + return this._lockMigrations(trx); + }).catch((err) => { + throw new LockError(err.message); + }); + } + + _freeLock(trx = this.knex) { + const tableName = getLockTableName(this.config.tableName); + return getTable(trx, tableName, this.config.schemaName).update({ + is_locked: 0, + }); + } + + // Run a batch of current migrations, in sequence. + async _runBatch(migrations, direction, trx) { + const canGetLockInTransaction = + this.knex.client.driverName !== 'cockroachdb'; + try { + await this._getLock(canGetLockInTransaction ? trx : undefined); + // When there is a wrapping transaction, some migrations + // could have been done while waiting for the lock: + const completed = trx + ? await migrationListResolver.listCompleted( + this.config.tableName, + this.config.schemaName, + trx + ) + : []; + + migrations = getNewMigrations( + this.config.migrationSource, + migrations, + completed + ); + + await Promise.all( + migrations.map(this._validateMigrationStructure.bind(this)) + ); + + let batchNo = await this._latestBatchNumber(trx); + if (direction === 'up') batchNo++; + const res = await this._waterfallBatch( + batchNo, + migrations, + direction, + trx + ); + await this._freeLock(canGetLockInTransaction ? trx : undefined); + return res; + } catch (error) { + let cleanupReady = Promise.resolve(); + + if (error instanceof LockError) { + // If locking error do not free the lock. + this.knex.client.logger.warn( + `Can't take lock to run migrations: ${error.message}` + ); + this.knex.client.logger.warn( + 'If you are sure migrations are not running you can release the ' + + "lock manually by running 'knex migrate:unlock'" + ); + } else { + if (this._activeMigration.fileName) { + this.knex.client.logger.warn( + `migration file "${this._activeMigration.fileName}" failed` + ); + } + this.knex.client.logger.warn( + `migration failed with error: ${error.message}` + ); + // If the error was not due to a locking issue, then remove the lock. + cleanupReady = this._freeLock( + canGetLockInTransaction ? trx : undefined + ); + } + + try { + await cleanupReady; + // eslint-disable-next-line no-empty + } catch (e) {} + throw error; + } + } + + // Validates some migrations by requiring and checking for an `up` and `down` + // function. + async _validateMigrationStructure(migration) { + const migrationName = + this.config.migrationSource.getMigrationName(migration); + // maybe promise + const migrationContent = await this.config.migrationSource.getMigration( + migration + ); + if ( + typeof migrationContent.up !== 'function' || + typeof migrationContent.down !== 'function' + ) { + throw new Error( + `Invalid migration: ${migrationName} must have both an up and down function` + ); + } + + return migration; + } + + // Get the last batch of migrations, by name, ordered by insert id in reverse + // order. + async _getLastBatch([allMigrations]) { + const { tableName, schemaName } = this.config; + const migrationNames = await getTable(this.knex, tableName, schemaName) + .where('batch', function (qb) { + qb.max('batch').from(getTableName(tableName, schemaName)); + }) + .orderBy('id', 'desc'); + + const lastBatchMigrations = migrationNames.map((migration) => { + return allMigrations.find((entry) => { + return ( + this.config.migrationSource.getMigrationName(entry) === migration.name + ); + }); + }); + return Promise.all(lastBatchMigrations); + } + + // Returns the latest batch number. + _latestBatchNumber(trx = this.knex) { + return trx + .from(getTableName(this.config.tableName, this.config.schemaName)) + .max('batch as max_batch') + .then((obj) => obj[0].max_batch || 0); + } + + // If transaction config for a single migration is defined, use that. + // Otherwise, rely on the common config. This allows enabling/disabling + // transaction for a single migration at will, regardless of the common + // config. + _useTransaction(migrationContent, allTransactionsDisabled) { + const singleTransactionValue = get(migrationContent, 'config.transaction'); + + return isBoolean(singleTransactionValue) + ? singleTransactionValue + : !allTransactionsDisabled; + } + + // Runs a batch of `migrations` in a specified `direction`, saving the + // appropriate database information as the migrations are run. + _waterfallBatch(batchNo, migrations, direction, trx) { + const trxOrKnex = trx || this.knex; + const { tableName, schemaName, disableTransactions } = this.config; + let current = Promise.resolve(); + const log = []; + migrations.forEach((migration) => { + const name = this.config.migrationSource.getMigrationName(migration); + this._activeMigration.fileName = name; + const migrationContent = + this.config.migrationSource.getMigration(migration); + + // We're going to run each of the migrations in the current "up". + current = current + .then(async () => await migrationContent) //maybe promise + .then((migrationContent) => { + this._activeMigration.fileName = name; + if ( + !trx && + this._useTransaction(migrationContent, disableTransactions) + ) { + this.knex.enableProcessing(); + return this._transaction( + this.knex, + migrationContent, + direction, + name + ); + } + + trxOrKnex.enableProcessing(); + return checkPromise( + this.knex.client.logger, + migrationContent[direction](trxOrKnex), + name + ); + }) + .then(() => { + trxOrKnex.disableProcessing(); + this.knex.disableProcessing(); + log.push(name); + if (direction === 'up') { + return trxOrKnex.into(getTableName(tableName, schemaName)).insert({ + name, + batch: batchNo, + migration_time: new Date(), + }); + } + if (direction === 'down') { + return trxOrKnex + .from(getTableName(tableName, schemaName)) + .where({ name }) + .del(); + } + }); + }); + + return current.then(() => [batchNo, log]); + } + + _transaction(knex, migrationContent, direction, name) { + return knex.transaction((trx) => { + return checkPromise( + knex.client.logger, + migrationContent[direction](trx), + name, + () => { + trx.commit(); + } + ); + }); + } +} + +// Validates that migrations are present in the appropriate directories. +function validateMigrationList(migrationSource, migrations) { + const [all, completed] = migrations; + const diff = getMissingMigrations(migrationSource, completed, all); + if (!isEmpty(diff)) { + const names = diff.map((d) => d.name); + throw new Error( + `The migration directory is corrupt, the following files are missing: ${names.join( + ', ' + )}` + ); + } +} + +function getMissingMigrations(migrationSource, completed, all) { + return differenceWith(completed, all, (c, a) => { + return c.name === migrationSource.getMigrationName(a); + }); +} + +function getNewMigrations(migrationSource, all, completed) { + return differenceWith(all, completed, (a, c) => { + return c.name === migrationSource.getMigrationName(a); + }); +} + +function checkPromise(logger, migrationPromise, name, commitFn) { + if (!migrationPromise || typeof migrationPromise.then !== 'function') { + logger.warn(`migration ${name} did not return a promise`); + if (commitFn) { + commitFn(); + } + } + return migrationPromise; +} + +module.exports = { + Migrator, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/migrate-stub.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/migrate-stub.js new file mode 100644 index 000000000..cd3e4ef44 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/migrate-stub.js @@ -0,0 +1,17 @@ +// Stub Migrate: +// Used for now in browser builds, where filesystem access isn't +// available. +const StubMigrate = (module.exports = function () {}); + +const noSuchMethod = async function () { + throw new Error('Migrations are not supported'); +}; + +StubMigrate.prototype = { + make: noSuchMethod, + latest: noSuchMethod, + rollback: noSuchMethod, + currentVersion: noSuchMethod, + up: noSuchMethod, + down: noSuchMethod, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/migration-list-resolver.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/migration-list-resolver.js new file mode 100644 index 000000000..873ad20b6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/migration-list-resolver.js @@ -0,0 +1,33 @@ +const { getTableName } = require('./table-resolver'); +const { ensureTable } = require('./table-creator'); + +// Lists all available migration versions, as a sorted array. +function listAll(migrationSource, loadExtensions) { + return migrationSource.getMigrations(loadExtensions); +} + +// Lists all migrations that have been completed for the current db, as an +// array. +async function listCompleted(tableName, schemaName, trxOrKnex) { + await ensureTable(tableName, schemaName, trxOrKnex); + + return await trxOrKnex + .from(getTableName(tableName, schemaName)) + .orderBy('id') + .select('name'); +} + +// Gets the migration list from the migration directory specified in config, as well as +// the list of completed migrations to check what should be run. +function listAllAndCompleted(config, trxOrKnex) { + return Promise.all([ + listAll(config.migrationSource, config.loadExtensions), + listCompleted(config.tableName, config.schemaName, trxOrKnex), + ]); +} + +module.exports = { + listAll, + listAllAndCompleted, + listCompleted, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/migrator-configuration-merger.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/migrator-configuration-merger.js new file mode 100644 index 000000000..aa6586933 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/migrator-configuration-merger.js @@ -0,0 +1,58 @@ +const { FsMigrations } = require('./sources/fs-migrations'); +const Logger = require('../../logger'); +const { DEFAULT_LOAD_EXTENSIONS } = require('../common/MigrationsLoader'); +const defaultLogger = new Logger(); + +const CONFIG_DEFAULT = Object.freeze({ + extension: 'js', + loadExtensions: DEFAULT_LOAD_EXTENSIONS, + tableName: 'knex_migrations', + schemaName: null, + directory: './migrations', + disableTransactions: false, + disableMigrationsListValidation: false, + sortDirsSeparately: false, +}); + +function getMergedConfig(config, currentConfig, logger = defaultLogger) { + // config is the user specified config, mergedConfig has defaults and current config + // applied to it. + const mergedConfig = Object.assign( + {}, + CONFIG_DEFAULT, + currentConfig || {}, + config + ); + + if ( + config && + // If user specifies any FS related config, + // clear specified migrationSource to avoid ambiguity + (config.directory || + config.sortDirsSeparately !== undefined || + config.loadExtensions) + ) { + if (config.migrationSource) { + logger.warn( + 'FS-related option specified for migration configuration. This resets migrationSource to default FsMigrations' + ); + } + mergedConfig.migrationSource = null; + } + + // If the user has not specified any configs, we need to + // default to fs migrations to maintain compatibility + if (!mergedConfig.migrationSource) { + mergedConfig.migrationSource = new FsMigrations( + mergedConfig.directory, + mergedConfig.sortDirsSeparately, + mergedConfig.loadExtensions + ); + } + + return mergedConfig; +} + +module.exports = { + getMergedConfig, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/sources/fs-migrations.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/sources/fs-migrations.js new file mode 100644 index 000000000..a72b3242f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/sources/fs-migrations.js @@ -0,0 +1,74 @@ +const path = require('path'); +const sortBy = require('lodash/sortBy'); + +const { readdir } = require('../../util/fs'); +const { AbstractMigrationsLoader } = require('../../common/MigrationsLoader'); + +class FsMigrations extends AbstractMigrationsLoader { + /** + * Gets the migration names + * @returns Promise + */ + getMigrations(loadExtensions) { + // Get a list of files in all specified migration directories + const readMigrationsPromises = this.migrationsPaths.map((configDir) => { + const absoluteDir = path.resolve(process.cwd(), configDir); + return readdir(absoluteDir).then((files) => ({ + files, + configDir, + absoluteDir, + })); + }); + + return Promise.all(readMigrationsPromises).then((allMigrations) => { + const migrations = allMigrations.reduce((acc, migrationDirectory) => { + // When true, files inside the folder should be sorted + if (this.sortDirsSeparately) { + migrationDirectory.files = migrationDirectory.files.sort(); + } + + migrationDirectory.files.forEach((file) => + acc.push({ file, directory: migrationDirectory.configDir }) + ); + + return acc; + }, []); + + // If true we have already sorted the migrations inside the folders + // return the migrations fully qualified + if (this.sortDirsSeparately) { + return filterMigrations( + this, + migrations, + loadExtensions || this.loadExtensions + ); + } + + return filterMigrations( + this, + sortBy(migrations, 'file'), + loadExtensions || this.loadExtensions + ); + }); + } + + getMigrationName(migration) { + return migration.file; + } + + getMigration(migrationInfo) { + return this.getFile(migrationInfo); + } +} + +function filterMigrations(migrationSource, migrations, loadExtensions) { + return migrations.filter((migration) => { + const migrationName = migrationSource.getMigrationName(migration); + const extension = path.extname(migrationName); + return loadExtensions.includes(extension); + }); +} + +module.exports = { + FsMigrations, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/cjs.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/cjs.stub new file mode 100644 index 000000000..dfae79b95 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/cjs.stub @@ -0,0 +1,15 @@ + +exports.up = function(knex) { + <% if (d.tableName) { %> + return knex.schema.createTable("<%= d.tableName %>", function(t) { + t.increments(); + t.timestamp(); + }); + <% } %> +}; + +exports.down = function(knex) { + <% if (d.tableName) { %> + return knex.schema.dropTable("<%= d.tableName %>"); + <% } %> +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/coffee.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/coffee.stub new file mode 100644 index 000000000..7eff32fe9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/coffee.stub @@ -0,0 +1,13 @@ + +exports.up = (knex) -> + <% if (d.tableName) { %> + knex.schema.createTable "<%= d.tableName %>", (t) -> + t.increments() + t.timestamp() + <% } %> + + +exports.down = (knex) -> + <% if (d.tableName) { %> + knex.schema.dropTable "<%= d.tableName %>" + <% } %> diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/eg.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/eg.stub new file mode 100644 index 000000000..cbf60a389 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/eg.stub @@ -0,0 +1,14 @@ +provide: up, down + +up = (knex) -> + <% if (d.tableName) { %> + knex.schema.createTable "<%= d.tableName %>": t -> + t.increments() + t.timestamp() + <% } %> + + +down = (knex) -> + <% if (d.tableName) { %> + knex.schema.dropTable("<%= d.tableName %>") + <% } %> diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/js-schema.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/js-schema.stub new file mode 100644 index 000000000..bf8d27434 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/js-schema.stub @@ -0,0 +1,22 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = function({schema}) { + <% if (d.tableName) { %> + return schema.createTable("<%= d.tableName %>", function(t) { + t.increments(); + t.timestamp(); + }); + <% } %> +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = function({schema}) { + <% if (d.tableName) { %> + return schema.dropTable("<%= d.tableName %>"); + <% } %> +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/js.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/js.stub new file mode 100644 index 000000000..566e2f594 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/js.stub @@ -0,0 +1,22 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = function(knex) { + <% if (d.tableName) { %> + return knex.schema.createTable("<%= d.tableName %>", function(t) { + t.increments(); + t.timestamp(); + }); + <% } %> +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = function(knex) { + <% if (d.tableName) { %> + return knex.schema.dropTable("<%= d.tableName %>"); + <% } %> +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-coffee.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-coffee.stub new file mode 100644 index 000000000..3de69488b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-coffee.stub @@ -0,0 +1,34 @@ +# Update with your config settings. + +module.exports = + + development: + client: 'sqlite3' + connection: + filename: './dev.sqlite3' + migrations: + tableName: 'knex_migrations' + + staging: + client: 'postgresql' + connection: + database: 'my_db' + user: 'username' + password: 'password' + pool: + min: 2 + max: 10 + migrations: + tableName: 'knex_migrations' + + production: + client: 'postgresql' + connection: + database: 'my_db' + user: 'username' + password: 'password' + pool: + min: 2 + max: 10 + migrations: + tableName: 'knex_migrations' diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-eg.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-eg.stub new file mode 100644 index 000000000..3b1af23e3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-eg.stub @@ -0,0 +1,43 @@ +;; Update with your config settings. + +module.exports = { + development = { + client = 'sqlite3' + connection = { + filename = './dev.sqlite3' + } + migrations = { + tableName = 'knex_migrations' + } + } + staging = { + client = 'postgresql' + connection = { + database = 'my_db' + user = 'username' + password = 'password' + } + pool = { + min = 2 + max = 10 + } + migrations = { + tableName = 'knex_migrations' + } + } + production = { + client = 'postgresql' + connection = { + database = 'my_db' + user = 'username' + password = 'password' + } + pool = { + min = 2 + max = 10 + } + migrations = { + tableName = 'knex_migrations' + } + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-js.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-js.stub new file mode 100644 index 000000000..565609eca --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-js.stub @@ -0,0 +1,47 @@ +// Update with your config settings. + +/** + * @type { Object. } + */ +module.exports = { + + development: { + client: 'sqlite3', + connection: { + filename: './dev.sqlite3' + } + }, + + staging: { + client: 'postgresql', + connection: { + database: 'my_db', + user: 'username', + password: 'password' + }, + pool: { + min: 2, + max: 10 + }, + migrations: { + tableName: 'knex_migrations' + } + }, + + production: { + client: 'postgresql', + connection: { + database: 'my_db', + user: 'username', + password: 'password' + }, + pool: { + min: 2, + max: 10 + }, + migrations: { + tableName: 'knex_migrations' + } + } + +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-ls.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-ls.stub new file mode 100644 index 000000000..2bb365721 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-ls.stub @@ -0,0 +1,35 @@ +# Update with your config settings. + +module.exports = + + development: + client: 'sqlite3' + connection: + filename: './dev.sqlite3' + migrations: + tableName: 'knex_migrations' + + staging: + client: 'postgresql' + connection: + database: 'my_db' + user: 'username' + password: 'password' + pool: + min: 2 + max: 10 + migrations: + tableName: 'knex_migrations' + + production: + client: 'postgresql' + connection: + database: 'my_db' + user: 'username' + password: 'password' + pool: + min: 2 + max: 10 + migrations: + tableName: 'knex_migrations' + diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-ts.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-ts.stub new file mode 100644 index 000000000..76618108f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/knexfile-ts.stub @@ -0,0 +1,47 @@ +import type { Knex } from "knex"; + +// Update with your config settings. + +const config: { [key: string]: Knex.Config } = { + development: { + client: "sqlite3", + connection: { + filename: "./dev.sqlite3" + } + }, + + staging: { + client: "postgresql", + connection: { + database: "my_db", + user: "username", + password: "password" + }, + pool: { + min: 2, + max: 10 + }, + migrations: { + tableName: "knex_migrations" + } + }, + + production: { + client: "postgresql", + connection: { + database: "my_db", + user: "username", + password: "password" + }, + pool: { + min: 2, + max: 10 + }, + migrations: { + tableName: "knex_migrations" + } + } + +}; + +module.exports = config; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/ls.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/ls.stub new file mode 100644 index 000000000..5dbe2194d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/ls.stub @@ -0,0 +1,14 @@ + +exports.up = (knex, Promise) -> + <% if (d.tableName) { %> + knex.schema.create-table "<%= d.tableName %>", (t) -> + t.increments! + t.timestamp! + <% } %> + + +exports.down = (knex, Promise) -> + <% if (d.tableName) { %> + knex.schema.drop-table "<%= d.tableName %>" + <% } %> + diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/mjs.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/mjs.stub new file mode 100644 index 000000000..7dd520fe4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/mjs.stub @@ -0,0 +1,23 @@ + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +export const up = async (knex) => { + <% if (d.tableName) { %> + await knex.schema.createTable("<%= d.tableName %>", function(t) { + t.increments(); + t.timestamp(); + }); + <% } %> +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +export const down = async (knex) => { + <% if (d.tableName) { %> + await knex.schema.dropTable("<%= d.tableName %>"); + <% } %> +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/ts-schema.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/ts-schema.stub new file mode 100644 index 000000000..850d1bfca --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/ts-schema.stub @@ -0,0 +1,21 @@ +import { Knex } from "knex"; + +<% if (d.tableName) { %> +export async function up({schema}: Knex): Promise { + return schema.createTable("<%= d.tableName %>", (t) => { + t.increments(); + t.timestamps(); + }); +} +<% } else { %> +export async function up({schema}: Knex): Promise { +} +<% } %> +<% if (d.tableName) { %> +export async function down({schema}: Knex): Promise { + return schema.dropTable("<%= d.tableName %>"); +} +<% } else { %> +export async function down({schema}: Knex): Promise { +} +<% } %> diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/ts.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/ts.stub new file mode 100644 index 000000000..c0c213fe9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/stub/ts.stub @@ -0,0 +1,21 @@ +import type { Knex } from "knex"; + +<% if (d.tableName) { %> +export async function up(knex: Knex): Promise { + return knex.schema.createTable("<%= d.tableName %>", (t) => { + t.increments(); + t.timestamps(); + }); +} +<% } else { %> +export async function up(knex: Knex): Promise { +} +<% } %> +<% if (d.tableName) { %> +export async function down(knex: Knex): Promise { + return knex.schema.dropTable("<%= d.tableName %>"); +} +<% } else { %> +export async function down(knex: Knex): Promise { +} +<% } %> diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/table-creator.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/table-creator.js new file mode 100644 index 000000000..4a6212828 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/table-creator.js @@ -0,0 +1,77 @@ +const { + getTable, + getLockTableName, + getLockTableNameWithSchema, + getTableName, +} = require('./table-resolver'); + +function ensureTable(tableName, schemaName, trxOrKnex) { + const lockTable = getLockTableName(tableName); + return getSchemaBuilder(trxOrKnex, schemaName) + .hasTable(tableName) + .then((exists) => { + return !exists && _createMigrationTable(tableName, schemaName, trxOrKnex); + }) + .then(() => { + return getSchemaBuilder(trxOrKnex, schemaName).hasTable(lockTable); + }) + .then((exists) => { + return ( + !exists && _createMigrationLockTable(lockTable, schemaName, trxOrKnex) + ); + }) + .then(() => { + return getTable(trxOrKnex, lockTable, schemaName).select('*'); + }) + .then((data) => { + return ( + !data.length && _insertLockRowIfNeeded(tableName, schemaName, trxOrKnex) + ); + }); +} + +function _createMigrationTable(tableName, schemaName, trxOrKnex) { + return getSchemaBuilder(trxOrKnex, schemaName).createTable( + getTableName(tableName), + function (t) { + t.increments(); + t.string('name'); + t.integer('batch'); + t.timestamp('migration_time'); + } + ); +} + +function _createMigrationLockTable(tableName, schemaName, trxOrKnex) { + return getSchemaBuilder(trxOrKnex, schemaName).createTable( + tableName, + function (t) { + t.increments('index').primary(); + t.integer('is_locked'); + } + ); +} + +function _insertLockRowIfNeeded(tableName, schemaName, trxOrKnex) { + const lockTableWithSchema = getLockTableNameWithSchema(tableName, schemaName); + return trxOrKnex + .select('*') + .from(lockTableWithSchema) + .then((data) => { + return !data.length + ? trxOrKnex.from(lockTableWithSchema).insert({ is_locked: 0 }) + : null; + }); +} + +//Get schema-aware schema builder for a given schema nam +function getSchemaBuilder(trxOrKnex, schemaName) { + return schemaName + ? trxOrKnex.schema.withSchema(schemaName) + : trxOrKnex.schema; +} + +module.exports = { + ensureTable, + getSchemaBuilder, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/table-resolver.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/table-resolver.js new file mode 100644 index 000000000..d8a4def3f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/migrate/table-resolver.js @@ -0,0 +1,27 @@ +//Get schema-aware table name +function getTableName(tableName, schemaName) { + return schemaName ? `${schemaName}.${tableName}` : tableName; +} + +//Get schema-aware query builder for a given table and schema name +function getTable(trxOrKnex, tableName, schemaName) { + return schemaName + ? trxOrKnex(tableName).withSchema(schemaName) + : trxOrKnex(tableName); +} +function getLockTableName(tableName) { + return tableName + '_lock'; +} + +function getLockTableNameWithSchema(tableName, schemaName) { + return schemaName + ? schemaName + '.' + getLockTableName(tableName) + : getLockTableName(tableName); +} + +module.exports = { + getLockTableName, + getLockTableNameWithSchema, + getTable, + getTableName, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/Seeder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/Seeder.js new file mode 100644 index 000000000..3c0c363e3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/Seeder.js @@ -0,0 +1,137 @@ +// Seeder +// ------- + +const path = require('path'); +const { ensureDirectoryExists } = require('../util/fs'); +const { writeJsFileUsingTemplate } = require('../util/template'); +const { yyyymmddhhmmss } = require('../util/timestamp'); +const { getMergedConfig } = require('./seeder-configuration-merger'); + +// The new seeds we're performing, typically called from the `knex.seed` +// interface on the main `knex` object. Passes the `knex` instance performing +// the seeds. +class Seeder { + constructor(knex) { + this.knex = knex; + this.config = this.resolveConfig(knex.client.config.seeds); + } + + // Runs seed files for the given environment. + async run(config) { + this.config = this.resolveConfig(config); + const files = await this.config.seedSource.getSeeds(this.config); + return this._runSeeds(files); + } + + // Creates a new seed file, with a given name. + async make(name, config) { + this.config = this.resolveConfig(config); + if (!name) + throw new Error('A name must be specified for the generated seed'); + await this._ensureFolder(config); + const seedPath = await this._writeNewSeed(name); + return seedPath; + } + + // Ensures a folder for the seeds exist, dependent on the + // seed config settings. + _ensureFolder() { + const dirs = this.config.seedSource._getConfigDirectories( + this.config.logger + ); + const promises = dirs.map(ensureDirectoryExists); + return Promise.all(promises); + } + + // Run seed files, in sequence. + async _runSeeds(seeds) { + for (const seed of seeds) { + await this._validateSeedStructure(seed); + } + return this._waterfallBatch(seeds); + } + + async _validateSeedStructure(filepath) { + const seed = await this.config.seedSource.getSeed(filepath); + if (typeof seed.seed !== 'function') { + throw new Error( + `Invalid seed file: ${filepath} must have a seed function` + ); + } + return filepath; + } + + _getStubPath() { + return ( + this.config.stub || + path.join(__dirname, 'stub', this.config.extension + '.stub') + ); + } + + _getNewStubFileName(name) { + if (name[0] === '-') name = name.slice(1); + + if (this.config.timestampFilenamePrefix === true) { + name = `${yyyymmddhhmmss()}_${name}`; + } + + return `${name}.${this.config.extension}`; + } + + _getNewStubFilePath(name) { + const fileName = this._getNewStubFileName(name); + const dirs = this.config.seedSource._getConfigDirectories( + this.config.logger + ); + const dir = dirs.slice(-1)[0]; // Get last specified directory + return path.join(dir, fileName); + } + + // Write a new seed to disk, using the config and generated filename, + // passing any `variables` given in the config to the template. + async _writeNewSeed(name) { + const seedPath = this._getNewStubFilePath(name); + await writeJsFileUsingTemplate( + seedPath, + this._getStubPath(), + { variable: 'd' }, + this.config.variables || {} + ); + return seedPath; + } + + async _listAll(config) { + this.config = this.resolveConfig(config); + return this.config.seedSource.getSeeds(this.config); + } + + // Runs a batch of seed files. + async _waterfallBatch(seeds) { + const { knex } = this; + const log = []; + for (const seedPath of seeds) { + const seed = await this.config.seedSource.getSeed(seedPath); + try { + await seed.seed(knex); + log.push(seedPath); + } catch (originalError) { + const error = new Error( + `Error while executing "${seedPath}" seed: ${originalError.message}` + ); + error.original = originalError; + error.stack = + error.stack.split('\n').slice(0, 2).join('\n') + + '\n' + + originalError.stack; + throw error; + } + } + return [log]; + } + + resolveConfig(config) { + return getMergedConfig(config, this.config, this.knex.client.logger); + } +} + +module.exports = Seeder; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/seed-stub.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/seed-stub.js new file mode 100644 index 000000000..9a0ce55e7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/seed-stub.js @@ -0,0 +1,13 @@ +// Stub Seed: +// Used for now in browser builds, where filesystem access isn't +// available. +const StubSeed = (module.exports = function () {}); + +const noSuchMethod = async function () { + throw new Error('Seeds are not supported'); +}; + +StubSeed.prototype = { + make: noSuchMethod, + run: noSuchMethod, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/seeder-configuration-merger.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/seeder-configuration-merger.js new file mode 100644 index 000000000..1ff4a6b61 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/seeder-configuration-merger.js @@ -0,0 +1,60 @@ +const { FsSeeds } = require('./sources/fs-seeds'); +const Logger = require('../../logger'); +const { DEFAULT_LOAD_EXTENSIONS } = require('../common/MigrationsLoader'); +const defaultLogger = new Logger(); + +const CONFIG_DEFAULT = Object.freeze({ + extension: 'js', + directory: './seeds', + loadExtensions: DEFAULT_LOAD_EXTENSIONS, + specific: null, + timestampFilenamePrefix: false, + recursive: false, + sortDirsSeparately: false, +}); + +function getMergedConfig(config, currentConfig, logger = defaultLogger) { + // config is the user specified config, mergedConfig has defaults and current config + // applied to it. + const mergedConfig = Object.assign( + {}, + CONFIG_DEFAULT, + currentConfig || {}, + config, + { + logger, + } + ); + + if ( + config && + // If user specifies any FS related config, + // clear specified migrationSource to avoid ambiguity + (config.directory || + config.sortDirsSeparately !== undefined || + config.loadExtensions) + ) { + if (config.seedSource) { + logger.warn( + 'FS-related option specified for seed configuration. This resets seedSource to default FsMigrations' + ); + } + mergedConfig.seedSource = null; + } + + // If the user has not specified any configs, we need to + // default to fs migrations to maintain compatibility + if (!mergedConfig.seedSource) { + mergedConfig.seedSource = new FsSeeds( + mergedConfig.directory, + mergedConfig.sortDirsSeparately, + mergedConfig.loadExtensions + ); + } + + return mergedConfig; +} + +module.exports = { + getMergedConfig, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/sources/fs-seeds.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/sources/fs-seeds.js new file mode 100644 index 000000000..912536e75 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/sources/fs-seeds.js @@ -0,0 +1,65 @@ +const path = require('path'); +const flatten = require('lodash/flatten'); +const includes = require('lodash/includes'); +const { AbstractMigrationsLoader } = require('../../common/MigrationsLoader'); +const { getFilepathsInFolder } = require('../../util/fs'); + +const filterByLoadExtensions = (extensions) => (value) => { + const extension = path.extname(value); + return includes(extensions, extension); +}; + +class FsSeeds extends AbstractMigrationsLoader { + _getConfigDirectories(logger) { + const directories = this.migrationsPaths; + return directories.map((directory) => { + if (!directory) { + logger.warn( + 'Empty value passed as a directory for Seeder, this is not supported.' + ); + } + return path.resolve(process.cwd(), directory); + }); + } + + async getSeeds(config) { + const { loadExtensions, recursive, specific } = config; + + const seeds = flatten( + await Promise.all( + this._getConfigDirectories(config.logger).map((d) => + getFilepathsInFolder(d, recursive) + ) + ) + ); + + // if true, each dir are already sorted + // (getFilepathsInFolderRecursively does this) + // if false, we need to sort all the seeds + let files = seeds.filter(filterByLoadExtensions(loadExtensions)); + if (!this.sortDirsSeparately) { + files.sort(); + } + + if (specific) { + files = files.filter((file) => path.basename(file) === specific); + if (files.length === 0) { + throw new Error( + `Invalid argument provided: the specific seed "${specific}" does not exist.` + ); + } + } + + return files; + } + + async getSeed(filepath) { + const importFile = require('../../util/import-file'); // late import + const seed = await importFile(filepath); + return seed; + } +} + +module.exports = { + FsSeeds, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/coffee.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/coffee.stub new file mode 100644 index 000000000..a8fd364d6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/coffee.stub @@ -0,0 +1,9 @@ +exports.seed = (knex) -> + knex('table_name').del() + .then () -> + # Inserts seed entries + knex('table_name').insert([ + {id: 1, colName: 'rowValue'} + {id: 2, colName: 'rowValue2'} + {id: 3, colName: 'rowValue3'} + ]) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/eg.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/eg.stub new file mode 100644 index 000000000..b64584660 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/eg.stub @@ -0,0 +1,11 @@ +provide: seed +seed = (knex) -> + ;; Deletes ALL existing entries + knex(.table_name).del() + .then(() -> + ;; Inserts seed entries + knex(.table_name).insert with [ + { id = 1, col-name = .row-value-1 } + { id = 2, col-name = .row-value-2 } + { id = 3, col-name = .row-value-3 } + ] diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/js.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/js.stub new file mode 100644 index 000000000..d0e654031 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/js.stub @@ -0,0 +1,13 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.seed = async function(knex) { + // Deletes ALL existing entries + await knex('table_name').del() + await knex('table_name').insert([ + {id: 1, colName: 'rowValue1'}, + {id: 2, colName: 'rowValue2'}, + {id: 3, colName: 'rowValue3'} + ]); +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/ls.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/ls.stub new file mode 100644 index 000000000..8dbf8acf3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/ls.stub @@ -0,0 +1,11 @@ +exports.seed = (knex) -> + # Deletes ALL existing entries + knex('table_name').del() + .then(() -> + # Inserts seed entries + knex('table_name').insert([ + {id: 1, colName: 'rowValue1'}, + {id: 2, colName: 'rowValue2'}, + {id: 3, colName: 'rowValue3'} + ]) + ) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/mjs.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/mjs.stub new file mode 100644 index 000000000..a324caee3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/mjs.stub @@ -0,0 +1,12 @@ + +export const seed = async (knex) => { + // Deletes ALL existing entries + await knex('table_name').del(); + + // Inserts seed entries + await knex('table_name').insert([ + {id: 1, colName: 'rowValue1'}, + {id: 2, colName: 'rowValue2'}, + {id: 3, colName: 'rowValue3'} + ]); +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/ts.stub b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/ts.stub new file mode 100644 index 000000000..a72588d24 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/seed/stub/ts.stub @@ -0,0 +1,13 @@ +import { Knex } from "knex"; + +export async function seed(knex: Knex): Promise { + // Deletes ALL existing entries + await knex("table_name").del(); + + // Inserts seed entries + await knex("table_name").insert([ + { id: 1, colName: "rowValue1" }, + { id: 2, colName: "rowValue2" }, + { id: 3, colName: "rowValue3" } + ]); +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/fs.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/fs.js new file mode 100644 index 000000000..02ad6f3bd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/fs.js @@ -0,0 +1,86 @@ +const fs = require('fs'); +const flatten = require('lodash/flatten'); +const os = require('os'); +const path = require('path'); +const { promisify } = require('util'); + +// Promisify common fs functions. +const stat = promisify(fs.stat); +const readFile = promisify(fs.readFile); +const writeFile = promisify(fs.writeFile); +const readdir = promisify(fs.readdir); +const mkdir = promisify(fs.mkdir); + +function existsSync(path) { + try { + fs.accessSync(path); + return true; + } catch (e) { + return false; + } +} + +/** + * Creates a temporary directory and returns it path. + * + * @returns {Promise} + */ +function createTemp() { + return promisify(fs.mkdtemp)(`${os.tmpdir()}${path.sep}`); +} + +/** + * Ensures the given path exists. + * - If the path already exist, it's fine - it does nothing. + * - If the path doesn't exist, it will create it. + * + * @param {string} path + * @returns {Promise} + */ +function ensureDirectoryExists(dir) { + return stat(dir).catch(() => mkdir(dir, { recursive: true })); +} + +/** + * Read a directory, + * sorting folders and files by alphabetically order. + * Can be browsed recursively. + * + * @param {string} dir + * The directory to analyse + * + * @param {boolean} recursive + * Browse directory recursively + * + * @returns {Promise<[string]>} + * All found files, concatenated to the current dir + */ +async function getFilepathsInFolder(dir, recursive = false) { + const pathsList = await readdir(dir); + return flatten( + await Promise.all( + pathsList.sort().map(async (currentPath) => { + const currentFile = path.resolve(dir, currentPath); + const statFile = await stat(currentFile); + if (statFile && statFile.isDirectory()) { + if (recursive) { + return await getFilepathsInFolder(currentFile, true); + } + return []; + } + return [currentFile]; + }) + ) + ); +} + +module.exports = { + existsSync, + stat, + readdir, + readFile, + writeFile, + createTemp, + ensureDirectoryExists, + getFilepathsInFolder, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/import-file.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/import-file.js new file mode 100644 index 000000000..3cbcac54c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/import-file.js @@ -0,0 +1,12 @@ +const isModuleType = require('./is-module-type'); + +/** + * imports 'mjs', else requires. + * NOTE: require me late! + * @param {string} filepath + */ +module.exports = async function importFile(filepath) { + return (await isModuleType(filepath)) + ? import(require('url').pathToFileURL(filepath)) + : require(filepath); +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/is-module-type.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/is-module-type.js new file mode 100644 index 000000000..88d3015a0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/is-module-type.js @@ -0,0 +1,9 @@ +const getPackageType = require('get-package-type'); + +module.exports = async function isModuleType(filepath) { + return ( + filepath.endsWith('.mjs') || + (!filepath.endsWith('.cjs') && + (await getPackageType(filepath)) === 'module') + ); +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/template.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/template.js new file mode 100644 index 000000000..bda3b8b2e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/template.js @@ -0,0 +1,52 @@ +const template = require('lodash/template'); + +const { readFile, writeFile } = require('./fs'); + +/** + * Light wrapper over lodash templates making it safer to be used with javascript source code. + * + * In particular, doesn't interfere with use of interpolated strings in javascript. + * + * @param {string} content Template source + * @param {_.TemplateOptions} options Template options + */ +const jsSourceTemplate = (content, options) => + template(content, { + interpolate: /<%=([\s\S]+?)%>/g, + ...options, + }); + +/** + * Compile the contents of specified (javascript) file as a lodash template + * + * @param {string} filePath Path of file to be used as template + * @param {_.TemplateOptions} options Lodash template options + */ +const jsFileTemplate = async (filePath, options) => { + const contentBuffer = await readFile(filePath); + return jsSourceTemplate(contentBuffer.toString(), options); +}; + +/** + * Write a javascript file using another file as a (lodash) template + * + * @param {string} targetFilePath + * @param {string} sourceFilePath + * @param {_.TemplateOptions} options options passed to lodash templates + */ +const writeJsFileUsingTemplate = async ( + targetFilePath, + sourceFilePath, + options, + variables +) => + writeFile( + targetFilePath, + (await jsFileTemplate(sourceFilePath, options))(variables) + ); + +module.exports = { + jsSourceTemplate, + jsFileTemplate, + writeJsFileUsingTemplate, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/timestamp.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/timestamp.js new file mode 100644 index 000000000..bc145ecd4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/migrations/util/timestamp.js @@ -0,0 +1,14 @@ +function yyyymmddhhmmss() { + const now = new Date(); + + return ( + now.getUTCFullYear().toString() + + (now.getUTCMonth() + 1).toString().padStart(2, '0') + + now.getUTCDate().toString().padStart(2, '0') + + now.getUTCHours().toString().padStart(2, '0') + + now.getUTCMinutes().toString().padStart(2, '0') + + now.getUTCSeconds().toString().padStart(2, '0') + ); +} + +module.exports = { yyyymmddhhmmss }; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/analytic.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/analytic.js new file mode 100644 index 000000000..94cde5d8b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/analytic.js @@ -0,0 +1,52 @@ +const assert = require('assert'); + +// Analytic +// ------- + +// The "Analytic" is an object holding any necessary info about a analytic function +// e.g row_number, rank, dense_rank, +class Analytic { + constructor(method, schema, alias, orderBy, partitions) { + this.schema = schema; + this.type = 'analytic'; + this.method = method; + this.order = orderBy || []; + this.partitions = partitions || []; + this.alias = alias; + this.and = this; + + this.grouping = 'columns'; + } + + partitionBy(column, direction) { + assert( + Array.isArray(column) || typeof column === 'string', + `The argument to an analytic partitionBy function must be either a string + or an array of string.` + ); + + if (Array.isArray(column)) { + this.partitions = this.partitions.concat(column); + } else { + this.partitions.push({ column: column, order: direction }); + } + return this; + } + + orderBy(column, direction) { + assert( + Array.isArray(column) || typeof column === 'string', + `The argument to an analytic orderBy function must be either a string + or an array of string.` + ); + + if (Array.isArray(column)) { + this.order = this.order.concat(column); + } else { + this.order.push({ column: column, order: direction }); + } + return this; + } +} + +module.exports = Analytic; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/constants.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/constants.js new file mode 100644 index 000000000..125001d9c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/constants.js @@ -0,0 +1,15 @@ +/** + * internal constants, do not use in application code + */ +module.exports = { + lockMode: { + forShare: 'forShare', + forUpdate: 'forUpdate', + forNoKeyUpdate: 'forNoKeyUpdate', + forKeyShare: 'forKeyShare', + }, + waitMode: { + skipLocked: 'skipLocked', + noWait: 'noWait', + }, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/joinclause.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/joinclause.js new file mode 100644 index 000000000..c696aa11c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/joinclause.js @@ -0,0 +1,270 @@ +const assert = require('assert'); + +// JoinClause +// ------- + +function getClauseFromArguments(compilerType, bool, first, operator, second) { + if (typeof first === 'function') { + return { + type: 'onWrapped', + value: first, + bool: bool, + }; + } + + switch (arguments.length) { + case 3: + return { type: 'onRaw', value: first, bool }; + case 4: + return { + type: compilerType, + column: first, + operator: '=', + value: operator, + bool, + }; + default: + return { + type: compilerType, + column: first, + operator, + value: second, + bool, + }; + } +} + +// The "JoinClause" is an object holding any necessary info about a join, +// including the type, and any associated tables & columns being joined. +class JoinClause { + constructor(table, type, schema) { + this.schema = schema; + this.table = table; + this.joinType = type; + this.and = this; + this.clauses = []; + } + + get or() { + return this._bool('or'); + } + + // Adds an "on" clause to the current join object. + on(first) { + if (typeof first === 'object' && typeof first.toSQL !== 'function') { + const keys = Object.keys(first); + let i = -1; + const method = this._bool() === 'or' ? 'orOn' : 'on'; + while (++i < keys.length) { + this[method](keys[i], first[keys[i]]); + } + return this; + } + + const data = getClauseFromArguments('onBasic', this._bool(), ...arguments); + + if (data) { + this.clauses.push(data); + } + + return this; + } + + // Adds an "or on" clause to the current join object. + orOn(first, operator, second) { + return this._bool('or').on.apply(this, arguments); + } + + onJsonPathEquals(columnFirst, jsonPathFirst, columnSecond, jsonPathSecond) { + this.clauses.push({ + type: 'onJsonPathEquals', + columnFirst: columnFirst, + jsonPathFirst: jsonPathFirst, + columnSecond: columnSecond, + jsonPathSecond: jsonPathSecond, + bool: this._bool(), + not: this._not(), + }); + return this; + } + + orOnJsonPathEquals(columnFirst, jsonPathFirst, columnSecond, jsonPathSecond) { + return this._bool('or').onJsonPathEquals.apply(this, arguments); + } + + // Adds a "using" clause to the current join. + using(column) { + return this.clauses.push({ type: 'onUsing', column, bool: this._bool() }); + } + + onVal(first) { + if (typeof first === 'object' && typeof first.toSQL !== 'function') { + const keys = Object.keys(first); + let i = -1; + const method = this._bool() === 'or' ? 'orOnVal' : 'onVal'; + while (++i < keys.length) { + this[method](keys[i], first[keys[i]]); + } + return this; + } + + const data = getClauseFromArguments('onVal', this._bool(), ...arguments); + + if (data) { + this.clauses.push(data); + } + + return this; + } + + andOnVal() { + return this.onVal(...arguments); + } + + orOnVal() { + return this._bool('or').onVal(...arguments); + } + + onBetween(column, values) { + assert( + Array.isArray(values), + 'The second argument to onBetween must be an array.' + ); + assert( + values.length === 2, + 'You must specify 2 values for the onBetween clause' + ); + this.clauses.push({ + type: 'onBetween', + column, + value: values, + bool: this._bool(), + not: this._not(), + }); + return this; + } + + onNotBetween(column, values) { + return this._not(true).onBetween(column, values); + } + + orOnBetween(column, values) { + return this._bool('or').onBetween(column, values); + } + + orOnNotBetween(column, values) { + return this._bool('or')._not(true).onBetween(column, values); + } + + onIn(column, values) { + if (Array.isArray(values) && values.length === 0) return this.on(1, '=', 0); + this.clauses.push({ + type: 'onIn', + column, + value: values, + not: this._not(), + bool: this._bool(), + }); + return this; + } + + onNotIn(column, values) { + return this._not(true).onIn(column, values); + } + + orOnIn(column, values) { + return this._bool('or').onIn(column, values); + } + + orOnNotIn(column, values) { + return this._bool('or')._not(true).onIn(column, values); + } + + onNull(column) { + this.clauses.push({ + type: 'onNull', + column, + not: this._not(), + bool: this._bool(), + }); + return this; + } + + orOnNull(callback) { + return this._bool('or').onNull(callback); + } + + onNotNull(callback) { + return this._not(true).onNull(callback); + } + + orOnNotNull(callback) { + return this._not(true)._bool('or').onNull(callback); + } + + onExists(callback) { + this.clauses.push({ + type: 'onExists', + value: callback, + not: this._not(), + bool: this._bool(), + }); + return this; + } + + orOnExists(callback) { + return this._bool('or').onExists(callback); + } + + onNotExists(callback) { + return this._not(true).onExists(callback); + } + + orOnNotExists(callback) { + return this._not(true)._bool('or').onExists(callback); + } + + // Explicitly set the type of join, useful within a function when creating a grouped join. + type(type) { + this.joinType = type; + return this; + } + + _bool(bool) { + if (arguments.length === 1) { + this._boolFlag = bool; + return this; + } + const ret = this._boolFlag || 'and'; + this._boolFlag = 'and'; + return ret; + } + + _not(val) { + if (arguments.length === 1) { + this._notFlag = val; + return this; + } + const ret = this._notFlag; + this._notFlag = false; + return ret; + } +} + +Object.assign(JoinClause.prototype, { + grouping: 'join', +}); + +JoinClause.prototype.andOn = JoinClause.prototype.on; +JoinClause.prototype.andOnIn = JoinClause.prototype.onIn; +JoinClause.prototype.andOnNotIn = JoinClause.prototype.onNotIn; +JoinClause.prototype.andOnNull = JoinClause.prototype.onNull; +JoinClause.prototype.andOnNotNull = JoinClause.prototype.onNotNull; +JoinClause.prototype.andOnExists = JoinClause.prototype.onExists; +JoinClause.prototype.andOnNotExists = JoinClause.prototype.onNotExists; +JoinClause.prototype.andOnBetween = JoinClause.prototype.onBetween; +JoinClause.prototype.andOnNotBetween = JoinClause.prototype.onNotBetween; +JoinClause.prototype.andOnJsonPathEquals = + JoinClause.prototype.onJsonPathEquals; + +module.exports = JoinClause; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/method-constants.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/method-constants.js new file mode 100644 index 000000000..afafe07bd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/method-constants.js @@ -0,0 +1,136 @@ +// All properties we can use to start a query chain +// from the `knex` object, e.g. `knex.select('*').from(...` +module.exports = [ + 'with', + 'withRecursive', + 'withMaterialized', + 'withNotMaterialized', + 'select', + 'as', + 'columns', + 'column', + 'from', + 'fromJS', + 'fromRaw', + 'into', + 'withSchema', + 'table', + 'distinct', + 'join', + 'joinRaw', + 'innerJoin', + 'leftJoin', + 'leftOuterJoin', + 'rightJoin', + 'rightOuterJoin', + 'outerJoin', + 'fullOuterJoin', + 'crossJoin', + 'where', + 'andWhere', + 'orWhere', + 'whereNot', + 'orWhereNot', + 'whereLike', + 'andWhereLike', + 'orWhereLike', + 'whereILike', + 'andWhereILike', + 'orWhereILike', + 'whereRaw', + 'whereWrapped', + 'havingWrapped', + 'orWhereRaw', + 'whereExists', + 'orWhereExists', + 'whereNotExists', + 'orWhereNotExists', + 'whereIn', + 'orWhereIn', + 'whereNotIn', + 'orWhereNotIn', + 'whereNull', + 'orWhereNull', + 'whereNotNull', + 'orWhereNotNull', + 'whereBetween', + 'whereNotBetween', + 'andWhereBetween', + 'andWhereNotBetween', + 'orWhereBetween', + 'orWhereNotBetween', + 'groupBy', + 'groupByRaw', + 'orderBy', + 'orderByRaw', + 'union', + 'unionAll', + 'intersect', + 'except', + 'having', + 'havingRaw', + 'orHaving', + 'orHavingRaw', + 'offset', + 'limit', + 'count', + 'countDistinct', + 'min', + 'max', + 'sum', + 'sumDistinct', + 'avg', + 'avgDistinct', + 'increment', + 'decrement', + 'first', + 'debug', + 'pluck', + 'clearSelect', + 'clearWhere', + 'clearGroup', + 'clearOrder', + 'clearHaving', + 'insert', + 'update', + 'returning', + 'del', + 'delete', + 'truncate', + 'transacting', + 'connection', + + // JSON methods + + // Json manipulation functions + 'jsonExtract', + 'jsonSet', + 'jsonInsert', + 'jsonRemove', + + // Wheres Json + 'whereJsonObject', + 'orWhereJsonObject', + 'andWhereJsonObject', + 'whereNotJsonObject', + 'orWhereNotJsonObject', + 'andWhereNotJsonObject', + + 'whereJsonPath', + 'orWhereJsonPath', + 'andWhereJsonPath', + + 'whereJsonSupersetOf', + 'orWhereJsonSupersetOf', + 'andWhereJsonSupersetOf', + 'whereJsonNotSupersetOf', + 'orWhereJsonNotSupersetOf', + 'andWhereJsonNotSupersetOf', + + 'whereJsonSubsetOf', + 'orWhereJsonSubsetOf', + 'andWhereJsonSubsetOf', + 'whereJsonNotSubsetOf', + 'orWhereJsonNotSubsetOf', + 'andWhereJsonNotSubsetOf', +]; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/querybuilder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/querybuilder.js new file mode 100644 index 000000000..0d3cff51d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/querybuilder.js @@ -0,0 +1,1793 @@ +// Builder +// ------- +const assert = require('assert'); +const { EventEmitter } = require('events'); +const assign = require('lodash/assign'); +const clone = require('lodash/clone'); +const each = require('lodash/each'); +const isEmpty = require('lodash/isEmpty'); +const isPlainObject = require('lodash/isPlainObject'); +const last = require('lodash/last'); +const reject = require('lodash/reject'); +const tail = require('lodash/tail'); +const toArray = require('lodash/toArray'); + +const { addQueryContext, normalizeArr } = require('../util/helpers'); +const JoinClause = require('./joinclause'); +const Analytic = require('./analytic'); +const saveAsyncStack = require('../util/save-async-stack'); +const { + isBoolean, + isNumber, + isObject, + isString, + isFunction, +} = require('../util/is'); + +const { lockMode, waitMode } = require('./constants'); +const { + augmentWithBuilderInterface, +} = require('../builder-interface-augmenter'); + +const SELECT_COMMANDS = new Set(['pluck', 'first', 'select']); +const CLEARABLE_STATEMENTS = new Set([ + 'with', + 'select', + 'columns', + 'hintComments', + 'where', + 'union', + 'join', + 'group', + 'order', + 'having', + 'limit', + 'offset', + 'counter', + 'counters', +]); +const LOCK_MODES = new Set([ + lockMode.forShare, + lockMode.forUpdate, + lockMode.forNoKeyUpdate, + lockMode.forKeyShare, +]); + +// Typically called from `knex.builder`, +// start a new query building chain. +class Builder extends EventEmitter { + constructor(client) { + super(); + this.client = client; + this.and = this; + this._single = {}; + this._comments = []; + this._statements = []; + this._method = 'select'; + if (client.config) { + saveAsyncStack(this, 5); + this._debug = client.config.debug; + } + // Internal flags used in the builder. + this._joinFlag = 'inner'; + this._boolFlag = 'and'; + this._notFlag = false; + this._asColumnFlag = false; + } + + toString() { + return this.toQuery(); + } + + // Convert the current query "toSQL" + toSQL(method, tz) { + return this.client.queryCompiler(this).toSQL(method || this._method, tz); + } + + // Create a shallow clone of the current query builder. + clone() { + const cloned = new this.constructor(this.client); + cloned._method = this._method; + cloned._single = clone(this._single); + cloned._comments = clone(this._comments); + cloned._statements = clone(this._statements); + cloned._debug = this._debug; + + // `_option` is assigned by the `Interface` mixin. + if (this._options !== undefined) { + cloned._options = clone(this._options); + } + if (this._queryContext !== undefined) { + cloned._queryContext = clone(this._queryContext); + } + if (this._connection !== undefined) { + cloned._connection = this._connection; + } + + return cloned; + } + + timeout(ms, { cancel } = {}) { + if (isNumber(ms) && ms > 0) { + this._timeout = ms; + if (cancel) { + this.client.assertCanCancelQuery(); + this._cancelOnTimeout = true; + } + } + return this; + } + + // With + // ------ + isValidStatementArg(statement) { + return ( + typeof statement === 'function' || + statement instanceof Builder || + (statement && statement.isRawInstance) + ); + } + + _validateWithArgs(alias, statementOrColumnList, nothingOrStatement, method) { + const [query, columnList] = + typeof nothingOrStatement === 'undefined' + ? [statementOrColumnList, undefined] + : [nothingOrStatement, statementOrColumnList]; + if (typeof alias !== 'string') { + throw new Error(`${method}() first argument must be a string`); + } + + if (this.isValidStatementArg(query) && typeof columnList === 'undefined') { + // Validated as two-arg variant (alias, statement). + return; + } + + // Attempt to interpret as three-arg variant (alias, columnList, statement). + const isNonEmptyNameList = + Array.isArray(columnList) && + columnList.length > 0 && + columnList.every((it) => typeof it === 'string'); + if (!isNonEmptyNameList) { + throw new Error( + `${method}() second argument must be a statement or non-empty column name list.` + ); + } + + if (this.isValidStatementArg(query)) { + return; + } + throw new Error( + `${method}() third argument must be a function / QueryBuilder or a raw when its second argument is a column name list` + ); + } + + with(alias, statementOrColumnList, nothingOrStatement) { + this._validateWithArgs( + alias, + statementOrColumnList, + nothingOrStatement, + 'with' + ); + return this.withWrapped(alias, statementOrColumnList, nothingOrStatement); + } + + withMaterialized(alias, statementOrColumnList, nothingOrStatement) { + throw new Error('With materialized is not supported by this dialect'); + } + + withNotMaterialized(alias, statementOrColumnList, nothingOrStatement) { + throw new Error('With materialized is not supported by this dialect'); + } + + // Helper for compiling any advanced `with` queries. + withWrapped(alias, statementOrColumnList, nothingOrStatement, materialized) { + const [query, columnList] = + typeof nothingOrStatement === 'undefined' + ? [statementOrColumnList, undefined] + : [nothingOrStatement, statementOrColumnList]; + const statement = { + grouping: 'with', + type: 'withWrapped', + alias: alias, + columnList, + value: query, + }; + if (materialized !== undefined) { + statement.materialized = materialized; + } + this._statements.push(statement); + return this; + } + + // With Recursive + // ------ + + withRecursive(alias, statementOrColumnList, nothingOrStatement) { + this._validateWithArgs( + alias, + statementOrColumnList, + nothingOrStatement, + 'withRecursive' + ); + return this.withRecursiveWrapped( + alias, + statementOrColumnList, + nothingOrStatement + ); + } + + // Helper for compiling any advanced `withRecursive` queries. + withRecursiveWrapped(alias, statementOrColumnList, nothingOrStatement) { + this.withWrapped(alias, statementOrColumnList, nothingOrStatement); + this._statements[this._statements.length - 1].recursive = true; + return this; + } + + // Select + // ------ + + // Adds a column or columns to the list of "columns" + // being selected on the query. + columns(column) { + if (!column && column !== 0) return this; + this._statements.push({ + grouping: 'columns', + value: normalizeArr(...arguments), + }); + return this; + } + + // Adds a comment to the query + comment(txt) { + if (!isString(txt)) { + throw new Error('Comment must be a string'); + } + const forbiddenChars = ['/*', '*/', '?']; + if (forbiddenChars.some((chars) => txt.includes(chars))) { + throw new Error(`Cannot include ${forbiddenChars.join(', ')} in comment`); + } + this._comments.push({ + comment: txt, + }); + return this; + } + + // Allow for a sub-select to be explicitly aliased as a column, + // without needing to compile the query in a where. + as(column) { + this._single.as = column; + return this; + } + + // Adds a single hint or an array of hits to the list of "hintComments" on the query. + hintComment(hints) { + hints = Array.isArray(hints) ? hints : [hints]; + if (hints.some((hint) => !isString(hint))) { + throw new Error('Hint comment must be a string'); + } + if (hints.some((hint) => hint.includes('/*') || hint.includes('*/'))) { + throw new Error('Hint comment cannot include "/*" or "*/"'); + } + if (hints.some((hint) => hint.includes('?'))) { + throw new Error('Hint comment cannot include "?"'); + } + this._statements.push({ + grouping: 'hintComments', + value: hints, + }); + return this; + } + + // Prepends the `schemaName` on `tableName` defined by `.table` and `.join`. + withSchema(schemaName) { + this._single.schema = schemaName; + return this; + } + + // Sets the `tableName` on the query. + // Alias to "from" for select and "into" for insert statements + // e.g. builder.insert({a: value}).into('tableName') + // `options`: options object containing keys: + // - `only`: whether the query should use SQL's ONLY to not return + // inheriting table data. Defaults to false. + table(tableName, options = {}) { + this._single.table = tableName; + this._single.only = options.only === true; + return this; + } + + // Adds a `distinct` clause to the query. + distinct(...args) { + this._statements.push({ + grouping: 'columns', + value: normalizeArr(...args), + distinct: true, + }); + return this; + } + + distinctOn(...args) { + if (isEmpty(args)) { + throw new Error('distinctOn requires at least on argument'); + } + this._statements.push({ + grouping: 'columns', + value: normalizeArr(...args), + distinctOn: true, + }); + return this; + } + + // Adds a join clause to the query, allowing for advanced joins + // with an anonymous function as the second argument. + join(table, first, ...args) { + let join; + const schema = + table instanceof Builder || typeof table === 'function' + ? undefined + : this._single.schema; + const joinType = this._joinType(); + if (typeof first === 'function') { + join = new JoinClause(table, joinType, schema); + first.call(join, join); + } else if (joinType === 'raw') { + join = new JoinClause(this.client.raw(table, first), 'raw'); + } else { + join = new JoinClause(table, joinType, schema); + if (first) { + join.on(first, ...args); + } + } + this._statements.push(join); + return this; + } + + using(tables) { + throw new Error( + "'using' function is only available in PostgreSQL dialect with Delete statements." + ); + } + + // JOIN blocks: + innerJoin(...args) { + return this._joinType('inner').join(...args); + } + + leftJoin(...args) { + return this._joinType('left').join(...args); + } + + leftOuterJoin(...args) { + return this._joinType('left outer').join(...args); + } + + rightJoin(...args) { + return this._joinType('right').join(...args); + } + + rightOuterJoin(...args) { + return this._joinType('right outer').join(...args); + } + + outerJoin(...args) { + return this._joinType('outer').join(...args); + } + + fullOuterJoin(...args) { + return this._joinType('full outer').join(...args); + } + + crossJoin(...args) { + return this._joinType('cross').join(...args); + } + + joinRaw(...args) { + return this._joinType('raw').join(...args); + } + + // Where modifiers: + get or() { + return this._bool('or'); + } + + get not() { + return this._not(true); + } + + // The where function can be used in several ways: + // The most basic is `where(key, value)`, which expands to + // where key = value. + where(column, operator, value) { + const argsLength = arguments.length; + + // Support "where true || where false" + if (column === false || column === true) { + return this.where(1, '=', column ? 1 : 0); + } + + // Check if the column is a function, in which case it's + // a where statement wrapped in parens. + if (typeof column === 'function') { + return this.whereWrapped(column); + } + + // Allows `where({id: 2})` syntax. + if (isObject(column) && !column.isRawInstance) + return this._objectWhere(column); + + // Allow a raw statement to be passed along to the query. + if (column && column.isRawInstance && argsLength === 1) + return this.whereRaw(column); + + // Enable the where('key', value) syntax, only when there + // are explicitly two arguments passed, so it's not possible to + // do where('key', '!=') and have that turn into where key != null + if (argsLength === 2) { + value = operator; + operator = '='; + + // If the value is null, and it's a two argument query, + // we assume we're going for a `whereNull`. + if (value === null) { + return this.whereNull(column); + } + } + + // lower case the operator for comparison purposes + const checkOperator = `${operator}`.toLowerCase().trim(); + + // If there are 3 arguments, check whether 'in' is one of them. + if (argsLength === 3) { + if (checkOperator === 'in' || checkOperator === 'not in') { + return this._not(checkOperator === 'not in').whereIn(column, value); + } + if (checkOperator === 'between' || checkOperator === 'not between') { + return this._not(checkOperator === 'not between').whereBetween( + column, + value + ); + } + } + + // If the value is still null, check whether they're meaning + // where value is null + if (value === null) { + // Check for .where(key, 'is', null) or .where(key, 'is not', 'null'); + if (checkOperator === 'is' || checkOperator === 'is not') { + return this._not(checkOperator === 'is not').whereNull(column); + } + } + + // Push onto the where statement stack. + this._statements.push({ + grouping: 'where', + type: 'whereBasic', + column, + operator, + value, + not: this._not(), + bool: this._bool(), + asColumn: this._asColumnFlag, + }); + return this; + } + + whereColumn(...args) { + this._asColumnFlag = true; + this.where(...args); + this._asColumnFlag = false; + return this; + } + + // Adds an `or where` clause to the query. + orWhere(column, ...args) { + this._bool('or'); + const obj = column; + if (isObject(obj) && !obj.isRawInstance) { + return this.whereWrapped(function () { + for (const key in obj) { + this.andWhere(key, obj[key]); + } + }); + } + return this.where(column, ...args); + } + + orWhereColumn(column, ...args) { + this._bool('or'); + const obj = column; + if (isObject(obj) && !obj.isRawInstance) { + return this.whereWrapped(function () { + for (const key in obj) { + this.andWhereColumn(key, '=', obj[key]); + } + }); + } + return this.whereColumn(column, ...args); + } + + // Adds an `not where` clause to the query. + whereNot(column, ...args) { + if (args.length >= 2) { + if (args[0] === 'in' || args[0] === 'between') { + this.client.logger.warn( + 'whereNot is not suitable for "in" and "between" type subqueries. You should use "not in" and "not between" instead.' + ); + } + } + return this._not(true).where(column, ...args); + } + + whereNotColumn(...args) { + return this._not(true).whereColumn(...args); + } + + // Adds an `or not where` clause to the query. + orWhereNot(...args) { + return this._bool('or').whereNot(...args); + } + + orWhereNotColumn(...args) { + return this._bool('or').whereNotColumn(...args); + } + + // Processes an object literal provided in a "where" clause. + _objectWhere(obj) { + const boolVal = this._bool(); + const notVal = this._not() ? 'Not' : ''; + for (const key in obj) { + this[boolVal + 'Where' + notVal](key, obj[key]); + } + return this; + } + + // Adds a raw `where` clause to the query. + whereRaw(sql, bindings) { + const raw = sql.isRawInstance ? sql : this.client.raw(sql, bindings); + + this._statements.push({ + grouping: 'where', + type: 'whereRaw', + value: raw, + not: this._not(), + bool: this._bool(), + }); + return this; + } + + orWhereRaw(sql, bindings) { + return this._bool('or').whereRaw(sql, bindings); + } + + // Helper for compiling any advanced `where` queries. + whereWrapped(callback) { + this._statements.push({ + grouping: 'where', + type: 'whereWrapped', + value: callback, + not: this._not(), + bool: this._bool(), + }); + return this; + } + + // Adds a `where exists` clause to the query. + whereExists(callback) { + this._statements.push({ + grouping: 'where', + type: 'whereExists', + value: callback, + not: this._not(), + bool: this._bool(), + }); + return this; + } + + // Adds an `or where exists` clause to the query. + orWhereExists(callback) { + return this._bool('or').whereExists(callback); + } + + // Adds a `where not exists` clause to the query. + whereNotExists(callback) { + return this._not(true).whereExists(callback); + } + + // Adds a `or where not exists` clause to the query. + orWhereNotExists(callback) { + return this._bool('or').whereNotExists(callback); + } + + // Adds a `where in` clause to the query. + whereIn(column, values) { + if (Array.isArray(values) && isEmpty(values)) + return this.where(this._not()); + this._statements.push({ + grouping: 'where', + type: 'whereIn', + column, + value: values, + not: this._not(), + bool: this._bool(), + }); + return this; + } + + // Adds a `or where in` clause to the query. + orWhereIn(column, values) { + return this._bool('or').whereIn(column, values); + } + + // Adds a `where not in` clause to the query. + whereNotIn(column, values) { + return this._not(true).whereIn(column, values); + } + + // Adds a `or where not in` clause to the query. + orWhereNotIn(column, values) { + return this._bool('or')._not(true).whereIn(column, values); + } + + // Adds a `where null` clause to the query. + whereNull(column) { + this._statements.push({ + grouping: 'where', + type: 'whereNull', + column, + not: this._not(), + bool: this._bool(), + }); + return this; + } + + // Adds a `or where null` clause to the query. + orWhereNull(column) { + return this._bool('or').whereNull(column); + } + + // Adds a `where not null` clause to the query. + whereNotNull(column) { + return this._not(true).whereNull(column); + } + + // Adds a `or where not null` clause to the query. + orWhereNotNull(column) { + return this._bool('or').whereNotNull(column); + } + + // Adds a `where between` clause to the query. + whereBetween(column, values) { + assert( + Array.isArray(values), + 'The second argument to whereBetween must be an array.' + ); + assert( + values.length === 2, + 'You must specify 2 values for the whereBetween clause' + ); + this._statements.push({ + grouping: 'where', + type: 'whereBetween', + column, + value: values, + not: this._not(), + bool: this._bool(), + }); + return this; + } + + // Adds a `where not between` clause to the query. + whereNotBetween(column, values) { + return this._not(true).whereBetween(column, values); + } + + // Adds a `or where between` clause to the query. + orWhereBetween(column, values) { + return this._bool('or').whereBetween(column, values); + } + + // Adds a `or where not between` clause to the query. + orWhereNotBetween(column, values) { + return this._bool('or').whereNotBetween(column, values); + } + + _whereLike(type, column, value) { + this._statements.push({ + grouping: 'where', + type: type, + column, + value: value, + not: this._not(), + bool: this._bool(), + asColumn: this._asColumnFlag, + }); + return this; + } + + // Adds a `where like` clause to the query. + whereLike(column, value) { + return this._whereLike('whereLike', column, value); + } + + // Adds a `or where like` clause to the query. + orWhereLike(column, value) { + return this._bool('or')._whereLike('whereLike', column, value); + } + + // Adds a `where ilike` clause to the query. + whereILike(column, value) { + return this._whereLike('whereILike', column, value); + } + + // Adds a `or where ilike` clause to the query. + orWhereILike(column, value) { + return this._bool('or')._whereLike('whereILike', column, value); + } + + // Adds a `group by` clause to the query. + groupBy(item) { + if (item && item.isRawInstance) { + return this.groupByRaw.apply(this, arguments); + } + this._statements.push({ + grouping: 'group', + type: 'groupByBasic', + value: normalizeArr(...arguments), + }); + return this; + } + + // Adds a raw `group by` clause to the query. + groupByRaw(sql, bindings) { + const raw = sql.isRawInstance ? sql : this.client.raw(sql, bindings); + this._statements.push({ + grouping: 'group', + type: 'groupByRaw', + value: raw, + }); + return this; + } + + // Adds a `order by` clause to the query. + orderBy(column, direction, nulls = '') { + if (Array.isArray(column)) { + return this._orderByArray(column); + } + this._statements.push({ + grouping: 'order', + type: 'orderByBasic', + value: column, + direction, + nulls, + }); + return this; + } + + // Adds a `order by` with multiple columns to the query. + _orderByArray(columnDefs) { + for (let i = 0; i < columnDefs.length; i++) { + const columnInfo = columnDefs[i]; + if (isObject(columnInfo)) { + this._statements.push({ + grouping: 'order', + type: 'orderByBasic', + value: columnInfo['column'], + direction: columnInfo['order'], + nulls: columnInfo['nulls'], + }); + } else if (isString(columnInfo) || isNumber(columnInfo)) { + this._statements.push({ + grouping: 'order', + type: 'orderByBasic', + value: columnInfo, + }); + } + } + return this; + } + + // Add a raw `order by` clause to the query. + orderByRaw(sql, bindings) { + const raw = sql.isRawInstance ? sql : this.client.raw(sql, bindings); + this._statements.push({ + grouping: 'order', + type: 'orderByRaw', + value: raw, + }); + return this; + } + + _union(clause, args) { + let callbacks = args[0]; + let wrap = args[1]; + if (args.length === 1 || (args.length === 2 && isBoolean(wrap))) { + if (!Array.isArray(callbacks)) { + callbacks = [callbacks]; + } + for (let i = 0, l = callbacks.length; i < l; i++) { + this._statements.push({ + grouping: 'union', + clause: clause, + value: callbacks[i], + wrap: wrap || false, + }); + } + } else { + callbacks = toArray(args).slice(0, args.length - 1); + wrap = args[args.length - 1]; + if (!isBoolean(wrap)) { + callbacks.push(wrap); + wrap = false; + } + this._union(clause, [callbacks, wrap]); + } + return this; + } + + // Add a union statement to the query. + union(...args) { + return this._union('union', args); + } + + // Adds a union all statement to the query. + unionAll(...args) { + return this._union('union all', args); + } + + intersect(...args) { + return this._union('intersect', args); + } + + except(...args) { + return this._union('except', args); + } + + // Adds a `having` clause to the query. + having(column, operator, value) { + if (column.isRawInstance && arguments.length === 1) { + return this.havingRaw(column); + } + + // Check if the column is a function, in which case it's + // a having statement wrapped in parens. + if (typeof column === 'function') { + return this.havingWrapped(column); + } + + this._statements.push({ + grouping: 'having', + type: 'havingBasic', + column, + operator, + value, + bool: this._bool(), + not: this._not(), + }); + return this; + } + + orHaving(column, ...args) { + this._bool('or'); + const obj = column; + if (isObject(obj) && !obj.isRawInstance) { + return this.havingWrapped(function () { + for (const key in obj) { + this.andHaving(key, obj[key]); + } + }); + } + return this.having(column, ...args); + } + + // Helper for compiling any advanced `having` queries. + havingWrapped(callback) { + this._statements.push({ + grouping: 'having', + type: 'havingWrapped', + value: callback, + bool: this._bool(), + not: this._not(), + }); + return this; + } + + havingNull(column) { + this._statements.push({ + grouping: 'having', + type: 'havingNull', + column, + not: this._not(), + bool: this._bool(), + }); + return this; + } + + orHavingNull(callback) { + return this._bool('or').havingNull(callback); + } + + havingNotNull(callback) { + return this._not(true).havingNull(callback); + } + + orHavingNotNull(callback) { + return this._not(true)._bool('or').havingNull(callback); + } + + havingExists(callback) { + this._statements.push({ + grouping: 'having', + type: 'havingExists', + value: callback, + not: this._not(), + bool: this._bool(), + }); + return this; + } + + orHavingExists(callback) { + return this._bool('or').havingExists(callback); + } + + havingNotExists(callback) { + return this._not(true).havingExists(callback); + } + + orHavingNotExists(callback) { + return this._not(true)._bool('or').havingExists(callback); + } + + havingBetween(column, values) { + assert( + Array.isArray(values), + 'The second argument to havingBetween must be an array.' + ); + assert( + values.length === 2, + 'You must specify 2 values for the havingBetween clause' + ); + this._statements.push({ + grouping: 'having', + type: 'havingBetween', + column, + value: values, + not: this._not(), + bool: this._bool(), + }); + return this; + } + + orHavingBetween(column, values) { + return this._bool('or').havingBetween(column, values); + } + + havingNotBetween(column, values) { + return this._not(true).havingBetween(column, values); + } + + orHavingNotBetween(column, values) { + return this._not(true)._bool('or').havingBetween(column, values); + } + + havingIn(column, values) { + if (Array.isArray(values) && isEmpty(values)) + return this.where(this._not()); + this._statements.push({ + grouping: 'having', + type: 'havingIn', + column, + value: values, + not: this._not(), + bool: this._bool(), + }); + return this; + } + + // Adds a `or where in` clause to the query. + orHavingIn(column, values) { + return this._bool('or').havingIn(column, values); + } + + // Adds a `where not in` clause to the query. + havingNotIn(column, values) { + return this._not(true).havingIn(column, values); + } + + // Adds a `or where not in` clause to the query. + orHavingNotIn(column, values) { + return this._bool('or')._not(true).havingIn(column, values); + } + + // Adds a raw `having` clause to the query. + havingRaw(sql, bindings) { + const raw = sql.isRawInstance ? sql : this.client.raw(sql, bindings); + this._statements.push({ + grouping: 'having', + type: 'havingRaw', + value: raw, + bool: this._bool(), + not: this._not(), + }); + return this; + } + + orHavingRaw(sql, bindings) { + return this._bool('or').havingRaw(sql, bindings); + } + + // set the skip binding parameter (= insert the raw value in the query) for an attribute. + _setSkipBinding(attribute, options) { + let skipBinding = options; + if (isObject(options)) { + skipBinding = options.skipBinding; + } + this._single.skipBinding = this._single.skipBinding || {}; + this._single.skipBinding[attribute] = skipBinding; + } + + // Only allow a single "offset" to be set for the current query. + offset(value, options) { + if (value == null || value.isRawInstance || value instanceof Builder) { + // Builder for backward compatibility + this._single.offset = value; + } else { + const val = parseInt(value, 10); + if (isNaN(val)) { + this.client.logger.warn('A valid integer must be provided to offset'); + } else if (val < 0) { + throw new Error(`A non-negative integer must be provided to offset.`); + } else { + this._single.offset = val; + } + } + this._setSkipBinding('offset', options); + return this; + } + + // Only allow a single "limit" to be set for the current query. + limit(value, options) { + const val = parseInt(value, 10); + if (isNaN(val)) { + this.client.logger.warn('A valid integer must be provided to limit'); + } else { + this._single.limit = val; + this._setSkipBinding('limit', options); + } + return this; + } + + // Retrieve the "count" result of the query. + count(column, options) { + return this._aggregate('count', column || '*', options); + } + + // Retrieve the minimum value of a given column. + min(column, options) { + return this._aggregate('min', column, options); + } + + // Retrieve the maximum value of a given column. + max(column, options) { + return this._aggregate('max', column, options); + } + + // Retrieve the sum of the values of a given column. + sum(column, options) { + return this._aggregate('sum', column, options); + } + + // Retrieve the average of the values of a given column. + avg(column, options) { + return this._aggregate('avg', column, options); + } + + // Retrieve the "count" of the distinct results of the query. + countDistinct(...columns) { + let options; + if (columns.length > 1 && isPlainObject(last(columns))) { + [options] = columns.splice(columns.length - 1, 1); + } + + if (!columns.length) { + columns = '*'; + } else if (columns.length === 1) { + columns = columns[0]; + } + + return this._aggregate('count', columns, { ...options, distinct: true }); + } + + // Retrieve the sum of the distinct values of a given column. + sumDistinct(column, options) { + return this._aggregate('sum', column, { ...options, distinct: true }); + } + + // Retrieve the vg of the distinct results of the query. + avgDistinct(column, options) { + return this._aggregate('avg', column, { ...options, distinct: true }); + } + + // Increments a column's value by the specified amount. + increment(column, amount = 1) { + if (isObject(column)) { + for (const key in column) { + this._counter(key, column[key]); + } + + return this; + } + + return this._counter(column, amount); + } + + // Decrements a column's value by the specified amount. + decrement(column, amount = 1) { + if (isObject(column)) { + for (const key in column) { + this._counter(key, -column[key]); + } + + return this; + } + + return this._counter(column, -amount); + } + + // Clears increments/decrements + clearCounters() { + this._single.counter = {}; + return this; + } + + // Sets the values for a `select` query, informing that only the first + // row should be returned (limit 1). + first(...args) { + if (this._method && this._method !== 'select') { + throw new Error(`Cannot chain .first() on "${this._method}" query`); + } + + this.select(normalizeArr(...args)); + this._method = 'first'; + this.limit(1); + return this; + } + + // Use existing connection to execute the query + // Same value that client.acquireConnection() for an according client returns should be passed + connection(_connection) { + this._connection = _connection; + this.client.processPassedConnection(_connection); + return this; + } + + // Pluck a column from a query. + pluck(column) { + if (this._method && this._method !== 'select') { + throw new Error(`Cannot chain .pluck() on "${this._method}" query`); + } + + this._method = 'pluck'; + this._single.pluck = column; + this._statements.push({ + grouping: 'columns', + type: 'pluck', + value: column, + }); + return this; + } + + // Deprecated. Remove everything from select clause + clearSelect() { + this._clearGrouping('columns'); + return this; + } + + // Deprecated. Remove everything from where clause + clearWhere() { + this._clearGrouping('where'); + return this; + } + + // Deprecated. Remove everything from group clause + clearGroup() { + this._clearGrouping('group'); + return this; + } + + // Deprecated. Remove everything from order clause + clearOrder() { + this._clearGrouping('order'); + return this; + } + + // Deprecated. Remove everything from having clause + clearHaving() { + this._clearGrouping('having'); + return this; + } + + // Remove everything from statement clause + clear(statement) { + if (!CLEARABLE_STATEMENTS.has(statement)) + throw new Error(`Knex Error: unknown statement '${statement}'`); + if (statement.startsWith('counter')) return this.clearCounters(); + if (statement === 'select') { + statement = 'columns'; + } + this._clearGrouping(statement); + return this; + } + + // Insert & Update + // ------ + + // Sets the values for an `insert` query. + insert(values, returning, options) { + this._method = 'insert'; + if (!isEmpty(returning)) this.returning(returning, options); + this._single.insert = values; + return this; + } + + // Sets the values for an `update`, allowing for both + // `.update(key, value, [returning])` and `.update(obj, [returning])` syntaxes. + update(values, returning, options) { + let ret; + const obj = this._single.update || {}; + this._method = 'update'; + if (isString(values)) { + if (isPlainObject(returning)) { + obj[values] = JSON.stringify(returning); + } else { + obj[values] = returning; + } + if (arguments.length > 2) { + ret = arguments[2]; + } + } else { + const keys = Object.keys(values); + if (this._single.update) { + this.client.logger.warn('Update called multiple times with objects.'); + } + let i = -1; + while (++i < keys.length) { + obj[keys[i]] = values[keys[i]]; + } + ret = arguments[1]; + } + if (!isEmpty(ret)) this.returning(ret, options); + this._single.update = obj; + return this; + } + + // Sets the returning value for the query. + returning(returning, options) { + this._single.returning = returning; + this._single.options = options; + return this; + } + + onConflict(columns) { + if (typeof columns === 'string') { + columns = [columns]; + } + return new OnConflictBuilder(this, columns || true); + } + + // Delete + // ------ + + // Executes a delete statement on the query; + delete(ret, options) { + this._method = 'del'; + if (!isEmpty(ret)) this.returning(ret, options); + return this; + } + + // Truncates a table, ends the query chain. + truncate(tableName) { + this._method = 'truncate'; + if (tableName) { + this._single.table = tableName; + } + return this; + } + + // Retrieves columns for the table specified by `knex(tableName)` + columnInfo(column) { + this._method = 'columnInfo'; + this._single.columnInfo = column; + return this; + } + + // Set a lock for update constraint. + forUpdate(...tables) { + this._single.lock = lockMode.forUpdate; + if (tables.length === 1 && Array.isArray(tables[0])) { + this._single.lockTables = tables[0]; + } else { + this._single.lockTables = tables; + } + return this; + } + + // Set a lock for share constraint. + forShare(...tables) { + this._single.lock = lockMode.forShare; + this._single.lockTables = tables; + return this; + } + + // Set a lock for no key update constraint. + forNoKeyUpdate(...tables) { + this._single.lock = lockMode.forNoKeyUpdate; + this._single.lockTables = tables; + return this; + } + + // Set a lock for key share constraint. + forKeyShare(...tables) { + this._single.lock = lockMode.forKeyShare; + this._single.lockTables = tables; + return this; + } + + // Skips locked rows when using a lock constraint. + skipLocked() { + if (!this._isSelectQuery()) { + throw new Error(`Cannot chain .skipLocked() on "${this._method}" query!`); + } + if (!this._hasLockMode()) { + throw new Error( + '.skipLocked() can only be used after a call to .forShare() or .forUpdate()!' + ); + } + if (this._single.waitMode === waitMode.noWait) { + throw new Error('.skipLocked() cannot be used together with .noWait()!'); + } + this._single.waitMode = waitMode.skipLocked; + return this; + } + + // Causes error when acessing a locked row instead of waiting for it to be released. + noWait() { + if (!this._isSelectQuery()) { + throw new Error(`Cannot chain .noWait() on "${this._method}" query!`); + } + if (!this._hasLockMode()) { + throw new Error( + '.noWait() can only be used after a call to .forShare() or .forUpdate()!' + ); + } + if (this._single.waitMode === waitMode.skipLocked) { + throw new Error('.noWait() cannot be used together with .skipLocked()!'); + } + this._single.waitMode = waitMode.noWait; + return this; + } + + // Takes a JS object of methods to call and calls them + fromJS(obj) { + each(obj, (val, key) => { + if (typeof this[key] !== 'function') { + this.client.logger.warn(`Knex Error: unknown key ${key}`); + } + if (Array.isArray(val)) { + this[key].apply(this, val); + } else { + this[key](val); + } + }); + return this; + } + + fromRaw(sql, bindings) { + const raw = sql.isRawInstance ? sql : this.client.raw(sql, bindings); + return this.from(raw); + } + + // Passes query to provided callback function, useful for e.g. composing + // domain-specific helpers + modify(callback) { + callback.apply(this, [this].concat(tail(arguments))); + return this; + } + + upsert(values, returning, options) { + throw new Error( + `Upsert is not yet supported for dialect ${this.client.dialect}` + ); + } + + // JSON support functions + _json(nameFunction, params) { + this._statements.push({ + grouping: 'columns', + type: 'json', + method: nameFunction, + params: params, + }); + return this; + } + + jsonExtract() { + const column = arguments[0]; + let path; + let alias; + let singleValue = true; + + // We use arguments to have the signatures : + // - column (string or array) + // - column + path + // - column + path + alias + // - column + path + alias + singleValue + // - column array + singleValue + if (arguments.length >= 2) { + path = arguments[1]; + } + if (arguments.length >= 3) { + alias = arguments[2]; + } + if (arguments.length === 4) { + singleValue = arguments[3]; + } + if ( + arguments.length === 2 && + Array.isArray(arguments[0]) && + isBoolean(arguments[1]) + ) { + singleValue = arguments[1]; + } + return this._json('jsonExtract', { + column: column, + path: path, + alias: alias, + singleValue, // boolean used only in MSSQL to use function for extract value instead of object/array. + }); + } + + jsonSet(column, path, value, alias) { + return this._json('jsonSet', { + column: column, + path: path, + value: value, + alias: alias, + }); + } + + jsonInsert(column, path, value, alias) { + return this._json('jsonInsert', { + column: column, + path: path, + value: value, + alias: alias, + }); + } + + jsonRemove(column, path, alias) { + return this._json('jsonRemove', { + column: column, + path: path, + alias: alias, + }); + } + + // Wheres for JSON + _isJsonObject(jsonValue) { + return isObject(jsonValue) && !(jsonValue instanceof Builder); + } + + _whereJsonWrappedValue(type, column, value) { + const whereJsonClause = { + grouping: 'where', + type: type, + column, + value: value, + not: this._not(), + bool: this._bool(), + asColumn: this._asColumnFlag, + }; + if (arguments[3]) { + whereJsonClause.operator = arguments[3]; + } + if (arguments[4]) { + whereJsonClause.jsonPath = arguments[4]; + } + this._statements.push(whereJsonClause); + } + + whereJsonObject(column, value) { + this._whereJsonWrappedValue('whereJsonObject', column, value); + return this; + } + + orWhereJsonObject(column, value) { + return this._bool('or').whereJsonObject(column, value); + } + + whereNotJsonObject(column, value) { + return this._not(true).whereJsonObject(column, value); + } + + orWhereNotJsonObject(column, value) { + return this._bool('or').whereNotJsonObject(column, value); + } + + whereJsonPath(column, path, operator, value) { + this._whereJsonWrappedValue('whereJsonPath', column, value, operator, path); + return this; + } + + orWhereJsonPath(column, path, operator, value) { + return this._bool('or').whereJsonPath(column, path, operator, value); + } + + // Json superset wheres + whereJsonSupersetOf(column, value) { + this._whereJsonWrappedValue('whereJsonSupersetOf', column, value); + return this; + } + + whereJsonNotSupersetOf(column, value) { + return this._not(true).whereJsonSupersetOf(column, value); + } + + orWhereJsonSupersetOf(column, value) { + return this._bool('or').whereJsonSupersetOf(column, value); + } + + orWhereJsonNotSupersetOf(column, value) { + return this._bool('or').whereJsonNotSupersetOf(column, value); + } + + // Json subset wheres + whereJsonSubsetOf(column, value) { + this._whereJsonWrappedValue('whereJsonSubsetOf', column, value); + return this; + } + + whereJsonNotSubsetOf(column, value) { + return this._not(true).whereJsonSubsetOf(column, value); + } + + orWhereJsonSubsetOf(column, value) { + return this._bool('or').whereJsonSubsetOf(column, value); + } + + orWhereJsonNotSubsetOf(column, value) { + return this._bool('or').whereJsonNotSubsetOf(column, value); + } + + whereJsonHasNone(column, values) { + this._not(true).whereJsonHasAll(column, values); + return this; + } + + // end of wheres for JSON + + _analytic(alias, second, third) { + let analytic; + const { schema } = this._single; + const method = this._analyticMethod(); + alias = typeof alias === 'string' ? alias : null; + + assert( + typeof second === 'function' || + second.isRawInstance || + Array.isArray(second) || + typeof second === 'string' || + typeof second === 'object', + `The second argument to an analytic function must be either a function, a raw, + an array of string or object, an object or a single string.` + ); + + if (third) { + assert( + Array.isArray(third) || + typeof third === 'string' || + typeof third === 'object', + 'The third argument to an analytic function must be either a string, an array of string or object or an object.' + ); + } + + if (isFunction(second)) { + analytic = new Analytic(method, schema, alias); + second.call(analytic, analytic); + } else if (second.isRawInstance) { + const raw = second; + analytic = { + grouping: 'columns', + type: 'analytic', + method: method, + raw: raw, + alias: alias, + }; + } else { + const order = !Array.isArray(second) ? [second] : second; + let partitions = third || []; + partitions = !Array.isArray(partitions) ? [partitions] : partitions; + analytic = { + grouping: 'columns', + type: 'analytic', + method: method, + order: order, + alias: alias, + partitions: partitions, + }; + } + this._statements.push(analytic); + return this; + } + + rank(...args) { + return this._analyticMethod('rank')._analytic(...args); + } + + denseRank(...args) { + return this._analyticMethod('dense_rank')._analytic(...args); + } + + rowNumber(...args) { + return this._analyticMethod('row_number')._analytic(...args); + } + + // ---------------------------------------------------------------------- + + // Helper for the incrementing/decrementing queries. + _counter(column, amount) { + amount = parseFloat(amount); + + this._method = 'update'; + + this._single.counter = this._single.counter || {}; + + this._single.counter[column] = amount; + + return this; + } + + // Helper to get or set the "boolFlag" value. + _bool(val) { + if (arguments.length === 1) { + this._boolFlag = val; + return this; + } + const ret = this._boolFlag; + this._boolFlag = 'and'; + return ret; + } + + // Helper to get or set the "notFlag" value. + _not(val) { + if (arguments.length === 1) { + this._notFlag = val; + return this; + } + const ret = this._notFlag; + this._notFlag = false; + return ret; + } + + // Helper to get or set the "joinFlag" value. + _joinType(val) { + if (arguments.length === 1) { + this._joinFlag = val; + return this; + } + const ret = this._joinFlag || 'inner'; + this._joinFlag = 'inner'; + return ret; + } + + _analyticMethod(val) { + if (arguments.length === 1) { + this._analyticFlag = val; + return this; + } + return this._analyticFlag || 'row_number'; + } + + // Helper for compiling any aggregate queries. + _aggregate(method, column, options = {}) { + this._statements.push({ + grouping: 'columns', + type: column.isRawInstance ? 'aggregateRaw' : 'aggregate', + method, + value: column, + aggregateDistinct: options.distinct || false, + alias: options.as, + }); + return this; + } + + // Helper function for clearing or reseting a grouping type from the builder + _clearGrouping(grouping) { + if (grouping in this._single) { + this._single[grouping] = undefined; + } else { + this._statements = reject(this._statements, { grouping }); + } + } + + // Helper function that checks if the builder will emit a select query + _isSelectQuery() { + return SELECT_COMMANDS.has(this._method); + } + + // Helper function that checks if the query has a lock mode set + _hasLockMode() { + return LOCK_MODES.has(this._single.lock); + } +} + +Builder.prototype.select = Builder.prototype.columns; +Builder.prototype.column = Builder.prototype.columns; +Builder.prototype.andWhereNot = Builder.prototype.whereNot; +Builder.prototype.andWhereNotColumn = Builder.prototype.whereNotColumn; +Builder.prototype.andWhere = Builder.prototype.where; +Builder.prototype.andWhereColumn = Builder.prototype.whereColumn; +Builder.prototype.andWhereRaw = Builder.prototype.whereRaw; +Builder.prototype.andWhereBetween = Builder.prototype.whereBetween; +Builder.prototype.andWhereNotBetween = Builder.prototype.whereNotBetween; +Builder.prototype.andWhereJsonObject = Builder.prototype.whereJsonObject; +Builder.prototype.andWhereNotJsonObject = Builder.prototype.whereNotJsonObject; +Builder.prototype.andWhereJsonPath = Builder.prototype.whereJsonPath; +Builder.prototype.andWhereLike = Builder.prototype.whereLike; +Builder.prototype.andWhereILike = Builder.prototype.whereILike; +Builder.prototype.andHaving = Builder.prototype.having; +Builder.prototype.andHavingIn = Builder.prototype.havingIn; +Builder.prototype.andHavingNotIn = Builder.prototype.havingNotIn; +Builder.prototype.andHavingNull = Builder.prototype.havingNull; +Builder.prototype.andHavingNotNull = Builder.prototype.havingNotNull; +Builder.prototype.andHavingExists = Builder.prototype.havingExists; +Builder.prototype.andHavingNotExists = Builder.prototype.havingNotExists; +Builder.prototype.andHavingBetween = Builder.prototype.havingBetween; +Builder.prototype.andHavingNotBetween = Builder.prototype.havingNotBetween; +Builder.prototype.from = Builder.prototype.table; +Builder.prototype.into = Builder.prototype.table; +Builder.prototype.del = Builder.prototype.delete; + +// Attach all of the top level promise methods that should be chainable. +augmentWithBuilderInterface(Builder); +addQueryContext(Builder); + +Builder.extend = (methodName, fn) => { + if (Object.prototype.hasOwnProperty.call(Builder.prototype, methodName)) { + throw new Error( + `Can't extend QueryBuilder with existing method ('${methodName}').` + ); + } + + assign(Builder.prototype, { [methodName]: fn }); +}; + +// Sub-builder for onConflict clauses +class OnConflictBuilder { + constructor(builder, columns) { + this.builder = builder; + this._columns = columns; + } + + // Sets insert query to ignore conflicts + ignore() { + this.builder._single.onConflict = this._columns; + this.builder._single.ignore = true; + return this.builder; + } + + // Sets insert query to update on conflict + merge(updates) { + this.builder._single.onConflict = this._columns; + this.builder._single.merge = { updates }; + return this.builder; + } + + // Prevent + then() { + throw new Error( + 'Incomplete onConflict clause. .onConflict() must be directly followed by either .merge() or .ignore()' + ); + } +} + +module.exports = Builder; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/querycompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/querycompiler.js new file mode 100644 index 000000000..ca79dac98 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/query/querycompiler.js @@ -0,0 +1,1591 @@ +// Query Compiler +// ------- +const helpers = require('../util/helpers'); +const Raw = require('../raw'); +const QueryBuilder = require('./querybuilder'); +const JoinClause = require('./joinclause'); +const debug = require('debug'); + +const assign = require('lodash/assign'); +const compact = require('lodash/compact'); +const groupBy = require('lodash/groupBy'); +const has = require('lodash/has'); +const isEmpty = require('lodash/isEmpty'); +const map = require('lodash/map'); +const omitBy = require('lodash/omitBy'); +const reduce = require('lodash/reduce'); +const { nanoid } = require('../util/nanoid'); +const { isString, isUndefined } = require('../util/is'); +const { + columnize: columnize_, + direction: direction_, + operator: operator_, + wrap: wrap_, + unwrapRaw: unwrapRaw_, + rawOrFn: rawOrFn_, +} = require('../formatter/wrappingFormatter'); + +const debugBindings = debug('knex:bindings'); + +const components = [ + 'comments', + 'columns', + 'join', + 'where', + 'union', + 'group', + 'having', + 'order', + 'limit', + 'offset', + 'lock', + 'waitMode', +]; + +// The "QueryCompiler" takes all of the query statements which +// have been gathered in the "QueryBuilder" and turns them into a +// properly formatted / bound query string. +class QueryCompiler { + constructor(client, builder, bindings) { + this.client = client; + this.method = builder._method || 'select'; + this.options = builder._options; + this.single = builder._single; + this.queryComments = builder._comments; + this.timeout = builder._timeout || false; + this.cancelOnTimeout = builder._cancelOnTimeout || false; + this.grouped = groupBy(builder._statements, 'grouping'); + this.formatter = client.formatter(builder); + // Used when the insert call is empty. + this._emptyInsertValue = 'default values'; + this.first = this.select; + + this.bindings = bindings || []; + this.formatter.bindings = this.bindings; + this.bindingsHolder = this; + this.builder = this.formatter.builder; + } + + // Collapse the builder into a single object + toSQL(method, tz) { + this._undefinedInWhereClause = false; + this.undefinedBindingsInfo = []; + + method = method || this.method; + const val = this[method]() || ''; + + const query = { + method, + options: reduce(this.options, assign, {}), + timeout: this.timeout, + cancelOnTimeout: this.cancelOnTimeout, + bindings: this.bindingsHolder.bindings || [], + __knexQueryUid: nanoid(), + }; + + Object.defineProperties(query, { + toNative: { + value: () => { + return { + sql: this.client.positionBindings(query.sql), + bindings: this.client.prepBindings(query.bindings), + }; + }, + enumerable: false, + }, + }); + + if (isString(val)) { + query.sql = val; + } else { + assign(query, val); + } + + if (method === 'select' || method === 'first') { + if (this.single.as) { + query.as = this.single.as; + } + } + + if (this._undefinedInWhereClause) { + debugBindings(query.bindings); + throw new Error( + `Undefined binding(s) detected when compiling ` + + `${method.toUpperCase()}. Undefined column(s): [${this.undefinedBindingsInfo.join( + ', ' + )}] query: ${query.sql}` + ); + } + + return query; + } + + // Compiles the `select` statement, or nested sub-selects by calling each of + // the component compilers, trimming out the empties, and returning a + // generated query string. + select() { + let sql = this.with(); + + let unionStatement = ''; + + const firstStatements = []; + const endStatements = []; + + components.forEach((component) => { + const statement = this[component](this); + // We store the 'union' statement to append it at the end. + // We still need to call the component sequentially because of + // order of bindings. + switch (component) { + case 'union': + unionStatement = statement; + break; + case 'comments': + case 'columns': + case 'join': + case 'where': + firstStatements.push(statement); + break; + default: + endStatements.push(statement); + break; + } + }); + + // Check if we need to wrap the main query. + // We need to wrap main query if one of union have wrap options to true + // to avoid error syntax (in PostgreSQL for example). + const wrapMainQuery = + this.grouped.union && + this.grouped.union.map((u) => u.wrap).some((u) => u); + + if (this.onlyUnions()) { + const statements = compact(firstStatements.concat(endStatements)).join( + ' ' + ); + sql += unionStatement + (statements ? ' ' + statements : ''); + } else { + const allStatements = + (wrapMainQuery ? '(' : '') + + compact(firstStatements).join(' ') + + (wrapMainQuery ? ')' : ''); + const endStat = compact(endStatements).join(' '); + sql += + allStatements + + (unionStatement ? ' ' + unionStatement : '') + + (endStat ? ' ' + endStat : endStat); + } + return sql; + } + + pluck() { + let toPluck = this.single.pluck; + if (toPluck.indexOf('.') !== -1) { + toPluck = toPluck.split('.').slice(-1)[0]; + } + return { + sql: this.select(), + pluck: toPluck, + }; + } + + // Compiles an "insert" query, allowing for multiple + // inserts using a single query statement. + insert() { + const insertValues = this.single.insert || []; + const sql = this.with() + `insert into ${this.tableName} `; + const body = this._insertBody(insertValues); + return body === '' ? '' : sql + body; + } + + _onConflictClause(columns) { + return columns instanceof Raw + ? this.formatter.wrap(columns) + : `(${this.formatter.columnize(columns)})`; + } + + _buildInsertValues(insertData) { + let sql = ''; + let i = -1; + while (++i < insertData.values.length) { + if (i !== 0) sql += '), ('; + sql += this.client.parameterize( + insertData.values[i], + this.client.valueForUndefined, + this.builder, + this.bindingsHolder + ); + } + return sql; + } + + _insertBody(insertValues) { + let sql = ''; + if (Array.isArray(insertValues)) { + if (insertValues.length === 0) { + return ''; + } + } else if (typeof insertValues === 'object' && isEmpty(insertValues)) { + return sql + this._emptyInsertValue; + } + + const insertData = this._prepInsert(insertValues); + if (typeof insertData === 'string') { + sql += insertData; + } else { + if (insertData.columns.length) { + sql += `(${columnize_( + insertData.columns, + this.builder, + this.client, + this.bindingsHolder + )}`; + sql += ') values (' + this._buildInsertValues(insertData) + ')'; + } else if (insertValues.length === 1 && insertValues[0]) { + sql += this._emptyInsertValue; + } else { + sql = ''; + } + } + return sql; + } + + // Compiles the "update" query. + update() { + // Make sure tableName is processed by the formatter first. + const withSQL = this.with(); + const { tableName } = this; + const updateData = this._prepUpdate(this.single.update); + const wheres = this.where(); + return ( + withSQL + + `update ${this.single.only ? 'only ' : ''}${tableName}` + + ' set ' + + updateData.join(', ') + + (wheres ? ` ${wheres}` : '') + ); + } + + _hintComments() { + let hints = this.grouped.hintComments || []; + hints = hints.map((hint) => compact(hint.value).join(' ')); + hints = compact(hints).join(' '); + return hints ? `/*+ ${hints} */ ` : ''; + } + + // Compiles the columns in the query, specifying if an item was distinct. + columns() { + let distinctClause = ''; + if (this.onlyUnions()) return ''; + const hints = this._hintComments(); + const columns = this.grouped.columns || []; + let i = -1, + sql = []; + if (columns) { + while (++i < columns.length) { + const stmt = columns[i]; + if (stmt.distinct) distinctClause = 'distinct '; + if (stmt.distinctOn) { + distinctClause = this.distinctOn(stmt.value); + continue; + } + if (stmt.type === 'aggregate') { + sql.push(...this.aggregate(stmt)); + } else if (stmt.type === 'aggregateRaw') { + sql.push(this.aggregateRaw(stmt)); + } else if (stmt.type === 'analytic') { + sql.push(this.analytic(stmt)); + } else if (stmt.type === 'json') { + sql.push(this.json(stmt)); + } else if (stmt.value && stmt.value.length > 0) { + sql.push( + columnize_( + stmt.value, + this.builder, + this.client, + this.bindingsHolder + ) + ); + } + } + } + if (sql.length === 0) sql = ['*']; + const select = this.onlyJson() ? '' : 'select '; + return ( + `${select}${hints}${distinctClause}` + + sql.join(', ') + + (this.tableName + ? ` from ${this.single.only ? 'only ' : ''}${this.tableName}` + : '') + ); + } + + // Add comments to the query + comments() { + if (!this.queryComments.length) return ''; + return this.queryComments + .map((comment) => `/* ${comment.comment} */`) + .join(' '); + } + + _aggregate(stmt, { aliasSeparator = ' as ', distinctParentheses } = {}) { + const value = stmt.value; + const method = stmt.method; + const distinct = stmt.aggregateDistinct ? 'distinct ' : ''; + const wrap = (identifier) => + wrap_( + identifier, + undefined, + this.builder, + this.client, + this.bindingsHolder + ); + const addAlias = (value, alias) => { + if (alias) { + return value + aliasSeparator + wrap(alias); + } + return value; + }; + const aggregateArray = (value, alias) => { + let columns = value.map(wrap).join(', '); + if (distinct) { + const openParen = distinctParentheses ? '(' : ' '; + const closeParen = distinctParentheses ? ')' : ''; + columns = distinct.trim() + openParen + columns + closeParen; + } + const aggregated = `${method}(${columns})`; + return addAlias(aggregated, alias); + }; + const aggregateString = (value, alias) => { + const aggregated = `${method}(${distinct + wrap(value)})`; + return addAlias(aggregated, alias); + }; + + if (Array.isArray(value)) { + return [aggregateArray(value)]; + } + + if (typeof value === 'object') { + if (stmt.alias) { + throw new Error('When using an object explicit alias can not be used'); + } + return Object.entries(value).map(([alias, column]) => { + if (Array.isArray(column)) { + return aggregateArray(column, alias); + } + return aggregateString(column, alias); + }); + } + + // Allows us to speciy an alias for the aggregate types. + const splitOn = value.toLowerCase().indexOf(' as '); + let column = value; + let { alias } = stmt; + if (splitOn !== -1) { + column = value.slice(0, splitOn); + if (alias) { + throw new Error(`Found multiple aliases for same column: ${column}`); + } + alias = value.slice(splitOn + 4); + } + return [aggregateString(column, alias)]; + } + + aggregate(stmt) { + return this._aggregate(stmt); + } + + aggregateRaw(stmt) { + const distinct = stmt.aggregateDistinct ? 'distinct ' : ''; + return `${stmt.method}(${ + distinct + + unwrapRaw_( + stmt.value, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + })`; + } + + _joinTable(join) { + return join.schema && !(join.table instanceof Raw) + ? `${join.schema}.${join.table}` + : join.table; + } + + // Compiles all each of the `join` clauses on the query, + // including any nested join queries. + join() { + let sql = ''; + let i = -1; + const joins = this.grouped.join; + if (!joins) return ''; + while (++i < joins.length) { + const join = joins[i]; + const table = this._joinTable(join); + if (i > 0) sql += ' '; + if (join.joinType === 'raw') { + sql += unwrapRaw_( + join.table, + undefined, + this.builder, + this.client, + this.bindingsHolder + ); + } else { + sql += + join.joinType + + ' join ' + + wrap_( + table, + undefined, + this.builder, + this.client, + this.bindingsHolder + ); + let ii = -1; + while (++ii < join.clauses.length) { + const clause = join.clauses[ii]; + if (ii > 0) { + sql += ` ${clause.bool} `; + } else { + sql += ` ${clause.type === 'onUsing' ? 'using' : 'on'} `; + } + const val = this[clause.type](clause); + if (val) { + sql += val; + } + } + } + } + return sql; + } + + onBetween(statement) { + return ( + wrap_( + statement.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ' ' + + this._not(statement, 'between') + + ' ' + + statement.value + .map((value) => + this.client.parameter(value, this.builder, this.bindingsHolder) + ) + .join(' and ') + ); + } + + onNull(statement) { + return ( + wrap_( + statement.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ' is ' + + this._not(statement, 'null') + ); + } + + onExists(statement) { + return ( + this._not(statement, 'exists') + + ' (' + + rawOrFn_( + statement.value, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ')' + ); + } + + onIn(statement) { + if (Array.isArray(statement.column)) return this.multiOnIn(statement); + + let values; + if (statement.value instanceof Raw) { + values = this.client.parameter( + statement.value, + this.builder, + this.formatter + ); + } else { + values = this.client.parameterize( + statement.value, + undefined, + this.builder, + this.bindingsHolder + ); + } + + return ( + wrap_( + statement.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ' ' + + this._not(statement, 'in ') + + this.wrap(values) + ); + } + + multiOnIn(statement) { + let i = -1, + sql = `(${columnize_( + statement.column, + this.builder, + this.client, + this.bindingsHolder + )}) `; + sql += this._not(statement, 'in ') + '(('; + while (++i < statement.value.length) { + if (i !== 0) sql += '),('; + sql += this.client.parameterize( + statement.value[i], + undefined, + this.builder, + this.bindingsHolder + ); + } + return sql + '))'; + } + + // Compiles all `where` statements on the query. + where() { + const wheres = this.grouped.where; + if (!wheres) return; + const sql = []; + let i = -1; + while (++i < wheres.length) { + const stmt = wheres[i]; + if ( + Object.prototype.hasOwnProperty.call(stmt, 'value') && + helpers.containsUndefined(stmt.value) + ) { + this.undefinedBindingsInfo.push(stmt.column); + this._undefinedInWhereClause = true; + } + const val = this[stmt.type](stmt); + if (val) { + if (sql.length === 0) { + sql[0] = 'where'; + } else { + sql.push(stmt.bool); + } + sql.push(val); + } + } + return sql.length > 1 ? sql.join(' ') : ''; + } + + group() { + return this._groupsOrders('group'); + } + + order() { + return this._groupsOrders('order'); + } + + // Compiles the `having` statements. + having() { + const havings = this.grouped.having; + if (!havings) return ''; + const sql = ['having']; + for (let i = 0, l = havings.length; i < l; i++) { + const s = havings[i]; + const val = this[s.type](s); + if (val) { + if (sql.length === 0) { + sql[0] = 'where'; + } + if (sql.length > 1 || (sql.length === 1 && sql[0] !== 'having')) { + sql.push(s.bool); + } + sql.push(val); + } + } + return sql.length > 1 ? sql.join(' ') : ''; + } + + havingRaw(statement) { + return ( + this._not(statement, '') + + unwrapRaw_( + statement.value, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + ); + } + + havingWrapped(statement) { + const val = rawOrFn_( + statement.value, + 'where', + this.builder, + this.client, + this.bindingsHolder + ); + return (val && this._not(statement, '') + '(' + val.slice(6) + ')') || ''; + } + + havingBasic(statement) { + return ( + this._not(statement, '') + + wrap_( + statement.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ' ' + + operator_( + statement.operator, + this.builder, + this.client, + this.bindingsHolder + ) + + ' ' + + this.client.parameter(statement.value, this.builder, this.bindingsHolder) + ); + } + + havingNull(statement) { + return ( + wrap_( + statement.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ' is ' + + this._not(statement, 'null') + ); + } + + havingExists(statement) { + return ( + this._not(statement, 'exists') + + ' (' + + rawOrFn_( + statement.value, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ')' + ); + } + + havingBetween(statement) { + return ( + wrap_( + statement.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ' ' + + this._not(statement, 'between') + + ' ' + + statement.value + .map((value) => + this.client.parameter(value, this.builder, this.bindingsHolder) + ) + .join(' and ') + ); + } + + havingIn(statement) { + if (Array.isArray(statement.column)) return this.multiHavingIn(statement); + return ( + wrap_( + statement.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ' ' + + this._not(statement, 'in ') + + this.wrap( + this.client.parameterize( + statement.value, + undefined, + this.builder, + this.bindingsHolder + ) + ) + ); + } + + multiHavingIn(statement) { + return this.multiOnIn(statement); + } + + // Compile the "union" queries attached to the main query. + union() { + const onlyUnions = this.onlyUnions(); + const unions = this.grouped.union; + if (!unions) return ''; + let sql = ''; + for (let i = 0, l = unions.length; i < l; i++) { + const union = unions[i]; + if (i > 0) sql += ' '; + if (i > 0 || !onlyUnions) sql += union.clause + ' '; + const statement = rawOrFn_( + union.value, + undefined, + this.builder, + this.client, + this.bindingsHolder + ); + if (statement) { + const wrap = union.wrap; + if (wrap) sql += '('; + sql += statement; + if (wrap) sql += ')'; + } + } + return sql; + } + + // If we haven't specified any columns or a `tableName`, we're assuming this + // is only being used for unions. + onlyUnions() { + return ( + (!this.grouped.columns || !!this.grouped.columns[0].value) && + this.grouped.union && + !this.tableName + ); + } + + _getValueOrParameterFromAttribute(attribute, rawValue) { + if (this.single.skipBinding[attribute] === true) { + return rawValue !== undefined && rawValue !== null + ? rawValue + : this.single[attribute]; + } + return this.client.parameter( + this.single[attribute], + this.builder, + this.bindingsHolder + ); + } + + onlyJson() { + return ( + !this.tableName && + this.grouped.columns && + this.grouped.columns.length === 1 && + this.grouped.columns[0].type === 'json' + ); + } + + limit() { + const noLimit = !this.single.limit && this.single.limit !== 0; + if (noLimit) return ''; + return `limit ${this._getValueOrParameterFromAttribute('limit')}`; + } + + offset() { + if (!this.single.offset) return ''; + return `offset ${this._getValueOrParameterFromAttribute('offset')}`; + } + + // Compiles a `delete` query. + del() { + // Make sure tableName is processed by the formatter first. + const { tableName } = this; + const withSQL = this.with(); + const wheres = this.where(); + const joins = this.join(); + // When using joins, delete the "from" table values as a default + const deleteSelector = joins ? tableName + ' ' : ''; + return ( + withSQL + + `delete ${deleteSelector}from ${ + this.single.only ? 'only ' : '' + }${tableName}` + + (joins ? ` ${joins}` : '') + + (wheres ? ` ${wheres}` : '') + ); + } + + // Compiles a `truncate` query. + truncate() { + return `truncate ${this.tableName}`; + } + + // Compiles the "locks". + lock() { + if (this.single.lock) { + return this[this.single.lock](); + } + } + + // Compiles the wait mode on the locks. + waitMode() { + if (this.single.waitMode) { + return this[this.single.waitMode](); + } + } + + // Fail on unsupported databases + skipLocked() { + throw new Error( + '.skipLocked() is currently only supported on MySQL 8.0+ and PostgreSQL 9.5+' + ); + } + + // Fail on unsupported databases + noWait() { + throw new Error( + '.noWait() is currently only supported on MySQL 8.0+, MariaDB 10.3.0+ and PostgreSQL 9.5+' + ); + } + + distinctOn(value) { + throw new Error('.distinctOn() is currently only supported on PostgreSQL'); + } + + // On Clause + // ------ + + onWrapped(clause) { + const self = this; + + const wrapJoin = new JoinClause(); + clause.value.call(wrapJoin, wrapJoin); + + let sql = ''; + + for (let ii = 0; ii < wrapJoin.clauses.length; ii++) { + const wrapClause = wrapJoin.clauses[ii]; + if (ii > 0) { + sql += ` ${wrapClause.bool} `; + } + const val = self[wrapClause.type](wrapClause); + if (val) { + sql += val; + } + } + + if (sql.length) { + return `(${sql})`; + } + return ''; + } + + onBasic(clause) { + const toWrap = clause.value instanceof QueryBuilder; + return ( + wrap_( + clause.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ' ' + + operator_( + clause.operator, + this.builder, + this.client, + this.bindingsHolder + ) + + ' ' + + (toWrap ? '(' : '') + + wrap_( + clause.value, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + (toWrap ? ')' : '') + ); + } + + onVal(clause) { + return ( + wrap_( + clause.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ' ' + + operator_( + clause.operator, + this.builder, + this.client, + this.bindingsHolder + ) + + ' ' + + this.client.parameter(clause.value, this.builder, this.bindingsHolder) + ); + } + + onRaw(clause) { + return unwrapRaw_( + clause.value, + undefined, + this.builder, + this.client, + this.bindingsHolder + ); + } + + onUsing(clause) { + return ( + '(' + + columnize_( + clause.column, + this.builder, + this.client, + this.bindingsHolder + ) + + ')' + ); + } + + // Where Clause + // ------ + + _valueClause(statement) { + return statement.asColumn + ? wrap_( + statement.value, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + : this.client.parameter( + statement.value, + this.builder, + this.bindingsHolder + ); + } + + _columnClause(statement) { + let columns; + if (Array.isArray(statement.column)) { + columns = `(${columnize_( + statement.column, + this.builder, + this.client, + this.bindingsHolder + )})`; + } else { + columns = wrap_( + statement.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + ); + } + return columns; + } + + whereIn(statement) { + const values = this.client.values( + statement.value, + this.builder, + this.bindingsHolder + ); + return `${this._columnClause(statement)} ${this._not( + statement, + 'in ' + )}${values}`; + } + + whereLike(statement) { + return `${this._columnClause(statement)} ${this._not( + statement, + 'like ' + )}${this._valueClause(statement)}`; + } + + whereILike(statement) { + return `${this._columnClause(statement)} ${this._not( + statement, + 'ilike ' + )}${this._valueClause(statement)}`; + } + + whereNull(statement) { + return ( + wrap_( + statement.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ' is ' + + this._not(statement, 'null') + ); + } + + // Compiles a basic "where" clause. + whereBasic(statement) { + return ( + this._not(statement, '') + + wrap_( + statement.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ' ' + + operator_( + statement.operator, + this.builder, + this.client, + this.bindingsHolder + ) + + ' ' + + this._valueClause(statement) + ); + } + + whereExists(statement) { + return ( + this._not(statement, 'exists') + + ' (' + + rawOrFn_( + statement.value, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ')' + ); + } + + whereWrapped(statement) { + const val = rawOrFn_( + statement.value, + 'where', + this.builder, + this.client, + this.bindingsHolder + ); + return (val && this._not(statement, '') + '(' + val.slice(6) + ')') || ''; + } + + whereBetween(statement) { + return ( + wrap_( + statement.column, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ' ' + + this._not(statement, 'between') + + ' ' + + statement.value + .map((value) => + this.client.parameter(value, this.builder, this.bindingsHolder) + ) + .join(' and ') + ); + } + + // Compiles a "whereRaw" query. + whereRaw(statement) { + return ( + this._not(statement, '') + + unwrapRaw_( + statement.value, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + ); + } + + _jsonWrapValue(jsonValue) { + if (!this.builder._isJsonObject(jsonValue)) { + try { + return JSON.stringify(JSON.parse(jsonValue.replace(/\n|\t/g, ''))); + } catch (e) { + return jsonValue; + } + } + return JSON.stringify(jsonValue); + } + + _jsonValueClause(statement) { + statement.value = this._jsonWrapValue(statement.value); + return this._valueClause(statement); + } + + whereJsonObject(statement) { + return `${this._columnClause(statement)} ${ + statement.not ? '!=' : '=' + } ${this._jsonValueClause(statement)}`; + } + + wrap(str) { + if (str.charAt(0) !== '(') return `(${str})`; + return str; + } + + json(stmt) { + return this[stmt.method](stmt.params); + } + + analytic(stmt) { + let sql = ''; + const self = this; + sql += stmt.method + '() over ('; + + if (stmt.raw) { + sql += stmt.raw; + } else { + if (stmt.partitions.length) { + sql += 'partition by '; + sql += + map(stmt.partitions, function (partition) { + if (isString(partition)) { + return self.formatter.columnize(partition); + } else return self.formatter.columnize(partition.column) + (partition.order ? ' ' + partition.order : ''); + }).join(', ') + ' '; + } + + sql += 'order by '; + sql += map(stmt.order, function (order) { + if (isString(order)) { + return self.formatter.columnize(order); + } else return self.formatter.columnize(order.column) + (order.order ? ' ' + order.order : ''); + }).join(', '); + } + + sql += ')'; + + if (stmt.alias) { + sql += ' as ' + stmt.alias; + } + + return sql; + } + + // Compiles all `with` statements on the query. + with() { + if (!this.grouped.with || !this.grouped.with.length) { + return ''; + } + const withs = this.grouped.with; + if (!withs) return; + const sql = []; + let i = -1; + let isRecursive = false; + while (++i < withs.length) { + const stmt = withs[i]; + if (stmt.recursive) { + isRecursive = true; + } + const val = this[stmt.type](stmt); + sql.push(val); + } + return `with ${isRecursive ? 'recursive ' : ''}${sql.join(', ')} `; + } + + withWrapped(statement) { + const val = rawOrFn_( + statement.value, + undefined, + this.builder, + this.client, + this.bindingsHolder + ); + const columnList = statement.columnList + ? '(' + + columnize_( + statement.columnList, + this.builder, + this.client, + this.bindingsHolder + ) + + ')' + : ''; + const materialized = + statement.materialized === undefined + ? '' + : statement.materialized + ? 'materialized ' + : 'not materialized '; + return ( + (val && + columnize_( + statement.alias, + this.builder, + this.client, + this.bindingsHolder + ) + + columnList + + ' as ' + + materialized + + '(' + + val + + ')') || + '' + ); + } + + // Determines whether to add a "not" prefix to the where clause. + _not(statement, str) { + if (statement.not) return `not ${str}`; + return str; + } + + _prepInsert(data) { + const isRaw = rawOrFn_( + data, + undefined, + this.builder, + this.client, + this.bindingsHolder + ); + if (isRaw) return isRaw; + let columns = []; + const values = []; + if (!Array.isArray(data)) data = data ? [data] : []; + let i = -1; + while (++i < data.length) { + if (data[i] == null) break; + if (i === 0) columns = Object.keys(data[i]).sort(); + const row = new Array(columns.length); + const keys = Object.keys(data[i]); + let j = -1; + while (++j < keys.length) { + const key = keys[j]; + let idx = columns.indexOf(key); + if (idx === -1) { + columns = columns.concat(key).sort(); + idx = columns.indexOf(key); + let k = -1; + while (++k < values.length) { + values[k].splice(idx, 0, undefined); + } + row.splice(idx, 0, undefined); + } + row[idx] = data[i][key]; + } + values.push(row); + } + return { + columns, + values, + }; + } + + // "Preps" the update. + _prepUpdate(data = {}) { + const { counter = {} } = this.single; + + for (const column of Object.keys(counter)) { + //Skip? + if (has(data, column)) { + //Needed? + this.client.logger.warn( + `increment/decrement called for a column that has already been specified in main .update() call. Ignoring increment/decrement and using value from .update() call.` + ); + continue; + } + + let value = counter[column]; + + const symbol = value < 0 ? '-' : '+'; + + if (symbol === '-') { + value = -value; + } + + data[column] = this.client.raw(`?? ${symbol} ?`, [column, value]); + } + + data = omitBy(data, isUndefined); + + const vals = []; + const columns = Object.keys(data); + let i = -1; + + while (++i < columns.length) { + vals.push( + wrap_( + columns[i], + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ' = ' + + this.client.parameter( + data[columns[i]], + this.builder, + this.bindingsHolder + ) + ); + } + + if (isEmpty(vals)) { + throw new Error( + [ + 'Empty .update() call detected!', + 'Update data does not contain any values to update.', + 'This will result in a faulty query.', + this.single.table ? `Table: ${this.single.table}.` : '', + this.single.update + ? `Columns: ${Object.keys(this.single.update)}.` + : '', + ].join(' ') + ); + } + + return vals; + } + + _formatGroupsItemValue(value, nulls) { + const { formatter } = this; + let nullOrder = ''; + if (nulls === 'last') { + nullOrder = ' is null'; + } else if (nulls === 'first') { + nullOrder = ' is not null'; + } + + let groupOrder; + if (value instanceof Raw) { + groupOrder = unwrapRaw_( + value, + undefined, + this.builder, + this.client, + this.bindingsHolder + ); + } else if (value instanceof QueryBuilder || nulls) { + groupOrder = '(' + formatter.columnize(value) + nullOrder + ')'; + } else { + groupOrder = formatter.columnize(value); + } + return groupOrder; + } + + _basicGroupOrder(item, type) { + const column = this._formatGroupsItemValue(item.value, item.nulls); + const direction = + type === 'order' && item.type !== 'orderByRaw' + ? ` ${direction_( + item.direction, + this.builder, + this.client, + this.bindingsHolder + )}` + : ''; + return column + direction; + } + + _groupOrder(item, type) { + return this._basicGroupOrder(item, type); + } + + _groupOrderNulls(item, type) { + const column = this._formatGroupsItemValue(item.value); + const direction = + type === 'order' && item.type !== 'orderByRaw' + ? ` ${direction_( + item.direction, + this.builder, + this.client, + this.bindingsHolder + )}` + : ''; + if (item.nulls && !(item.value instanceof Raw)) { + return `${column}${direction ? direction : ''} nulls ${item.nulls}`; + } + return column + direction; + } + + // Compiles the `order by` statements. + _groupsOrders(type) { + const items = this.grouped[type]; + if (!items) return ''; + const sql = items.map((item) => { + return this._groupOrder(item, type); + }); + return sql.length ? type + ' by ' + sql.join(', ') : ''; + } + + // Get the table name, wrapping it if necessary. + // Implemented as a property to prevent ordering issues as described in #704. + get tableName() { + if (!this._tableName) { + // Only call this.formatter.wrap() the first time this property is accessed. + let tableName = this.single.table; + const schemaName = this.single.schema; + + if (tableName && schemaName) { + const isQueryBuilder = tableName instanceof QueryBuilder; + const isRawQuery = tableName instanceof Raw; + const isFunction = typeof tableName === 'function'; + + if (!isQueryBuilder && !isRawQuery && !isFunction) { + tableName = `${schemaName}.${tableName}`; + } + } + + this._tableName = tableName + ? // Wrap subQuery with parenthesis, #3485 + wrap_( + tableName, + tableName instanceof QueryBuilder, + this.builder, + this.client, + this.bindingsHolder + ) + : ''; + } + return this._tableName; + } + + _jsonPathWrap(extraction) { + return this.client.parameter( + extraction.path || extraction[1], + this.builder, + this.bindingsHolder + ); + } + + // Json common functions + _jsonExtract(nameFunction, params) { + let extractions; + if (Array.isArray(params.column)) { + extractions = params.column; + } else { + extractions = [params]; + } + if (!Array.isArray(nameFunction)) { + nameFunction = [nameFunction]; + } + return extractions + .map((extraction) => { + let jsonCol = `${columnize_( + extraction.column || extraction[0], + this.builder, + this.client, + this.bindingsHolder + )}, ${this._jsonPathWrap(extraction)}`; + nameFunction.forEach((f) => { + jsonCol = f + '(' + jsonCol + ')'; + }); + const alias = extraction.alias || extraction[2]; + return alias + ? this.client.alias(jsonCol, this.formatter.wrap(alias)) + : jsonCol; + }) + .join(', '); + } + + _jsonSet(nameFunction, params) { + const jsonSet = `${nameFunction}(${columnize_( + params.column, + this.builder, + this.client, + this.bindingsHolder + )}, ${this.client.parameter( + params.path, + this.builder, + this.bindingsHolder + )}, ${this.client.parameter( + params.value, + this.builder, + this.bindingsHolder + )})`; + return params.alias + ? this.client.alias(jsonSet, this.formatter.wrap(params.alias)) + : jsonSet; + } + + _whereJsonPath(nameFunction, statement) { + return `${nameFunction}(${this._columnClause( + statement + )}, ${this._jsonPathWrap({ path: statement.jsonPath })}) ${operator_( + statement.operator, + this.builder, + this.client, + this.bindingsHolder + )} ${this._jsonValueClause(statement)}`; + } + + _onJsonPathEquals(nameJoinFunction, clause) { + return ( + nameJoinFunction + + '(' + + wrap_( + clause.columnFirst, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ', ' + + this.client.parameter( + clause.jsonPathFirst, + this.builder, + this.bindingsHolder + ) + + ') = ' + + nameJoinFunction + + '(' + + wrap_( + clause.columnSecond, + undefined, + this.builder, + this.client, + this.bindingsHolder + ) + + ', ' + + this.client.parameter( + clause.jsonPathSecond, + this.builder, + this.bindingsHolder + ) + + ')' + ); + } +} + +module.exports = QueryCompiler; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/raw.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/raw.js new file mode 100644 index 000000000..e4c2feb0c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/raw.js @@ -0,0 +1,139 @@ +// Raw +// ------- +const { EventEmitter } = require('events'); +const debug = require('debug'); +const assign = require('lodash/assign'); +const isPlainObject = require('lodash/isPlainObject'); +const reduce = require('lodash/reduce'); + +const { + replaceRawArrBindings, + replaceKeyBindings, +} = require('./formatter/rawFormatter'); +const helpers = require('./util/helpers'); +const saveAsyncStack = require('./util/save-async-stack'); +const { nanoid } = require('./util/nanoid'); +const { isNumber, isObject } = require('./util/is'); +const { + augmentWithBuilderInterface, +} = require('./builder-interface-augmenter'); + +const debugBindings = debug('knex:bindings'); + +class Raw extends EventEmitter { + constructor(client) { + super(); + + this.client = client; + + this.sql = ''; + this.bindings = []; + + // Todo: Deprecate + this._wrappedBefore = undefined; + this._wrappedAfter = undefined; + if (client && client.config) { + this._debug = client.config.debug; + saveAsyncStack(this, 4); + } + } + set(sql, bindings) { + this.sql = sql; + this.bindings = + (isObject(bindings) && !bindings.toSQL) || bindings === undefined + ? bindings + : [bindings]; + + return this; + } + + timeout(ms, { cancel } = {}) { + if (isNumber(ms) && ms > 0) { + this._timeout = ms; + if (cancel) { + this.client.assertCanCancelQuery(); + this._cancelOnTimeout = true; + } + } + return this; + } + + // Wraps the current sql with `before` and `after`. + wrap(before, after) { + this._wrappedBefore = before; + this._wrappedAfter = after; + return this; + } + + // Calls `toString` on the Knex object. + toString() { + return this.toQuery(); + } + + // Returns the raw sql for the query. + toSQL(method, tz) { + let obj; + if (Array.isArray(this.bindings)) { + obj = replaceRawArrBindings(this, this.client); + } else if (this.bindings && isPlainObject(this.bindings)) { + obj = replaceKeyBindings(this, this.client); + } else { + obj = { + method: 'raw', + sql: this.sql, + bindings: this.bindings === undefined ? [] : [this.bindings], + }; + } + + if (this._wrappedBefore) { + obj.sql = this._wrappedBefore + obj.sql; + } + if (this._wrappedAfter) { + obj.sql = obj.sql + this._wrappedAfter; + } + + obj.options = reduce(this._options, assign, {}); + + if (this._timeout) { + obj.timeout = this._timeout; + if (this._cancelOnTimeout) { + obj.cancelOnTimeout = this._cancelOnTimeout; + } + } + + obj.bindings = obj.bindings || []; + if (helpers.containsUndefined(obj.bindings)) { + const undefinedBindingIndices = helpers.getUndefinedIndices( + this.bindings + ); + debugBindings(obj.bindings); + throw new Error( + `Undefined binding(s) detected for keys [${undefinedBindingIndices}] when compiling RAW query: ${obj.sql}` + ); + } + + obj.__knexQueryUid = nanoid(); + + Object.defineProperties(obj, { + toNative: { + value: () => ({ + sql: this.client.positionBindings(obj.sql), + bindings: this.client.prepBindings(obj.bindings), + }), + enumerable: false, + }, + }); + + return obj; + } +} + +// Workaround to avoid circular dependency between wrappingFormatter.unwrapRaw and rawFormatter +Raw.prototype.isRawInstance = true; + +// Allow the `Raw` object to be utilized with full access to the relevant +// promise API. +augmentWithBuilderInterface(Raw); +helpers.addQueryContext(Raw); + +module.exports = Raw; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/ref.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/ref.js new file mode 100644 index 000000000..2e1c9eab6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/ref.js @@ -0,0 +1,39 @@ +const Raw = require('./raw'); + +class Ref extends Raw { + constructor(client, ref) { + super(client); + + this.ref = ref; + this._schema = null; + this._alias = null; + } + + withSchema(schema) { + this._schema = schema; + + return this; + } + + as(alias) { + this._alias = alias; + + return this; + } + + toSQL() { + const string = this._schema ? `${this._schema}.${this.ref}` : this.ref; + + const formatter = this.client.formatter(this); + + const ref = formatter.columnize(string); + + const sql = this._alias ? `${ref} as ${formatter.wrap(this._alias)}` : ref; + + this.set(sql, []); + + return super.toSQL(...arguments); + } +} + +module.exports = Ref; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/builder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/builder.js new file mode 100644 index 000000000..82eade4a8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/builder.js @@ -0,0 +1,115 @@ +const { EventEmitter } = require('events'); +const toArray = require('lodash/toArray'); +const assign = require('lodash/assign'); +const { addQueryContext } = require('../util/helpers'); +const saveAsyncStack = require('../util/save-async-stack'); +const { + augmentWithBuilderInterface, +} = require('../builder-interface-augmenter'); + +// Constructor for the builder instance, typically called from +// `knex.builder`, accepting the current `knex` instance, +// and pulling out the `client` and `grammar` from the current +// knex instance. +class SchemaBuilder extends EventEmitter { + constructor(client) { + super(); + this.client = client; + this._sequence = []; + + if (client.config) { + this._debug = client.config.debug; + saveAsyncStack(this, 4); + } + } + + withSchema(schemaName) { + this._schema = schemaName; + return this; + } + + toString() { + return this.toQuery(); + } + + toSQL() { + return this.client.schemaCompiler(this).toSQL(); + } + + async generateDdlCommands() { + return await this.client.schemaCompiler(this).generateDdlCommands(); + } +} + +// Each of the schema builder methods just add to the +// "_sequence" array for consistency. +[ + 'createTable', + 'createTableIfNotExists', + 'createTableLike', + 'createView', + 'createViewOrReplace', + 'createMaterializedView', + 'refreshMaterializedView', + 'dropView', + 'dropViewIfExists', + 'dropMaterializedView', + 'dropMaterializedViewIfExists', + 'createSchema', + 'createSchemaIfNotExists', + 'dropSchema', + 'dropSchemaIfExists', + 'createExtension', + 'createExtensionIfNotExists', + 'dropExtension', + 'dropExtensionIfExists', + 'table', + 'alterTable', + 'view', + 'alterView', + 'hasTable', + 'hasColumn', + 'dropTable', + 'renameTable', + 'renameView', + 'dropTableIfExists', + 'raw', +].forEach(function (method) { + SchemaBuilder.prototype[method] = function () { + if (method === 'createTableIfNotExists') { + this.client.logger.warn( + [ + 'Use async .hasTable to check if table exists and then use plain .createTable. Since ', + '.createTableIfNotExists actually just generates plain "CREATE TABLE IF NOT EXIST..." ', + 'query it will not work correctly if there are any alter table queries generated for ', + 'columns afterwards. To not break old migrations this function is left untouched for now', + ', but it should not be used when writing new code and it is removed from documentation.', + ].join('') + ); + } + if (method === 'table') method = 'alterTable'; + if (method === 'view') method = 'alterView'; + this._sequence.push({ + method, + args: toArray(arguments), + }); + return this; + }; +}); + +SchemaBuilder.extend = (methodName, fn) => { + if ( + Object.prototype.hasOwnProperty.call(SchemaBuilder.prototype, methodName) + ) { + throw new Error( + `Can't extend SchemaBuilder with existing method ('${methodName}').` + ); + } + + assign(SchemaBuilder.prototype, { [methodName]: fn }); +}; + +augmentWithBuilderInterface(SchemaBuilder); +addQueryContext(SchemaBuilder); + +module.exports = SchemaBuilder; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/columnbuilder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/columnbuilder.js new file mode 100644 index 000000000..f7e497ca8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/columnbuilder.js @@ -0,0 +1,146 @@ +const extend = require('lodash/extend'); +const assign = require('lodash/assign'); +const toArray = require('lodash/toArray'); +const { addQueryContext } = require('../util/helpers'); + +// The chainable interface off the original "column" method. +class ColumnBuilder { + constructor(client, tableBuilder, type, args) { + this.client = client; + this._method = 'add'; + this._single = {}; + this._modifiers = {}; + this._statements = []; + this._type = columnAlias[type] || type; + this._args = args; + this._tableBuilder = tableBuilder; + + // If we're altering the table, extend the object + // with the available "alter" methods. + if (tableBuilder._method === 'alter') { + extend(this, AlterMethods); + } + } + + // Specify that the current column "references" a column, + // which may be tableName.column or just "column" + references(value) { + return this._tableBuilder.foreign + .call(this._tableBuilder, this._args[0], undefined, this) + ._columnBuilder(this) + .references(value); + } +} + +// All of the modifier methods that can be used to modify the current query. +const modifiers = [ + 'default', + 'defaultsTo', + 'defaultTo', + 'unsigned', + 'nullable', + 'first', + 'after', + 'comment', + 'collate', + 'check', + 'checkPositive', + 'checkNegative', + 'checkIn', + 'checkNotIn', + 'checkBetween', + 'checkLength', + 'checkRegex', +]; + +// Aliases for convenience. +const aliasMethod = { + default: 'defaultTo', + defaultsTo: 'defaultTo', +}; + +// If we call any of the modifiers (index or otherwise) on the chainable, we pretend +// as though we're calling `table.method(column)` directly. +modifiers.forEach(function (method) { + const key = aliasMethod[method] || method; + ColumnBuilder.prototype[method] = function () { + this._modifiers[key] = toArray(arguments); + return this; + }; +}); + +addQueryContext(ColumnBuilder); + +ColumnBuilder.prototype.notNull = ColumnBuilder.prototype.notNullable = + function notNullable() { + return this.nullable(false); + }; + +['index', 'primary', 'unique'].forEach(function (method) { + ColumnBuilder.prototype[method] = function () { + if (this._type.toLowerCase().indexOf('increments') === -1) { + this._tableBuilder[method].apply( + this._tableBuilder, + [this._args[0]].concat(toArray(arguments)) + ); + } + return this; + }; +}); + +ColumnBuilder.extend = (methodName, fn) => { + if ( + Object.prototype.hasOwnProperty.call(ColumnBuilder.prototype, methodName) + ) { + throw new Error( + `Can't extend ColumnBuilder with existing method ('${methodName}').` + ); + } + + assign(ColumnBuilder.prototype, { [methodName]: fn }); +}; + +const AlterMethods = {}; + +// Specify that the column is to be dropped. This takes precedence +// over all other rules for the column. +AlterMethods.drop = function () { + this._single.drop = true; + + return this; +}; + +// Specify the "type" that we're looking to set the +// Knex takes no responsibility for any data-loss that may +// occur when changing data types. +AlterMethods.alterType = function (type) { + this._statements.push({ + grouping: 'alterType', + value: type, + }); + + return this; +}; + +// Set column method to alter (default is add). +AlterMethods.alter = function ({ + alterNullable = true, + alterType = true, +} = {}) { + this._method = 'alter'; + this.alterNullable = alterNullable; + this.alterType = alterType; + + return this; +}; + +// Alias a few methods for clarity when processing. +const columnAlias = { + float: 'floating', + enum: 'enu', + boolean: 'bool', + string: 'varchar', + bigint: 'bigInteger', +}; + +module.exports = ColumnBuilder; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/columncompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/columncompiler.js new file mode 100644 index 000000000..e7d495fd7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/columncompiler.js @@ -0,0 +1,307 @@ +// Column Compiler +// Used for designating column definitions +// during the table "create" / "alter" statements. +// ------- +const helpers = require('./internal/helpers'); +const groupBy = require('lodash/groupBy'); +const first = require('lodash/first'); +const has = require('lodash/has'); +const tail = require('lodash/tail'); +const { toNumber } = require('../util/helpers'); +const { formatDefault } = require('../formatter/formatterUtils'); +const { operator: operator_ } = require('../formatter/wrappingFormatter'); + +class ColumnCompiler { + constructor(client, tableCompiler, columnBuilder) { + this.client = client; + this.tableCompiler = tableCompiler; + this.columnBuilder = columnBuilder; + this._commonBuilder = this.columnBuilder; + this.args = columnBuilder._args; + this.type = columnBuilder._type.toLowerCase(); + this.grouped = groupBy(columnBuilder._statements, 'grouping'); + this.modified = columnBuilder._modifiers; + this.isIncrements = this.type.indexOf('increments') !== -1; + + this.formatter = client.formatter(columnBuilder); + this.bindings = []; + this.formatter.bindings = this.bindings; + this.bindingsHolder = this; + + this.sequence = []; + this.modifiers = []; + + this.checksCount = 0; + } + + _addCheckModifiers() { + this.modifiers.push( + 'check', + 'checkPositive', + 'checkNegative', + 'checkIn', + 'checkNotIn', + 'checkBetween', + 'checkLength', + 'checkRegex' + ); + } + + defaults(label) { + if (Object.prototype.hasOwnProperty.call(this._defaultMap, label)) { + return this._defaultMap[label].bind(this)(); + } else { + throw new Error( + `There is no default for the specified identifier ${label}` + ); + } + } + + // To convert to sql, we first go through and build the + // column as it would be in the insert statement + toSQL() { + this.pushQuery(this.compileColumn()); + if (this.sequence.additional) { + this.sequence = this.sequence.concat(this.sequence.additional); + } + return this.sequence; + } + + // Compiles a column. + compileColumn() { + return ( + this.formatter.wrap(this.getColumnName()) + + ' ' + + this.getColumnType() + + this.getModifiers() + ); + } + + // Assumes the autoincrementing key is named `id` if not otherwise specified. + getColumnName() { + const value = first(this.args); + return value || this.defaults('columnName'); + } + + getColumnType() { + // Column type is cached so side effects (such as in pg native enums) are only run once + if (!this._columnType) { + const type = this[this.type]; + this._columnType = + typeof type === 'function' ? type.apply(this, tail(this.args)) : type; + } + + return this._columnType; + } + + getModifiers() { + const modifiers = []; + + for (let i = 0, l = this.modifiers.length; i < l; i++) { + const modifier = this.modifiers[i]; + + //Cannot allow 'nullable' modifiers on increments types + if (!this.isIncrements || (this.isIncrements && modifier === 'comment')) { + if (has(this.modified, modifier)) { + const val = this[modifier].apply(this, this.modified[modifier]); + if (val) modifiers.push(val); + } + } + } + + return modifiers.length > 0 ? ` ${modifiers.join(' ')}` : ''; + } + + // Types + // ------ + varchar(length) { + return `varchar(${toNumber(length, 255)})`; + } + + floating(precision, scale) { + return `float(${toNumber(precision, 8)}, ${toNumber(scale, 2)})`; + } + + decimal(precision, scale) { + if (precision === null) { + throw new Error( + 'Specifying no precision on decimal columns is not supported for that SQL dialect.' + ); + } + return `decimal(${toNumber(precision, 8)}, ${toNumber(scale, 2)})`; + } + + // Used to support custom types + specifictype(type) { + return type; + } + + // Modifiers + // ------- + + nullable(nullable) { + return nullable === false ? 'not null' : 'null'; + } + + notNullable() { + return this.nullable(false); + } + + defaultTo(value) { + return `default ${formatDefault(value, this.type, this.client)}`; + } + + increments(options = { primaryKey: true }) { + return ( + 'integer not null' + + (this.tableCompiler._canBeAddPrimaryKey(options) ? ' primary key' : '') + + ' autoincrement' + ); + } + + bigincrements(options = { primaryKey: true }) { + return this.increments(options); + } + + _pushAlterCheckQuery(checkPredicate, constraintName) { + let checkName = constraintName; + if (!checkName) { + this.checksCount++; + checkName = + this.tableCompiler.tableNameRaw + + '_' + + this.getColumnName() + + '_' + + this.checksCount; + } + this.pushAdditional(function () { + this.pushQuery( + `alter table ${this.tableCompiler.tableName()} add constraint ${checkName} check(${checkPredicate})` + ); + }); + } + + _checkConstraintName(constraintName) { + return constraintName ? `constraint ${constraintName} ` : ''; + } + + _check(checkPredicate, constraintName) { + if (this.columnBuilder._method === 'alter') { + this._pushAlterCheckQuery(checkPredicate, constraintName); + return ''; + } + return `${this._checkConstraintName( + constraintName + )}check (${checkPredicate})`; + } + + checkPositive(constraintName) { + return this._check( + `${this.formatter.wrap(this.getColumnName())} ${operator_( + '>', + this.columnBuilder, + this.bindingsHolder + )} 0`, + constraintName + ); + } + + checkNegative(constraintName) { + return this._check( + `${this.formatter.wrap(this.getColumnName())} ${operator_( + '<', + this.columnBuilder, + this.bindingsHolder + )} 0`, + constraintName + ); + } + + _checkIn(values, constraintName, not) { + return this._check( + `${this.formatter.wrap(this.getColumnName())} ${ + not ? 'not ' : '' + }in (${values.map((v) => this.client._escapeBinding(v)).join(',')})`, + constraintName + ); + } + + checkIn(values, constraintName) { + return this._checkIn(values, constraintName); + } + + checkNotIn(values, constraintName) { + return this._checkIn(values, constraintName, true); + } + + checkBetween(intervals, constraintName) { + if ( + intervals.length === 2 && + !Array.isArray(intervals[0]) && + !Array.isArray(intervals[1]) + ) { + intervals = [intervals]; + } + const intervalChecks = intervals + .map((interval) => { + return `${this.formatter.wrap( + this.getColumnName() + )} between ${this.client._escapeBinding( + interval[0] + )} and ${this.client._escapeBinding(interval[1])}`; + }) + .join(' or '); + return this._check(intervalChecks, constraintName); + } + + checkLength(operator, length, constraintName) { + return this._check( + `length(${this.formatter.wrap(this.getColumnName())}) ${operator_( + operator, + this.columnBuilder, + this.bindingsHolder + )} ${toNumber(length)}`, + constraintName + ); + } +} + +ColumnCompiler.prototype.binary = 'blob'; +ColumnCompiler.prototype.bool = 'boolean'; +ColumnCompiler.prototype.date = 'date'; +ColumnCompiler.prototype.datetime = 'datetime'; +ColumnCompiler.prototype.time = 'time'; +ColumnCompiler.prototype.timestamp = 'timestamp'; +ColumnCompiler.prototype.geometry = 'geometry'; +ColumnCompiler.prototype.geography = 'geography'; +ColumnCompiler.prototype.point = 'point'; +ColumnCompiler.prototype.enu = 'varchar'; +ColumnCompiler.prototype.bit = ColumnCompiler.prototype.json = 'text'; +ColumnCompiler.prototype.uuid = ({ + useBinaryUuid = false, + primaryKey = false, +} = {}) => (useBinaryUuid ? 'binary(16)' : 'char(36)'); +ColumnCompiler.prototype.integer = + ColumnCompiler.prototype.smallint = + ColumnCompiler.prototype.mediumint = + 'integer'; +ColumnCompiler.prototype.biginteger = 'bigint'; +ColumnCompiler.prototype.text = 'text'; +ColumnCompiler.prototype.tinyint = 'tinyint'; + +ColumnCompiler.prototype.pushQuery = helpers.pushQuery; +ColumnCompiler.prototype.pushAdditional = helpers.pushAdditional; +ColumnCompiler.prototype.unshiftQuery = helpers.unshiftQuery; + +ColumnCompiler.prototype._defaultMap = { + columnName: function () { + if (!this.isIncrements) { + throw new Error( + `You did not specify a column name for the ${this.type} column.` + ); + } + return 'id'; + }, +}; + +module.exports = ColumnCompiler; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/compiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/compiler.js new file mode 100644 index 000000000..8b3bbbaa6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/compiler.js @@ -0,0 +1,187 @@ +const { + pushQuery, + pushAdditional, + unshiftQuery, +} = require('./internal/helpers'); + +// The "SchemaCompiler" takes all of the query statements which have been +// gathered in the "SchemaBuilder" and turns them into an array of +// properly formatted / bound query strings. +class SchemaCompiler { + constructor(client, builder) { + this.builder = builder; + this._commonBuilder = this.builder; + this.client = client; + this.schema = builder._schema; + + this.bindings = []; + this.bindingsHolder = this; + this.formatter = client.formatter(builder); + this.formatter.bindings = this.bindings; + this.sequence = []; + } + + createSchema() { + throwOnlyPGError('createSchema'); + } + + createSchemaIfNotExists() { + throwOnlyPGError('createSchemaIfNotExists'); + } + + dropSchema() { + throwOnlyPGError('dropSchema'); + } + + dropSchemaIfExists() { + throwOnlyPGError('dropSchemaIfExists'); + } + + dropTable(tableName) { + this.pushQuery( + this.dropTablePrefix + + this.formatter.wrap(prefixedTableName(this.schema, tableName)) + ); + } + + dropTableIfExists(tableName) { + this.pushQuery( + this.dropTablePrefix + + 'if exists ' + + this.formatter.wrap(prefixedTableName(this.schema, tableName)) + ); + } + + dropView(viewName) { + this._dropView(viewName, false, false); + } + + dropViewIfExists(viewName) { + this._dropView(viewName, true, false); + } + + dropMaterializedView(viewName) { + throw new Error('materialized views are not supported by this dialect.'); + } + + dropMaterializedViewIfExists(viewName) { + throw new Error('materialized views are not supported by this dialect.'); + } + + renameView(from, to) { + throw new Error( + 'rename view is not supported by this dialect (instead drop then create another view).' + ); + } + + refreshMaterializedView() { + throw new Error('materialized views are not supported by this dialect.'); + } + + _dropView(viewName, ifExists, materialized) { + this.pushQuery( + (materialized ? this.dropMaterializedViewPrefix : this.dropViewPrefix) + + (ifExists ? 'if exists ' : '') + + this.formatter.wrap(prefixedTableName(this.schema, viewName)) + ); + } + + raw(sql, bindings) { + this.sequence.push(this.client.raw(sql, bindings).toSQL()); + } + + toSQL() { + const sequence = this.builder._sequence; + for (let i = 0, l = sequence.length; i < l; i++) { + const query = sequence[i]; + this[query.method].apply(this, query.args); + } + return this.sequence; + } + + async generateDdlCommands() { + const generatedCommands = this.toSQL(); + return { + pre: [], + sql: Array.isArray(generatedCommands) + ? generatedCommands + : [generatedCommands], + check: null, + post: [], + }; + } +} + +SchemaCompiler.prototype.dropTablePrefix = 'drop table '; +SchemaCompiler.prototype.dropViewPrefix = 'drop view '; +SchemaCompiler.prototype.dropMaterializedViewPrefix = 'drop materialized view '; +SchemaCompiler.prototype.alterViewPrefix = 'alter view '; + +SchemaCompiler.prototype.alterTable = buildTable('alter'); +SchemaCompiler.prototype.createTable = buildTable('create'); +SchemaCompiler.prototype.createTableIfNotExists = buildTable('createIfNot'); +SchemaCompiler.prototype.createTableLike = buildTable('createLike'); + +SchemaCompiler.prototype.createView = buildView('create'); +SchemaCompiler.prototype.createViewOrReplace = buildView('createOrReplace'); +SchemaCompiler.prototype.createMaterializedView = buildView( + 'createMaterializedView' +); +SchemaCompiler.prototype.alterView = buildView('alter'); + +SchemaCompiler.prototype.pushQuery = pushQuery; +SchemaCompiler.prototype.pushAdditional = pushAdditional; +SchemaCompiler.prototype.unshiftQuery = unshiftQuery; + +function build(builder) { + // pass queryContext down to tableBuilder but do not overwrite it if already set + const queryContext = this.builder.queryContext(); + if (queryContext !== undefined && builder.queryContext() === undefined) { + builder.queryContext(queryContext); + } + + builder.setSchema(this.schema); + const sql = builder.toSQL(); + + for (let i = 0, l = sql.length; i < l; i++) { + this.sequence.push(sql[i]); + } +} + +function buildTable(type) { + if (type === 'createLike') { + return function (tableName, tableNameLike, fn) { + const builder = this.client.tableBuilder( + type, + tableName, + tableNameLike, + fn + ); + build.call(this, builder); + }; + } else { + return function (tableName, fn) { + const builder = this.client.tableBuilder(type, tableName, null, fn); + build.call(this, builder); + }; + } +} + +function buildView(type) { + return function (viewName, fn) { + const builder = this.client.viewBuilder(type, viewName, fn); + build.call(this, builder); + }; +} + +function prefixedTableName(prefix, table) { + return prefix ? `${prefix}.${table}` : table; +} + +function throwOnlyPGError(operationName) { + throw new Error( + `${operationName} is not supported for this dialect (only PostgreSQL supports it currently).` + ); +} + +module.exports = SchemaCompiler; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/internal/helpers.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/internal/helpers.js new file mode 100644 index 000000000..77d9621ed --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/internal/helpers.js @@ -0,0 +1,55 @@ +const tail = require('lodash/tail'); +const { isString } = require('../../util/is'); + +// Push a new query onto the compiled "sequence" stack, +// creating a new formatter, returning the compiler. +function pushQuery(query) { + if (!query) return; + if (isString(query)) { + query = { sql: query }; + } + if (!query.bindings) { + query.bindings = this.bindingsHolder.bindings; + } + this.sequence.push(query); + + this.formatter = this.client.formatter(this._commonBuilder); + this.bindings = []; + this.formatter.bindings = this.bindings; +} + +// Used in cases where we need to push some additional column specific statements. +function pushAdditional(fn) { + const child = new this.constructor( + this.client, + this.tableCompiler, + this.columnBuilder + ); + fn.call(child, tail(arguments)); + this.sequence.additional = (this.sequence.additional || []).concat( + child.sequence + ); +} + +// Unshift a new query onto the compiled "sequence" stack, +// creating a new formatter, returning the compiler. +function unshiftQuery(query) { + if (!query) return; + if (isString(query)) { + query = { sql: query }; + } + if (!query.bindings) { + query.bindings = this.bindingsHolder.bindings; + } + this.sequence.unshift(query); + + this.formatter = this.client.formatter(this._commonBuilder); + this.bindings = []; + this.formatter.bindings = this.bindings; +} + +module.exports = { + pushAdditional, + pushQuery, + unshiftQuery, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/tablebuilder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/tablebuilder.js new file mode 100644 index 000000000..99f849a14 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/tablebuilder.js @@ -0,0 +1,376 @@ +// TableBuilder + +// Takes the function passed to the "createTable" or "table/editTable" +// functions and calls it with the "TableBuilder" as both the context and +// the first argument. Inside this function we can specify what happens to the +// method, pushing everything we want to do onto the "allStatements" array, +// which is then compiled into sql. +// ------ +const each = require('lodash/each'); +const extend = require('lodash/extend'); +const assign = require('lodash/assign'); +const toArray = require('lodash/toArray'); +const helpers = require('../util/helpers'); +const { isString, isFunction, isObject } = require('../util/is'); + +class TableBuilder { + constructor(client, method, tableName, tableNameLike, fn) { + this.client = client; + this._fn = fn; + this._method = method; + this._schemaName = undefined; + this._tableName = tableName; + this._tableNameLike = tableNameLike; + this._statements = []; + this._single = {}; + + if (!tableNameLike && !isFunction(this._fn)) { + throw new TypeError( + 'A callback function must be supplied to calls against `.createTable` ' + + 'and `.table`' + ); + } + } + + setSchema(schemaName) { + this._schemaName = schemaName; + } + + // Convert the current tableBuilder object "toSQL" + // giving us additional methods if we're altering + // rather than creating the table. + toSQL() { + if (this._method === 'alter') { + extend(this, AlterMethods); + } + // With 'create table ... like' callback function is useless. + if (this._fn) { + this._fn.call(this, this); + } + return this.client.tableCompiler(this).toSQL(); + } + + // The "timestamps" call is really just sets the `created_at` and `updated_at` columns. + + timestamps(useTimestamps, defaultToNow, useCamelCase) { + if (isObject(useTimestamps)) { + ({ useTimestamps, defaultToNow, useCamelCase } = useTimestamps); + } + const method = useTimestamps === true ? 'timestamp' : 'datetime'; + const createdAt = this[method](useCamelCase ? 'createdAt' : 'created_at'); + const updatedAt = this[method](useCamelCase ? 'updatedAt' : 'updated_at'); + + if (defaultToNow === true) { + const now = this.client.raw('CURRENT_TIMESTAMP'); + createdAt.notNullable().defaultTo(now); + updatedAt.notNullable().defaultTo(now); + } + } + + // Set the comment value for a table, they're only allowed to be called + // once per table. + comment(value) { + if (typeof value !== 'string') { + throw new TypeError('Table comment must be string'); + } + this._single.comment = value; + } + + // Set a foreign key on the table, calling + // `table.foreign('column_name').references('column').on('table').onDelete()... + // Also called from the ColumnBuilder context when chaining. + foreign(column, keyName) { + const foreignData = { column: column, keyName: keyName }; + this._statements.push({ + grouping: 'alterTable', + method: 'foreign', + args: [foreignData], + }); + let returnObj = { + references(tableColumn) { + let pieces; + if (isString(tableColumn)) { + pieces = tableColumn.split('.'); + } + if (!pieces || pieces.length === 1) { + foreignData.references = pieces ? pieces[0] : tableColumn; + return { + on(tableName) { + if (typeof tableName !== 'string') { + throw new TypeError( + `Expected tableName to be a string, got: ${typeof tableName}` + ); + } + foreignData.inTable = tableName; + return returnObj; + }, + inTable() { + return this.on.apply(this, arguments); + }, + }; + } + foreignData.inTable = pieces[0]; + foreignData.references = pieces[1]; + return returnObj; + }, + withKeyName(keyName) { + foreignData.keyName = keyName; + return returnObj; + }, + onUpdate(statement) { + foreignData.onUpdate = statement; + return returnObj; + }, + onDelete(statement) { + foreignData.onDelete = statement; + return returnObj; + }, + deferrable: (type) => { + const unSupported = [ + 'mysql', + 'mssql', + 'redshift', + 'mysql2', + 'oracledb', + ]; + if (unSupported.indexOf(this.client.dialect) !== -1) { + throw new Error(`${this.client.dialect} does not support deferrable`); + } + foreignData.deferrable = type; + return returnObj; + }, + _columnBuilder(builder) { + extend(builder, returnObj); + returnObj = builder; + return builder; + }, + }; + return returnObj; + } + + check(checkPredicate, bindings, constraintName) { + this._statements.push({ + grouping: 'checks', + args: [checkPredicate, bindings, constraintName], + }); + return this; + } +} + +[ + // Each of the index methods can be called individually, with the + // column name to be used, e.g. table.unique('column'). + 'index', + 'primary', + 'unique', + + // Key specific + 'dropPrimary', + 'dropUnique', + 'dropIndex', + 'dropForeign', +].forEach((method) => { + TableBuilder.prototype[method] = function () { + this._statements.push({ + grouping: 'alterTable', + method, + args: toArray(arguments), + }); + return this; + }; +}); + +// Warn for dialect-specific table methods, since that's the +// only time these are supported. +const specialMethods = { + mysql: ['engine', 'charset', 'collate'], + postgresql: ['inherits'], +}; +each(specialMethods, function (methods, dialect) { + methods.forEach(function (method) { + TableBuilder.prototype[method] = function (value) { + if (this.client.dialect !== dialect) { + throw new Error( + `Knex only supports ${method} statement with ${dialect}.` + ); + } + if (this._method === 'alter') { + throw new Error( + `Knex does not support altering the ${method} outside of create ` + + `table, please use knex.raw statement.` + ); + } + this._single[method] = value; + }; + }); +}); + +helpers.addQueryContext(TableBuilder); + +// Each of the column types that we can add, we create a new ColumnBuilder +// instance and push it onto the statements array. +const columnTypes = [ + // Numeric + 'tinyint', + 'smallint', + 'mediumint', + 'int', + 'bigint', + 'decimal', + 'float', + 'double', + 'real', + 'bit', + 'boolean', + 'serial', + + // Date / Time + 'date', + 'datetime', + 'timestamp', + 'time', + 'year', + + // Geometry + 'geometry', + 'geography', + 'point', + + // String + 'char', + 'varchar', + 'tinytext', + 'tinyText', + 'text', + 'mediumtext', + 'mediumText', + 'longtext', + 'longText', + 'binary', + 'varbinary', + 'tinyblob', + 'tinyBlob', + 'mediumblob', + 'mediumBlob', + 'blob', + 'longblob', + 'longBlob', + 'enum', + 'set', + + // Increments, Aliases, and Additional + 'bool', + 'dateTime', + 'increments', + 'bigincrements', + 'bigIncrements', + 'integer', + 'biginteger', + 'bigInteger', + 'string', + 'json', + 'jsonb', + 'uuid', + 'enu', + 'specificType', +]; + +// For each of the column methods, create a new "ColumnBuilder" interface, +// push it onto the "allStatements" stack, and then return the interface, +// with which we can add indexes, etc. +columnTypes.forEach((type) => { + TableBuilder.prototype[type] = function () { + const args = toArray(arguments); + const builder = this.client.columnBuilder(this, type, args); + this._statements.push({ + grouping: 'columns', + builder, + }); + return builder; + }; +}); + +const AlterMethods = { + // Renames the current column `from` the current + // TODO: this.column(from).rename(to) + renameColumn(from, to) { + this._statements.push({ + grouping: 'alterTable', + method: 'renameColumn', + args: [from, to], + }); + return this; + }, + + dropTimestamps() { + // arguments[0] = useCamelCase + return this.dropColumns( + arguments[0] === true + ? ['createdAt', 'updatedAt'] + : ['created_at', 'updated_at'] + ); + }, + + setNullable(column) { + this._statements.push({ + grouping: 'alterTable', + method: 'setNullable', + args: [column], + }); + + return this; + }, + + check(checkPredicate, bindings, constraintName) { + this._statements.push({ + grouping: 'alterTable', + method: 'check', + args: [checkPredicate, bindings, constraintName], + }); + }, + + dropChecks() { + this._statements.push({ + grouping: 'alterTable', + method: 'dropChecks', + args: toArray(arguments), + }); + }, + + dropNullable(column) { + this._statements.push({ + grouping: 'alterTable', + method: 'dropNullable', + args: [column], + }); + + return this; + }, + + // TODO: changeType +}; + +// Drop a column from the current table. +// TODO: Enable this.column(columnName).drop(); +AlterMethods.dropColumn = AlterMethods.dropColumns = function () { + this._statements.push({ + grouping: 'alterTable', + method: 'dropColumn', + args: toArray(arguments), + }); + return this; +}; + +TableBuilder.extend = (methodName, fn) => { + if ( + Object.prototype.hasOwnProperty.call(TableBuilder.prototype, methodName) + ) { + throw new Error( + `Can't extend TableBuilder with existing method ('${methodName}').` + ); + } + + assign(TableBuilder.prototype, { [methodName]: fn }); +}; + +module.exports = TableBuilder; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/tablecompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/tablecompiler.js new file mode 100644 index 000000000..68d2d4958 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/tablecompiler.js @@ -0,0 +1,439 @@ +/* eslint max-len:0 */ + +// Table Compiler +// ------- +const { + pushAdditional, + pushQuery, + unshiftQuery, +} = require('./internal/helpers'); +const helpers = require('../util/helpers'); +const groupBy = require('lodash/groupBy'); +const indexOf = require('lodash/indexOf'); +const isEmpty = require('lodash/isEmpty'); +const tail = require('lodash/tail'); +const { normalizeArr } = require('../util/helpers'); + +class TableCompiler { + constructor(client, tableBuilder) { + this.client = client; + this.tableBuilder = tableBuilder; + this._commonBuilder = this.tableBuilder; + this.method = tableBuilder._method; + this.schemaNameRaw = tableBuilder._schemaName; + this.tableNameRaw = tableBuilder._tableName; + this.tableNameLikeRaw = tableBuilder._tableNameLike; + this.single = tableBuilder._single; + this.grouped = groupBy(tableBuilder._statements, 'grouping'); + + this.formatter = client.formatter(tableBuilder); + this.bindings = []; + this.formatter.bindings = this.bindings; + this.bindingsHolder = this; + + this.sequence = []; + this._formatting = client.config && client.config.formatting; + + this.checksCount = 0; + } + + // Convert the tableCompiler toSQL + toSQL() { + this[this.method](); + return this.sequence; + } + + // Column Compilation + // ------- + + // If this is a table "creation", we need to first run through all + // of the columns to build them into a single string, + // and then run through anything else and push it to the query sequence. + create(ifNot, like) { + const columnBuilders = this.getColumns(); + const columns = columnBuilders.map((col) => col.toSQL()); + const columnTypes = this.getColumnTypes(columns); + if (this.createAlterTableMethods) { + this.alterTableForCreate(columnTypes); + } + this.createQuery(columnTypes, ifNot, like); + this.columnQueries(columns); + delete this.single.comment; + this.alterTable(); + } + + // Only create the table if it doesn't exist. + createIfNot() { + this.create(true); + } + + createLike() { + this.create(false, true); + } + + createLikeIfNot() { + this.create(true, true); + } + + // If we're altering the table, we need to one-by-one + // go through and handle each of the queries associated + // with altering the table's schema. + alter() { + const addColBuilders = this.getColumns(); + const addColumns = addColBuilders.map((col) => col.toSQL()); + const alterColBuilders = this.getColumns('alter'); + const alterColumns = alterColBuilders.map((col) => col.toSQL()); + const addColumnTypes = this.getColumnTypes(addColumns); + const alterColumnTypes = this.getColumnTypes(alterColumns); + + this.addColumns(addColumnTypes); + this.alterColumns(alterColumnTypes, alterColBuilders); + this.columnQueries(addColumns); + this.columnQueries(alterColumns); + this.alterTable(); + } + + foreign(foreignData) { + if (foreignData.inTable && foreignData.references) { + const keyName = foreignData.keyName + ? this.formatter.wrap(foreignData.keyName) + : this._indexCommand('foreign', this.tableNameRaw, foreignData.column); + const column = this.formatter.columnize(foreignData.column); + const references = this.formatter.columnize(foreignData.references); + const inTable = this.formatter.wrap(foreignData.inTable); + const onUpdate = foreignData.onUpdate + ? (this.lowerCase ? ' on update ' : ' ON UPDATE ') + + foreignData.onUpdate + : ''; + const onDelete = foreignData.onDelete + ? (this.lowerCase ? ' on delete ' : ' ON DELETE ') + + foreignData.onDelete + : ''; + const deferrable = foreignData.deferrable + ? this.lowerCase + ? ` deferrable initially ${foreignData.deferrable.toLowerCase()} ` + : ` DEFERRABLE INITIALLY ${foreignData.deferrable.toUpperCase()} ` + : ''; + if (this.lowerCase) { + this.pushQuery( + (!this.forCreate ? `alter table ${this.tableName()} add ` : '') + + 'constraint ' + + keyName + + ' ' + + 'foreign key (' + + column + + ') references ' + + inTable + + ' (' + + references + + ')' + + onUpdate + + onDelete + + deferrable + ); + } else { + this.pushQuery( + (!this.forCreate ? `ALTER TABLE ${this.tableName()} ADD ` : '') + + 'CONSTRAINT ' + + keyName + + ' ' + + 'FOREIGN KEY (' + + column + + ') REFERENCES ' + + inTable + + ' (' + + references + + ')' + + onUpdate + + onDelete + + deferrable + ); + } + } + } + + // Get all of the column sql & bindings individually for building the table queries. + getColumnTypes(columns) { + return columns.reduce( + function (memo, columnSQL) { + const column = columnSQL[0]; + memo.sql.push(column.sql); + memo.bindings.concat(column.bindings); + return memo; + }, + { sql: [], bindings: [] } + ); + } + + // Adds all of the additional queries from the "column" + columnQueries(columns) { + const queries = columns.reduce(function (memo, columnSQL) { + const column = tail(columnSQL); + if (!isEmpty(column)) return memo.concat(column); + return memo; + }, []); + for (const q of queries) { + this.pushQuery(q); + } + } + + // All of the columns to "add" for the query + addColumns(columns, prefix) { + prefix = prefix || this.addColumnsPrefix; + + if (columns.sql.length > 0) { + const columnSql = columns.sql.map((column) => { + return prefix + column; + }); + this.pushQuery({ + sql: + (this.lowerCase ? 'alter table ' : 'ALTER TABLE ') + + this.tableName() + + ' ' + + columnSql.join(', '), + bindings: columns.bindings, + }); + } + } + + alterColumns(columns, colBuilders) { + if (columns.sql.length > 0) { + this.addColumns(columns, this.alterColumnsPrefix, colBuilders); + } + } + + // Compile the columns as needed for the current create or alter table + getColumns(method) { + const columns = this.grouped.columns || []; + method = method || 'add'; + + const queryContext = this.tableBuilder.queryContext(); + + return columns + .filter((column) => column.builder._method === method) + .map((column) => { + // pass queryContext down to columnBuilder but do not overwrite it if already set + if ( + queryContext !== undefined && + column.builder.queryContext() === undefined + ) { + column.builder.queryContext(queryContext); + } + return this.client.columnCompiler(this, column.builder); + }); + } + + tableName() { + const name = this.schemaNameRaw + ? `${this.schemaNameRaw}.${this.tableNameRaw}` + : this.tableNameRaw; + + return this.formatter.wrap(name); + } + + tableNameLike() { + const name = this.schemaNameRaw + ? `${this.schemaNameRaw}.${this.tableNameLikeRaw}` + : this.tableNameLikeRaw; + + return this.formatter.wrap(name); + } + + // Generate all of the alter column statements necessary for the query. + alterTable() { + const alterTable = this.grouped.alterTable || []; + for (let i = 0, l = alterTable.length; i < l; i++) { + const statement = alterTable[i]; + if (this[statement.method]) { + this[statement.method].apply(this, statement.args); + } else { + this.client.logger.error(`Debug: ${statement.method} does not exist`); + } + } + for (const item in this.single) { + if (typeof this[item] === 'function') this[item](this.single[item]); + } + } + + alterTableForCreate(columnTypes) { + this.forCreate = true; + const savedSequence = this.sequence; + const alterTable = this.grouped.alterTable || []; + this.grouped.alterTable = []; + for (let i = 0, l = alterTable.length; i < l; i++) { + const statement = alterTable[i]; + if (indexOf(this.createAlterTableMethods, statement.method) < 0) { + this.grouped.alterTable.push(statement); + continue; + } + if (this[statement.method]) { + this.sequence = []; + this[statement.method].apply(this, statement.args); + columnTypes.sql.push(this.sequence[0].sql); + } else { + this.client.logger.error(`Debug: ${statement.method} does not exist`); + } + } + this.sequence = savedSequence; + this.forCreate = false; + } + + // Drop the index on the current table. + dropIndex(value) { + this.pushQuery(`drop index${value}`); + } + + dropUnique() { + throw new Error('Method implemented in the dialect driver'); + } + + dropForeign() { + throw new Error('Method implemented in the dialect driver'); + } + + dropColumn() { + const columns = helpers.normalizeArr.apply(null, arguments); + const drops = (Array.isArray(columns) ? columns : [columns]).map( + (column) => { + return this.dropColumnPrefix + this.formatter.wrap(column); + } + ); + this.pushQuery( + (this.lowerCase ? 'alter table ' : 'ALTER TABLE ') + + this.tableName() + + ' ' + + drops.join(', ') + ); + } + + //Default implementation of setNullable. Overwrite on dialect-specific tablecompiler when needed + //(See postgres/mssql for reference) + _setNullableState(column, nullable) { + const tableName = this.tableName(); + const columnName = this.formatter.columnize(column); + const alterColumnPrefix = this.alterColumnsPrefix; + return this.pushQuery({ + sql: 'SELECT 1', + output: () => { + return this.client + .queryBuilder() + .from(this.tableNameRaw) + .columnInfo(column) + .then((columnInfo) => { + if (isEmpty(columnInfo)) { + throw new Error( + `.setNullable: Column ${columnName} does not exist in table ${tableName}.` + ); + } + const nullableType = nullable ? 'null' : 'not null'; + const columnType = + columnInfo.type + + (columnInfo.maxLength ? `(${columnInfo.maxLength})` : ''); + const defaultValue = + columnInfo.defaultValue !== null && + columnInfo.defaultValue !== void 0 + ? `default '${columnInfo.defaultValue}'` + : ''; + const sql = `alter table ${tableName} ${alterColumnPrefix} ${columnName} ${columnType} ${nullableType} ${defaultValue}`; + return this.client.raw(sql); + }); + }, + }); + } + + setNullable(column) { + return this._setNullableState(column, true); + } + + dropNullable(column) { + return this._setNullableState(column, false); + } + + dropChecks(checkConstraintNames) { + if (checkConstraintNames === undefined) return ''; + checkConstraintNames = normalizeArr(checkConstraintNames); + const tableName = this.tableName(); + const sql = `alter table ${tableName} ${checkConstraintNames + .map((constraint) => `drop constraint ${constraint}`) + .join(', ')}`; + this.pushQuery(sql); + } + + check(checkPredicate, bindings, constraintName) { + const tableName = this.tableName(); + let checkConstraint = constraintName; + if (!checkConstraint) { + this.checksCount++; + checkConstraint = tableName + '_' + this.checksCount; + } + const sql = `alter table ${tableName} add constraint ${checkConstraint} check(${checkPredicate})`; + this.pushQuery(sql); + } + + _addChecks() { + if (this.grouped.checks) { + return ( + ', ' + + this.grouped.checks + .map((c) => { + return `${ + c.args[2] ? 'constraint ' + c.args[2] + ' ' : '' + }check (${this.client.raw(c.args[0], c.args[1])})`; + }) + .join(', ') + ); + } + return ''; + } + + // If no name was specified for this index, we will create one using a basic + // convention of the table name, followed by the columns, followed by an + // index type, such as primary or index, which makes the index unique. + _indexCommand(type, tableName, columns) { + if (!Array.isArray(columns)) columns = columns ? [columns] : []; + const table = tableName.replace(/\.|-/g, '_'); + const indexName = ( + table + + '_' + + columns.join('_') + + '_' + + type + ).toLowerCase(); + return this.formatter.wrap(indexName); + } + + _getPrimaryKeys() { + return (this.grouped.alterTable || []) + .filter((a) => a.method === 'primary') + .flatMap((a) => a.args) + .flat(); + } + + _canBeAddPrimaryKey(options) { + return options.primaryKey && this._getPrimaryKeys().length === 0; + } + + _getIncrementsColumnNames() { + return this.grouped.columns + .filter((c) => c.builder._type === 'increments') + .map((c) => c.builder._args[0]); + } + + _getBigIncrementsColumnNames() { + return this.grouped.columns + .filter((c) => c.builder._type === 'bigincrements') + .map((c) => c.builder._args[0]); + } +} + +TableCompiler.prototype.pushQuery = pushQuery; +TableCompiler.prototype.pushAdditional = pushAdditional; +TableCompiler.prototype.unshiftQuery = unshiftQuery; +TableCompiler.prototype.lowerCase = true; +TableCompiler.prototype.createAlterTableMethods = null; +TableCompiler.prototype.addColumnsPrefix = 'add column '; +TableCompiler.prototype.alterColumnsPrefix = 'alter column '; +TableCompiler.prototype.modifyColumnPrefix = 'modify column '; +TableCompiler.prototype.dropColumnPrefix = 'drop column '; + +module.exports = TableCompiler; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/viewbuilder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/viewbuilder.js new file mode 100644 index 000000000..8ef6c1a34 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/viewbuilder.js @@ -0,0 +1,92 @@ +const helpers = require('../util/helpers'); +const extend = require('lodash/extend'); +const assign = require('lodash/assign'); + +class ViewBuilder { + constructor(client, method, viewName, fn) { + this.client = client; + this._method = method; + this._schemaName = undefined; + this._columns = undefined; + this._fn = fn; + this._viewName = viewName; + this._statements = []; + this._single = {}; + } + + setSchema(schemaName) { + this._schemaName = schemaName; + } + + columns(columns) { + this._columns = columns; + } + + as(selectQuery) { + this._selectQuery = selectQuery; + } + + checkOption() { + throw new Error( + 'check option definition is not supported by this dialect.' + ); + } + + localCheckOption() { + throw new Error( + 'check option definition is not supported by this dialect.' + ); + } + + cascadedCheckOption() { + throw new Error( + 'check option definition is not supported by this dialect.' + ); + } + + toSQL() { + if (this._method === 'alter') { + extend(this, AlterMethods); + } + this._fn.call(this, this); + return this.client.viewCompiler(this).toSQL(); + } +} + +const AlterMethods = { + column(column) { + const self = this; + return { + rename: function (newName) { + self._statements.push({ + grouping: 'alterView', + method: 'renameColumn', + args: [column, newName], + }); + return this; + }, + defaultTo: function (defaultValue) { + self._statements.push({ + grouping: 'alterView', + method: 'defaultTo', + args: [column, defaultValue], + }); + return this; + }, + }; + }, +}; + +helpers.addQueryContext(ViewBuilder); + +ViewBuilder.extend = (methodName, fn) => { + if (Object.prototype.hasOwnProperty.call(ViewBuilder.prototype, methodName)) { + throw new Error( + `Can't extend ViewBuilder with existing method ('${methodName}').` + ); + } + + assign(ViewBuilder.prototype, { [methodName]: fn }); +}; + +module.exports = ViewBuilder; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/viewcompiler.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/viewcompiler.js new file mode 100644 index 000000000..19a9a0177 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/schema/viewcompiler.js @@ -0,0 +1,138 @@ +/* eslint max-len:0 */ + +// View Compiler +// ------- +const { pushQuery } = require('./internal/helpers'); +const groupBy = require('lodash/groupBy'); +const { columnize: columnize_ } = require('../formatter/wrappingFormatter'); + +class ViewCompiler { + constructor(client, viewBuilder) { + this.client = client; + this.viewBuilder = viewBuilder; + this._commonBuilder = this.viewBuilder; + this.method = viewBuilder._method; + this.schemaNameRaw = viewBuilder._schemaName; + this.viewNameRaw = viewBuilder._viewName; + this.single = viewBuilder._single; + this.selectQuery = viewBuilder._selectQuery; + this.columns = viewBuilder._columns; + this.grouped = groupBy(viewBuilder._statements, 'grouping'); + + this.formatter = client.formatter(viewBuilder); + this.bindings = []; + this.formatter.bindings = this.bindings; + this.bindingsHolder = this; + + this.sequence = []; + } + + // Convert the tableCompiler toSQL + toSQL() { + this[this.method](); + return this.sequence; + } + + // Column Compilation + // ------- + + create() { + this.createQuery(this.columns, this.selectQuery); + } + + createOrReplace() { + throw new Error('replace views is not supported by this dialect.'); + } + + createMaterializedView() { + throw new Error('materialized views are not supported by this dialect.'); + } + + createQuery(columns, selectQuery, materialized, replace) { + const createStatement = + 'create ' + + (materialized ? 'materialized ' : '') + + (replace ? 'or replace ' : '') + + 'view '; + const columnList = columns + ? ' (' + + columnize_( + columns, + this.viewBuilder, + this.client, + this.bindingsHolder + ) + + ')' + : ''; + let sql = createStatement + this.viewName() + columnList; + sql += ' as '; + sql += selectQuery.toString(); + switch (this.single.checkOption) { + case 'default_option': + sql += ' with check option'; + break; + case 'local': + sql += ' with local check option'; + break; + case 'cascaded': + sql += ' with cascaded check option'; + break; + default: + break; + } + this.pushQuery({ + sql, + }); + } + + renameView(from, to) { + throw new Error( + 'rename view is not supported by this dialect (instead drop, then create another view).' + ); + } + + refreshMaterializedView() { + throw new Error('materialized views are not supported by this dialect.'); + } + + alter() { + this.alterView(); + } + + alterView() { + const alterView = this.grouped.alterView || []; + for (let i = 0, l = alterView.length; i < l; i++) { + const statement = alterView[i]; + if (this[statement.method]) { + this[statement.method].apply(this, statement.args); + } else { + this.client.logger.error(`Debug: ${statement.method} does not exist`); + } + } + for (const item in this.single) { + if (typeof this[item] === 'function') this[item](this.single[item]); + } + } + + renameColumn(from, to) { + throw new Error('rename column of views is not supported by this dialect.'); + } + + defaultTo(column, defaultValue) { + throw new Error( + 'change default values of views is not supported by this dialect.' + ); + } + + viewName() { + const name = this.schemaNameRaw + ? `${this.schemaNameRaw}.${this.viewNameRaw}` + : this.viewNameRaw; + + return this.formatter.wrap(name); + } +} + +ViewCompiler.prototype.pushQuery = pushQuery; + +module.exports = ViewCompiler; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/finally-mixin.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/finally-mixin.js new file mode 100644 index 000000000..dc672926a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/finally-mixin.js @@ -0,0 +1,13 @@ +const noop = require('./noop'); + +const finallyMixin = (prototype) => + Object.assign(prototype, { + finally(onFinally) { + return this.then().finally(onFinally); + }, + }); + +// FYI: Support for `Promise.prototype.finally` was not introduced until Node 9. +// Therefore, Knex will need to conditionally inject support for `.finally(..)` +// until support for Node 8 is officially dropped. +module.exports = Promise.prototype.finally ? finallyMixin : noop; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/helpers.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/helpers.js new file mode 100644 index 000000000..056cedb74 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/helpers.js @@ -0,0 +1,95 @@ +const isPlainObject = require('lodash/isPlainObject'); +const isTypedArray = require('lodash/isTypedArray'); +const { CLIENT_ALIASES } = require('../constants'); +const { isFunction } = require('./is'); + +// Check if the first argument is an array, otherwise uses all arguments as an +// array. +function normalizeArr(...args) { + if (Array.isArray(args[0])) { + return args[0]; + } + + return args; +} + +function containsUndefined(mixed) { + let argContainsUndefined = false; + + if (isTypedArray(mixed)) return false; + + if (mixed && isFunction(mixed.toSQL)) { + //Any QueryBuilder or Raw will automatically be validated during compile. + return argContainsUndefined; + } + + if (Array.isArray(mixed)) { + for (let i = 0; i < mixed.length; i++) { + if (argContainsUndefined) break; + argContainsUndefined = containsUndefined(mixed[i]); + } + } else if (isPlainObject(mixed)) { + Object.keys(mixed).forEach((key) => { + if (!argContainsUndefined) { + argContainsUndefined = containsUndefined(mixed[key]); + } + }); + } else { + argContainsUndefined = mixed === undefined; + } + + return argContainsUndefined; +} + +function getUndefinedIndices(mixed) { + const indices = []; + + if (Array.isArray(mixed)) { + mixed.forEach((item, index) => { + if (containsUndefined(item)) { + indices.push(index); + } + }); + } else if (isPlainObject(mixed)) { + Object.keys(mixed).forEach((key) => { + if (containsUndefined(mixed[key])) { + indices.push(key); + } + }); + } else { + indices.push(0); + } + + return indices; +} + +function addQueryContext(Target) { + // Stores or returns (if called with no arguments) context passed to + // wrapIdentifier and postProcessResponse hooks + Target.prototype.queryContext = function (context) { + if (context === undefined) { + return this._queryContext; + } + this._queryContext = context; + return this; + }; +} + +function resolveClientNameWithAliases(clientName) { + return CLIENT_ALIASES[clientName] || clientName; +} + +function toNumber(val, fallback) { + if (val === undefined || val === null) return fallback; + const number = parseInt(val, 10); + return isNaN(number) ? fallback : number; +} + +module.exports = { + addQueryContext, + containsUndefined, + getUndefinedIndices, + normalizeArr, + resolveClientNameWithAliases, + toNumber, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/is.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/is.js new file mode 100644 index 000000000..5adfc434a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/is.js @@ -0,0 +1,32 @@ +function isString(value) { + return typeof value === 'string'; +} + +function isNumber(value) { + return typeof value === 'number'; +} + +function isBoolean(value) { + return typeof value === 'boolean'; +} + +function isUndefined(value) { + return typeof value === 'undefined'; +} + +function isObject(value) { + return typeof value === 'object' && value !== null; +} + +function isFunction(value) { + return typeof value === 'function'; +} + +module.exports = { + isString, + isNumber, + isBoolean, + isUndefined, + isObject, + isFunction, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/nanoid.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/nanoid.js new file mode 100644 index 000000000..f5ac10489 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/nanoid.js @@ -0,0 +1,40 @@ +// This alphabet uses `A-Za-z0-9_-` symbols. The genetic algorithm helped +// optimize the gzip compression for this alphabet. +const urlAlphabet = + 'ModuleSymbhasOwnPr-0123456789ABCDEFGHNRVfgctiUvz_KqYTJkLxpZXIjQW'; + +const numberAlphabet = '0123456789'; + +/** + * Generate URL-friendly unique ID. This method uses the non-secure + * predictable random generator with bigger collision probability. + * Based on https://github.com/ai/nanoid + * + * ```js + * model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL" + * ``` + * + * @param size Size of the ID. The default size is 21. + * @returns A random string. + */ +function nanoid(size = 21) { + let id = ''; + // A compact alternative for `for (var i = 0; i < step; i++)`. + let i = size; + while (i--) { + // `| 0` is more compact and faster than `Math.floor()`. + id += urlAlphabet[(Math.random() * 64) | 0]; + } + return id; +} + +function nanonum(size = 21) { + let id = ''; + let i = size; + while (i--) { + id += numberAlphabet[(Math.random() * 10) | 0]; + } + return id; +} + +module.exports = { nanoid, nanonum }; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/noop.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/noop.js new file mode 100644 index 000000000..ea41b01de --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/noop.js @@ -0,0 +1 @@ +module.exports = function () {}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/save-async-stack.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/save-async-stack.js new file mode 100644 index 000000000..cdcc64c2e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/save-async-stack.js @@ -0,0 +1,14 @@ +module.exports = function saveAsyncStack(instance, lines) { + if (instance.client.config.asyncStackTraces) { + // a hack to get a callstack into the client code despite this + // node.js bug https://github.com/nodejs/node/issues/11865 + + // Save error here but not error trace + // reading trace with '--enable-source-maps' flag on node can be very costly + + instance._asyncStack = { + error: new Error(), + lines, + }; + } +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/security.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/security.js new file mode 100644 index 000000000..d4b4edb90 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/security.js @@ -0,0 +1,26 @@ +/** + * Sets a hidden (non-enumerable) property on the `target` object, copying it + * from `source`. + * + * This is useful when we want to protect certain data from being accidentally + * leaked through logs, also when the property is non-enumerable on the `source` + * object and we want to ensure that it is properly copied. + * + * @param {object} target + * @param {object} source - default: target + * @param {string} propertyName - default: 'password' + */ +function setHiddenProperty(target, source, propertyName = 'password') { + if (!source) { + source = target; + } + + Object.defineProperty(target, propertyName, { + enumerable: false, + value: source[propertyName], + }); +} + +module.exports = { + setHiddenProperty, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/string.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/string.js new file mode 100644 index 000000000..2358362ae --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/string.js @@ -0,0 +1,190 @@ +/*eslint max-len: 0, no-var:0 */ + +const charsRegex = /[\0\b\t\n\r\x1a"'\\]/g; // eslint-disable-line no-control-regex +const charsMap = { + '\0': '\\0', + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\r': '\\r', + '\x1a': '\\Z', + '"': '\\"', + "'": "\\'", + '\\': '\\\\', +}; + +function wrapEscape(escapeFn) { + return function finalEscape(val, ctx = {}) { + return escapeFn(val, finalEscape, ctx); + }; +} + +function makeEscape(config = {}) { + const finalEscapeDate = config.escapeDate || dateToString; + const finalEscapeArray = config.escapeArray || arrayToList; + const finalEscapeBuffer = config.escapeBuffer || bufferToString; + const finalEscapeString = config.escapeString || escapeString; + const finalEscapeObject = config.escapeObject || escapeObject; + const finalWrap = config.wrap || wrapEscape; + + function escapeFn(val, finalEscape, ctx) { + if (val === undefined || val === null) { + return 'NULL'; + } + switch (typeof val) { + case 'boolean': + return val ? 'true' : 'false'; + case 'number': + return val + ''; + case 'object': + if (val instanceof Date) { + val = finalEscapeDate(val, finalEscape, ctx); + } else if (Array.isArray(val)) { + return finalEscapeArray(val, finalEscape, ctx); + } else if (Buffer.isBuffer(val)) { + return finalEscapeBuffer(val, finalEscape, ctx); + } else { + return finalEscapeObject(val, finalEscape, ctx); + } + } + return finalEscapeString(val, finalEscape, ctx); + } + + return finalWrap ? finalWrap(escapeFn) : escapeFn; +} + +function escapeObject(val, finalEscape, ctx) { + if (val && typeof val.toSQL === 'function') { + return val.toSQL(ctx); + } else { + return JSON.stringify(val); + } +} + +function arrayToList(array, finalEscape, ctx) { + let sql = ''; + for (let i = 0; i < array.length; i++) { + const val = array[i]; + if (Array.isArray(val)) { + sql += + (i === 0 ? '' : ', ') + '(' + arrayToList(val, finalEscape, ctx) + ')'; + } else { + sql += (i === 0 ? '' : ', ') + finalEscape(val, ctx); + } + } + return sql; +} + +function bufferToString(buffer) { + return 'X' + escapeString(buffer.toString('hex')); +} + +function escapeString(val, finalEscape, ctx) { + let chunkIndex = (charsRegex.lastIndex = 0); + let escapedVal = ''; + let match; + + while ((match = charsRegex.exec(val))) { + escapedVal += val.slice(chunkIndex, match.index) + charsMap[match[0]]; + chunkIndex = charsRegex.lastIndex; + } + + if (chunkIndex === 0) { + // Nothing was escaped + return "'" + val + "'"; + } + + if (chunkIndex < val.length) { + return "'" + escapedVal + val.slice(chunkIndex) + "'"; + } + + return "'" + escapedVal + "'"; +} + +function dateToString(date, finalEscape, ctx = {}) { + const timeZone = ctx.timeZone || 'local'; + + const dt = new Date(date); + let year; + let month; + let day; + let hour; + let minute; + let second; + let millisecond; + + if (timeZone === 'local') { + year = dt.getFullYear(); + month = dt.getMonth() + 1; + day = dt.getDate(); + hour = dt.getHours(); + minute = dt.getMinutes(); + second = dt.getSeconds(); + millisecond = dt.getMilliseconds(); + } else { + const tz = convertTimezone(timeZone); + + if (tz !== false && tz !== 0) { + dt.setTime(dt.getTime() + tz * 60000); + } + + year = dt.getUTCFullYear(); + month = dt.getUTCMonth() + 1; + day = dt.getUTCDate(); + hour = dt.getUTCHours(); + minute = dt.getUTCMinutes(); + second = dt.getUTCSeconds(); + millisecond = dt.getUTCMilliseconds(); + } + + // YYYY-MM-DD HH:mm:ss.mmm + return ( + zeroPad(year, 4) + + '-' + + zeroPad(month, 2) + + '-' + + zeroPad(day, 2) + + ' ' + + zeroPad(hour, 2) + + ':' + + zeroPad(minute, 2) + + ':' + + zeroPad(second, 2) + + '.' + + zeroPad(millisecond, 3) + ); +} + +function zeroPad(number, length) { + number = number.toString(); + while (number.length < length) { + number = '0' + number; + } + return number; +} + +function convertTimezone(tz) { + if (tz === 'Z') { + return 0; + } + const m = tz.match(/([+\-\s])(\d\d):?(\d\d)?/); + if (m) { + return ( + (m[1] == '-' ? -1 : 1) * + (parseInt(m[2], 10) + (m[3] ? parseInt(m[3], 10) : 0) / 60) * + 60 + ); + } + return false; +} + +module.exports = { + arrayToList, + bufferToString, + dateToString, + escapeString, + charsRegex, + charsMap, + escapeObject, + makeEscape, +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/timeout.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/timeout.js new file mode 100644 index 000000000..c941b85f4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/lib/util/timeout.js @@ -0,0 +1,29 @@ +class KnexTimeoutError extends Error { + constructor(message) { + super(message); + this.name = 'KnexTimeoutError'; + } +} + +function timeout(promise, ms) { + return new Promise(function (resolve, reject) { + const id = setTimeout(function () { + reject(new KnexTimeoutError('operation timed out')); + }, ms); + + function wrappedResolve(value) { + clearTimeout(id); + resolve(value); + } + + function wrappedReject(err) { + clearTimeout(id); + reject(err); + } + + promise.then(wrappedResolve, wrappedReject); + }); +} + +module.exports.KnexTimeoutError = KnexTimeoutError; +module.exports.timeout = timeout; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/LICENSE new file mode 100644 index 000000000..1a9820e26 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/LICENSE @@ -0,0 +1,20 @@ +(The MIT License) + +Copyright (c) 2014-2017 TJ Holowaychuk +Copyright (c) 2018-2021 Josh Junon + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/README.md new file mode 100644 index 000000000..e9c3e047c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/README.md @@ -0,0 +1,481 @@ +# debug +[![Build Status](https://travis-ci.org/debug-js/debug.svg?branch=master)](https://travis-ci.org/debug-js/debug) [![Coverage Status](https://coveralls.io/repos/github/debug-js/debug/badge.svg?branch=master)](https://coveralls.io/github/debug-js/debug?branch=master) [![Slack](https://visionmedia-community-slackin.now.sh/badge.svg)](https://visionmedia-community-slackin.now.sh/) [![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers) +[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors) + + + +A tiny JavaScript debugging utility modelled after Node.js core's debugging +technique. Works in Node.js and web browsers. + +## Installation + +```bash +$ npm install debug +``` + +## Usage + +`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole. + +Example [_app.js_](./examples/node/app.js): + +```js +var debug = require('debug')('http') + , http = require('http') + , name = 'My App'; + +// fake app + +debug('booting %o', name); + +http.createServer(function(req, res){ + debug(req.method + ' ' + req.url); + res.end('hello\n'); +}).listen(3000, function(){ + debug('listening'); +}); + +// fake worker of some kind + +require('./worker'); +``` + +Example [_worker.js_](./examples/node/worker.js): + +```js +var a = require('debug')('worker:a') + , b = require('debug')('worker:b'); + +function work() { + a('doing lots of uninteresting work'); + setTimeout(work, Math.random() * 1000); +} + +work(); + +function workb() { + b('doing some work'); + setTimeout(workb, Math.random() * 2000); +} + +workb(); +``` + +The `DEBUG` environment variable is then used to enable these based on space or +comma-delimited names. + +Here are some examples: + +screen shot 2017-08-08 at 12 53 04 pm +screen shot 2017-08-08 at 12 53 38 pm +screen shot 2017-08-08 at 12 53 25 pm + +#### Windows command prompt notes + +##### CMD + +On Windows the environment variable is set using the `set` command. + +```cmd +set DEBUG=*,-not_this +``` + +Example: + +```cmd +set DEBUG=* & node app.js +``` + +##### PowerShell (VS Code default) + +PowerShell uses different syntax to set environment variables. + +```cmd +$env:DEBUG = "*,-not_this" +``` + +Example: + +```cmd +$env:DEBUG='app';node app.js +``` + +Then, run the program to be debugged as usual. + +npm script example: +```js + "windowsDebug": "@powershell -Command $env:DEBUG='*';node app.js", +``` + +## Namespace Colors + +Every debug instance has a color generated for it based on its namespace name. +This helps when visually parsing the debug output to identify which debug instance +a debug line belongs to. + +#### Node.js + +In Node.js, colors are enabled when stderr is a TTY. You also _should_ install +the [`supports-color`](https://npmjs.org/supports-color) module alongside debug, +otherwise debug will only use a small handful of basic colors. + + + +#### Web Browser + +Colors are also enabled on "Web Inspectors" that understand the `%c` formatting +option. These are WebKit web inspectors, Firefox ([since version +31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/)) +and the Firebug plugin for Firefox (any version). + + + + +## Millisecond diff + +When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls. + + + +When stdout is not a TTY, `Date#toISOString()` is used, making it more useful for logging the debug information as shown below: + + + + +## Conventions + +If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". If you append a "*" to the end of your name, it will always be enabled regardless of the setting of the DEBUG environment variable. You can then use it for normal output as well as debug output. + +## Wildcards + +The `*` character may be used as a wildcard. Suppose for example your library has +debuggers named "connect:bodyParser", "connect:compress", "connect:session", +instead of listing all three with +`DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do +`DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`. + +You can also exclude specific debuggers by prefixing them with a "-" character. +For example, `DEBUG=*,-connect:*` would include all debuggers except those +starting with "connect:". + +## Environment Variables + +When running through Node.js, you can set a few environment variables that will +change the behavior of the debug logging: + +| Name | Purpose | +|-----------|-------------------------------------------------| +| `DEBUG` | Enables/disables specific debugging namespaces. | +| `DEBUG_HIDE_DATE` | Hide date from debug output (non-TTY). | +| `DEBUG_COLORS`| Whether or not to use colors in the debug output. | +| `DEBUG_DEPTH` | Object inspection depth. | +| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. | + + +__Note:__ The environment variables beginning with `DEBUG_` end up being +converted into an Options object that gets used with `%o`/`%O` formatters. +See the Node.js documentation for +[`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options) +for the complete list. + +## Formatters + +Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. +Below are the officially supported formatters: + +| Formatter | Representation | +|-----------|----------------| +| `%O` | Pretty-print an Object on multiple lines. | +| `%o` | Pretty-print an Object all on a single line. | +| `%s` | String. | +| `%d` | Number (both integer and float). | +| `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. | +| `%%` | Single percent sign ('%'). This does not consume an argument. | + + +### Custom formatters + +You can add custom formatters by extending the `debug.formatters` object. +For example, if you wanted to add support for rendering a Buffer as hex with +`%h`, you could do something like: + +```js +const createDebug = require('debug') +createDebug.formatters.h = (v) => { + return v.toString('hex') +} + +// …elsewhere +const debug = createDebug('foo') +debug('this is hex: %h', new Buffer('hello world')) +// foo this is hex: 68656c6c6f20776f726c6421 +0ms +``` + + +## Browser Support + +You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify), +or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest), +if you don't want to build it yourself. + +Debug's enable state is currently persisted by `localStorage`. +Consider the situation shown below where you have `worker:a` and `worker:b`, +and wish to debug both. You can enable this using `localStorage.debug`: + +```js +localStorage.debug = 'worker:*' +``` + +And then refresh the page. + +```js +a = debug('worker:a'); +b = debug('worker:b'); + +setInterval(function(){ + a('doing some work'); +}, 1000); + +setInterval(function(){ + b('doing some work'); +}, 1200); +``` + +In Chromium-based web browsers (e.g. Brave, Chrome, and Electron), the JavaScript console will—by default—only show messages logged by `debug` if the "Verbose" log level is _enabled_. + + + +## Output streams + + By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method: + +Example [_stdout.js_](./examples/node/stdout.js): + +```js +var debug = require('debug'); +var error = debug('app:error'); + +// by default stderr is used +error('goes to stderr!'); + +var log = debug('app:log'); +// set this namespace to log via console.log +log.log = console.log.bind(console); // don't forget to bind to console! +log('goes to stdout'); +error('still goes to stderr!'); + +// set all output to go via console.info +// overrides all per-namespace log settings +debug.log = console.info.bind(console); +error('now goes to stdout via console.info'); +log('still goes to stdout, but via console.info now'); +``` + +## Extend +You can simply extend debugger +```js +const log = require('debug')('auth'); + +//creates new debug instance with extended namespace +const logSign = log.extend('sign'); +const logLogin = log.extend('login'); + +log('hello'); // auth hello +logSign('hello'); //auth:sign hello +logLogin('hello'); //auth:login hello +``` + +## Set dynamically + +You can also enable debug dynamically by calling the `enable()` method : + +```js +let debug = require('debug'); + +console.log(1, debug.enabled('test')); + +debug.enable('test'); +console.log(2, debug.enabled('test')); + +debug.disable(); +console.log(3, debug.enabled('test')); + +``` + +print : +``` +1 false +2 true +3 false +``` + +Usage : +`enable(namespaces)` +`namespaces` can include modes separated by a colon and wildcards. + +Note that calling `enable()` completely overrides previously set DEBUG variable : + +``` +$ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"))' +=> false +``` + +`disable()` + +Will disable all namespaces. The functions returns the namespaces currently +enabled (and skipped). This can be useful if you want to disable debugging +temporarily without knowing what was enabled to begin with. + +For example: + +```js +let debug = require('debug'); +debug.enable('foo:*,-foo:bar'); +let namespaces = debug.disable(); +debug.enable(namespaces); +``` + +Note: There is no guarantee that the string will be identical to the initial +enable string, but semantically they will be identical. + +## Checking whether a debug target is enabled + +After you've created a debug instance, you can determine whether or not it is +enabled by checking the `enabled` property: + +```javascript +const debug = require('debug')('http'); + +if (debug.enabled) { + // do stuff... +} +``` + +You can also manually toggle this property to force the debug instance to be +enabled or disabled. + +## Usage in child processes + +Due to the way `debug` detects if the output is a TTY or not, colors are not shown in child processes when `stderr` is piped. A solution is to pass the `DEBUG_COLORS=1` environment variable to the child process. +For example: + +```javascript +worker = fork(WORKER_WRAP_PATH, [workerPath], { + stdio: [ + /* stdin: */ 0, + /* stdout: */ 'pipe', + /* stderr: */ 'pipe', + 'ipc', + ], + env: Object.assign({}, process.env, { + DEBUG_COLORS: 1 // without this settings, colors won't be shown + }), +}); + +worker.stderr.pipe(process.stderr, { end: false }); +``` + + +## Authors + + - TJ Holowaychuk + - Nathan Rajlich + - Andrew Rhyne + - Josh Junon + +## Backers + +Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## Sponsors + +Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## License + +(The MIT License) + +Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca> +Copyright (c) 2018-2021 Josh Junon + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/package.json new file mode 100644 index 000000000..3bcdc242f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/package.json @@ -0,0 +1,59 @@ +{ + "name": "debug", + "version": "4.3.4", + "repository": { + "type": "git", + "url": "git://github.com/debug-js/debug.git" + }, + "description": "Lightweight debugging utility for Node.js and the browser", + "keywords": [ + "debug", + "log", + "debugger" + ], + "files": [ + "src", + "LICENSE", + "README.md" + ], + "author": "Josh Junon ", + "contributors": [ + "TJ Holowaychuk ", + "Nathan Rajlich (http://n8.io)", + "Andrew Rhyne " + ], + "license": "MIT", + "scripts": { + "lint": "xo", + "test": "npm run test:node && npm run test:browser && npm run lint", + "test:node": "istanbul cover _mocha -- test.js", + "test:browser": "karma start --single-run", + "test:coverage": "cat ./coverage/lcov.info | coveralls" + }, + "dependencies": { + "ms": "2.1.2" + }, + "devDependencies": { + "brfs": "^2.0.1", + "browserify": "^16.2.3", + "coveralls": "^3.0.2", + "istanbul": "^0.4.5", + "karma": "^3.1.4", + "karma-browserify": "^6.0.0", + "karma-chrome-launcher": "^2.2.0", + "karma-mocha": "^1.3.0", + "mocha": "^5.2.0", + "mocha-lcov-reporter": "^1.2.0", + "xo": "^0.23.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + }, + "main": "./src/index.js", + "browser": "./src/browser.js", + "engines": { + "node": ">=6.0" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/browser.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/browser.js new file mode 100644 index 000000000..cd0fc35d1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/browser.js @@ -0,0 +1,269 @@ +/* eslint-env browser */ + +/** + * This is the web browser implementation of `debug()`. + */ + +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = localstorage(); +exports.destroy = (() => { + let warned = false; + + return () => { + if (!warned) { + warned = true; + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + }; +})(); + +/** + * Colors. + */ + +exports.colors = [ + '#0000CC', + '#0000FF', + '#0033CC', + '#0033FF', + '#0066CC', + '#0066FF', + '#0099CC', + '#0099FF', + '#00CC00', + '#00CC33', + '#00CC66', + '#00CC99', + '#00CCCC', + '#00CCFF', + '#3300CC', + '#3300FF', + '#3333CC', + '#3333FF', + '#3366CC', + '#3366FF', + '#3399CC', + '#3399FF', + '#33CC00', + '#33CC33', + '#33CC66', + '#33CC99', + '#33CCCC', + '#33CCFF', + '#6600CC', + '#6600FF', + '#6633CC', + '#6633FF', + '#66CC00', + '#66CC33', + '#9900CC', + '#9900FF', + '#9933CC', + '#9933FF', + '#99CC00', + '#99CC33', + '#CC0000', + '#CC0033', + '#CC0066', + '#CC0099', + '#CC00CC', + '#CC00FF', + '#CC3300', + '#CC3333', + '#CC3366', + '#CC3399', + '#CC33CC', + '#CC33FF', + '#CC6600', + '#CC6633', + '#CC9900', + '#CC9933', + '#CCCC00', + '#CCCC33', + '#FF0000', + '#FF0033', + '#FF0066', + '#FF0099', + '#FF00CC', + '#FF00FF', + '#FF3300', + '#FF3333', + '#FF3366', + '#FF3399', + '#FF33CC', + '#FF33FF', + '#FF6600', + '#FF6633', + '#FF9900', + '#FF9933', + '#FFCC00', + '#FFCC33' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +// eslint-disable-next-line complexity +function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { + return true; + } + + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + + // Is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // Is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // Is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // Double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); +} + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs(args) { + args[0] = (this.useColors ? '%c' : '') + + this.namespace + + (this.useColors ? ' %c' : ' ') + + args[0] + + (this.useColors ? '%c ' : ' ') + + '+' + module.exports.humanize(this.diff); + + if (!this.useColors) { + return; + } + + const c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit'); + + // The final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + let index = 0; + let lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, match => { + if (match === '%%') { + return; + } + index++; + if (match === '%c') { + // We only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); +} + +/** + * Invokes `console.debug()` when available. + * No-op when `console.debug` is not a "function". + * If `console.debug` is not available, falls back + * to `console.log`. + * + * @api public + */ +exports.log = console.debug || console.log || (() => {}); + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ +function save(namespaces) { + try { + if (namespaces) { + exports.storage.setItem('debug', namespaces); + } else { + exports.storage.removeItem('debug'); + } + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ +function load() { + let r; + try { + r = exports.storage.getItem('debug'); + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; +} + +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + +function localstorage() { + try { + // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context + // The Browser also has localStorage in the global context. + return localStorage; + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +module.exports = require('./common')(exports); + +const {formatters} = module.exports; + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +formatters.j = function (v) { + try { + return JSON.stringify(v); + } catch (error) { + return '[UnexpectedJSONParseError]: ' + error.message; + } +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/common.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/common.js new file mode 100644 index 000000000..e3291b20f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/common.js @@ -0,0 +1,274 @@ + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */ + +function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = require('ms'); + createDebug.destroy = destroy; + + Object.keys(env).forEach(key => { + createDebug[key] = env[key]; + }); + + /** + * The currently active debug mode names, and names to skip. + */ + + createDebug.names = []; + createDebug.skips = []; + + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + createDebug.formatters = {}; + + /** + * Selects a color for a debug namespace + * @param {String} namespace The namespace string for the debug instance to be colored + * @return {Number|String} An ANSI color code for the given namespace + * @api private + */ + function selectColor(namespace) { + let hash = 0; + + for (let i = 0; i < namespace.length; i++) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; + } + createDebug.selectColor = selectColor; + + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + function createDebug(namespace) { + let prevTime; + let enableOverride = null; + let namespacesCache; + let enabledCache; + + function debug(...args) { + // Disabled? + if (!debug.enabled) { + return; + } + + const self = debug; + + // Set `diff` timestamp + const curr = Number(new Date()); + const ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + args[0] = createDebug.coerce(args[0]); + + if (typeof args[0] !== 'string') { + // Anything else let's inspect with %O + args.unshift('%O'); + } + + // Apply any `formatters` transformations + let index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { + // If we encounter an escaped % then don't increase the array index + if (match === '%%') { + return '%'; + } + index++; + const formatter = createDebug.formatters[format]; + if (typeof formatter === 'function') { + const val = args[index]; + match = formatter.call(self, val); + + // Now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // Apply env-specific formatting (colors, etc.) + createDebug.formatArgs.call(self, args); + + const logFn = self.log || createDebug.log; + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.useColors = createDebug.useColors(); + debug.color = createDebug.selectColor(namespace); + debug.extend = extend; + debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release. + + Object.defineProperty(debug, 'enabled', { + enumerable: true, + configurable: false, + get: () => { + if (enableOverride !== null) { + return enableOverride; + } + if (namespacesCache !== createDebug.namespaces) { + namespacesCache = createDebug.namespaces; + enabledCache = createDebug.enabled(namespace); + } + + return enabledCache; + }, + set: v => { + enableOverride = v; + } + }); + + // Env-specific initialization logic for debug instances + if (typeof createDebug.init === 'function') { + createDebug.init(debug); + } + + return debug; + } + + function extend(namespace, delimiter) { + const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); + newDebug.log = this.log; + return newDebug; + } + + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + function enable(namespaces) { + createDebug.save(namespaces); + createDebug.namespaces = namespaces; + + createDebug.names = []; + createDebug.skips = []; + + let i; + const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + const len = split.length; + + for (i = 0; i < len; i++) { + if (!split[i]) { + // ignore empty strings + continue; + } + + namespaces = split[i].replace(/\*/g, '.*?'); + + if (namespaces[0] === '-') { + createDebug.skips.push(new RegExp('^' + namespaces.slice(1) + '$')); + } else { + createDebug.names.push(new RegExp('^' + namespaces + '$')); + } + } + } + + /** + * Disable debug output. + * + * @return {String} namespaces + * @api public + */ + function disable() { + const namespaces = [ + ...createDebug.names.map(toNamespace), + ...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace) + ].join(','); + createDebug.enable(''); + return namespaces; + } + + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + function enabled(name) { + if (name[name.length - 1] === '*') { + return true; + } + + let i; + let len; + + for (i = 0, len = createDebug.skips.length; i < len; i++) { + if (createDebug.skips[i].test(name)) { + return false; + } + } + + for (i = 0, len = createDebug.names.length; i < len; i++) { + if (createDebug.names[i].test(name)) { + return true; + } + } + + return false; + } + + /** + * Convert regexp to namespace + * + * @param {RegExp} regxep + * @return {String} namespace + * @api private + */ + function toNamespace(regexp) { + return regexp.toString() + .substring(2, regexp.toString().length - 2) + .replace(/\.\*\?$/, '*'); + } + + /** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } + return val; + } + + /** + * XXX DO NOT USE. This is a temporary stub function. + * XXX It WILL be removed in the next major release. + */ + function destroy() { + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + + createDebug.enable(createDebug.load()); + + return createDebug; +} + +module.exports = setup; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/index.js new file mode 100644 index 000000000..bf4c57f25 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/index.js @@ -0,0 +1,10 @@ +/** + * Detect Electron renderer / nwjs process, which is node, but we should + * treat as a browser. + */ + +if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) { + module.exports = require('./browser.js'); +} else { + module.exports = require('./node.js'); +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/node.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/node.js new file mode 100644 index 000000000..79bc085cb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/debug/src/node.js @@ -0,0 +1,263 @@ +/** + * Module dependencies. + */ + +const tty = require('tty'); +const util = require('util'); + +/** + * This is the Node.js implementation of `debug()`. + */ + +exports.init = init; +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.destroy = util.deprecate( + () => {}, + 'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.' +); + +/** + * Colors. + */ + +exports.colors = [6, 2, 3, 4, 5, 1]; + +try { + // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) + // eslint-disable-next-line import/no-extraneous-dependencies + const supportsColor = require('supports-color'); + + if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { + exports.colors = [ + 20, + 21, + 26, + 27, + 32, + 33, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 56, + 57, + 62, + 63, + 68, + 69, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 92, + 93, + 98, + 99, + 112, + 113, + 128, + 129, + 134, + 135, + 148, + 149, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 178, + 179, + 184, + 185, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 214, + 215, + 220, + 221 + ]; + } +} catch (error) { + // Swallow - we only care if `supports-color` is available; it doesn't have to be. +} + +/** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ + +exports.inspectOpts = Object.keys(process.env).filter(key => { + return /^debug_/i.test(key); +}).reduce((obj, key) => { + // Camel-case + const prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, (_, k) => { + return k.toUpperCase(); + }); + + // Coerce string value into JS value + let val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) { + val = true; + } else if (/^(no|off|false|disabled)$/i.test(val)) { + val = false; + } else if (val === 'null') { + val = null; + } else { + val = Number(val); + } + + obj[prop] = val; + return obj; +}, {}); + +/** + * Is stdout a TTY? Colored output is enabled when `true`. + */ + +function useColors() { + return 'colors' in exports.inspectOpts ? + Boolean(exports.inspectOpts.colors) : + tty.isatty(process.stderr.fd); +} + +/** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ + +function formatArgs(args) { + const {namespace: name, useColors} = this; + + if (useColors) { + const c = this.color; + const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c); + const prefix = ` ${colorCode};1m${name} \u001B[0m`; + + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m'); + } else { + args[0] = getDate() + name + ' ' + args[0]; + } +} + +function getDate() { + if (exports.inspectOpts.hideDate) { + return ''; + } + return new Date().toISOString() + ' '; +} + +/** + * Invokes `util.format()` with the specified arguments and writes to stderr. + */ + +function log(...args) { + return process.stderr.write(util.format(...args) + '\n'); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ +function save(namespaces) { + if (namespaces) { + process.env.DEBUG = namespaces; + } else { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + return process.env.DEBUG; +} + +/** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ + +function init(debug) { + debug.inspectOpts = {}; + + const keys = Object.keys(exports.inspectOpts); + for (let i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + } +} + +module.exports = require('./common')(exports); + +const {formatters} = module.exports; + +/** + * Map %o to `util.inspect()`, all on a single line. + */ + +formatters.o = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .split('\n') + .map(str => str.trim()) + .join(' '); +}; + +/** + * Map %O to `util.inspect()`, allowing multiple lines if needed. + */ + +formatters.O = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/index.js new file mode 100644 index 000000000..c4498bcc2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/index.js @@ -0,0 +1,162 @@ +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var w = d * 7; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +module.exports = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isFinite(val)) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'weeks': + case 'week': + case 'w': + return n * w; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return Math.round(ms / d) + 'd'; + } + if (msAbs >= h) { + return Math.round(ms / h) + 'h'; + } + if (msAbs >= m) { + return Math.round(ms / m) + 'm'; + } + if (msAbs >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return plural(ms, msAbs, d, 'day'); + } + if (msAbs >= h) { + return plural(ms, msAbs, h, 'hour'); + } + if (msAbs >= m) { + return plural(ms, msAbs, m, 'minute'); + } + if (msAbs >= s) { + return plural(ms, msAbs, s, 'second'); + } + return ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/license.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/license.md new file mode 100644 index 000000000..69b61253a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/license.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Zeit, Inc. + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/package.json new file mode 100644 index 000000000..eea666e1f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/package.json @@ -0,0 +1,37 @@ +{ + "name": "ms", + "version": "2.1.2", + "description": "Tiny millisecond conversion utility", + "repository": "zeit/ms", + "main": "./index", + "files": [ + "index.js" + ], + "scripts": { + "precommit": "lint-staged", + "lint": "eslint lib/* bin/*", + "test": "mocha tests.js" + }, + "eslintConfig": { + "extends": "eslint:recommended", + "env": { + "node": true, + "es6": true + } + }, + "lint-staged": { + "*.js": [ + "npm run lint", + "prettier --single-quote --write", + "git add" + ] + }, + "license": "MIT", + "devDependencies": { + "eslint": "4.12.1", + "expect.js": "0.3.1", + "husky": "0.14.3", + "lint-staged": "5.0.0", + "mocha": "4.0.1" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/readme.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/readme.md new file mode 100644 index 000000000..9a1996b17 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/node_modules/ms/readme.md @@ -0,0 +1,60 @@ +# ms + +[![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms) +[![Join the community on Spectrum](https://withspectrum.github.io/badge/badge.svg)](https://spectrum.chat/zeit) + +Use this package to easily convert various time formats to milliseconds. + +## Examples + +```js +ms('2 days') // 172800000 +ms('1d') // 86400000 +ms('10h') // 36000000 +ms('2.5 hrs') // 9000000 +ms('2h') // 7200000 +ms('1m') // 60000 +ms('5s') // 5000 +ms('1y') // 31557600000 +ms('100') // 100 +ms('-3 days') // -259200000 +ms('-1h') // -3600000 +ms('-200') // -200 +``` + +### Convert from Milliseconds + +```js +ms(60000) // "1m" +ms(2 * 60000) // "2m" +ms(-3 * 60000) // "-3m" +ms(ms('10 hours')) // "10h" +``` + +### Time Format Written-Out + +```js +ms(60000, { long: true }) // "1 minute" +ms(2 * 60000, { long: true }) // "2 minutes" +ms(-3 * 60000, { long: true }) // "-3 minutes" +ms(ms('10 hours'), { long: true }) // "10 hours" +``` + +## Features + +- Works both in [Node.js](https://nodejs.org) and in the browser +- If a number is supplied to `ms`, a string with a unit is returned +- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`) +- If you pass a string with a number and a valid unit, the number of equivalent milliseconds is returned + +## Related Packages + +- [ms.macro](https://github.com/knpwrs/ms.macro) - Run `ms` as a macro at build-time. + +## Caught a Bug? + +1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device +2. Link the package to the global module directory: `npm link` +3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, Node.js will now use your clone of ms! + +As always, you can run the tests using: `npm test` diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/package.json new file mode 100644 index 000000000..98993dbbc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/package.json @@ -0,0 +1,267 @@ +{ + "name": "knex", + "version": "3.1.0", + "description": "A batteries-included SQL query & schema builder for PostgresSQL, MySQL, CockroachDB, MSSQL and SQLite3", + "main": "knex", + "types": "types/index.d.ts", + "engines": { + "node": ">=16" + }, + "scripts": { + "build": "npm run build:gitignore && npm run build:ts && npm run format", + "clean": "node scripts/clean.js", + "build:ts": "tsc", + "build:gitignore": "node scripts/update_gitignore_for_tsc_output.js run", + "format": "prettier --write --list-different .", + "format:check": "prettier --list-different .", + "debug:test": "mocha --inspect-brk --exit -t 0 test/all-tests-suite.js", + "debug:tape": "node --inspect-brk test/tape/index.js", + "coveralls": "nyc report --reporter=lcov", + "lint": "eslint --cache .", + "lint:fix": "eslint --cache --fix .", + "lint:types": "tsd", + "lint:types:legacy": "dtslint types", + "lint:everything": "npm run lint && npm run lint:types", + "lint:fix:everything": "npm run lint:fix && npm run lint:types", + "test:unit": "npm run test:unit-only && npm run test:cli", + "test:unit-only": "mocha --exit -t 10000 --config test/mocha-unit-config-test.js", + "test:db": "mocha --exit -t 10000 --config test/mocha-integration-config-test.js", + "test:db:coverage": "nyc mocha --exit --check-leaks -t 10000 --config test/mocha-integration-config-test.js && npm run test:tape", + "test:db:no-oracle": "cross-env DB=\"mssql mysql mysql2 postgres sqlite3\" mocha --exit -t 10000 --config test/mocha-integration-config-test.js && npm run test:tape", + "test": "mocha --exit -t 10000 --config test/mocha-all-config-test.js && npm run test:tape && npm run test:cli", + "test:coverage": "nyc mocha --exit --check-leaks -t 10000 --config test/mocha-all-config-test.js && npm run test:tape && npm run test:cli", + "test:everything": "npm run lint:everything && npm run test:coverage", + "test:mssql": "cross-env DB=mssql npm run test:db", + "test:mysql": "cross-env DB=mysql npm run test:db", + "test:mysql2": "cross-env DB=mysql2 npm run test:db", + "test:oracledb": "cross-env DB=oracledb npm run test:db", + "test:sqlite": "cross-env DB=sqlite3 npm run test:db", + "test:better-sqlite3": "cross-env DB=better-sqlite3 npm run test:db", + "test:postgres": "cross-env DB=postgres npm run test:db", + "test:cockroachdb": "cross-env DB=cockroachdb npm run test:db", + "test:pgnative": "cross-env DB=pgnative npm run test:db", + "test:tape": "node test/tape/index.js | tap-spec", + "test:cli": "cross-env KNEX_PATH=../knex.js KNEX=bin/cli.js jake -f test/jake/Jakefile", + "db:start": "docker-compose -f scripts/docker-compose.yml up --build -d mysql oracledb postgres mssql cockroachdb pgnative && docker-compose -f scripts/docker-compose.yml up waitmssql waitmysql waitpostgres waitoracledb", + "db:start:no-oracle": "docker-compose -f scripts/docker-compose.yml up --build -d mysql postgres mssql cockroachdb pgnative && docker-compose -f scripts/docker-compose.yml up waitmssql waitmysql waitpostgres", + "db:stop": "docker-compose -f scripts/docker-compose.yml down", + "db:start:postgres": "docker-compose -f scripts/docker-compose.yml up --build -d postgres && docker-compose -f scripts/docker-compose.yml up waitpostgres", + "db:stop:postgres": "docker-compose -f scripts/docker-compose.yml down", + "db:start:pgnative": "docker-compose -f scripts/docker-compose.yml up --build -d pgnative && docker-compose -f scripts/docker-compose.yml up waitpgnative", + "db:stop:pgnative": "docker-compose -f scripts/docker-compose.yml down", + "db:start:mysql": "docker-compose -f scripts/docker-compose.yml up --build -d mysql && docker-compose -f scripts/docker-compose.yml up waitmysql", + "db:stop:mysql": "docker-compose -f scripts/docker-compose.yml down", + "db:start:mssql": "docker-compose -f scripts/docker-compose.yml up --build -d mssql && docker-compose -f scripts/docker-compose.yml up waitmssql", + "db:stop:mssql": "docker-compose -f scripts/docker-compose.yml down", + "db:start:cockroachdb": "docker-compose -f scripts/docker-compose.yml up --build -d cockroachdb && docker-compose -f scripts/docker-compose.yml up waitcockroachdb", + "db:stop:cockroachdb": "docker-compose -f scripts/docker-compose.yml down", + "db:start:oracle": "docker-compose -f scripts/docker-compose.yml up --build -d oracledb && docker-compose -f scripts/docker-compose.yml up waitoracledb", + "db:stop:oracle": "docker-compose -f scripts/docker-compose.yml down", + "stress:init": "docker-compose -f scripts/stress-test/docker-compose.yml up --no-start && docker-compose -f scripts/stress-test/docker-compose.yml start", + "stress:test": "node scripts/stress-test/knex-stress-test.js | grep -A 5 -B 60 -- '- STATS '", + "stress:destroy": "docker-compose -f scripts/stress-test/docker-compose.yml stop" + }, + "dependencies": { + "colorette": "2.0.19", + "commander": "^10.0.0", + "debug": "4.3.4", + "escalade": "^3.1.1", + "esm": "^3.2.25", + "get-package-type": "^0.1.0", + "getopts": "2.3.0", + "interpret": "^2.2.0", + "lodash": "^4.17.21", + "pg-connection-string": "2.6.2", + "rechoir": "^0.8.0", + "resolve-from": "^5.0.0", + "tarn": "^3.0.2", + "tildify": "2.0.0" + }, + "peerDependenciesMeta": { + "tedious": { + "optional": true + }, + "mysql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "better-sqlite3": { + "optional": true + } + }, + "lint-staged": { + "*": "prettier --ignore-unknown --write", + "*.js": "eslint --cache --fix" + }, + "devDependencies": { + "@tsconfig/recommended": "^1.0.1", + "@types/node": "^20.4.0", + "better-sqlite3": "^9.1.1", + "chai": "^4.3.6", + "chai-as-promised": "^7.1.1", + "chai-subset-in-order": "^3.1.0", + "cli-testlab": "^2.2.0", + "coveralls": "^3.1.1", + "cross-env": "^7.0.3", + "dtslint": "4.2.1", + "eslint": "^8.54.0", + "eslint-config-prettier": "^8.6.0", + "eslint-plugin-import": "^2.29.0", + "eslint-plugin-mocha-no-only": "^1.1.1", + "eslint-plugin-prettier": "^4.2.1", + "husky": "^8.0.1", + "jake": "^10.8.5", + "JSONStream": "^1.3.5", + "lint-staged": "^13.0.0", + "mocha": "^10.0.0", + "mock-fs": "^5.1.4", + "mysql": "^2.18.1", + "mysql2": "^3.2.0", + "nyc": "^15.1.0", + "oracledb": "^6.1.0", + "pg": "^8.8.0", + "pg-query-stream": "^4.2.4", + "prettier": "2.8.7", + "rimraf": "^5.0.5", + "sinon": "^15.0.1", + "sinon-chai": "^3.7.0", + "source-map-support": "^0.5.21", + "sqlite3": "^5.0.11", + "tap-spec": "^5.0.0", + "tape": "^5.6.0", + "tedious": "^16.6.1", + "toxiproxy-node-client": "^2.0.6", + "ts-node": "^10.9.1", + "tsd": "^0.28.1", + "typescript": "5.0.4" + }, + "buildDependencies": [ + "rimraf" + ], + "bin": { + "knex": "./bin/cli.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/knex/knex.git" + }, + "homepage": "https://knex.github.io/documentation/", + "keywords": [ + "sql", + "query", + "postgresql", + "postgres", + "mysql", + "cockroachdb", + "sqlite3", + "oracle", + "mssql", + "builder", + "querybuilder", + "build", + "db", + "database" + ], + "author": { + "name": "Tim Griesser", + "web": "https://github.com/tgriesser" + }, + "contributors": [ + { + "name": "Mikael Lepisto" + }, + { + "name": "Igor Savin", + "web": "https://www.codeflashbacks.com" + }, + { + "name": "Olivier Cavadenti" + }, + { + "name": "Simon Liden" + }, + { + "name": "Paul Gaurab", + "web": "https://lorefnon.tech" + }, + { + "name": "Brian Lauber", + "web": "https://briandamaged.org" + } + ], + "browser": { + "./lib/migrations/migrate/Migrator.js": "./lib/util/noop.js", + "./lib/bin/cli.js": "./lib/util/noop.js", + "./lib/migrations/seed/Seeder.js": "./lib/util/noop.js", + "tedious": false, + "mysql": false, + "mysql2": false, + "pg": false, + "pg-native": false, + "pg-query-stream": false, + "oracle": false, + "sqlite3": false, + "better-sqlite3": false, + "oracledb": false + }, + "react-native": { + "./lib/migrate": "./lib/util/noop.js", + "./lib/seed": "./lib/util/noop.js" + }, + "files": [ + "bin/*", + "lib/", + "lib/**/*.js", + "!lib/**/*.ts", + "!lib/**/*.d.ts", + "!lib/**/*.js.map", + "!lib/.gitignore", + "scripts/*", + "types/index.d.ts", + "types/result.d.ts", + "types/tables.d.ts", + "CHANGELOG.md", + "CONTRIBUTING.md", + "knex.js", + "knex.mjs", + "LICENSE", + "README.md", + "UPGRADING.md" + ], + "license": "MIT", + "tonicExampleFilename": "scripts/runkit-example.js", + "nyc": { + "check-coverage": true, + "lines": 84, + "statements": 82, + "functions": 83, + "branches": 69, + "extension": [ + ".js" + ], + "exclude": [ + "lib/dialects/oracle", + "lib/dialects/oracledb", + "test/**/*.spec.js" + ] + }, + "tsd": { + "directory": "test-tsd", + "compilerOptions": { + "esModuleInterop": false, + "module": "commonjs", + "target": "ES2017" + } + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/build.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/build.js new file mode 100644 index 000000000..bd7b4829f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/build.js @@ -0,0 +1,125 @@ +#!/usr/bin/env node +const fs = require('fs'); +const path = require('path'); +const child_process = require('child_process'); +const _ = require('lodash'); + +const exec = function (cmd, args) { + return new Promise(function (resolve, reject) { + // Execute command + const child = child_process.exec(cmd, { + cwd: process.cwd(), + env: process.env, + }); + + // Pass stdout and stderr + child.stdout.on('data', function (data) { + process.stdout.write(data.toString()); + }); + child.stderr.on('data', function (data) { + process.stderr.write(data.toString()); + }); + // Handle result + child.on('exit', function (code) { + if (code) reject(code); + else resolve(); + }); + child.on('error', reject); + }); +}; + +const CWD = process.cwd(); +const POSTINSTALL_BUILD_CWD = process.env.POSTINSTALL_BUILD_CWD; + +// If we didn't have this check, then we'd be stuck in an infinite `postinstall` +// loop, since we run `npm install --only=dev` below, triggering another +// `postinstall`. We can't use `--ignore-scripts` because that ignores scripts +// on all the modules that get installed, too, which would break stuff. So +// instead, we set an environment variable, `POSTINSTALL_BUILD_CWD`, that keeps +// track of what we're installing. It's more than just a yes/no flag because +// the dev dependencies we're installing might use `postinstall-build` too, and +// we don't want the flag to prevent them from running. +if (POSTINSTALL_BUILD_CWD !== CWD) { + const BUILD_ARTIFACT = process.argv[2]; + const BUILD_COMMAND = process.argv[3]; + + fs.stat(BUILD_ARTIFACT, function (err, stats) { + if (err || !(stats.isFile() || stats.isDirectory())) { + // This script will run again after we run `npm install` below. Set an + // environment variable to tell it to skip the check. Really we just want + // the execSync's `env` to be modified, but it's easier just modify and + // pass along the entire `process.env`. + process.env.POSTINSTALL_BUILD_CWD = CWD; + // We already have prod dependencies, that's what triggered `postinstall` + // in the first place. So only install dev. + + // Fetch package.json + const pkgJson = require(path.join(CWD, 'package.json')); + const devDeps = pkgJson.devDependencies; + // Values listed under `buildDependencies` contain the dependency names + // that are required for `lib` building. + const buildDependencies = _.pick(devDeps, pkgJson.buildDependencies); + + // Proceed only if there is something to install + if (!_.isEmpty(buildDependencies)) { + const opts = { env: process.env, stdio: 'inherit' }; + + console.log('Building Knex.js'); + + // Map all key (dependency) value (semver) pairs to + // "dependency@semver dependency@semver ..." string that can be used + // for `npm install` command + const installArgs = _(buildDependencies) + .pickBy(function (semver, dep) { + // Check if the dependency is already installed + try { + require(dep); + return false; + } catch (err) { + return true; + } + }) + .map(function (semver, dep) { + // Format installable dependencies + return dep + '@' + semver; + }) + .value() + .join(' '); + const needsDepInstallation = !_.isEmpty(installArgs); + const dependenciesInstalledQ = needsDepInstallation + ? exec('npm install ' + installArgs, opts) + : Promise.resolve(); + dependenciesInstalledQ + .then(function () { + console.log('✓'); + // Don't need the flag anymore as `postinstall` was already run. + // Change it back so the environment is minimally changed for the + // remaining commands. + process.env.POSTINSTALL_BUILD_CWD = POSTINSTALL_BUILD_CWD; + console.log('Building compiled files (' + BUILD_COMMAND + ')'); + return exec(BUILD_COMMAND, opts); + }) + .catch(function (err) { + console.error(err); + process.exit(1); + }) + .then(function () { + if (process.env.NODE_ENV === 'production') { + console.log('✓'); + console.log('Pruning dev dependencies for production build'); + return exec('npm prune --production', opts); + } else { + console.log('Skipping npm prune'); + } + }) + .then(function () { + console.log('✓'); + }) + .catch(function (err) { + console.error(err); + process.exit(1); + }); + } + } + }); +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/clean.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/clean.js new file mode 100644 index 000000000..a4dc12bbd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/clean.js @@ -0,0 +1,31 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const path = require('path'); +const { execSync } = require('child_process'); + +function main() { + const repoDir = path.dirname(__dirname); + const gitDir = path.join(repoDir, '.git'); + const gitDirExists = doesDirectoryExist(gitDir); + if (!gitDirExists) { + console.log("No .git directory detected so can not clean 'lib/'. Exiting."); + process.exit(0); + } + console.log( + "Cleaning 'lib/' of outputted files from Typescript compilation ..." + ); + const cmd = 'git clean -f -X lib/'; + const output = execSync(cmd, { cwd: repoDir }); + console.log(output.toString('utf8')); + console.log('Done'); +} + +function doesDirectoryExist(p) { + if (fs.existsSync(p)) { + return fs.lstatSync(p).isDirectory(); + } + return false; +} + +main(); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/docker-compose.yml b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/docker-compose.yml new file mode 100644 index 000000000..a8a5d0016 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/docker-compose.yml @@ -0,0 +1,152 @@ +version: '3' + +services: + mssql: + image: mcr.microsoft.com/mssql/server:2019-latest + ports: + - '21433:1433' + environment: + - ACCEPT_EULA=Y + - SA_PASSWORD=S0meVeryHardPassword + healthcheck: + test: /opt/mssql-tools/bin/sqlcmd -S mssql -U sa -P 'S0meVeryHardPassword' -Q 'select 1' + waitmssql: + image: mcr.microsoft.com/mssql/server:2017-latest + links: + - mssql + depends_on: + - mssql + entrypoint: + - bash + - -c + # https://docs.microsoft.com/en-us/sql/relational-databases/logs/control-transaction-durability?view=sql-server-ver15#bkmk_DbControl + - 'until /opt/mssql-tools/bin/sqlcmd -S mssql -U sa -P S0meVeryHardPassword -d master -Q "CREATE DATABASE knex_test; ALTER DATABASE knex_test SET ALLOW_SNAPSHOT_ISOLATION ON; ALTER DATABASE knex_test SET DELAYED_DURABILITY = FORCED"; do sleep 5; done' + + mysql: + image: mysql + # https://dev.mysql.com/doc/refman/8.0/en/mysql-acid.html + # https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_flush_method + # nosync only for unix, edit for local start on other systems + command: --default-authentication-plugin=mysql_native_password --sync_binlog=0 --innodb_doublewrite=OFF --innodb-flush-log-at-trx-commit=0 --innodb-flush-method=nosync + ports: + - '23306:3306' + environment: + - MYSQL_ROOT_PASSWORD=testrootpassword + - MYSQL_DATABASE=knex_test + - MYSQL_USER=testuser + - MYSQL_PASSWORD=testpassword + healthcheck: + test: + [ + 'CMD', + '/usr/bin/mysql', + '-hlocalhost', + '-utestuser', + '-ptestpassword', + '-e', + 'SELECT 1', + ] + interval: 30s + timeout: 5s + retries: 3 + restart: always + volumes: + - mysql_data:/var/lib/mysql + waitmysql: + image: mysql + links: + - mysql + depends_on: + - mysql + entrypoint: + - bash + - -c + - 'until /usr/bin/mysql -hmysql -utestuser -ptestpassword -e "SELECT 1"; do sleep 5; done' + + postgres: + image: postgres:13-alpine + # see https://www.postgresql.org/docs/current/non-durability.html + command: '-c full_page_writes=off -c fsync=off -c synchronous_commit=off' + ports: + - '25432:5432' + environment: + - POSTGRES_USER=testuser + - POSTGRES_PASSWORD=knextest + - POSTGRES_DB=knex_test + waitpostgres: + image: postgres:13-alpine + links: + - postgres + depends_on: + - postgres + entrypoint: + - bash + - -c + - 'until /usr/local/bin/psql postgres://testuser:knextest@postgres/knex_test -c "SELECT 1"; do sleep 5; done' + + cockroachdb: + image: cockroachdb/cockroach:latest-v21.2 + container_name: crdb + hostname: crdb + command: start-single-node --cluster-name=example-single-node --insecure + ports: + - '26257:26257' + - '8080:8080' + + waitcockroachdb: + container_name: crdb-init + hostname: crdb-init + image: timveil/cockroachdb-remote-client:latest + environment: + - COCKROACH_HOST=crdb:26257 + - COCKROACH_INSECURE=true + - DATABASE_NAME=test + depends_on: + - cockroachdb + + pgnative: + image: postgres:13-alpine + # see https://www.postgresql.org/docs/current/non-durability.html + command: '-c full_page_writes=off -c fsync=off -c synchronous_commit=off' + ports: + - '25433:5432' + environment: + - POSTGRES_USER=testuser + - POSTGRES_PASSWORD=knextest + - POSTGRES_DB=knex_test + waitpgnative: + image: postgres:13-alpine + links: + - pgnative + depends_on: + - pgnative + entrypoint: + - bash + - -c + - 'until /usr/local/bin/psql postgres://testuser:knextest@pgnative/knex_test -c "SELECT 1"; do sleep 5; done' + + oracledb: + image: quillbuilduser/oracle-18-xe + container_name: oracledb_container + ports: + - '21521:1521' + environment: + - ORACLE_ALLOW_REMOTE=true + waitoracledb: + image: quillbuilduser/oracle-18-xe + links: + - oracledb + depends_on: + - oracledb + environment: + - ORACLE_HOME=/opt/oracle/product/18c/dbhomeXE + entrypoint: + - bash + - -c + - 'until /opt/oracle/product/18c/dbhomeXE/bin/sqlplus -s sys/Oracle18@oracledb/XE as sysdba <<< "SELECT 13376411 FROM DUAL; exit;" | grep "13376411"; do echo "Could not connect to oracle... sleep for a while"; sleep 5; done' + +volumes: + mysql_data: + driver_opts: + type: tmpfs + device: tmpfs diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/next-release-howto.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/next-release-howto.md new file mode 100644 index 000000000..de924c553 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/next-release-howto.md @@ -0,0 +1,24 @@ +# Checklist for crating knex @next releases + +1. Go through all commits since the last release and add them to CHANGELOG.md under unreleased changes section. +2. Commit changes to CHANGELOG +3. Check that master compiles and tests are running fine (check also that CI tests are passing) + +```sh + npm run build + + # run bunch of tests, but skipping coverage which doesn't really work locally at least + npm plaintest + npm bin_test + npm oracledb:test + npm mssql:init + npm mssql:test + npm mssql:destroy +``` + +4. Update package.json version to be e.g. 0.16.0-next1 or 0.16.0-next2 and commit yo master +5. Publish it under @next tag + +```sh + npm publish --tag next +``` diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/oracledb-install-driver-libs.sh b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/oracledb-install-driver-libs.sh new file mode 100644 index 000000000..ff45afb8f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/oracledb-install-driver-libs.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash + +# Exit on error +set -e + +# Directory constants +repo_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." >/dev/null 2>&1 && pwd )" +exec_dir="$( pwd )" +script_dir="$repo_dir/scripts/" +docker_compose_file="$repo_dir/scripts/docker-compose.yml" + +help_text=" +Helper script to install oracle drivers on local linux machine from Oracle +database container. + + oracledb-install-driver-libs.sh COMMAND + + COMMAND: + run: Do the driver install. + dry-run: Do the driver install but do not save any files. + help: Print this menu. + + NOTES FOR USAGE: + 1. This script is tested to work on Ubuntu 18.04 LTS. + 2. This script requires you to have sudo capabilities so to use ldconfig. +" + +# Main script logic +cmd="$1" + +function main () { + case "$1" in + "run") + printf "Starting run ...\n" + do_install true + exit 0 + ;; + "dry-run") + printf "Starting dry-run ...\n" + do_install false + exit 0 + ;; + "help"|"--help"|"-h"|"") + printf "$help_text" + exit 0 + ;; + *) + printf "Unsupported command: $cmd\n" + printf "Try running with 'help' to see supported commands.\n" + exit 1 + ;; + esac +} + +function do_install () { + do_changes="$1" + printf "\nEnsuring oracle containers from docker-compose are up ...\n" + docker-compose -f "$docker_compose_file" up --build -d oracledb + docker-compose -f "$docker_compose_file" up waitoracledb + printf "\nSleeping an extra 15 seconds to ensure oracle has fully started ...\n" + sleep 15 + printf "\nInstalling oracle client libs to db container ...\n" + set -x + docker-compose -f "$docker_compose_file" exec -T oracledb curl http://yum.oracle.com/public-yum-ol7.repo -o /etc/yum.repos.d/public-yum-ol7.repo + docker-compose -f "$docker_compose_file" exec -T oracledb yum install -y yum-utils + docker-compose -f "$docker_compose_file" exec -T oracledb yum-config-manager --enable ol7_oracle_instantclient + docker-compose -f "$docker_compose_file" exec -T oracledb yum install -y oracle-instantclient18.3-basiclite + set +x + printf "\nCopying to host's ~/lib directory and adding to ldconfig ...\n" + if [ "$do_changes" = "true" ]; then + set -x + docker cp oracledb_container:/usr/lib/oracle/18.3/client64/lib/ ~/ + sudo sh -c "echo $HOME/lib > /etc/ld.so.conf.d/oracle-instantclient.conf" + sudo ldconfig + set +x + else + printf "(skipping because dry-run)\n" + fi +} + +# Start the bash app's main function +main "$cmd" diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/release.sh b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/release.sh new file mode 100644 index 000000000..a618fb197 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/release.sh @@ -0,0 +1,36 @@ +#!/bin/bash -e + +changelog=node_modules/.bin/changelog + +update_version() { + echo "$(node -p "p=require('./${1}');p.version='${2}';JSON.stringify(p,null,2)")" > $1 + echo "Updated ${1} version to ${2}" +} + +current_version=$(node -p "require('./package').version") + +printf "Next version (current is $current_version)? " +read next_version + +if ! [[ $next_version =~ ^[0-9]\.[0-9]+\.[0-9](-.+)? ]]; then + echo "Version must be a valid semver string, e.g. 1.0.2 or 2.3.0-beta.1" + exit 1 +fi + +next_ref="v$next_version" + +git add -u + +npm run build +npm run format:check +npm run lint:everything +npm test + +update_version 'package.json' $next_version + +git commit -am "release $next_version" +git tag $next_version + +git push --tags + +npm publish diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/runkit-example.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/runkit-example.js new file mode 100644 index 000000000..533cb8d2c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/runkit-example.js @@ -0,0 +1,35 @@ +require('sqlite3'); +const Knex = require('knex'); + +const knexSqlite = Knex({ + client: 'sqlite', + connection: ':memory:', +}); + +// eslint-disable-next-line no-unused-vars +const knexMysql = Knex({ + client: 'mysql2', +}); + +const knexPg = Knex({ + client: 'pg', +}); + +(async function run() { + await knexSqlite.schema.createTable('test', (t) => { + t.increments('id').primary(); + t.string('data'); + }); + + await knexSqlite('test').insert([{ data: 'foo' }, { data: 'bar' }]); + + console.log('test table data:', await knexSqlite('test')); + + console.log( + knexPg({ f: 'foo', b: 'bar' }) + .select('foo.*') + .where('f.name', knexPg.raw('??', ['b.name'])) + .whereIn('something', knexPg('bar').select('id')) + .toSQL().sql + ); +})(); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/README.txt b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/README.txt new file mode 100644 index 000000000..11ce72c2e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/README.txt @@ -0,0 +1,18 @@ +# Test scripts to evaluate stability of drivers / pool etc. + +# To run this test you need to be in this directory + have node >= 8 +# and startup docker containers with proxy and sql servers + +docker-compose up --no-start +docker-compose start + +# Select different test script to run: + +node mysql2-random-hanging-every-now-and-then.js 2> /dev/null | grep -B500 -A2 -- "- STATS" +node mysql2-sudden-exit-without-error +node knex-stress-test.js | grep -A 3 -- "- STATS " +node reconnect-test-mysql-based-drivers.js 2> /dev/null | grep -A 3 -- "- STATS " + +# Shut down docker instances when done: + +docker-compose down diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/docker-compose.yml b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/docker-compose.yml new file mode 100644 index 000000000..c6f4558fa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/docker-compose.yml @@ -0,0 +1,57 @@ +version: '3' + +services: + toxiproxy: + image: shopify/toxiproxy + ports: + - '8474:8474' + - '23306:23306' + - '25432:25432' + - '25433:25433' + - '21521:21521' + - '21433:21433' + links: + - 'mysql' + - 'postgresql' + - 'pgnative' + - 'oracledb' + - 'mssql' + + mysql: + image: mysql:5.7 + ports: + - '33306:3306' + environment: + - TZ=UTC + - MYSQL_ROOT_PASSWORD=mysqlrootpassword + + postgresql: + image: mdillon/postgis + ports: + - '35432:5432' + environment: + - POSTGRES_PASSWORD=postgresrootpassword + - POSTGRES_USER=postgres + + pgnative: + image: mdillon/postgis + ports: + - '35433:5432' + environment: + - POSTGRES_PASSWORD=postgresrootpassword + - POSTGRES_USER=postgres + + oracledb: + image: quillbuilduser/oracle-18-xe + ports: + - '31521:1521' + environment: + - ORACLE_ALLOW_REMOTE=true + + mssql: + image: microsoft/mssql-server-linux:2017-latest + ports: + - '31433:1433' + environment: + - ACCEPT_EULA=Y + - SA_PASSWORD=S0meVeryHardPassword diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/knex-stress-test.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/knex-stress-test.js new file mode 100644 index 000000000..0b1092ef1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/knex-stress-test.js @@ -0,0 +1,212 @@ +const Knex = require('../../lib'); + +const toxiproxy = require('toxiproxy-node-client'); +const toxicli = new toxiproxy.Toxiproxy('http://localhost:8474'); +const rp = require('request-promise-native'); +const delay = require('../../lib/execution/internal/delay'); + +// init instances +const pg = Knex({ + client: 'pg', + connection: + 'postgres://postgres:postgresrootpassword@localhost:25432/postgres', + pool: { max: 50 }, +}); + +const pgnative = Knex({ + client: 'pgnative', + connection: + 'postgres://postgres:postgresrootpassword@localhost:25433/postgres', + pool: { max: 50 }, +}); + +const mysql2 = Knex({ + client: 'mysql2', + connection: + 'mysql://root:mysqlrootpassword@localhost:23306/?charset=utf8&connectTimeout=500', + pool: { max: 50 }, +}); + +const mysql = Knex({ + client: 'mysql', + connection: + 'mysql://root:mysqlrootpassword@localhost:23306/?charset=utf8&connectTimeout=500', + pool: { max: 50 }, +}); + +const mssql = Knex({ + client: 'mssql', + connection: { + port: 21433, + user: 'sa', + password: 'S0meVeryHardPassword', + server: 'localhost', + requestTimeout: 500, + }, + pool: { max: 50 }, +}); + +/* TODO: figure out how to nicely install oracledb node driver on osx +const oracledb = Knex({ + client: 'oracledb', + connection: { + user : "travis", + password : "travis", + connectString : "localhost/XE", + // https://github.com/oracle/node-oracledb/issues/525 + stmtCacheSize : 0 + }, + pool: { max: 50 } +}); +*/ + +const counters = {}; + +function setQueryCounters(instance, name) { + const counts = (counters[name] = { queries: 0, results: 0, errors: 0 }); + instance.on('query', () => (counts.queries += 1)); + instance.on('query-response', () => (counts.results += 1)); + instance.on('query-error', () => (counts.errors += 1)); +} + +setQueryCounters(pg, 'pg'); +setQueryCounters(mysql, 'mysql'); +setQueryCounters(mysql2, 'mysql2'); +setQueryCounters(mssql, 'mssql'); + +const _ = require('lodash'); + +// start printing out counters +let lastCounters = _.cloneDeep(counters); + +setInterval(() => { + const reqsPerSec = {}; + for (const key of Object.keys(counters)) { + reqsPerSec[key] = { + queries: (counters[key].queries - lastCounters[key].queries) / 2, + results: (counters[key].results - lastCounters[key].results) / 2, + errors: (counters[key].errors - lastCounters[key].errors) / 2, + }; + } + console.log( + '------------------------ STATS PER SECOND ------------------------' + ); + console.dir(reqsPerSec, { colors: true }); + console.log( + '------------------------------- EOS ------------------------------' + ); + lastCounters = _.cloneDeep(counters); +}, 2000); + +async function killConnectionsPg(client) { + return client.raw(`SELECT pg_terminate_backend(pg_stat_activity.pid) + FROM pg_stat_activity + WHERE pg_stat_activity.datname = 'postgres' + AND pid <> pg_backend_pid()`); +} + +async function killConnectionsMyslq(client) { + const [rows] = await client.raw(`SHOW FULL PROCESSLIST`); + await Promise.all(rows.map((row) => client.raw(`KILL ${row.Id}`))); +} + +async function killConnectionsMssql() { + const rows = await mssql('sys.dm_exec_sessions').select('session_id'); + await Promise.all(rows.map((row) => mssql.raw(`KILL ${row.session_id}`))); +} + +async function main() { + async function loopQueries(prefix, query) { + const queries = () => [...Array(50).fill(query)]; + + // eslint-disable-next-line no-constant-condition + while (true) { + try { + await Promise.all(queries()); + } catch (err) { + console.log(prefix, err); + } + } + } + + async function recreateProxy(serviceName, listenPort, proxyToPort) { + try { + await rp.delete({ + url: `${toxicli.host}/proxies/${serviceName}`, + }); + } catch (err) { + /* empty */ + } + + const proxy = await toxicli.createProxy({ + name: serviceName, + listen: `0.0.0.0:${listenPort}`, + upstream: `${serviceName}:${proxyToPort}`, + }); + + // add some latency + await proxy.addToxic( + new toxiproxy.Toxic(proxy, { + type: 'latency', + attributes: { latency: 1, jitter: 1 }, + }) + ); + + // cause connections to be closed every 500 bytes + await proxy.addToxic( + new toxiproxy.Toxic(proxy, { + type: 'limit_data', + attributes: { bytes: 5000 }, + }) + ); + } + + // create TCP proxies for simulating bad connections etc. + async function recreateProxies() { + await recreateProxy('postgresql', 25432, 5432); + await recreateProxy('postgresql', 25433, 5433); + await recreateProxy('mysql', 23306, 3306); + await recreateProxy('oracledb', 21521, 1521); + await recreateProxy('mssql', 21433, 1433); + } + + await recreateProxies(); + + loopQueries('PSQL:', pg.raw('select 1')); + loopQueries('PSQL TO:', pg.raw('select 1').timeout(20)); + + loopQueries('PGNATIVE:', pgnative.raw('select 1')); + loopQueries('PGNATIVE TO:', pgnative.raw('select 1').timeout(20)); + + loopQueries('MYSQL:', mysql.raw('select 1')); + loopQueries('MYSQL TO:', mysql.raw('select 1').timeout(20)); + + // mysql2 still crashes app (without connection killer nor timeouts) + // https://github.com/sidorares/node-mysql2/issues/731 + // loopQueries('MYSQL2:', mysql2.raw('select 1')); + // loopQueries('MYSQL2 TO:', mysql2.raw('select 1').timeout(20)); + + loopQueries('MSSQL:', mssql.raw('select 1')); + loopQueries('MSSQL TO:', mssql.raw('select 1').timeout(20)); + + setInterval(recreateProxies, 2000); + + // eslint-disable-next-line no-constant-condition + while (true) { + await delay(20); // kill everything every quite often from server side + try { + await Promise.all([ + killConnectionsPg(pg), + killConnectionsPg(pgnative), + killConnectionsMyslq(mysql), + // killConnectionsMyslq(mysql2), + killConnectionsMssql(), + ]); + } catch (err) { + console.log('KILLER ERROR:', err); + } + } +} + +process.on('exit', () => console.log('- STATS PRINT NEAR END LOGS ')); // marker for grep... +main(); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/mysql2-random-hanging-every-now-and-then.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/mysql2-random-hanging-every-now-and-then.js new file mode 100644 index 000000000..b21f60104 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/mysql2-random-hanging-every-now-and-then.js @@ -0,0 +1,149 @@ +/** + * Test case for figuring out robust way to recognize if connection is dead + * for mysql based drivers. + */ +const delay = require('../../lib/execution/internal/delay'); +const toxiproxy = require('toxiproxy-node-client'); +const toxicli = new toxiproxy.Toxiproxy('http://localhost:8474'); +const rp = require('request-promise-native'); +const _ = require('lodash'); + +async function stdMysqlQuery(con, sql) { + return new Promise((resolve, reject) => { + try { + con.query( + { + sql, + timeout: 500, + }, + function (error, results, fields) { + if (error) { + reject(error); + } else { + resolve(results); + } + } + ); + } catch (err) { + reject(err); // double sure... + } + }); +} + +const mysql2 = require('mysql2'); +let mysql2Con = { _fatalError: 'initmefirst' }; +async function mysql2Query(sql) { + // recreate connection on fatal error + if (mysql2Con._fatalError) { + console.log('========== Reconnecting mysql2'); + mysql2Con = mysql2.createConnection({ + host: 'localhost', + user: 'root', + password: 'mysqlrootpassword', + port: 23306, + connectTimeout: 500, + debug: true, + }); + mysql2Con.on('error', (err) => { + console.log('- STATS Mysql2 connection died:', err); + }); + } + console.log('================ MYSQL2 Running query ======'); + const res = await stdMysqlQuery(mysql2Con, sql); + console.log('====================== done ================'); + return res; +} + +const counters = {}; +function setMysqlQueryCounters(name) { + counters[name] = { queries: 0, results: 0, errors: 0 }; +} +setMysqlQueryCounters('mysql2'); + +// start printing out counters +let lastCounters = _.cloneDeep(counters); +setInterval(() => { + const reqsPerSec = {}; + for (const key of Object.keys(counters)) { + reqsPerSec[key] = { + queries: counters[key].queries - lastCounters[key].queries, + results: counters[key].results - lastCounters[key].results, + errors: counters[key].errors - lastCounters[key].errors, + }; + } + console.log( + '------------------------ STATS PER SECOND ------------------------' + ); + console.dir(reqsPerSec, { colors: true }); + console.log( + '------------------------------- EOS ------------------------------' + ); + lastCounters = _.cloneDeep(counters); +}, 1000); + +async function recreateProxy(serviceName, listenPort, proxyToPort) { + try { + await rp.delete({ + url: `${toxicli.host}/proxies/${serviceName}`, + }); + } catch (err) { + /* empty */ + } + + const proxy = await toxicli.createProxy({ + name: serviceName, + listen: `0.0.0.0:${listenPort}`, + upstream: `${serviceName}:${proxyToPort}`, + }); + + // add some latency + await proxy.addToxic( + new toxiproxy.Toxic(proxy, { + type: 'latency', + attributes: { latency: 1, jitter: 1 }, + }) + ); + + // cause connections to be closed every some transferred bytes + await proxy.addToxic( + new toxiproxy.Toxic(proxy, { + type: 'limit_data', + attributes: { bytes: 1000 }, + }) + ); +} + +async function main() { + await recreateProxy('mysql', 23306, 3306); + setInterval(() => recreateProxy('mysql', 23306, 3306), 2000); + + async function loopQueries(prefix, query) { + const counts = counters[prefix]; + + // eslint-disable-next-line no-constant-condition + while (true) { + try { + counts.queries += 1; + // without this delay we might endup to busy failure loop + await delay(0); + await query(); + counts.results += 1; + } catch (err) { + counts.errors += 1; + console.log(prefix, err); + } + } + } + + loopQueries('mysql2', () => mysql2Query('select 1')); + + // wait forever + // eslint-disable-next-line no-constant-condition + while (true) { + await delay(1000); + } +} + +main() + .then(() => console.log('DONE')) + .catch((err) => console.log(err)); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/mysql2-sudden-exit-without-error.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/mysql2-sudden-exit-without-error.js new file mode 100644 index 000000000..81e7910f3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/mysql2-sudden-exit-without-error.js @@ -0,0 +1,101 @@ +/** + * Test case when mysql2 driver strangely exits when one tries to send query + * to dead connection. + */ + +const delay = require('../../lib/execution/internal/delay'); +const toxiproxy = require('toxiproxy-node-client'); +const toxicli = new toxiproxy.Toxiproxy('http://localhost:8474'); +const rp = require('request-promise-native'); + +// drops old toxicproxy and creates new +async function recreateProxy(serviceName, listenPort, proxyToPort) { + try { + await rp.delete({ + url: `${toxicli.host}/proxies/${serviceName}`, + }); + } catch (err) { + // there was no proxy by that name... its ok + } + + await toxicli.createProxy({ + name: serviceName, + listen: `0.0.0.0:${listenPort}`, + upstream: `${serviceName}:${proxyToPort}`, + }); +} + +async function insanelyParanoidQuery(con) { + console.log('sending query'); + const res = await new Promise((resolve, reject) => { + try { + con.query('select 1', [], function (err, rows, fields) { + if (err) { + reject(err); + } else { + resolve(rows); + } + }); + } catch (err) { + console.log('Huh synchronous exception?! (shouldnt be possible)'); + reject(err); + } + }); + console.log(res); +} + +async function main() { + // create proxy from localhost:23306 -> mysqldocker:3306 + await recreateProxy('mysql', 23306, 3306); + + // ------------- setup mysql2 db driver connection + const mysql2 = require('mysql2'); // with mysql this works... + const mysql2Con = await mysql2.createConnection({ + host: 'localhost', + user: 'root', + password: 'mysqlrootpassword', + port: 23306, + }); + + mysql2Con.on('error', function (err) { + console.log("I'm dead", err); + }); + + console.log('Going to cut connections'); + + // cut connection during recreate + await recreateProxy('mysql', 23306, 3306); + + console.log('Proxy recreated... start waiting'); + + // wait forever + // eslint-disable-next-line no-constant-condition + while (true) { + await delay(1000); + try { + await insanelyParanoidQuery(mysql2Con); + } catch (err) { + console.log('query failed:', err); + } + await recreateProxy('mysql', 23306, 3306); + } +} + +main() + .then(() => console.log('Process stopped normally')) + .catch((err) => { + console.log('Process stopped to failure', err); + }); + +console.log('Waiting for eventloop to stop...'); + +process.on('uncaughtException', function (err) { + console.log('uncaughtException', err); +}); + +process.on('exit', function () { + console.log( + 'Did someone call process.exit() or wat? exitCode:', + process.exitCode + ); +}); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/reconnect-test-mysql-based-drivers.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/reconnect-test-mysql-based-drivers.js new file mode 100644 index 000000000..2723a81d2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/stress-test/reconnect-test-mysql-based-drivers.js @@ -0,0 +1,188 @@ +/** + * Test case for figuring out robust way to recognize if connection is dead + * for mysql based drivers. + */ +const delay = require('../../lib/execution/internal/delay'); +const toxiproxy = require('toxiproxy-node-client'); +const toxicli = new toxiproxy.Toxiproxy('http://localhost:8474'); +const rp = require('request-promise-native'); + +async function stdMysqlQuery(con, sql) { + return new Promise((resolve, reject) => { + try { + con.query( + { + sql, + timeout: 4000, + }, + function (error, results, fields) { + if (error) { + reject(error); + } else { + resolve(results); + } + } + ); + } catch (err) { + reject(err); // double sure... + } + }); +} + +// ALL THE DRIVERS HAS DIFFERENT BAG OF TRICKS TO RECOVER AND +// RECOGNIZE WHEN CONNECTION HAS BEEN CLOSED + +// ------------- setup mysql db driver connection +const mysql = require('mysql'); +let mysqlCon = { state: 'disconnected' }; +async function mysqlQuery(sql) { + // best way to check if connection is still alive + if (mysqlCon.state === 'disconnected') { + console.log('reconnecting mysql'); + mysqlCon = mysql.createConnection({ + host: 'localhost', + user: 'root', + password: 'mysqlrootpassword', + port: 23306, + connectTimeout: 500, + }); + // not always triggered, if this happens during query + mysqlCon.on('error', (err) => { + console.log('- STATS Mysql connection died:', err); + }); + } + return stdMysqlQuery(mysqlCon, sql); +} + +// ------------- setup mysql2 db driver connection +const mysql2 = require('mysql2'); +let mysql2Con = { _fatalError: 'initmefirst' }; +async function mysql2Query(sql) { + if (mysql2Con._fatalError) { + console.log('reconnecting mysql2'); + mysql2Con = mysql2.createConnection({ + host: 'localhost', + user: 'root', + password: 'mysqlrootpassword', + port: 23306, + connectTimeout: 500, + }); + mysql2Con.on('error', (err) => { + console.log('- STATS Mysql2 connection died:', err); + }); + } + console.log('================ MYSQL2 Running query....'); + const res = await stdMysqlQuery(mysql2Con, sql); + console.log('=========== done'); + return res; +} + +const counters = {}; +function setMysqlQueryCounters(name) { + counters[name] = { queries: 0, results: 0, errors: 0 }; +} +setMysqlQueryCounters('mysql'); +setMysqlQueryCounters('mysql2'); + +const _ = require('lodash'); + +// start printing out counters +let lastCounters = _.cloneDeep(counters); + +setInterval(() => { + const reqsPerSec = {}; + for (const key of Object.keys(counters)) { + reqsPerSec[key] = { + queries: counters[key].queries - lastCounters[key].queries, + results: counters[key].results - lastCounters[key].results, + errors: counters[key].errors - lastCounters[key].errors, + }; + } + console.log( + '------------------------ STATS PER SECOND ------------------------' + ); + console.dir(reqsPerSec, { colors: true }); + console.log( + '------------------------------- EOS ------------------------------' + ); + lastCounters = _.cloneDeep(counters); + + // if hang + ///if (reqsPerSec.mysql2.queries === 0) process.exit(0); +}, 1000); + +async function main() { + async function recreateProxy(serviceName, listenPort, proxyToPort) { + try { + await rp.delete({ + url: `${toxicli.host}/proxies/${serviceName}`, + }); + } catch (err) { + /* empty */ + } + + const proxy = await toxicli.createProxy({ + name: serviceName, + listen: `0.0.0.0:${listenPort}`, + upstream: `${serviceName}:${proxyToPort}`, + }); + + // add some latency + await proxy.addToxic( + new toxiproxy.Toxic(proxy, { + type: 'latency', + attributes: { latency: 1, jitter: 1 }, + }) + ); + + // cause connections to be closed every some transferred bytes + await proxy.addToxic( + new toxiproxy.Toxic(proxy, { + type: 'limit_data', + attributes: { bytes: 1000 }, + }) + ); + } + + // create TCP proxies for simulating bad connections etc. + async function recreateProxies() { + console.log('----- Recreating proxies -> cutting connections completely'); + await recreateProxy('postgresql', 25432, 5432); + await recreateProxy('mysql', 23306, 3306); + await recreateProxy('oracledb', 21521, 1521); + } + setInterval(() => recreateProxies(), 2000); + + async function loopQueries(prefix, query) { + const counts = counters[prefix]; + + // eslint-disable-next-line no-constant-condition + while (true) { + try { + counts.queries += 1; + // without this delay we endup to busy failure loop + await delay(0); + await query(); + counts.results += 1; + } catch (err) { + counts.errors += 1; + console.log(prefix, err); + } + } + } + + await recreateProxies(); + + loopQueries('mysql', () => mysqlQuery('select 1')); + loopQueries('mysql2', () => mysql2Query('select 1')); + + // wait forever + // eslint-disable-next-line no-constant-condition + while (true) { + await delay(1000); + } +} + +main() + .then(() => console.log('DONE')) + .catch((err) => console.log(err)); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/update_gitignore_for_tsc_output.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/update_gitignore_for_tsc_output.js new file mode 100644 index 000000000..f48f7d576 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/scripts/update_gitignore_for_tsc_output.js @@ -0,0 +1,90 @@ +#!/usr/bin/env node + +const path = require('path'); +const fs = require('fs'); + +// Directory constants +const scriptDirectory = __dirname; +const repoDirectory = path.join(scriptDirectory, '..'); +const libDirectory = path.join(repoDirectory, 'lib'); + +const helpText = ` +Helper script to update lib/.gitignore for all .js files from .ts files. + + update_gitignore_for_tsc_output.js COMMAND + + COMMAND: + run: Update lib/.gitignore file. + help: Print this menu. + + NOTES FOR USAGE: + 1. This script is tested to work on Ubuntu 18.04 LTS. +`; + +const gitignoreHeader = `# DO NOT EDIT, GENERATED BY: scripts/update_gitignore_for_tsc_output.js + +# Do not include tsc generated type definitions +**/*.d.ts + +# Do not include tsc source maps +**/*.js.map + +# Do not include .js files from .ts files +`; + +function main(cliCommand) { + if (cliCommand === 'run') { + console.log('Generating lib/.gitignore ...'); + + // Find all .ts files in lib/ + const directoriesToProcess = [libDirectory]; + const tsFiles = []; + while (directoriesToProcess.length > 0) { + const directory = directoriesToProcess.pop(); + if (!fs.existsSync(directory)) { + throw new Error("Directory doesn't exist:", directory); + } + + const files = fs.readdirSync(directory); + files.forEach((file) => { + const filename = path.join(directory, file); + const stat = fs.lstatSync(filename); + if (stat.isDirectory()) { + directoriesToProcess.push(filename); + } else if (filename.endsWith('.ts') && !filename.endsWith('.d.ts')) { + tsFiles.push(filename); + console.log('Found .ts file:', filename); + } + }); + } + + // Get paths of .js files to ignore + const jsFilesToIgnore = tsFiles.map((filepath) => { + // Cuts off `${libDirectory}/` + const relativeTsPath = filepath.slice(libDirectory.length + 1); + // Swaps .ts for .js file ending + const relativeJsPath = + relativeTsPath.slice(0, relativeTsPath.length - 3) + '.js'; + // Always use POSIX-style path separators - .gitignore requires it + return relativeJsPath.split(path.sep).join(path.posix.sep); + }); + const jsFilesToIgnoreString = jsFilesToIgnore.join('\n'); + const libGitignorePath = path.join(libDirectory, '.gitignore'); + fs.writeFileSync( + libGitignorePath, + gitignoreHeader + jsFilesToIgnoreString + '\n' + ); + console.log('DONE'); + } else if (['help', '--help', '-h', undefined].includes(cliCommand)) { + console.log(helpText); + } else { + console.log(`Unsupported command: ${cliCommand}`); + console.log("Try running with 'help' to see supported commands."); + process.exit(1); + } +} + +// Main script logic +const cliCommand = process.argv[2]; +// Start the bash app's main function +main(cliCommand); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/types/index.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/types/index.d.ts new file mode 100644 index 000000000..d191bd476 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/types/index.d.ts @@ -0,0 +1,3275 @@ +// Originally based on contributions to DefinitelyTyped: +// Definitions by: Qubo +// Pablo Rodríguez +// Matt R. Wilson +// Satana Charuwichitratana +// Shrey Jain +// TypeScript Version: 4.1 + +import tarn = require('tarn'); +import events = require('events'); +import stream = require('stream'); +import ResultTypes = require('./result'); + +import { Tables } from './tables'; + +import { Stream } from 'stream'; +import { ConnectionOptions } from 'tls'; + +// # Generic type-level utilities + +// If T is object then make it a partial otherwise fallback to any +// +// This is primarily to prevent type incompatibilities where target can be unknown. +// While unknown can be assigned to any, Partial can't be. +type SafePartial = Partial>; + +type MaybeArray = T | T[]; + +type StrKey = string & keyof T; + +// If T is unknown then convert to any, else retain original +type UnknownToAny = unknown extends T ? any : T; +type CurlyCurlyToAny = T extends unknown // distribute + ? (() => U extends T ? 0 : 1) extends () => U extends {} ? 0 : 1 + ? any + : T + : never; +type UnknownOrCurlyCurlyToAny = [UnknownToAny | CurlyCurlyToAny][0]; +type AnyToUnknown = unknown extends T ? unknown : T; +type AnyOrUnknownToOther = unknown extends T1 ? T2 : T1; + +// Intersection conditionally applied only when TParams is non-empty +// This is primarily to keep the signatures more intuitive. +type AugmentParams = TParams extends {} + ? keyof TParams extends never + ? TTarget + : {} & TTarget & TParams + : TTarget; + +// Check if provided keys (expressed as a single or union type) are members of TBase +type AreKeysOf = Boxed extends Boxed + ? true + : false; + +// https://stackoverflow.com/a/50375286/476712 +type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ( + k: infer I +) => void + ? I + : never; + +type ComparisonOperator = '=' | '>' | '>=' | '<' | '<=' | '<>'; + +// If T is an array, get the type of member, else fall back to never +type ArrayMember = T extends (infer M)[] ? M : never; + +// If T is an array, get the type of member, else retain original +type UnwrapArrayMember = T extends (infer M)[] ? M : T; + +// Wrap a type in a container, making it an object type. +// This is primarily useful in circumventing special handling of union/intersection in typescript +interface Boxed { + _value: T; +} + +// If T can't be assigned to TBase fallback to an alternate type TAlt +type IncompatibleToAlt = T extends TBase ? T : TAlt; + +type ArrayIfAlready = AnyToUnknown extends any[] ? T2[] : T2; + +// Boxing is necessary to prevent distribution of conditional types: +// https://lorefnon.tech/2019/05/02/using-boxing-to-prevent-distribution-of-conditional-types/ +type PartialOrAny = Boxed extends Boxed + ? {} + : Boxed extends Boxed + ? SafePick + : any; + +// Retain the association of original keys with aliased keys at type level +// to facilitates type-safe aliasing for object syntax +type MappedAliasType = {} & { + [K in keyof TAliasMapping]: TAliasMapping[K] extends keyof TBase + ? TBase[TAliasMapping[K]] + : any; +}; + +// Container type for situations when we want a partial/intersection eventually +// but the keys being selected or additional properties being augmented are not +// all known at once and we would want to effectively build up a partial/intersection +// over multiple steps. +type DeferredKeySelection< + // The base of selection. In intermediate stages this may be unknown. + // If it remains unknown at the point of resolution, the selection will fall back to any + TBase, + // Union of keys to be selected + // In intermediate stages this may be never. + TKeys extends string, + // Changes how the resolution should behave if TKeys is never. + // If true, then we assume that some keys were selected, and if TKeys is never, we will fall back to any. + // If false, and TKeys is never, then we select TBase in its entirety + THasSelect extends true | false = false, + // Mapping of aliases -> + TAliasMapping extends {} = {}, + // If enabled, then instead of extracting a partial, during resolution + // we will pick just a single property. + TSingle extends boolean = false, + // Extra props which will be intersected with the result + TIntersectProps extends {} = {}, + // Extra props which will be unioned with the result + TUnionProps = never +> = { + // These properties are not actually used, but exist simply because + // typescript doesn't end up happy when type parameters are unused + _base: TBase; + _hasSelection: THasSelect; + _keys: TKeys; + _aliases: TAliasMapping; + _single: TSingle; + _intersectProps: TIntersectProps; + _unionProps: TUnionProps; +}; + +// An companion namespace for DeferredKeySelection which provides type operators +// to build up participants of intersection/partial over multiple invocations +// and for final resolution. +// +// While the comments use wordings such as replacement and addition, it is important +// to keep in mind that types are always immutable and all type operators return new altered types. +declare namespace DeferredKeySelection { + type Any = DeferredKeySelection; + + // Replace the Base if already a deferred selection. + // If not, create a new deferred selection with specified base. + type SetBase = TSelection extends DeferredKeySelection< + any, + infer TKeys, + infer THasSelect, + infer TAliasMapping, + infer TSingle, + infer TIntersectProps, + infer TUnionProps + > + ? DeferredKeySelection< + TBase, + TKeys, + THasSelect, + TAliasMapping, + TSingle, + TIntersectProps, + TUnionProps + > + : DeferredKeySelection; + + // If TSelection is already a deferred selection, then replace the base with TBase + // If unknown, create a new deferred selection with TBase as the base + // Else, retain original + // + // For practical reasons applicable to current context, we always return arrays of + // deferred selections. So, this particular operator may not be useful in generic contexts. + type ReplaceBase = + UnwrapArrayMember extends DeferredKeySelection.Any + ? ArrayIfAlready< + TSelection, + DeferredKeySelection.SetBase, TBase> + > + : unknown extends UnwrapArrayMember + ? ArrayIfAlready> + : TSelection; + + // Type operators to substitute individual type parameters: + + type SetSingle< + TSelection, + TSingle extends boolean + > = TSelection extends DeferredKeySelection< + infer TBase, + infer TKeys, + infer THasSelect, + infer TAliasMapping, + any, + infer TIntersectProps, + infer TUnionProps + > + ? DeferredKeySelection< + TBase, + TKeys, + THasSelect, + TAliasMapping, + TSingle, + TIntersectProps, + TUnionProps + > + : never; + + type AddKey< + TSelection, + TKey extends string + > = TSelection extends DeferredKeySelection< + infer TBase, + infer TKeys, + any, + infer TAliasMapping, + infer TSingle, + infer TIntersectProps, + infer TUnionProps + > + ? DeferredKeySelection< + TBase, + TKeys | TKey, + true, + TAliasMapping, + TSingle, + TIntersectProps, + TUnionProps + > + : DeferredKeySelection; + + type AddAliases< + TSelection, + T extends {} + > = TSelection extends DeferredKeySelection< + infer TBase, + infer TKeys, + infer THasSelect, + infer TAliasMapping, + infer TSingle, + infer TIntersectProps, + infer TUnionProps + > + ? DeferredKeySelection< + TBase, + TKeys, + THasSelect, + TAliasMapping & T, + TSingle, + TIntersectProps, + TUnionProps + > + : DeferredKeySelection; + + type AddUnionMember = TSelection extends DeferredKeySelection< + infer TBase, + infer TKeys, + infer THasSelect, + infer TAliasMapping, + infer TSingle, + infer TIntersectProps, + infer TUnionProps + > + ? DeferredKeySelection< + TBase, + TKeys, + THasSelect, + TAliasMapping, + TSingle, + TIntersectProps, + TUnionProps | T + > + : DeferredKeySelection; + + // Convenience utility to set base, keys and aliases in a single type + // application + type Augment< + T, + TBase, + TKey extends string, + TAliasMapping extends {} = {} + > = AddAliases, TKey>, TAliasMapping>; + + // Core resolution logic -- Refer to docs for DeferredKeySelection for specifics + type ResolveOne = TSelection extends DeferredKeySelection< + infer TBase, + infer TKeys, + infer THasSelect, + infer TAliasMapping, + infer TSingle, + infer TIntersectProps, + infer TUnionProps + > + ? UnknownOrCurlyCurlyToAny< + // ^ We convert final result to any if it is unknown for backward compatibility. + // Historically knex typings have been liberal with returning any and changing + // default return type to unknown would be a major breaking change for users. + // + // So we compromise on type safety here and return any. + | AugmentParams< + AnyToUnknown extends {} + ? // ^ Conversion of any -> unknown is needed here to prevent distribution + // of any over the conditional + TSingle extends true + ? TKeys extends keyof TBase + ? TBase[TKeys] + : any + : AugmentParams< + true extends THasSelect + ? PartialOrAny + : TBase, + MappedAliasType + > + : unknown, + TIntersectProps + > + | TUnionProps + > + : TSelection; + + type Resolve = TSelection extends DeferredKeySelection.Any + ? Knex.ResolveTableType> + : TSelection extends DeferredKeySelection.Any[] + ? Knex.ResolveTableType>[] + : TSelection extends (infer I)[] + ? UnknownOrCurlyCurlyToAny>[] + : UnknownOrCurlyCurlyToAny>; +} + +type AggregationQueryResult< + TResult, + TIntersectProps2 extends {} +> = ArrayIfAlready< + TResult, + UnwrapArrayMember extends DeferredKeySelection< + infer TBase, + infer TKeys, + infer THasSelect, + infer TAliasMapping, + infer TSingle, + infer TIntersectProps, + infer TUnionProps + > + ? true extends THasSelect + ? DeferredKeySelection< + TBase, + TKeys, + THasSelect, + TAliasMapping, + TSingle, + TIntersectProps & TIntersectProps2, + TUnionProps + > + : DeferredKeySelection<{}, never, true, {}, false, TIntersectProps2> + : TIntersectProps2 +>; + +// If we have more categories of deferred selection in future, +// this will combine all of them +type ResolveResult = DeferredKeySelection.Resolve; + +// # Type-aliases for common type combinations + +type Callback = Function; +type Client = Function; + +type Dict = { [k: string]: T }; + +type SafePick = T extends {} ? Pick : any; + +type TableOptions = PgTableOptions; + +interface PgTableOptions { + only?: boolean; +} + +interface DMLOptions { + includeTriggerModifications?: boolean; +} + +interface Knex + extends Knex.QueryInterface, + events.EventEmitter { + ( + tableName: TTable, + options?: TableOptions + ): Knex.QueryBuilder< + Knex.TableType, + DeferredKeySelection>, never>[] + >; + < + TRecord2 extends {} = TRecord, + TResult2 = DeferredKeySelection[] + >( + tableName?: Knex.TableDescriptor | Knex.AliasDict, + options?: TableOptions + ): Knex.QueryBuilder; + VERSION: string; + __knex__: string; + + raw: Knex.RawBuilder; + + transactionProvider( + config?: Knex.TransactionConfig + ): Knex.TransactionProvider; + transaction(config?: Knex.TransactionConfig): Promise; + transaction( + transactionScope?: null, + config?: Knex.TransactionConfig + ): Promise; + transaction( + transactionScope: (trx: Knex.Transaction) => Promise | void, + config?: Knex.TransactionConfig + ): Promise; + initialize(config?: Knex.Config): void; + destroy(callback: Function): void; + destroy(): Promise; + + batchInsert( + tableName: Knex.TableDescriptor, + data: TRecord2 extends Knex.CompositeTableType + ? ReadonlyArray> + : ReadonlyArray>, + chunkSize?: number + ): Knex.BatchInsertBuilder; + + schema: Knex.SchemaBuilder; + queryBuilder< + TRecord2 extends {} = TRecord, + TResult2 = TResult + >(): Knex.QueryBuilder; + + client: any; + migrate: Knex.Migrator; + seed: Knex.Seeder; + fn: Knex.FunctionHelper; + ref: Knex.RefBuilder; + userParams: Record; + withUserParams(params: Record): Knex; + isTransaction?: boolean; +} + +declare function knex( + config: Knex.Config | string +): Knex; + +declare namespace knex { + export { knex, knex as default, Knex }; + export class QueryBuilder { + static extend( + methodName: string, + fn: ( + this: Knex.QueryBuilder, + ...args: any[] + ) => + | Knex.QueryBuilder + | Promise< + | Knex.QueryBuilder + | DeferredKeySelection.Resolve + > + ): void; + } + + export class TableBuilder { + static extend( + methodName: string, + fn: (this: T, ...args: any[]) => B + ): void; + } + export class ViewBuilder { + static extend( + methodName: string, + fn: (this: T, ...args: any[]) => B + ): void; + } + export class SchemaBuilder { + static extend( + methodName: string, + fn: (this: T, ...args: any[]) => B + ): void; + } + export class ColumnBuilder { + static extend( + methodName: string, + fn: (this: T, ...args: any[]) => B + ): void; + } + + export class KnexTimeoutError extends Error {} + + export const Client: typeof Knex.Client; +} + +declare namespace Knex { + // + // Utility Types + // + + type Value = + | string + | number + | boolean + | null + | Date + | Array + | Array + | Array + | Array + | Buffer + | object + | Knex.Raw; + + interface ValueDict extends Dict {} + interface AliasDict extends Dict {} + + type ColumnDescriptor = + | string + | Knex.Raw + | Knex.QueryBuilder + | Dict; + + type InferrableColumnDescriptor = + | keyof TRecord + | Knex.Ref + | Dict; + + type TableDescriptor = string | Knex.Raw | Knex.QueryBuilder; + + type Lookup< + TRegistry extends {}, + TKey extends string, + TDefault = never + > = TKey extends keyof TRegistry ? TRegistry[TKey] : TDefault; + + type MaybeRawColumn = TColumn | Raw; + + type MaybeRawRecord = { + [K in keyof TRecord]: MaybeRawColumn; + }; + + type DbColumn = Readonly>; + + type DbRecord = Readonly>>; + + type DbRecordArr = Readonly>>; + + export type CompositeTableType< + TBase, + TInsert = TBase, + TUpdate = Partial, + TUpsert = Partial + > = { + base: TBase; + insert: TInsert; + update: TUpdate; + upsert: TUpsert; + }; + + type TableNames = keyof Tables; + + type TableInterfaceScope = keyof CompositeTableType; + + type TableType = Tables[TTable]; + + type ResolveTableType< + TCompositeTableType, + TScope extends TableInterfaceScope = 'base' + > = TCompositeTableType extends CompositeTableType<{}> + ? TCompositeTableType[TScope] + : TCompositeTableType; + + interface OnConflictQueryBuilder { + ignore(): QueryBuilder; + merge( + mergeColumns?: (keyof ResolveTableType)[] + ): QueryBuilder; + merge( + data?: Extract>, object> + ): QueryBuilder; + } + + // + // QueryInterface + // + type ClearStatements = + | 'with' + | 'select' + | 'columns' + | 'hintComments' + | 'where' + | 'union' + | 'using' + | 'join' + | 'group' + | 'order' + | 'having' + | 'limit' + | 'offset' + | 'counter' + | 'counters'; + + interface QueryInterface { + select: Select; + as: As; + columns: Select; + column: Select; + comment: Comment; + hintComment: HintComment; + from: Table; + fromRaw: Table; + into: Table; + table: Table; + distinct: Distinct; + distinctOn: DistinctOn; + + // Joins + join: Join; + joinRaw: JoinRaw; + innerJoin: Join; + leftJoin: Join; + leftOuterJoin: Join; + rightJoin: Join; + rightOuterJoin: Join; + outerJoin: Join; + fullOuterJoin: Join; + crossJoin: Join; + + // Json manipulation + jsonExtract: JsonExtract; + jsonSet: JsonSet; + jsonInsert: JsonInsert; + jsonRemove: JsonRemove; + + // Using + using: Using; + + // Withs + with: With; + withMaterialized: With; + withNotMaterialized: With; + withRecursive: With; + withRaw: WithRaw; + withSchema: WithSchema; + withWrapped: WithWrapped; + + // Wheres + where: Where; + andWhere: Where; + orWhere: Where; + whereNot: Where; + andWhereNot: Where; + orWhereNot: Where; + whereRaw: WhereRaw; + orWhereRaw: WhereRaw; + andWhereRaw: WhereRaw; + whereWrapped: WhereWrapped; + havingWrapped: WhereWrapped; + whereExists: WhereExists; + orWhereExists: WhereExists; + whereNotExists: WhereExists; + orWhereNotExists: WhereExists; + whereIn: WhereIn; + orWhereIn: WhereIn; + whereNotIn: WhereIn; + orWhereNotIn: WhereIn; + whereLike: Where; + andWhereLike: Where; + orWhereLike: Where; + whereILike: Where; + andWhereILike: Where; + orWhereILike: Where; + whereNull: WhereNull; + orWhereNull: WhereNull; + whereNotNull: WhereNull; + orWhereNotNull: WhereNull; + whereBetween: WhereBetween; + orWhereBetween: WhereBetween; + andWhereBetween: WhereBetween; + whereNotBetween: WhereBetween; + orWhereNotBetween: WhereBetween; + andWhereNotBetween: WhereBetween; + + whereJsonObject: WhereJsonObject; + orWhereJsonObject: WhereJsonObject; + andWhereJsonObject: WhereJsonObject; + whereNotJsonObject: WhereJsonObject; + orWhereNotJsonObject: WhereJsonObject; + andWhereNotJsonObject: WhereJsonObject; + + whereJsonPath: WhereJsonPath; + orWhereJsonPath: WhereJsonPath; + andWhereJsonPath: WhereJsonPath; + + whereJsonSupersetOf: WhereJsonObject; + orWhereJsonSupersetOf: WhereJsonObject; + andWhereJsonSupersetOf: WhereJsonObject; + whereJsonNotSupersetOf: WhereJsonObject; + orWhereJsonNotSupersetOf: WhereJsonObject; + andWhereJsonNotSupersetOf: WhereJsonObject; + + whereJsonSubsetOf: WhereJsonObject; + orWhereJsonSubsetOf: WhereJsonObject; + andWhereJsonSubsetOf: WhereJsonObject; + whereJsonNotSubsetOf: WhereJsonObject; + orWhereJsonNotSubsetOf: WhereJsonObject; + andWhereJsonNotSubsetOf: WhereJsonObject; + + // Group by + groupBy: GroupBy; + groupByRaw: RawQueryBuilder; + + // Order by + orderBy: OrderBy; + orderByRaw: RawQueryBuilder; + + // Partition by + partitionBy: PartitionBy; + + // Unions + union: Union; + unionAll: Union; + intersect: Intersect; + except: Except; + + // Having + having: Having; + andHaving: Having; + havingRaw: RawQueryBuilder; + orHaving: Having; + orHavingRaw: RawQueryBuilder; + havingIn: HavingRange; + orHavingNotBetween: HavingRange; + havingNotBetween: HavingRange; + orHavingBetween: HavingRange; + havingBetween: HavingRange; + havingNotIn: HavingRange; + andHavingNotIn: HavingRange; + orHavingNotIn: HavingRange; + havingNull: HavingNull; + havingNotNull: HavingNull; + orHavingNull: HavingNull; + orHavingNotNull: HavingNull; + + // Clear + clearSelect(): QueryBuilder< + TRecord, + UnwrapArrayMember extends DeferredKeySelection< + infer TBase, + infer TKeys, + true, + any, + any, + any, + any + > + ? DeferredKeySelection[] + : TResult + >; + clearWhere(): QueryBuilder; + clearGroup(): QueryBuilder; + clearOrder(): QueryBuilder; + clearHaving(): QueryBuilder; + clearCounters(): QueryBuilder; + clear(statement: ClearStatements): QueryBuilder; + + // Paging + offset( + offset: number, + options?: boolean | Readonly<{ skipBinding?: boolean }> + ): QueryBuilder; + limit( + limit: number, + options?: string | Readonly<{ skipBinding?: boolean }> + ): QueryBuilder; + + // Aggregation + count: AsymmetricAggregation< + TRecord, + TResult, + Lookup + >; + countDistinct: AsymmetricAggregation< + TRecord, + TResult, + Lookup + >; + min: TypePreservingAggregation; + max: TypePreservingAggregation; + sum: TypePreservingAggregation; + sumDistinct: TypePreservingAggregation; + avg: TypePreservingAggregation; + avgDistinct: TypePreservingAggregation; + + increment( + columnName: keyof TRecord, + amount?: number + ): QueryBuilder; + increment( + columnName: string, + amount?: number + ): QueryBuilder; + increment(columns: { + [column in keyof TRecord]: number; + }): QueryBuilder; + + decrement( + columnName: keyof TRecord, + amount?: number + ): QueryBuilder; + decrement( + columnName: string, + amount?: number + ): QueryBuilder; + decrement(columns: { + [column in keyof TRecord]: number; + }): QueryBuilder; + + // Analytics + rank: AnalyticFunction; + denseRank: AnalyticFunction; + rowNumber: AnalyticFunction; + + // Others + first: Select< + TRecord, + DeferredKeySelection.AddUnionMember, undefined> + >; + + pluck( + column: K + ): QueryBuilder; + pluck(column: string): QueryBuilder; + + insert( + data: TRecord extends CompositeTableType + ? + | ResolveTableType + | ReadonlyArray> + : DbRecordArr | ReadonlyArray>, + returning: '*', + options?: DMLOptions + ): QueryBuilder[]>; + insert< + TKey extends StrKey>, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + TKey + >[] + >( + data: TRecord extends CompositeTableType + ? + | ResolveTableType + | ReadonlyArray> + : DbRecordArr | ReadonlyArray>, + returning: TKey, + options?: DMLOptions + ): QueryBuilder; + insert< + TKey extends StrKey>, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + TKey + >[] + >( + data: TRecord extends CompositeTableType + ? + | ResolveTableType + | ReadonlyArray> + : DbRecordArr | ReadonlyArray>, + returning: readonly TKey[], + options?: DMLOptions + ): QueryBuilder; + insert< + TKey extends string, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + TRecord, + TKey + >[] + >( + data: TRecord extends CompositeTableType + ? + | ResolveTableType + | ReadonlyArray> + : DbRecordArr | ReadonlyArray>, + returning: TKey, + options?: DMLOptions + ): QueryBuilder; + insert< + TKey extends string, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + TRecord, + TKey + >[] + >( + data: TRecord extends CompositeTableType + ? + | ResolveTableType + | ReadonlyArray> + : DbRecordArr | ReadonlyArray>, + returning: readonly TKey[], + options?: DMLOptions + ): QueryBuilder; + insert( + data: TRecord extends CompositeTableType + ? + | ResolveTableType + | ReadonlyArray> + : DbRecordArr | ReadonlyArray> + ): QueryBuilder; + + upsert( + data: TRecord extends CompositeTableType + ? + | ResolveTableType + | ReadonlyArray> + : DbRecordArr | ReadonlyArray>, + returning: '*', + options?: DMLOptions + ): QueryBuilder[]>; + upsert< + TKey extends StrKey>, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + TKey + >[] + >( + data: TRecord extends CompositeTableType + ? + | ResolveTableType + | ReadonlyArray> + : DbRecordArr | ReadonlyArray>, + returning: TKey, + options?: DMLOptions + ): QueryBuilder; + upsert< + TKey extends StrKey>, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + TKey + >[] + >( + data: TRecord extends CompositeTableType + ? + | ResolveTableType + | ReadonlyArray> + : DbRecordArr | ReadonlyArray>, + returning: readonly TKey[], + options?: DMLOptions + ): QueryBuilder; + upsert< + TKey extends string, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + TRecord, + TKey + >[] + >( + data: TRecord extends CompositeTableType + ? + | ResolveTableType + | ReadonlyArray> + : DbRecordArr | ReadonlyArray>, + returning: TKey, + options?: DMLOptions + ): QueryBuilder; + upsert< + TKey extends string, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + TRecord, + TKey + >[] + >( + data: TRecord extends CompositeTableType + ? + | ResolveTableType + | ReadonlyArray> + : DbRecordArr | ReadonlyArray>, + returning: readonly TKey[], + options?: DMLOptions + ): QueryBuilder; + upsert( + data: TRecord extends CompositeTableType + ? + | ResolveTableType + | ReadonlyArray> + : DbRecordArr | ReadonlyArray> + ): QueryBuilder; + + modify( + callback: QueryCallbackWithArgs, + ...args: any[] + ): QueryBuilder; + update< + K1 extends StrKey>, + K2 extends StrKey>, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + K2 + >[] + >( + columnName: K1, + value: DbColumn[K1]>, + returning: K2, + options?: DMLOptions + ): QueryBuilder; + update< + K1 extends StrKey>, + K2 extends StrKey>, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + K2 + >[] + >( + columnName: K1, + value: DbColumn[K1]>, + returning: readonly K2[], + options?: DMLOptions + ): QueryBuilder; + update( + columnName: K, + value: DbColumn + ): QueryBuilder; + update[]>( + columnName: string, + value: Value, + returning: string | readonly string[], + options?: DMLOptions + ): QueryBuilder; + update( + data: DbRecordArr, + returning: '*', + options?: DMLOptions + ): QueryBuilder[]>; + update< + TKey extends StrKey>, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + TKey + >[] + >( + data: TRecord extends CompositeTableType + ? ResolveTableType + : DbRecordArr, + returning: TKey, + options?: DMLOptions + ): QueryBuilder; + update< + TKey extends StrKey>, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + TKey + >[] + >( + data: TRecord extends CompositeTableType + ? ResolveTableType + : DbRecordArr, + returning: readonly TKey[], + options?: DMLOptions + ): QueryBuilder; + update< + TKey extends string = string, + TResult2 extends {}[] = DeferredKeySelection.Augment< + UnwrapArrayMember, + TRecord, + TKey + >[] + >( + data: TRecord extends CompositeTableType + ? ResolveTableType + : DbRecordArr, + returning: TKey | readonly TKey[], + options?: DMLOptions + ): QueryBuilder; + update< + TKey extends string, + TResult2 extends {}[] = DeferredKeySelection.Augment< + UnwrapArrayMember, + TRecord, + TKey + >[] + >( + data: TRecord extends CompositeTableType + ? ResolveTableType + : DbRecordArr, + returning: readonly TKey[], + options?: DMLOptions + ): QueryBuilder; + update( + data: TRecord extends CompositeTableType + ? ResolveTableType + : DbRecordArr + ): QueryBuilder; + + update( + columnName: string, + value: Value + ): QueryBuilder; + + returning( + column: '*', + options?: DMLOptions + ): QueryBuilder[]>; + returning< + TKey extends StrKey>, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + TKey + >[] + >( + column: TKey, + options?: DMLOptions + ): QueryBuilder; + returning< + TKey extends StrKey>, + TResult2 = DeferredKeySelection.SetSingle< + DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + TKey + >, + false + >[] + >( + columns: readonly TKey[], + options?: DMLOptions + ): QueryBuilder; + returning[]>( + column: string | readonly (string | Raw)[] | Raw, + options?: DMLOptions + ): QueryBuilder; + + onConflict>>( + column: TKey + ): OnConflictQueryBuilder; + onConflict>>( + columns: readonly TKey[] + ): OnConflictQueryBuilder; + + onConflict(columns: string): OnConflictQueryBuilder; + + onConflict(columns: string[]): OnConflictQueryBuilder; + + onConflict(raw: Raw): OnConflictQueryBuilder; + + onConflict(): OnConflictQueryBuilder; + + updateFrom: Table; + + del( + returning: '*', + options?: DMLOptions + ): QueryBuilder[]>; + del< + TKey extends StrKey, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + TRecord, + TKey + >[] + >( + returning: TKey, + options?: DMLOptions + ): QueryBuilder; + del< + TKey extends StrKey, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + TRecord, + TKey + >[] + >( + returning: readonly TKey[], + options?: DMLOptions + ): QueryBuilder; + del[]>( + returning: string | readonly string[], + options?: DMLOptions + ): QueryBuilder; + del(): QueryBuilder; + + delete( + returning: '*', + options?: DMLOptions + ): QueryBuilder[]>; + delete< + TKey extends StrKey>, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + TKey + >[] + >( + returning: TKey, + options?: DMLOptions + ): QueryBuilder; + delete< + TKey extends StrKey, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + TRecord, + TKey + >[] + >( + returning: readonly TKey[], + options?: DMLOptions + ): QueryBuilder; + delete( + returning: string | readonly (string | Raw)[] | Raw, + options?: DMLOptions + ): QueryBuilder; + delete(): QueryBuilder; + + truncate(): QueryBuilder; + } + + interface As { + (columnName: keyof TRecord): QueryBuilder; + (columnName: string): QueryBuilder; + } + + type IntersectAliases = UnionToIntersection< + IncompatibleToAlt< + AliasUT extends (infer I)[] + ? I extends Ref + ? TMapping + : I + : never, + Dict, + {} + > + > & {}; // filters out `null` and `undefined` + + interface AliasQueryBuilder { + < + AliasUT extends InferrableColumnDescriptor>[], + TResult2 = ArrayIfAlready< + TResult, + DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + IncompatibleToAlt, string, never>, + IntersectAliases + > + > + >( + ...aliases: AliasUT + ): QueryBuilder; + + < + AliasUT extends InferrableColumnDescriptor>[], + TResult2 = ArrayIfAlready< + TResult, + DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + IncompatibleToAlt, string, never>, + IntersectAliases + > + > + >( + aliases: AliasUT + ): QueryBuilder; + + < + AliasUT extends (Dict | string)[], + TResult2 = ArrayIfAlready< + TResult, + DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + IncompatibleToAlt, string, never>, + IntersectAliases + > + > + >( + ...aliases: AliasUT + ): QueryBuilder; + + < + AliasUT extends (Dict | string)[], + TResult2 = ArrayIfAlready< + TResult, + DeferredKeySelection.Augment< + UnwrapArrayMember, + TRecord, + IncompatibleToAlt, string, never>, + IntersectAliases + > + > + >( + aliases: AliasUT + ): QueryBuilder; + } + + interface Select + extends AliasQueryBuilder, + ColumnNameQueryBuilder { + (): QueryBuilder; + + < + TResult2 = ArrayIfAlready, + TInnerRecord extends {} = any, + TInnerResult = any + >( + ...subQueryBuilders: readonly QueryBuilder[] + ): QueryBuilder; + + < + TResult2 = ArrayIfAlready, + TInnerRecord extends {} = any, + TInnerResult = any + >( + subQueryBuilders: readonly QueryBuilder[] + ): QueryBuilder; + } + + interface JsonExtraction { + column: string | Raw | QueryBuilder; + path: string; + alias?: string; + singleValue?: boolean; + } + + interface JsonExtract { + ( + column: string | Raw | QueryBuilder, + path: string, + alias?: string, + singleValue?: boolean + ): QueryBuilder; + (column: JsonExtraction[] | any[][], singleValue?: boolean): QueryBuilder< + TRecord, + TResult + >; + } + + interface JsonSet { + ( + column: string | Raw | QueryBuilder, + path: string, + value: any, + alias?: string + ): QueryBuilder; + } + + interface JsonInsert { + ( + column: string | Raw | QueryBuilder, + path: string, + value: any, + alias?: string + ): QueryBuilder; + } + + interface JsonRemove { + ( + column: string | Raw | QueryBuilder, + path: string, + alias?: string + ): QueryBuilder; + } + + interface Comment { + (comment: string): QueryBuilder; + } + + interface HintComment { + (hint: string): QueryBuilder; + (hints: readonly string[]): QueryBuilder; + } + + interface Table { + < + TTable extends TableNames, + TRecord2 extends {} = TableType, + TResult2 = DeferredKeySelection.ReplaceBase< + TResult, + ResolveTableType + > + >( + tableName: TTable, + options?: TableOptions + ): QueryBuilder; + < + TRecord2 extends {} = {}, + TResult2 = DeferredKeySelection.ReplaceBase + >( + tableName: TableDescriptor | AliasDict, + options?: TableOptions + ): QueryBuilder; + < + TRecord2 extends {} = {}, + TResult2 = DeferredKeySelection.ReplaceBase + >( + callback: Function, + options?: TableOptions + ): QueryBuilder; + < + TRecord2 extends {} = {}, + TResult2 = DeferredKeySelection.ReplaceBase + >( + raw: Raw, + options?: TableOptions + ): QueryBuilder; + } + + interface Distinct + extends ColumnNameQueryBuilder {} + + interface DistinctOn { + ( + ...columnNames: readonly ColNameUT[] + ): QueryBuilder; + + ( + columnNames: readonly ColNameUT[] + ): QueryBuilder; + + (...columnNames: readonly string[]): QueryBuilder; + (columnNames: readonly string[]): QueryBuilder; + } + + interface JoinCallback { + (this: JoinClause, join: JoinClause): void; + } + + interface Join { + < + TJoinTargetRecord extends {} = any, + TRecord2 extends {} = TRecord & TJoinTargetRecord, + TResult2 = DeferredKeySelection.ReplaceBase + >( + raw: Raw + ): QueryBuilder; + < + TTable extends TableNames, + TRecord2 extends {} = ResolveTableType & + ResolveTableType>, + TResult2 = DeferredKeySelection.ReplaceBase + >( + tableName: TTable, + clause: JoinCallback + ): QueryBuilder; + < + TJoinTargetRecord extends {} = any, + TRecord2 extends {} = TRecord & TJoinTargetRecord, + TResult2 = DeferredKeySelection.ReplaceBase + >( + tableName: TableDescriptor | AliasDict | QueryCallback, + clause: JoinCallback + ): QueryBuilder; + < + TJoinTargetRecord extends {} = any, + TRecord2 extends {} = TRecord & TJoinTargetRecord, + TResult2 = DeferredKeySelection.ReplaceBase + >( + tableName: TableDescriptor | AliasDict | QueryCallback, + columns: { [key: string]: string | number | boolean | Raw } + ): QueryBuilder; + < + TJoinTargetRecord extends {} = any, + TRecord2 extends {} = TRecord & TJoinTargetRecord, + TResult2 = DeferredKeySelection.ReplaceBase + >( + tableName: TableDescriptor | AliasDict | QueryCallback, + raw: Raw + ): QueryBuilder; + < + TTable1 extends TableNames, + TTable2 extends TableNames, + TKey1 extends StrKey>> & + StrKey, + TKey2 extends StrKey>>, + TRecord1 = ResolveTableType, + TRecord2 extends {} = TRecord1 & ResolveTableType>, + TResult2 = DeferredKeySelection.ReplaceBase + >( + tableName: TTable2, + column1: `${TTable1}.${TKey1}`, + column2: `${TTable2}.${TKey2}` + ): QueryBuilder; + < + TTable1 extends TableNames, + TTable2 extends TableNames, + TKey1 extends StrKey>> & + StrKey, + TKey2 extends StrKey>>, + TRecord1 = ResolveTableType, + TRecord2 extends {} = TRecord1 & ResolveTableType>, + TResult2 = DeferredKeySelection.ReplaceBase + >( + tableName: TTable2, + column1: `${TTable2}.${TKey2}`, + column2: `${TTable1}.${TKey1}` + ): QueryBuilder; + < + TJoinTargetRecord extends {} = any, + TRecord2 extends {} = TRecord & TJoinTargetRecord, + TResult2 = DeferredKeySelection.ReplaceBase + >( + tableName: TableDescriptor | AliasDict | QueryCallback, + column1: string, + column2: string + ): QueryBuilder; + < + TJoinTargetRecord extends {} = any, + TRecord2 extends {} = TRecord & TJoinTargetRecord, + TResult2 = DeferredKeySelection.ReplaceBase + >( + tableName: TableDescriptor | AliasDict | QueryCallback, + column1: string, + raw: Raw + ): QueryBuilder; + < + TTable1 extends TableNames, + TTable2 extends TableNames, + TKey1 extends StrKey>> & + StrKey, + TKey2 extends StrKey>>, + TRecord1 = ResolveTableType, + TRecord2 extends {} = TRecord1 & ResolveTableType>, + TResult2 = DeferredKeySelection.ReplaceBase + >( + tableName: TTable2, + column1: `${TTable1}.${TKey1}`, + operator: string, + column2: `${TTable2}.${TKey2}` + ): QueryBuilder; + < + TTable1 extends TableNames, + TTable2 extends TableNames, + TKey1 extends StrKey>> & + StrKey, + TKey2 extends StrKey>>, + TRecord1 = ResolveTableType, + TRecord2 extends {} = TRecord1 & ResolveTableType>, + TResult2 = DeferredKeySelection.ReplaceBase + >( + tableName: TTable2, + column1: `${TTable2}.${TKey2}`, + operator: string, + column2: `${TTable1}.${TKey1}` + ): QueryBuilder; + < + TJoinTargetRecord extends {} = any, + TRecord2 extends {} = TRecord & TJoinTargetRecord, + TResult2 = DeferredKeySelection.ReplaceBase + >( + tableName: TableDescriptor | AliasDict | QueryCallback, + column1: string, + operator: string, + column2: string + ): QueryBuilder; + } + + interface JoinClause { + on(raw: Raw): JoinClause; + on(callback: JoinCallback): JoinClause; + on(columns: { [key: string]: string | Raw }): JoinClause; + on(column1: string, column2: string): JoinClause; + on(column1: string, raw: Raw): JoinClause; + on(column1: string, operator: string, column2: string | Raw): JoinClause; + andOn(raw: Raw): JoinClause; + andOn(callback: JoinCallback): JoinClause; + andOn(columns: { [key: string]: string | Raw }): JoinClause; + andOn(column1: string, column2: string): JoinClause; + andOn(column1: string, raw: Raw): JoinClause; + andOn(column1: string, operator: string, column2: string | Raw): JoinClause; + orOn(raw: Raw): JoinClause; + orOn(callback: JoinCallback): JoinClause; + orOn(columns: { [key: string]: string | Raw }): JoinClause; + orOn(column1: string, column2: string): JoinClause; + orOn(column1: string, raw: Raw): JoinClause; + orOn(column1: string, operator: string, column2: string | Raw): JoinClause; + onVal(column1: string, value: Value): JoinClause; + onVal(column1: string, operator: string, value: Value): JoinClause; + andOnVal(column1: string, value: Value): JoinClause; + andOnVal(column1: string, operator: string, value: Value): JoinClause; + orOnVal(column1: string, value: Value): JoinClause; + orOnVal(column1: string, operator: string, value: Value): JoinClause; + onIn(column1: string, values: readonly any[] | Raw): JoinClause; + andOnIn(column1: string, values: readonly any[] | Raw): JoinClause; + orOnIn(column1: string, values: readonly any[] | Raw): JoinClause; + onNotIn(column1: string, values: readonly any[] | Raw): JoinClause; + andOnNotIn(column1: string, values: readonly any[] | Raw): JoinClause; + orOnNotIn(column1: string, values: readonly any[] | Raw): JoinClause; + onNull(column1: string): JoinClause; + andOnNull(column1: string): JoinClause; + orOnNull(column1: string): JoinClause; + onNotNull(column1: string): JoinClause; + andOnNotNull(column1: string): JoinClause; + orOnNotNull(column1: string): JoinClause; + onExists(callback: QueryCallback): JoinClause; + andOnExists(callback: QueryCallback): JoinClause; + orOnExists(callback: QueryCallback): JoinClause; + onNotExists(callback: QueryCallback): JoinClause; + andOnNotExists(callback: QueryCallback): JoinClause; + orOnNotExists(callback: QueryCallback): JoinClause; + onBetween(column1: string, range: readonly [any, any]): JoinClause; + andOnBetween(column1: string, range: readonly [any, any]): JoinClause; + orOnBetween(column1: string, range: readonly [any, any]): JoinClause; + onNotBetween(column1: string, range: readonly [any, any]): JoinClause; + andOnNotBetween(column1: string, range: readonly [any, any]): JoinClause; + orOnNotBetween(column1: string, range: readonly [any, any]): JoinClause; + onJsonPathEquals( + columnFirst: string, + jsonPathFirst: string, + columnSecond: string, + jsonPathSecond: string + ): JoinClause; + orOnJsonPathEquals( + columnFirst: string, + jsonPathFirst: string, + columnSecond: string, + jsonPathSecond: string + ): JoinClause; + using( + column: string | readonly string[] | Raw | { [key: string]: string | Raw } + ): JoinClause; + type(type: string): JoinClause; + } + + interface JoinRaw { + (tableName: string, binding?: Value | Value[] | ValueDict): QueryBuilder< + TRecord, + TResult + >; + } + + interface Using { + (tables: string[]): QueryBuilder; + } + + interface With + extends WithRaw, + WithWrapped {} + + interface WithRaw { + (alias: string, raw: Raw | QueryBuilder): QueryBuilder; + ( + alias: string, + sql: string, + bindings?: readonly Value[] | Object + ): QueryBuilder; + ( + alias: string, + columnList: string[], + raw: Raw | QueryBuilder + ): QueryBuilder; + ( + alias: string, + columnList: string[], + sql: string, + bindings?: readonly Value[] | Object + ): QueryBuilder; + } + + interface WithSchema { + (schema: string): QueryBuilder; + } + + interface WithWrapped { + (alias: string, queryBuilder: QueryBuilder): QueryBuilder; + ( + alias: string, + callback: (queryBuilder: QueryBuilder) => any + ): QueryBuilder; + ( + alias: string, + columnList: string[], + queryBuilder: QueryBuilder + ): QueryBuilder; + ( + alias: string, + columnList: string[], + callback: (queryBuilder: QueryBuilder) => any + ): QueryBuilder; + } + + interface Where + extends WhereRaw, + WhereWrapped, + WhereNull { + (raw: Raw): QueryBuilder; + + (callback: QueryCallback): QueryBuilder; + + (object: DbRecord>): QueryBuilder< + TRecord, + TResult + >; + + (object: Readonly): QueryBuilder; + + >( + columnName: T, + value: DbColumn[T]> | null + ): QueryBuilder; + + (columnName: string, value: Value | null): QueryBuilder; + + >( + columnName: T, + operator: ComparisonOperator, + value: DbColumn[T]> | null + ): QueryBuilder; + + (columnName: string, operator: string, value: Value | null): QueryBuilder< + TRecord, + TResult + >; + + < + T extends keyof ResolveTableType, + TRecordInner extends {}, + TResultInner + >( + columnName: T, + operator: ComparisonOperator, + value: QueryBuilder + ): QueryBuilder; + + ( + columnName: string, + operator: string, + value: QueryBuilder + ): QueryBuilder; + + (left: Raw, operator: string, right: Value | null): QueryBuilder< + TRecord, + TResult + >; + + ( + left: Raw, + operator: string, + right: QueryBuilder + ): QueryBuilder; + } + + interface WhereRaw + extends RawQueryBuilder { + (condition: boolean): QueryBuilder; + } + + interface WhereWrapped { + (callback: QueryCallback): QueryBuilder; + } + + interface WhereNull { + (columnName: keyof TRecord): QueryBuilder; + (columnName: string): QueryBuilder; + } + + interface WhereBetween { + ( + columnName: K, + range: readonly [DbColumn, DbColumn] + ): QueryBuilder; + (columnName: string, range: readonly [Value, Value]): QueryBuilder< + TRecord, + TResult + >; + } + + interface WhereExists { + (callback: QueryCallback): QueryBuilder; + ( + query: QueryBuilder + ): QueryBuilder; + } + + interface WhereJsonObject { + (columnName: keyof ResolveTableType, value: any): QueryBuilder< + TRecord, + TResult + >; + } + + interface WhereJsonPath { + ( + columnName: keyof ResolveTableType, + jsonPath: string, + operator: string, + value: any + ): QueryBuilder; + } + + interface WhereIn { + >( + columnName: K, + values: readonly DbColumn[K]>[] | QueryCallback + ): QueryBuilder; + ( + columnName: string, + values: readonly Value[] | QueryCallback + ): QueryBuilder; + >( + columnNames: readonly K[], + values: + | readonly (readonly DbColumn[K]>[])[] + | QueryCallback + ): QueryBuilder; + ( + columnNames: readonly string[], + values: readonly Value[][] | QueryCallback + ): QueryBuilder; + ( + columnName: K, + values: QueryBuilder + ): QueryBuilder; + ( + columnName: string, + values: Value[] | QueryBuilder + ): QueryBuilder; + ( + columnNames: readonly K[], + values: QueryBuilder + ): QueryBuilder; + ( + columnNames: readonly string[], + values: QueryBuilder + ): QueryBuilder; + } + + // Note: Attempting to unify AsymmetricAggregation & TypePreservingAggregation + // by extracting out a common base interface will not work because order of overloads + // is significant. + + interface AsymmetricAggregation< + TRecord extends {} = any, + TResult = unknown[], + TValue = any + > { + < + TOptions extends { as: string }, + TResult2 = AggregationQueryResult< + TResult, + { [k in TOptions['as']]: TValue } + > + >( + columnName: Readonly>, + options: Readonly + ): QueryBuilder; + >>( + ...columnNames: readonly (keyof ResolveTableType)[] + ): QueryBuilder; + < + TAliases extends {} = Record, + TResult2 = AggregationQueryResult< + TResult, + { [k in keyof TAliases]?: TValue } + > + >( + aliases: TAliases + ): QueryBuilder; + >>( + ...columnNames: ReadonlyArray< + | Readonly> + | Knex.Raw + | string + > + ): QueryBuilder; + } + + interface TypePreservingAggregation< + TRecord extends {} = any, + TResult = unknown[], + TValue = any + > { + < + TKey extends keyof ResolveTableType, + TOptions extends { as: string }, + TResult2 = AggregationQueryResult< + TResult, + { + [k in TOptions['as']]: ResolveTableType[TKey]; + } + > + >( + columnName: TKey, + options: Readonly + ): QueryBuilder; + < + TKey extends keyof ResolveTableType, + TResult2 = AggregationQueryResult< + TResult, + Dict[TKey]> + > + >( + ...columnNames: readonly TKey[] + ): QueryBuilder; + < + TAliases extends {} = Readonly< + Record + >, + TResult2 = AggregationQueryResult< + TResult, + { + // We have optional here because in most dialects aggregating by multiple keys simultaneously + // causes rest of the keys to be dropped and only first to be considered + [K in keyof TAliases]?: K extends keyof TRecord ? TRecord[K] : TValue; + } + > + >( + aliases: TAliases + ): QueryBuilder; + >>( + ...columnNames: ReadonlyArray< + | Readonly> + | Knex.Raw + | string + > + ): QueryBuilder; + } + + interface AnalyticFunction { + < + TAlias extends string, + TResult2 = AggregationQueryResult + >( + alias: TAlias, + raw: Raw | QueryCallback + ): QueryBuilder; + < + TAlias extends string, + TKey extends keyof ResolveTableType, + TResult2 = AggregationQueryResult + >( + alias: TAlias, + orderBy: + | TKey + | TKey[] + | { + column: TKey; + order?: 'asc' | 'desc'; + nulls?: 'first' | 'last'; + }, + partitionBy?: TKey | TKey[] | { column: TKey; order?: 'asc' | 'desc' } + ): QueryBuilder; + } + + interface GroupBy + extends RawQueryBuilder, + ColumnNameQueryBuilder {} + + interface OrderBy { + ( + columnName: keyof TRecord | QueryBuilder, + order?: 'asc' | 'desc', + nulls?: 'first' | 'last' + ): QueryBuilder; + ( + columnName: string | QueryBuilder, + order?: string, + nulls?: string + ): QueryBuilder; + ( + columnDefs: Array< + | keyof TRecord + | Readonly<{ + column: keyof TRecord | QueryBuilder; + order?: 'asc' | 'desc'; + nulls?: 'first' | 'last'; + }> + > + ): QueryBuilder; + ( + columnDefs: Array< + | string + | Readonly<{ + column: string | QueryBuilder; + order?: string; + nulls?: string; + }> + > + ): QueryBuilder; + } + + interface PartitionBy + extends OrderBy {} + + interface Intersect { + ( + callback: MaybeArray | Raw>, + wrap?: boolean + ): QueryBuilder; + ( + ...callbacks: readonly (QueryCallback | Raw | QueryBuilder)[] + ): QueryBuilder; + } + + interface Except + extends Intersect {} + + interface Union + extends Intersect {} + + interface Having + extends WhereWrapped { + ( + column: K, + operator: ComparisonOperator, + value: DbColumn + ): QueryBuilder; + + ( + column: string | Raw, + operator: string, + value: Value | QueryBuilder | null + ): QueryBuilder; + + (raw: Raw): QueryBuilder; + } + + interface HavingRange { + ( + columnName: K, + values: readonly DbColumn[] + ): QueryBuilder; + (columnName: string, values: readonly Value[]): QueryBuilder< + TRecord, + TResult + >; + } + + interface HavingNull { + (columnName: keyof TRecord): QueryBuilder; + (columnName: string): QueryBuilder; + } + + // commons + + interface ColumnNameQueryBuilder< + TRecord extends {} = any, + TResult = unknown[] + > { + // When all columns are known to be keys of original record, + // we can extend our selection by these columns + (columnName: '*'): QueryBuilder< + TRecord, + ArrayIfAlready> + >; + + < + ColNameUT extends keyof ResolveTableType, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + ColNameUT & string + >[] + >( + ...columnNames: readonly ColNameUT[] + ): QueryBuilder; + + < + ColNameUT extends keyof ResolveTableType, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + ColNameUT & string + >[] + >( + columnNames: readonly ColNameUT[] + ): QueryBuilder; + + // For non-inferrable column selection, we will allow consumer to + // specify result type and if not widen the result to entire record type with any omissions permitted + < + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + SafePartial, + keyof TRecord & string + >[] + >( + ...columnNames: readonly ColumnDescriptor[] + ): QueryBuilder; + + < + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + SafePartial, + keyof TRecord & string + >[] + >( + columnNames: readonly ColumnDescriptor[] + ): QueryBuilder; + } + + type RawBinding = Value | QueryBuilder; + + interface RawQueryBuilder { + ( + sql: string, + bindings?: readonly RawBinding[] | ValueDict | RawBinding + ): QueryBuilder; + (raw: Raw): QueryBuilder; + } + + // Raw + + interface Raw + extends events.EventEmitter, + ChainableInterface> { + timeout(ms: number, options?: { cancel?: boolean }): Raw; + wrap(before: string, after: string): Raw; + toSQL(): Sql; + queryContext(context: any): Raw; + queryContext(): any; + } + + interface RawBuilder { + (value: Value): Raw; + (sql: string, binding: RawBinding): Raw; + ( + sql: string, + bindings: readonly RawBinding[] | ValueDict + ): Raw; + } + + const RefMemberTag: unique symbol; + + interface Ref extends Raw { + // TypeScript can behave weirdly if type parameters are not + // actually used in the members of type. + // + // See: https://github.com/knex/knex/issues/3932 + // + // We simply need to propagate the type context so that we can extract + // them later, but we just add a "phantom" property so that typescript + // doesn't think that these parameters are unused + // + // Because unique symbol is used here, there is no way to actually + // access this at runtime + [RefMemberTag]: { + src: TSrc; + mapping: TMapping; + }; + withSchema(schema: string): this; + as( + alias: TAlias + ): Ref; + } + + interface RefBuilder { + (src: TSrc): Ref; + } + + interface BatchInsertBuilder + extends Promise> { + transacting(trx: Transaction): this; + // see returning methods from QueryInterface + returning( + column: '*' + ): BatchInsertBuilder[]>; + returning< + TKey extends StrKey>, + TResult2 = DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + TKey + >[] + >( + column: TKey + ): BatchInsertBuilder; + returning< + TKey extends StrKey>, + TResult2 = DeferredKeySelection.SetSingle< + DeferredKeySelection.Augment< + UnwrapArrayMember, + ResolveTableType, + TKey + >, + false + >[] + >( + columns: readonly TKey[] + ): BatchInsertBuilder; + // if data with specific type passed, exclude this method + returning[]>( + column: unknown extends TRecord + ? string | readonly (string | Raw)[] | Raw + : never + ): BatchInsertBuilder; + } + + // + // QueryBuilder + // + + type QueryCallback = ( + this: QueryBuilder, + builder: QueryBuilder + ) => void; + + type QueryCallbackWithArgs = ( + this: QueryBuilder, + builder: QueryBuilder, + ...args: any[] + ) => void; + + interface QueryBuilder + extends QueryInterface, + ChainableInterface> { + client: Client; + or: QueryBuilder; + not: QueryBuilder; + and: QueryBuilder; + + // TODO: Promise? + columnInfo( + column: keyof DeferredKeySelection.Resolve + ): Promise; + columnInfo(): Promise< + Record, ColumnInfo> + >; + + forUpdate(...tableNames: string[]): QueryBuilder; + forUpdate(tableNames: readonly string[]): QueryBuilder; + + forShare(...tableNames: string[]): QueryBuilder; + forShare(tableNames: readonly string[]): QueryBuilder; + + forNoKeyUpdate(...tableNames: string[]): QueryBuilder; + forNoKeyUpdate( + tableNames: readonly string[] + ): QueryBuilder; + + forKeyShare(...tableNames: string[]): QueryBuilder; + forKeyShare(tableNames: readonly string[]): QueryBuilder; + + skipLocked(): QueryBuilder; + noWait(): QueryBuilder; + + toSQL(): Sql; + + on(event: string, callback: Function): QueryBuilder; + + queryContext(context: any): QueryBuilder; + queryContext(): any; + + clone(): QueryBuilder; + timeout( + ms: number, + options?: { cancel?: boolean } + ): QueryBuilder; + } + + interface Sql { + method: string; + options: any; + bindings: readonly Value[]; + sql: string; + toNative(): SqlNative; + } + + interface SqlNative { + bindings: readonly Value[]; + sql: string; + } + + // + // Chainable interface + // + + type ExposedPromiseKeys = 'then' | 'catch' | 'finally'; + + interface StringTagSupport { + readonly [Symbol.toStringTag]: string; + } + interface ChainableInterface + extends Pick, keyof Promise & ExposedPromiseKeys>, + StringTagSupport { + generateDdlCommands(): Promise<{ + pre: string[]; + sql: string[]; + check: string | null; + post: string[]; + }>; + toQuery(): string; + options(options: Readonly<{ [key: string]: any }>): this; + connection(connection: any): this; + debug(enabled: boolean): this; + transacting(trx: Transaction): this; + stream(handler: (readable: stream.PassThrough) => any): Promise; + stream( + options: Readonly<{ [key: string]: any }>, + handler: (readable: stream.PassThrough) => any + ): Promise; + stream( + options?: Readonly<{ [key: string]: any }> + ): stream.PassThrough & AsyncIterable>; + pipe( + writable: T, + options?: Readonly<{ [key: string]: any }> + ): stream.PassThrough; + asCallback(callback: Function): Promise; + } + + // Not all of these are possible for all drivers, notably, sqlite doesn't support any of these + type IsolationLevels = + | 'read uncommitted' + | 'read committed' + | 'snapshot' + | 'repeatable read' + | 'serializable'; + interface TransactionConfig { + isolationLevel?: IsolationLevels; + userParams?: Record; + doNotRejectOnRollback?: boolean; + connection?: any; + readOnly?: boolean; + } + + interface Transaction + extends Knex { + executionPromise: Promise; + parentTransaction?: Transaction; + isCompleted: () => boolean; + + query( + conn: any, + sql: any, + status: any, + value: any + ): QueryBuilder; + savepoint(transactionScope: (trx: Transaction) => any): Promise; + commit(value?: any): QueryBuilder; + rollback(error?: any): QueryBuilder; + } + + type TransactionProvider = () => Promise; + + // + // Schema builder + // + + interface SchemaBuilder extends ChainableInterface { + // Views + createView( + viewName: string, + callback: (viewBuilder: ViewBuilder) => any + ): SchemaBuilder; + createViewOrReplace( + viewName: string, + callback: (viewBuilder: ViewBuilder) => any + ): SchemaBuilder; + createMaterializedView( + viewName: string, + callback: (viewBuilder: ViewBuilder) => any + ): SchemaBuilder; + refreshMaterializedView( + viewName: string, + concurrently?: boolean + ): SchemaBuilder; + dropView(viewName: string): SchemaBuilder; + dropViewIfExists(viewName: string): SchemaBuilder; + dropMaterializedView(viewName: string): SchemaBuilder; + dropMaterializedViewIfExists(viewName: string): SchemaBuilder; + renameView(oldViewName: string, newViewName: string): SchemaBuilder; + view( + viewName: string, + callback: (viewBuilder: AlterViewBuilder) => any + ): SchemaBuilder; + alterView( + viewName: string, + callback: (tableBuilder: AlterViewBuilder) => any + ): SchemaBuilder; + + // Tables + createTable( + tableName: string, + callback: (tableBuilder: CreateTableBuilder) => any + ): SchemaBuilder; + createTableIfNotExists( + tableName: string, + callback: (tableBuilder: CreateTableBuilder) => any + ): SchemaBuilder; + createTableLike( + tableName: string, + tableNameLike: string, + callback?: (tableBuilder: CreateTableBuilder) => any + ): SchemaBuilder; + alterTable( + tableName: string, + callback: (tableBuilder: CreateTableBuilder) => any + ): SchemaBuilder; + renameTable(oldTableName: string, newTableName: string): Promise; + dropTable(tableName: string): SchemaBuilder; + hasTable(tableName: string): Promise; + table( + tableName: string, + callback: (tableBuilder: AlterTableBuilder) => any + ): SchemaBuilder; + dropTableIfExists(tableName: string): SchemaBuilder; + + // Schema + createSchema(schemaName: string): SchemaBuilder; + createSchemaIfNotExists(schemaName: string): SchemaBuilder; + dropSchema(schemaName: string, cascade?: boolean): SchemaBuilder; + dropSchemaIfExists(schemaName: string, cascade?: boolean): SchemaBuilder; + withSchema(schemaName: string): SchemaBuilder; + + // Others + hasColumn(tableName: string, columnName: string): Promise; + raw(statement: string): SchemaBuilder; + queryContext(context: any): SchemaBuilder; + toString(): string; + toSQL(): Sql[]; + } + + interface TableBuilder { + increments( + columnName?: string, + options?: { primaryKey?: boolean } + ): ColumnBuilder; + bigIncrements( + columnName?: string, + options?: { primaryKey?: boolean } + ): ColumnBuilder; + dropColumn(columnName: string): TableBuilder; + dropColumns(...columnNames: string[]): TableBuilder; + renameColumn(from: string, to: string): TableBuilder; + integer(columnName: string, length?: number): ColumnBuilder; + tinyint(columnName: string, length?: number): ColumnBuilder; + smallint(columnName: string): ColumnBuilder; + mediumint(columnName: string): ColumnBuilder; + bigint(columnName: string): ColumnBuilder; + bigInteger(columnName: string): ColumnBuilder; + text(columnName: string, textType?: string): ColumnBuilder; + string(columnName: string, length?: number): ColumnBuilder; + float( + columnName: string, + precision?: number, + scale?: number + ): ColumnBuilder; + double( + columnName: string, + precision?: number, + scale?: number + ): ColumnBuilder; + decimal( + columnName: string, + precision?: number | null, + scale?: number + ): ColumnBuilder; + boolean(columnName: string): ColumnBuilder; + date(columnName: string): ColumnBuilder; + dateTime( + columnName: string, + options?: Readonly<{ useTz?: boolean; precision?: number }> + ): ColumnBuilder; + datetime( + columnName: string, + options?: Readonly<{ useTz?: boolean; precision?: number }> + ): ColumnBuilder; + time(columnName: string): ColumnBuilder; + timestamp( + columnName: string, + options?: Readonly<{ useTz?: boolean; precision?: number }> + ): ColumnBuilder; + /** @deprecated */ + timestamp( + columnName: string, + withoutTz?: boolean, + precision?: number + ): ColumnBuilder; + timestamps( + useTimestamps?: boolean, + defaultToNow?: boolean, + useCamelCase?: boolean + ): ColumnBuilder; + timestamps( + options?: Readonly<{ + useTimestamps?: boolean; + defaultToNow?: boolean; + useCamelCase?: boolean; + }> + ): void; + geometry(columnName: string): ColumnBuilder; + geography(columnName: string): ColumnBuilder; + point(columnName: string): ColumnBuilder; + binary(columnName: string, length?: number): ColumnBuilder; + enum( + columnName: string, + values: readonly Value[] | null, + options?: EnumOptions + ): ColumnBuilder; + enu( + columnName: string, + values: readonly Value[] | null, + options?: EnumOptions + ): ColumnBuilder; + json(columnName: string): ColumnBuilder; + jsonb(columnName: string): ColumnBuilder; + uuid( + columnName: string, + options?: Readonly<{ useBinaryUuid?: boolean; primaryKey?: boolean }> + ): ColumnBuilder; + comment(val: string): void; + specificType(columnName: string, type: string): ColumnBuilder; + primary( + columnNames: readonly string[], + options?: Readonly<{ + constraintName?: string; + deferrable?: deferrableType; + }> + ): TableBuilder; + /** @deprecated */ + primary( + columnNames: readonly string[], + constraintName?: string + ): TableBuilder; + index( + columnNames: string | readonly (string | Raw)[], + indexName?: string, + indexType?: string + ): TableBuilder; + index( + columnNames: string | readonly (string | Raw)[], + indexName?: string, + options?: Readonly<{ + indexType?: string; + storageEngineIndexType?: storageEngineIndexType; + predicate?: QueryBuilder; + }> + ): TableBuilder; + setNullable(column: string): TableBuilder; + dropNullable(column: string): TableBuilder; + unique( + columnNames: string | readonly (string | Raw)[], + options?: Readonly<{ + indexName?: string; + storageEngineIndexType?: string; + deferrable?: deferrableType; + useConstraint?: boolean; + predicate?: QueryBuilder; + }> + ): TableBuilder; + /** @deprecated */ + unique( + columnNames: string | readonly (string | Raw)[], + indexName?: string + ): TableBuilder; + foreign(column: string, foreignKeyName?: string): ForeignConstraintBuilder; + foreign( + columns: readonly string[], + foreignKeyName?: string + ): MultikeyForeignConstraintBuilder; + check( + checkPredicate: string, + bindings?: Record, + constraintName?: string + ): TableBuilder; + dropForeign( + columnNames: string | readonly string[], + foreignKeyName?: string + ): TableBuilder; + dropUnique( + columnNames: readonly (string | Raw)[], + indexName?: string + ): TableBuilder; + dropPrimary(constraintName?: string): TableBuilder; + dropIndex( + columnNames: string | readonly (string | Raw)[], + indexName?: string + ): TableBuilder; + dropTimestamps(useCamelCase?: boolean): TableBuilder; + dropChecks(checkConstraintNames: string | string[]): TableBuilder; + queryContext(context: any): TableBuilder; + } + + interface ViewBuilder { + columns(columns: any): ViewBuilder; + as(selectQuery: QueryBuilder): ViewBuilder; + checkOption(): Promise; + localCheckOption(): Promise; + cascadedCheckOption(): Promise; + queryContext(context: any): ViewBuilder; + } + + interface CreateTableBuilder extends TableBuilder { + engine(val: string): CreateTableBuilder; + charset(val: string): CreateTableBuilder; + collate(val: string): CreateTableBuilder; + inherits(val: string): CreateTableBuilder; + } + + interface AlterTableBuilder extends TableBuilder {} + + interface AlterColumnView extends ViewBuilder { + rename(newName: string): AlterColumnView; + defaultTo(defaultValue: string): AlterColumnView; + } + + interface AlterViewBuilder extends ViewBuilder { + column(column: string): AlterColumnView; + } + + type deferrableType = 'not deferrable' | 'immediate' | 'deferred'; + type storageEngineIndexType = 'hash' | 'btree'; + type lengthOperator = '>' | '<' | '<=' | '>=' | '!=' | '='; + + interface ColumnBuilder { + index(indexName?: string): ColumnBuilder; + primary( + options?: Readonly<{ + constraintName?: string; + deferrable?: deferrableType; + }> + ): ColumnBuilder; + /** @deprecated */ + primary(constraintName?: string): ColumnBuilder; + + unique( + options?: Readonly<{ indexName?: string; deferrable?: deferrableType }> + ): ColumnBuilder; + /** @deprecated */ + unique(indexName?: string): ColumnBuilder; + references(columnName: string): ReferencingColumnBuilder; + defaultTo(value: Value | null, options?: DefaultToOptions): ColumnBuilder; + unsigned(): ColumnBuilder; + notNullable(): ColumnBuilder; + nullable(): ColumnBuilder; + comment(value: string): ColumnBuilder; + alter( + options?: Readonly<{ alterNullable?: boolean; alterType?: boolean }> + ): ColumnBuilder; + queryContext(context: any): ColumnBuilder; + after(columnName: string): ColumnBuilder; + first(): ColumnBuilder; + checkPositive(constraintName?: string): ColumnBuilder; + checkNegative(constraintName?: string): ColumnBuilder; + checkIn(values: string[], constraintName?: string): ColumnBuilder; + checkNotIn(values: string[], constraintName?: string): ColumnBuilder; + checkBetween( + values: any[] | any[][], + constraintName?: string + ): ColumnBuilder; + checkLength( + operator: lengthOperator, + length: number, + constraintName?: string + ): ColumnBuilder; + checkRegex(regex: string, constraintName?: string): ColumnBuilder; + collate(collation: string): ColumnBuilder; + } + + interface ForeignConstraintBuilder { + references(columnName: string): ReferencingColumnBuilder; + } + + interface MultikeyForeignConstraintBuilder { + references(columnNames: readonly string[]): ReferencingColumnBuilder; + } + + interface PostgreSqlColumnBuilder extends ColumnBuilder { + index( + indexName?: string, + options?: Readonly<{ indexType?: string; predicate?: QueryBuilder }> + ): ColumnBuilder; + index(indexName?: string, indexType?: string): ColumnBuilder; + } + + interface SqlLiteColumnBuilder extends ColumnBuilder { + index( + indexName?: string, + options?: Readonly<{ predicate?: QueryBuilder }> + ): ColumnBuilder; + } + + interface MsSqlColumnBuilder extends ColumnBuilder { + index( + indexName?: string, + options?: Readonly<{ predicate?: QueryBuilder }> + ): ColumnBuilder; + } + + interface MySqlColumnBuilder extends ColumnBuilder { + index( + indexName?: string, + options?: Readonly<{ + indexType?: string; + storageEngineIndexType?: storageEngineIndexType; + }> + ): ColumnBuilder; + } + + // patched ColumnBuilder methods to return ReferencingColumnBuilder with new methods + // relies on ColumnBuilder returning only ColumnBuilder + type ReferencingColumnBuilder = { + [K in keyof ColumnBuilder]: ( + ...args: Parameters + ) => ReferencingColumnBuilder; + } & { + inTable(tableName: string): ReferencingColumnBuilder; + deferrable(type: deferrableType): ReferencingColumnBuilder; + withKeyName(keyName: string): ReferencingColumnBuilder; + onDelete(command: string): ReferencingColumnBuilder; + onUpdate(command: string): ReferencingColumnBuilder; + }; + + interface AlterColumnBuilder extends ColumnBuilder {} + + interface MySqlAlterColumnBuilder extends AlterColumnBuilder { + first(): AlterColumnBuilder; + after(columnName: string): AlterColumnBuilder; + } + + // + // Configurations + // + + interface ColumnInfo { + defaultValue: Value; + type: string; + maxLength: number; + nullable: boolean; + } + + interface Config { + debug?: boolean; + client?: string | typeof Client; + dialect?: string; + jsonbSupport?: boolean; + version?: string; + connection?: string | StaticConnectionConfig | ConnectionConfigProvider; + pool?: PoolConfig; + migrations?: MigratorConfig; + postProcessResponse?: (result: any, queryContext: any) => any; + wrapIdentifier?: ( + value: string, + origImpl: (value: string) => string, + queryContext: any + ) => string; + seeds?: SeederConfig; + acquireConnectionTimeout?: number; + useNullAsDefault?: boolean; + searchPath?: string | readonly string[]; + asyncStackTraces?: boolean; + log?: Logger; + compileSqlOnError?: boolean; + fetchAsString?: string[]; + } + + type StaticConnectionConfig = + | ConnectionConfig + | MariaSqlConnectionConfig + | MySqlConnectionConfig + | MySql2ConnectionConfig + | MsSqlConnectionConfig + | OracleDbConnectionConfig + | PgConnectionConfig + | RedshiftConnectionConfig + | Sqlite3ConnectionConfig + | BetterSqlite3ConnectionConfig + | SocketConnectionConfig; + + type ConnectionConfigProvider = + | SyncConnectionConfigProvider + | AsyncConnectionConfigProvider; + type SyncConnectionConfigProvider = () => StaticConnectionConfig; + type AsyncConnectionConfigProvider = () => Promise; + + interface ConnectionConfig { + host: string; + user: string; + password: string; + database: string; + domain?: string; + instanceName?: string; + debug?: boolean; + requestTimeout?: number; + } + + type MsSqlAuthenticationTypeOptions = + | 'default' + | 'ntlm' + | 'azure-active-directory-password' + | 'azure-active-directory-access-token' + | 'azure-active-directory-msi-vm' + | 'azure-active-directory-msi-app-service' + | 'azure-active-directory-service-principal-secret'; + + interface MsSqlDefaultAuthenticationConfig extends MsSqlConnectionConfigBase { + type?: 'default' | never; + } + + interface MsSqlAzureActiveDirectoryMsiAppServiceAuthenticationConfig + extends MsSqlConnectionConfigBase { + type: 'azure-active-directory-msi-app-service'; + /** + * If you user want to connect to an Azure app service using a specific client account + * they need to provide `clientId` asscoiate to their created idnetity. + * + * This is optional for retrieve token from azure web app service + */ + clientId?: string; + /** + * A msi app service environment need to provide `msiEndpoint` for retriving the accesstoken. + */ + msiEndpoint?: string; + /** + * A msi app service environment need to provide `msiSecret` for retriving the accesstoken. + */ + msiSecret?: string; + } + + interface MsSqlAzureActiveDirectoryMsiVmAuthenticationConfig + extends MsSqlConnectionConfigBase { + type: 'azure-active-directory-msi-vm'; + /** + * If you user want to connect to an Azure app service using a specific client account + * they need to provide `clientId` asscoiate to their created idnetity. + * + * This is optional for retrieve token from azure web app service + */ + clientId?: string; + /** + * A user need to provide `msiEndpoint` for retriving the accesstoken. + */ + msiEndpoint?: string; + } + + interface MsSqlAzureActiveDirectoryAccessTokenAuthenticationConfig + extends MsSqlConnectionConfigBase { + type: 'azure-active-directory-access-token'; + /** + * A user-provided access token + */ + token: string; + } + interface MsSqlAzureActiveDirectoryPasswordAuthenticationConfig + extends MsSqlConnectionConfigBase { + type: 'azure-active-directory-password'; + /** + * Optional parameter for specific Azure tenant ID + */ + domain: string; + userName: string; + password: string; + } + + interface MsSqlAzureActiveDirectoryServicePrincipalSecretConfig + extends MsSqlConnectionConfigBase { + type: 'azure-active-directory-service-principal-secret'; + /** + * Application (`client`) ID from your registered Azure application + */ + clientId: string; + /** + * The created `client secret` for this registered Azure application + */ + clientSecret: string; + /** + * Directory (`tenant`) ID from your registered Azure application + */ + tenantId: string; + } + + interface MsSqlNtlmAuthenticationConfig extends MsSqlConnectionConfigBase { + type: 'ntlm'; + /** + * Once you set domain for ntlm authentication type, driver will connect to SQL Server using domain login. + * + * This is necessary for forming a connection using ntlm type + */ + domain: string; + userName: string; + password: string; + } + + type MsSqlConnectionConfig = + | MsSqlDefaultAuthenticationConfig + | MsSqlNtlmAuthenticationConfig + | MsSqlAzureActiveDirectoryAccessTokenAuthenticationConfig + | MsSqlAzureActiveDirectoryMsiAppServiceAuthenticationConfig + | MsSqlAzureActiveDirectoryMsiVmAuthenticationConfig + | MsSqlAzureActiveDirectoryPasswordAuthenticationConfig + | MsSqlAzureActiveDirectoryServicePrincipalSecretConfig; + + // Config object for tedious: see http://tediousjs.github.io/tedious/api-connection.html + interface MsSqlConnectionConfigBase { + type?: MsSqlAuthenticationTypeOptions; + + driver?: string; + userName?: string; // equivalent to knex "user" + password?: string; + server: string; // equivalent to knex "host" + port?: number; + domain?: string; + database: string; + connectionTimeout?: number; + requestTimeout?: number; + stream?: boolean; + parseJSON?: boolean; + expirationChecker?(): boolean; + options?: Readonly<{ + encrypt?: boolean; + instanceName?: string; + useUTC?: boolean; + tdsVersion?: string; + appName?: string; + abortTransactionOnError?: boolean; + trustedConnection?: boolean; + enableArithAbort?: boolean; + isolationLevel?: + | 'READ_UNCOMMITTED' + | 'READ_COMMITTED' + | 'REPEATABLE_READ' + | 'SERIALIZABLE' + | 'SNAPSHOT'; + maxRetriesOnTransientErrors?: number; + multiSubnetFailover?: boolean; + packetSize?: number; + trustServerCertificate?: boolean; + mapBinding?: (value: any) => { value: any; type: any } | undefined; + }>; + pool?: Readonly<{ + min?: number; + max?: number; + idleTimeoutMillis?: number; + maxWaitingClients?: number; + testOnBorrow?: boolean; + acquireTimeoutMillis?: number; + fifo?: boolean; + priorityRange?: number; + autostart?: boolean; + evictionRunIntervalMillis?: number; + numTestsPerRun?: number; + softIdleTimeoutMillis?: number; + Promise?: any; + }>; + } + + // Config object for mariasql: https://github.com/mscdex/node-mariasql#client-methods + interface MariaSqlConnectionConfig { + user?: string; + password?: string; + host?: string; + port?: number; + unixSocket?: string; + protocol?: string; + db?: string; + keepQueries?: boolean; + multiStatements?: boolean; + connTimeout?: number; + pingInterval?: number; + secureAuth?: boolean; + compress?: boolean; + ssl?: boolean | MariaSslConfiguration; + local_infile?: boolean; + read_default_file?: string; + read_default_group?: string; + charset?: string; + streamHWM?: number; + expirationChecker?(): boolean; + } + + interface MariaSslConfiguration { + key?: string; + cert?: string; + ca?: string; + capath?: string; + cipher?: string; + rejectUnauthorized?: boolean; + expirationChecker?(): boolean; + } + + // Config object for mysql: https://github.com/mysqljs/mysql#connection-options + interface MySqlConnectionConfig { + host?: string; + port?: number; + localAddress?: string; + socketPath?: string; + user?: string; + password?: string; + database?: string; + charset?: string; + timezone?: string; + connectTimeout?: number; + stringifyObjects?: boolean; + insecureAuth?: boolean; + typeCast?: any; + queryFormat?: (query: string, values: any) => string; + supportBigNumbers?: boolean; + bigNumberStrings?: boolean; + dateStrings?: boolean; + debug?: boolean; + trace?: boolean; + multipleStatements?: boolean; + flags?: string; + ssl?: string | MariaSslConfiguration; + decimalNumbers?: boolean; + expirationChecker?(): boolean; + } + + // Config object for mysql2: https://github.com/sidorares/node-mysql2/blob/master/lib/connection_config.js + // Some options for connection pooling and MySQL server API are excluded. + interface MySql2ConnectionConfig extends MySqlConnectionConfig { + authPlugins?: { + [pluginName: string]: (pluginMetadata: any) => (pluginData: any) => any; + }; + authSwitchHandler?: (data: any, callback: () => void) => any; + charsetNumber?: number; + compress?: boolean; + connectAttributes?: { [attrNames: string]: any }; + enableKeepAlive?: boolean; + keepAliveInitialDelay?: number; + maxPreparedStatements?: number; + namedPlaceholders?: boolean; + nestTables?: boolean | string; + passwordSha1?: string; + rowsAsArray?: boolean; + stream?: boolean | ((opts: any) => Stream) | Stream; + uri?: string; + } + + interface OracleDbConnectionConfig { + host: string; + user: string; + password?: string; + database?: string; + domain?: string; + instanceName?: string; + debug?: boolean; + requestTimeout?: number; + connectString?: string; + expirationChecker?(): boolean; + } + + // Config object for pg: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/pg/index.d.ts + interface PgConnectionConfig { + user?: string; + database?: string; + password?: string | (() => string | Promise); + port?: number; + host?: string; + connectionString?: string; + keepAlive?: boolean; + stream?: () => stream.Duplex | stream.Duplex | undefined; + statement_timeout?: false | number; + parseInputDatesAsUTC?: boolean; + ssl?: boolean | ConnectionOptions; + query_timeout?: number; + keepAliveInitialDelayMillis?: number; + idle_in_transaction_session_timeout?: number; + application_name?: string; + connectionTimeoutMillis?: number; + types?: PgCustomTypesConfig; + options?: string; + expirationChecker?(): boolean; + } + + type PgGetTypeParser = (oid: number, format: string) => any; + + interface PgCustomTypesConfig { + getTypeParser: PgGetTypeParser; + } + + type RedshiftConnectionConfig = PgConnectionConfig; + + /** Used with SQLite3 adapter */ + interface Sqlite3ConnectionConfig { + filename: string; + flags?: string[]; + debug?: boolean; + expirationChecker?(): boolean; + } + + /** Used with `better-sqlite3` adapter */ + interface BetterSqlite3ConnectionConfig { + filename: string; + options?: { + nativeBinding?: string; + readonly?: boolean; + }; + } + + interface SocketConnectionConfig { + socketPath: string; + user: string; + password: string; + database: string; + debug?: boolean; + expirationChecker?(): boolean; + } + + interface PoolConfig { + name?: string; + afterCreate?: Function; + min?: number; + max?: number; + refreshIdle?: boolean; + idleTimeoutMillis?: number; + reapIntervalMillis?: number; + returnToHead?: boolean; + priorityRange?: number; + log?: (message: string, logLevel: string) => void; + + // tarn configs + propagateCreateError?: boolean; + createRetryIntervalMillis?: number; + createTimeoutMillis?: number; + destroyTimeoutMillis?: number; + acquireTimeoutMillis?: number; + } + + type LogFn = (message: any) => void; + + interface Logger { + warn?: LogFn; + error?: LogFn; + debug?: LogFn; + inspectionDepth?: number; + enableColors?: boolean; + deprecate?: (method: string, alternative: string) => void; + } + + interface Migration { + up: (knex: Knex) => PromiseLike; + down?: (knex: Knex) => PromiseLike; + } + + interface MigrationSource { + getMigrations(loadExtensions: readonly string[]): Promise; + getMigrationName(migration: TMigrationSpec): string; + getMigration(migration: TMigrationSpec): Promise; + } + + interface MigratorConfig { + database?: string; + directory?: string | readonly string[]; + extension?: string; + stub?: string; + tableName?: string; + schemaName?: string; + disableTransactions?: boolean; + disableMigrationsListValidation?: boolean; + sortDirsSeparately?: boolean; + loadExtensions?: readonly string[]; + migrationSource?: MigrationSource; + name?: string; + } + + interface Migrator { + make(name: string, config?: MigratorConfig): Promise; + latest(config?: MigratorConfig): Promise; + rollback(config?: MigratorConfig, all?: boolean): Promise; + status(config?: MigratorConfig): Promise; + currentVersion(config?: MigratorConfig): Promise; + list(config?: MigratorConfig): Promise; + up(config?: MigratorConfig): Promise; + down(config?: MigratorConfig): Promise; + forceFreeMigrationsLock(config?: MigratorConfig): Promise; + } + + interface Seed { + seed: (knex: Knex) => PromiseLike; + } + + interface SeedSource { + getSeeds(config: SeederConfig): Promise; + getSeed(seed: TSeedSpec): Promise; + } + + interface SeederConfig { + extension?: string; + directory?: string | readonly string[]; + loadExtensions?: readonly string[]; + specific?: string; + timestampFilenamePrefix?: boolean; + recursive?: boolean; + sortDirsSeparately?: boolean; + stub?: string; + variables?: V; + seedSource?: SeedSource; + } + + class Seeder { + constructor(knex: Knex); + setConfig(config: SeederConfig): SeederConfig; + run(config?: SeederConfig): Promise<[string[]]>; + make(name: string, config?: SeederConfig): Promise; + } + + interface FunctionHelper { + now(precision?: number): Raw; + uuid(): Raw; + uuidToBin(uuid: string, ordered?: boolean): Buffer; + binToUuid(bin: Buffer, ordered?: boolean): string; + } + + interface EnumOptions { + useNative: boolean; + existingType?: boolean; + schemaName?: string; + enumName: string; + } + + interface DefaultToOptions { + // only supported by mssql driver + constraintName?: string; + } + + class Client extends events.EventEmitter { + constructor(config: Config); + config: Config; + dialect: string; + driverName: string; + connectionSettings: object; + + acquireRawConnection(): Promise; + destroyRawConnection(connection: any): Promise; + validateConnection(connection: any): Promise; + logger: Logger; + version?: string; + connectionConfigProvider: any; + connectionConfigExpirationChecker: null | (() => boolean); + valueForUndefined: any; + formatter(builder: any): any; + queryBuilder(): QueryBuilder; + queryCompiler(builder: any): any; + schemaBuilder(): SchemaBuilder; + schemaCompiler(builder: SchemaBuilder): any; + tableBuilder( + type: any, + tableName: any, + tableNameLike: any, + fn: any + ): TableBuilder; + tableCompiler(tableBuilder: any): any; + columnBuilder(tableBuilder: any, type: any, args: any): ColumnBuilder; + columnCompiler(tableBuilder: any, columnBuilder: any): any; + runner(builder: any): any; + transaction(container: any, config: any, outerTx: any): Transaction; + raw(...args: any[]): any; + ref(...args: any[]): Ref; + query(connection: any, obj: any): any; + stream(connection: any, obj: any, stream: any, options: any): any; + prepBindings(bindings: any): any; + positionBindings(sql: any): any; + postProcessResponse(resp: any, queryContext: any): any; + wrapIdentifier(value: any, queryContext: any): any; + customWrapIdentifier(value: any, origImpl: any, queryContext: any): any; + wrapIdentifierImpl(value: any): string; + initializeDriver(): void; + driver: any; + poolDefaults(): { + min: number; + max: number; + propagateCreateError: boolean; + }; + getPoolSettings(poolConfig: any): any; + initializePool(config?: {}): void; + pool: tarn.Pool | undefined; + acquireConnection(): any; + releaseConnection(connection: any): any; + destroy(callback: any): any; + database(): any; + canCancelQuery: boolean; + assertCanCancelQuery(): void; + cancelQuery(): void; + } +} + +export = knex; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/types/result.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/types/result.d.ts new file mode 100644 index 000000000..82b482a67 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/types/result.d.ts @@ -0,0 +1,27 @@ +// This empty interface serves as a placeholder which userland code can augment to +// override result types. +// +// Currently only available result type which is overridable is Count, which defaults to +// number | string; +// +// Following example in userland code will alter this to be just number: +// +// declare module "knex/types/result" { +// interface Registry { +// Count: number; +// } +// } +// +// Prior discussion: https://github.com/tgriesser/knex/issues/3247 +export interface Registry { + // We can't actually have default types here + // because typescript's augmentation will not permit + // overriding the type of a property already present. + // + // But the effective defaults are documented below: + // + // Count: number | string; + // + // Refer to Knex.Lookup type operator to see how the defaults + // are actually specified. +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/types/tables.d.ts b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/types/tables.d.ts new file mode 100644 index 000000000..f24a3cf16 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/knex/types/tables.d.ts @@ -0,0 +1,4 @@ +// Placeholder interface for Table -> Record mapping +// Allows to define the mapping of tables and interfaces in one place +// and to have correct types when using `knex.from('table')` +export interface Tables {} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/LICENSE new file mode 100644 index 000000000..77c42f140 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/LICENSE @@ -0,0 +1,47 @@ +Copyright OpenJS Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +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. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/README.md new file mode 100644 index 000000000..3ab1a05ce --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/README.md @@ -0,0 +1,39 @@ +# lodash v4.17.21 + +The [Lodash](https://lodash.com/) library exported as [Node.js](https://nodejs.org/) modules. + +## Installation + +Using npm: +```shell +$ npm i -g npm +$ npm i --save lodash +``` + +In Node.js: +```js +// Load the full build. +var _ = require('lodash'); +// Load the core build. +var _ = require('lodash/core'); +// Load the FP build for immutable auto-curried iteratee-first data-last methods. +var fp = require('lodash/fp'); + +// Load method categories. +var array = require('lodash/array'); +var object = require('lodash/fp/object'); + +// Cherry-pick methods for smaller browserify/rollup/webpack bundles. +var at = require('lodash/at'); +var curryN = require('lodash/fp/curryN'); +``` + +See the [package source](https://github.com/lodash/lodash/tree/4.17.21-npm) for more details. + +**Note:**
    +Install [n_](https://www.npmjs.com/package/n_) for Lodash use in the Node.js < 6 REPL. + +## Support + +Tested in Chrome 74-75, Firefox 66-67, IE 11, Edge 18, Safari 11-12, & Node.js 8-12.
    +Automated [browser](https://saucelabs.com/u/lodash) & [CI](https://travis-ci.org/lodash/lodash/) test runs are available. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_DataView.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_DataView.js new file mode 100644 index 000000000..ac2d57ca6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_DataView.js @@ -0,0 +1,7 @@ +var getNative = require('./_getNative'), + root = require('./_root'); + +/* Built-in method references that are verified to be native. */ +var DataView = getNative(root, 'DataView'); + +module.exports = DataView; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Hash.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Hash.js new file mode 100644 index 000000000..b504fe340 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Hash.js @@ -0,0 +1,32 @@ +var hashClear = require('./_hashClear'), + hashDelete = require('./_hashDelete'), + hashGet = require('./_hashGet'), + hashHas = require('./_hashHas'), + hashSet = require('./_hashSet'); + +/** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Hash(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `Hash`. +Hash.prototype.clear = hashClear; +Hash.prototype['delete'] = hashDelete; +Hash.prototype.get = hashGet; +Hash.prototype.has = hashHas; +Hash.prototype.set = hashSet; + +module.exports = Hash; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_LazyWrapper.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_LazyWrapper.js new file mode 100644 index 000000000..81786c7f1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_LazyWrapper.js @@ -0,0 +1,28 @@ +var baseCreate = require('./_baseCreate'), + baseLodash = require('./_baseLodash'); + +/** Used as references for the maximum length and index of an array. */ +var MAX_ARRAY_LENGTH = 4294967295; + +/** + * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. + * + * @private + * @constructor + * @param {*} value The value to wrap. + */ +function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = MAX_ARRAY_LENGTH; + this.__views__ = []; +} + +// Ensure `LazyWrapper` is an instance of `baseLodash`. +LazyWrapper.prototype = baseCreate(baseLodash.prototype); +LazyWrapper.prototype.constructor = LazyWrapper; + +module.exports = LazyWrapper; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_ListCache.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_ListCache.js new file mode 100644 index 000000000..26895c3a8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_ListCache.js @@ -0,0 +1,32 @@ +var listCacheClear = require('./_listCacheClear'), + listCacheDelete = require('./_listCacheDelete'), + listCacheGet = require('./_listCacheGet'), + listCacheHas = require('./_listCacheHas'), + listCacheSet = require('./_listCacheSet'); + +/** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `ListCache`. +ListCache.prototype.clear = listCacheClear; +ListCache.prototype['delete'] = listCacheDelete; +ListCache.prototype.get = listCacheGet; +ListCache.prototype.has = listCacheHas; +ListCache.prototype.set = listCacheSet; + +module.exports = ListCache; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_LodashWrapper.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_LodashWrapper.js new file mode 100644 index 000000000..c1e4d9df7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_LodashWrapper.js @@ -0,0 +1,22 @@ +var baseCreate = require('./_baseCreate'), + baseLodash = require('./_baseLodash'); + +/** + * The base constructor for creating `lodash` wrapper objects. + * + * @private + * @param {*} value The value to wrap. + * @param {boolean} [chainAll] Enable explicit method chain sequences. + */ +function LodashWrapper(value, chainAll) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__chain__ = !!chainAll; + this.__index__ = 0; + this.__values__ = undefined; +} + +LodashWrapper.prototype = baseCreate(baseLodash.prototype); +LodashWrapper.prototype.constructor = LodashWrapper; + +module.exports = LodashWrapper; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Map.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Map.js new file mode 100644 index 000000000..b73f29a0f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Map.js @@ -0,0 +1,7 @@ +var getNative = require('./_getNative'), + root = require('./_root'); + +/* Built-in method references that are verified to be native. */ +var Map = getNative(root, 'Map'); + +module.exports = Map; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_MapCache.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_MapCache.js new file mode 100644 index 000000000..4a4eea7bf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_MapCache.js @@ -0,0 +1,32 @@ +var mapCacheClear = require('./_mapCacheClear'), + mapCacheDelete = require('./_mapCacheDelete'), + mapCacheGet = require('./_mapCacheGet'), + mapCacheHas = require('./_mapCacheHas'), + mapCacheSet = require('./_mapCacheSet'); + +/** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function MapCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `MapCache`. +MapCache.prototype.clear = mapCacheClear; +MapCache.prototype['delete'] = mapCacheDelete; +MapCache.prototype.get = mapCacheGet; +MapCache.prototype.has = mapCacheHas; +MapCache.prototype.set = mapCacheSet; + +module.exports = MapCache; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Promise.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Promise.js new file mode 100644 index 000000000..247b9e1ba --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Promise.js @@ -0,0 +1,7 @@ +var getNative = require('./_getNative'), + root = require('./_root'); + +/* Built-in method references that are verified to be native. */ +var Promise = getNative(root, 'Promise'); + +module.exports = Promise; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Set.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Set.js new file mode 100644 index 000000000..b3c8dcbf0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Set.js @@ -0,0 +1,7 @@ +var getNative = require('./_getNative'), + root = require('./_root'); + +/* Built-in method references that are verified to be native. */ +var Set = getNative(root, 'Set'); + +module.exports = Set; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_SetCache.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_SetCache.js new file mode 100644 index 000000000..6468b0647 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_SetCache.js @@ -0,0 +1,27 @@ +var MapCache = require('./_MapCache'), + setCacheAdd = require('./_setCacheAdd'), + setCacheHas = require('./_setCacheHas'); + +/** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ +function SetCache(values) { + var index = -1, + length = values == null ? 0 : values.length; + + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } +} + +// Add methods to `SetCache`. +SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; +SetCache.prototype.has = setCacheHas; + +module.exports = SetCache; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Stack.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Stack.js new file mode 100644 index 000000000..80b2cf1b0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Stack.js @@ -0,0 +1,27 @@ +var ListCache = require('./_ListCache'), + stackClear = require('./_stackClear'), + stackDelete = require('./_stackDelete'), + stackGet = require('./_stackGet'), + stackHas = require('./_stackHas'), + stackSet = require('./_stackSet'); + +/** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; +} + +// Add methods to `Stack`. +Stack.prototype.clear = stackClear; +Stack.prototype['delete'] = stackDelete; +Stack.prototype.get = stackGet; +Stack.prototype.has = stackHas; +Stack.prototype.set = stackSet; + +module.exports = Stack; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Symbol.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Symbol.js new file mode 100644 index 000000000..a013f7c5b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Symbol.js @@ -0,0 +1,6 @@ +var root = require('./_root'); + +/** Built-in value references. */ +var Symbol = root.Symbol; + +module.exports = Symbol; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Uint8Array.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Uint8Array.js new file mode 100644 index 000000000..2fb30e157 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_Uint8Array.js @@ -0,0 +1,6 @@ +var root = require('./_root'); + +/** Built-in value references. */ +var Uint8Array = root.Uint8Array; + +module.exports = Uint8Array; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_WeakMap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_WeakMap.js new file mode 100644 index 000000000..567f86c61 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_WeakMap.js @@ -0,0 +1,7 @@ +var getNative = require('./_getNative'), + root = require('./_root'); + +/* Built-in method references that are verified to be native. */ +var WeakMap = getNative(root, 'WeakMap'); + +module.exports = WeakMap; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_apply.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_apply.js new file mode 100644 index 000000000..36436dda5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_apply.js @@ -0,0 +1,21 @@ +/** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ +function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); +} + +module.exports = apply; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayAggregator.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayAggregator.js new file mode 100644 index 000000000..d96c3ca47 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayAggregator.js @@ -0,0 +1,22 @@ +/** + * A specialized version of `baseAggregator` for arrays. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ +function arrayAggregator(array, setter, iteratee, accumulator) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + var value = array[index]; + setter(accumulator, value, iteratee(value), array); + } + return accumulator; +} + +module.exports = arrayAggregator; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayEach.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayEach.js new file mode 100644 index 000000000..2c5f57968 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayEach.js @@ -0,0 +1,22 @@ +/** + * A specialized version of `_.forEach` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ +function arrayEach(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; +} + +module.exports = arrayEach; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayEachRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayEachRight.js new file mode 100644 index 000000000..976ca5c29 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayEachRight.js @@ -0,0 +1,21 @@ +/** + * A specialized version of `_.forEachRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ +function arrayEachRight(array, iteratee) { + var length = array == null ? 0 : array.length; + + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; +} + +module.exports = arrayEachRight; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayEvery.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayEvery.js new file mode 100644 index 000000000..e26a91845 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayEvery.js @@ -0,0 +1,23 @@ +/** + * A specialized version of `_.every` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + */ +function arrayEvery(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; +} + +module.exports = arrayEvery; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayFilter.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayFilter.js new file mode 100644 index 000000000..75ea25445 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayFilter.js @@ -0,0 +1,25 @@ +/** + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ +function arrayFilter(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; +} + +module.exports = arrayFilter; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayIncludes.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayIncludes.js new file mode 100644 index 000000000..3737a6d9e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayIncludes.js @@ -0,0 +1,17 @@ +var baseIndexOf = require('./_baseIndexOf'); + +/** + * A specialized version of `_.includes` for arrays without support for + * specifying an index to search from. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ +function arrayIncludes(array, value) { + var length = array == null ? 0 : array.length; + return !!length && baseIndexOf(array, value, 0) > -1; +} + +module.exports = arrayIncludes; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayIncludesWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayIncludesWith.js new file mode 100644 index 000000000..235fd9758 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayIncludesWith.js @@ -0,0 +1,22 @@ +/** + * This function is like `arrayIncludes` except that it accepts a comparator. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @param {Function} comparator The comparator invoked per element. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ +function arrayIncludesWith(array, value, comparator) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (comparator(value, array[index])) { + return true; + } + } + return false; +} + +module.exports = arrayIncludesWith; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayLikeKeys.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayLikeKeys.js new file mode 100644 index 000000000..b2ec9ce78 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayLikeKeys.js @@ -0,0 +1,49 @@ +var baseTimes = require('./_baseTimes'), + isArguments = require('./isArguments'), + isArray = require('./isArray'), + isBuffer = require('./isBuffer'), + isIndex = require('./_isIndex'), + isTypedArray = require('./isTypedArray'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ +function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; +} + +module.exports = arrayLikeKeys; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayMap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayMap.js new file mode 100644 index 000000000..22b22464e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayMap.js @@ -0,0 +1,21 @@ +/** + * A specialized version of `_.map` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ +function arrayMap(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; +} + +module.exports = arrayMap; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayPush.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayPush.js new file mode 100644 index 000000000..7d742b383 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayPush.js @@ -0,0 +1,20 @@ +/** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ +function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; +} + +module.exports = arrayPush; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayReduce.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayReduce.js new file mode 100644 index 000000000..de8b79b28 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayReduce.js @@ -0,0 +1,26 @@ +/** + * A specialized version of `_.reduce` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the first element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ +function arrayReduce(array, iteratee, accumulator, initAccum) { + var index = -1, + length = array == null ? 0 : array.length; + + if (initAccum && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; +} + +module.exports = arrayReduce; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayReduceRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayReduceRight.js new file mode 100644 index 000000000..22d8976de --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayReduceRight.js @@ -0,0 +1,24 @@ +/** + * A specialized version of `_.reduceRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the last element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ +function arrayReduceRight(array, iteratee, accumulator, initAccum) { + var length = array == null ? 0 : array.length; + if (initAccum && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; +} + +module.exports = arrayReduceRight; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arraySample.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arraySample.js new file mode 100644 index 000000000..fcab0105e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arraySample.js @@ -0,0 +1,15 @@ +var baseRandom = require('./_baseRandom'); + +/** + * A specialized version of `_.sample` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @returns {*} Returns the random element. + */ +function arraySample(array) { + var length = array.length; + return length ? array[baseRandom(0, length - 1)] : undefined; +} + +module.exports = arraySample; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arraySampleSize.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arraySampleSize.js new file mode 100644 index 000000000..8c7e364f5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arraySampleSize.js @@ -0,0 +1,17 @@ +var baseClamp = require('./_baseClamp'), + copyArray = require('./_copyArray'), + shuffleSelf = require('./_shuffleSelf'); + +/** + * A specialized version of `_.sampleSize` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ +function arraySampleSize(array, n) { + return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length)); +} + +module.exports = arraySampleSize; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayShuffle.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayShuffle.js new file mode 100644 index 000000000..46313a39b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arrayShuffle.js @@ -0,0 +1,15 @@ +var copyArray = require('./_copyArray'), + shuffleSelf = require('./_shuffleSelf'); + +/** + * A specialized version of `_.shuffle` for arrays. + * + * @private + * @param {Array} array The array to shuffle. + * @returns {Array} Returns the new shuffled array. + */ +function arrayShuffle(array) { + return shuffleSelf(copyArray(array)); +} + +module.exports = arrayShuffle; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arraySome.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arraySome.js new file mode 100644 index 000000000..6fd02fd4a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_arraySome.js @@ -0,0 +1,23 @@ +/** + * A specialized version of `_.some` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ +function arraySome(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; +} + +module.exports = arraySome; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_asciiSize.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_asciiSize.js new file mode 100644 index 000000000..11d29c33a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_asciiSize.js @@ -0,0 +1,12 @@ +var baseProperty = require('./_baseProperty'); + +/** + * Gets the size of an ASCII `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ +var asciiSize = baseProperty('length'); + +module.exports = asciiSize; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_asciiToArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_asciiToArray.js new file mode 100644 index 000000000..8e3dd5b47 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_asciiToArray.js @@ -0,0 +1,12 @@ +/** + * Converts an ASCII `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function asciiToArray(string) { + return string.split(''); +} + +module.exports = asciiToArray; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_asciiWords.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_asciiWords.js new file mode 100644 index 000000000..d765f0f76 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_asciiWords.js @@ -0,0 +1,15 @@ +/** Used to match words composed of alphanumeric characters. */ +var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; + +/** + * Splits an ASCII `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ +function asciiWords(string) { + return string.match(reAsciiWord) || []; +} + +module.exports = asciiWords; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_assignMergeValue.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_assignMergeValue.js new file mode 100644 index 000000000..cb1185e99 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_assignMergeValue.js @@ -0,0 +1,20 @@ +var baseAssignValue = require('./_baseAssignValue'), + eq = require('./eq'); + +/** + * This function is like `assignValue` except that it doesn't assign + * `undefined` values. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function assignMergeValue(object, key, value) { + if ((value !== undefined && !eq(object[key], value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } +} + +module.exports = assignMergeValue; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_assignValue.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_assignValue.js new file mode 100644 index 000000000..40839575b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_assignValue.js @@ -0,0 +1,28 @@ +var baseAssignValue = require('./_baseAssignValue'), + eq = require('./eq'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } +} + +module.exports = assignValue; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_assocIndexOf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_assocIndexOf.js new file mode 100644 index 000000000..5b77a2bdd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_assocIndexOf.js @@ -0,0 +1,21 @@ +var eq = require('./eq'); + +/** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; +} + +module.exports = assocIndexOf; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAggregator.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAggregator.js new file mode 100644 index 000000000..4bc9e91f4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAggregator.js @@ -0,0 +1,21 @@ +var baseEach = require('./_baseEach'); + +/** + * Aggregates elements of `collection` on `accumulator` with keys transformed + * by `iteratee` and values set by `setter`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ +function baseAggregator(collection, setter, iteratee, accumulator) { + baseEach(collection, function(value, key, collection) { + setter(accumulator, value, iteratee(value), collection); + }); + return accumulator; +} + +module.exports = baseAggregator; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAssign.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAssign.js new file mode 100644 index 000000000..e5c4a1a5b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAssign.js @@ -0,0 +1,17 @@ +var copyObject = require('./_copyObject'), + keys = require('./keys'); + +/** + * The base implementation of `_.assign` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ +function baseAssign(object, source) { + return object && copyObject(source, keys(source), object); +} + +module.exports = baseAssign; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAssignIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAssignIn.js new file mode 100644 index 000000000..6624f9006 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAssignIn.js @@ -0,0 +1,17 @@ +var copyObject = require('./_copyObject'), + keysIn = require('./keysIn'); + +/** + * The base implementation of `_.assignIn` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ +function baseAssignIn(object, source) { + return object && copyObject(source, keysIn(source), object); +} + +module.exports = baseAssignIn; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAssignValue.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAssignValue.js new file mode 100644 index 000000000..d6f66ef3a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAssignValue.js @@ -0,0 +1,25 @@ +var defineProperty = require('./_defineProperty'); + +/** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } +} + +module.exports = baseAssignValue; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAt.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAt.js new file mode 100644 index 000000000..90e4237a0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseAt.js @@ -0,0 +1,23 @@ +var get = require('./get'); + +/** + * The base implementation of `_.at` without support for individual paths. + * + * @private + * @param {Object} object The object to iterate over. + * @param {string[]} paths The property paths to pick. + * @returns {Array} Returns the picked elements. + */ +function baseAt(object, paths) { + var index = -1, + length = paths.length, + result = Array(length), + skip = object == null; + + while (++index < length) { + result[index] = skip ? undefined : get(object, paths[index]); + } + return result; +} + +module.exports = baseAt; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseClamp.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseClamp.js new file mode 100644 index 000000000..a1c569292 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseClamp.js @@ -0,0 +1,22 @@ +/** + * The base implementation of `_.clamp` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + */ +function baseClamp(number, lower, upper) { + if (number === number) { + if (upper !== undefined) { + number = number <= upper ? number : upper; + } + if (lower !== undefined) { + number = number >= lower ? number : lower; + } + } + return number; +} + +module.exports = baseClamp; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseClone.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseClone.js new file mode 100644 index 000000000..69f87054c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseClone.js @@ -0,0 +1,166 @@ +var Stack = require('./_Stack'), + arrayEach = require('./_arrayEach'), + assignValue = require('./_assignValue'), + baseAssign = require('./_baseAssign'), + baseAssignIn = require('./_baseAssignIn'), + cloneBuffer = require('./_cloneBuffer'), + copyArray = require('./_copyArray'), + copySymbols = require('./_copySymbols'), + copySymbolsIn = require('./_copySymbolsIn'), + getAllKeys = require('./_getAllKeys'), + getAllKeysIn = require('./_getAllKeysIn'), + getTag = require('./_getTag'), + initCloneArray = require('./_initCloneArray'), + initCloneByTag = require('./_initCloneByTag'), + initCloneObject = require('./_initCloneObject'), + isArray = require('./isArray'), + isBuffer = require('./isBuffer'), + isMap = require('./isMap'), + isObject = require('./isObject'), + isSet = require('./isSet'), + keys = require('./keys'), + keysIn = require('./keysIn'); + +/** Used to compose bitmasks for cloning. */ +var CLONE_DEEP_FLAG = 1, + CLONE_FLAT_FLAG = 2, + CLONE_SYMBOLS_FLAG = 4; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]', + weakMapTag = '[object WeakMap]'; + +var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + +/** Used to identify `toStringTag` values supported by `_.clone`. */ +var cloneableTags = {}; +cloneableTags[argsTag] = cloneableTags[arrayTag] = +cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = +cloneableTags[boolTag] = cloneableTags[dateTag] = +cloneableTags[float32Tag] = cloneableTags[float64Tag] = +cloneableTags[int8Tag] = cloneableTags[int16Tag] = +cloneableTags[int32Tag] = cloneableTags[mapTag] = +cloneableTags[numberTag] = cloneableTags[objectTag] = +cloneableTags[regexpTag] = cloneableTags[setTag] = +cloneableTags[stringTag] = cloneableTags[symbolTag] = +cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = +cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; +cloneableTags[errorTag] = cloneableTags[funcTag] = +cloneableTags[weakMapTag] = false; + +/** + * The base implementation of `_.clone` and `_.cloneDeep` which tracks + * traversed objects. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} bitmask The bitmask flags. + * 1 - Deep clone + * 2 - Flatten inherited properties + * 4 - Clone symbols + * @param {Function} [customizer] The function to customize cloning. + * @param {string} [key] The key of `value`. + * @param {Object} [object] The parent object of `value`. + * @param {Object} [stack] Tracks traversed objects and their clone counterparts. + * @returns {*} Returns the cloned value. + */ +function baseClone(value, bitmask, customizer, key, object, stack) { + var result, + isDeep = bitmask & CLONE_DEEP_FLAG, + isFlat = bitmask & CLONE_FLAT_FLAG, + isFull = bitmask & CLONE_SYMBOLS_FLAG; + + if (customizer) { + result = object ? customizer(value, key, object, stack) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return copyArray(value, result); + } + } else { + var tag = getTag(value), + isFunc = tag == funcTag || tag == genTag; + + if (isBuffer(value)) { + return cloneBuffer(value, isDeep); + } + if (tag == objectTag || tag == argsTag || (isFunc && !object)) { + result = (isFlat || isFunc) ? {} : initCloneObject(value); + if (!isDeep) { + return isFlat + ? copySymbolsIn(value, baseAssignIn(result, value)) + : copySymbols(value, baseAssign(result, value)); + } + } else { + if (!cloneableTags[tag]) { + return object ? value : {}; + } + result = initCloneByTag(value, tag, isDeep); + } + } + // Check for circular references and return its corresponding clone. + stack || (stack = new Stack); + var stacked = stack.get(value); + if (stacked) { + return stacked; + } + stack.set(value, result); + + if (isSet(value)) { + value.forEach(function(subValue) { + result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack)); + }); + } else if (isMap(value)) { + value.forEach(function(subValue, key) { + result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + } + + var keysFunc = isFull + ? (isFlat ? getAllKeysIn : getAllKeys) + : (isFlat ? keysIn : keys); + + var props = isArr ? undefined : keysFunc(value); + arrayEach(props || value, function(subValue, key) { + if (props) { + key = subValue; + subValue = value[key]; + } + // Recursively populate clone (susceptible to call stack limits). + assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + return result; +} + +module.exports = baseClone; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseConforms.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseConforms.js new file mode 100644 index 000000000..947e20d40 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseConforms.js @@ -0,0 +1,18 @@ +var baseConformsTo = require('./_baseConformsTo'), + keys = require('./keys'); + +/** + * The base implementation of `_.conforms` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property predicates to conform to. + * @returns {Function} Returns the new spec function. + */ +function baseConforms(source) { + var props = keys(source); + return function(object) { + return baseConformsTo(object, source, props); + }; +} + +module.exports = baseConforms; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseConformsTo.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseConformsTo.js new file mode 100644 index 000000000..e449cb84b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseConformsTo.js @@ -0,0 +1,27 @@ +/** + * The base implementation of `_.conformsTo` which accepts `props` to check. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + */ +function baseConformsTo(object, source, props) { + var length = props.length; + if (object == null) { + return !length; + } + object = Object(object); + while (length--) { + var key = props[length], + predicate = source[key], + value = object[key]; + + if ((value === undefined && !(key in object)) || !predicate(value)) { + return false; + } + } + return true; +} + +module.exports = baseConformsTo; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseCreate.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseCreate.js new file mode 100644 index 000000000..ffa6a52ac --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseCreate.js @@ -0,0 +1,30 @@ +var isObject = require('./isObject'); + +/** Built-in value references. */ +var objectCreate = Object.create; + +/** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ +var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; +}()); + +module.exports = baseCreate; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseDelay.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseDelay.js new file mode 100644 index 000000000..1486d697e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseDelay.js @@ -0,0 +1,21 @@ +/** Error message constants. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/** + * The base implementation of `_.delay` and `_.defer` which accepts `args` + * to provide to `func`. + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {Array} args The arguments to provide to `func`. + * @returns {number|Object} Returns the timer id or timeout object. + */ +function baseDelay(func, wait, args) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { func.apply(undefined, args); }, wait); +} + +module.exports = baseDelay; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseDifference.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseDifference.js new file mode 100644 index 000000000..343ac19f0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseDifference.js @@ -0,0 +1,67 @@ +var SetCache = require('./_SetCache'), + arrayIncludes = require('./_arrayIncludes'), + arrayIncludesWith = require('./_arrayIncludesWith'), + arrayMap = require('./_arrayMap'), + baseUnary = require('./_baseUnary'), + cacheHas = require('./_cacheHas'); + +/** Used as the size to enable large array optimizations. */ +var LARGE_ARRAY_SIZE = 200; + +/** + * The base implementation of methods like `_.difference` without support + * for excluding multiple arrays or iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Array} values The values to exclude. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + */ +function baseDifference(array, values, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + isCommon = true, + length = array.length, + result = [], + valuesLength = values.length; + + if (!length) { + return result; + } + if (iteratee) { + values = arrayMap(values, baseUnary(iteratee)); + } + if (comparator) { + includes = arrayIncludesWith; + isCommon = false; + } + else if (values.length >= LARGE_ARRAY_SIZE) { + includes = cacheHas; + isCommon = false; + values = new SetCache(values); + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee == null ? value : iteratee(value); + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === computed) { + continue outer; + } + } + result.push(value); + } + else if (!includes(values, computed, comparator)) { + result.push(value); + } + } + return result; +} + +module.exports = baseDifference; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseEach.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseEach.js new file mode 100644 index 000000000..512c06768 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseEach.js @@ -0,0 +1,14 @@ +var baseForOwn = require('./_baseForOwn'), + createBaseEach = require('./_createBaseEach'); + +/** + * The base implementation of `_.forEach` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ +var baseEach = createBaseEach(baseForOwn); + +module.exports = baseEach; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseEachRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseEachRight.js new file mode 100644 index 000000000..0a8feeca4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseEachRight.js @@ -0,0 +1,14 @@ +var baseForOwnRight = require('./_baseForOwnRight'), + createBaseEach = require('./_createBaseEach'); + +/** + * The base implementation of `_.forEachRight` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ +var baseEachRight = createBaseEach(baseForOwnRight, true); + +module.exports = baseEachRight; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseEvery.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseEvery.js new file mode 100644 index 000000000..fa52f7bc7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseEvery.js @@ -0,0 +1,21 @@ +var baseEach = require('./_baseEach'); + +/** + * The base implementation of `_.every` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false` + */ +function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; +} + +module.exports = baseEvery; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseExtremum.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseExtremum.js new file mode 100644 index 000000000..9d6aa77ed --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseExtremum.js @@ -0,0 +1,32 @@ +var isSymbol = require('./isSymbol'); + +/** + * The base implementation of methods like `_.max` and `_.min` which accepts a + * `comparator` to determine the extremum value. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The iteratee invoked per iteration. + * @param {Function} comparator The comparator used to compare values. + * @returns {*} Returns the extremum value. + */ +function baseExtremum(array, iteratee, comparator) { + var index = -1, + length = array.length; + + while (++index < length) { + var value = array[index], + current = iteratee(value); + + if (current != null && (computed === undefined + ? (current === current && !isSymbol(current)) + : comparator(current, computed) + )) { + var computed = current, + result = value; + } + } + return result; +} + +module.exports = baseExtremum; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFill.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFill.js new file mode 100644 index 000000000..46ef9c761 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFill.js @@ -0,0 +1,32 @@ +var toInteger = require('./toInteger'), + toLength = require('./toLength'); + +/** + * The base implementation of `_.fill` without an iteratee call guard. + * + * @private + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + */ +function baseFill(array, value, start, end) { + var length = array.length; + + start = toInteger(start); + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = (end === undefined || end > length) ? length : toInteger(end); + if (end < 0) { + end += length; + } + end = start > end ? 0 : toLength(end); + while (start < end) { + array[start++] = value; + } + return array; +} + +module.exports = baseFill; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFilter.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFilter.js new file mode 100644 index 000000000..467847736 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFilter.js @@ -0,0 +1,21 @@ +var baseEach = require('./_baseEach'); + +/** + * The base implementation of `_.filter` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ +function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; +} + +module.exports = baseFilter; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFindIndex.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFindIndex.js new file mode 100644 index 000000000..e3f5d8aa2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFindIndex.js @@ -0,0 +1,24 @@ +/** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; +} + +module.exports = baseFindIndex; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFindKey.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFindKey.js new file mode 100644 index 000000000..2e430f3a2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFindKey.js @@ -0,0 +1,23 @@ +/** + * The base implementation of methods like `_.findKey` and `_.findLastKey`, + * without support for iteratee shorthands, which iterates over `collection` + * using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the found element or its key, else `undefined`. + */ +function baseFindKey(collection, predicate, eachFunc) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = key; + return false; + } + }); + return result; +} + +module.exports = baseFindKey; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFlatten.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFlatten.js new file mode 100644 index 000000000..4b1e009b1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFlatten.js @@ -0,0 +1,38 @@ +var arrayPush = require('./_arrayPush'), + isFlattenable = require('./_isFlattenable'); + +/** + * The base implementation of `_.flatten` with support for restricting flattening. + * + * @private + * @param {Array} array The array to flatten. + * @param {number} depth The maximum recursion depth. + * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. + * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. + * @param {Array} [result=[]] The initial result value. + * @returns {Array} Returns the new flattened array. + */ +function baseFlatten(array, depth, predicate, isStrict, result) { + var index = -1, + length = array.length; + + predicate || (predicate = isFlattenable); + result || (result = []); + + while (++index < length) { + var value = array[index]; + if (depth > 0 && predicate(value)) { + if (depth > 1) { + // Recursively flatten arrays (susceptible to call stack limits). + baseFlatten(value, depth - 1, predicate, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; +} + +module.exports = baseFlatten; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFor.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFor.js new file mode 100644 index 000000000..d946590f8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFor.js @@ -0,0 +1,16 @@ +var createBaseFor = require('./_createBaseFor'); + +/** + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ +var baseFor = createBaseFor(); + +module.exports = baseFor; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseForOwn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseForOwn.js new file mode 100644 index 000000000..503d52344 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseForOwn.js @@ -0,0 +1,16 @@ +var baseFor = require('./_baseFor'), + keys = require('./keys'); + +/** + * The base implementation of `_.forOwn` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ +function baseForOwn(object, iteratee) { + return object && baseFor(object, iteratee, keys); +} + +module.exports = baseForOwn; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseForOwnRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseForOwnRight.js new file mode 100644 index 000000000..a4b10e6c5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseForOwnRight.js @@ -0,0 +1,16 @@ +var baseForRight = require('./_baseForRight'), + keys = require('./keys'); + +/** + * The base implementation of `_.forOwnRight` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ +function baseForOwnRight(object, iteratee) { + return object && baseForRight(object, iteratee, keys); +} + +module.exports = baseForOwnRight; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseForRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseForRight.js new file mode 100644 index 000000000..32842cd81 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseForRight.js @@ -0,0 +1,15 @@ +var createBaseFor = require('./_createBaseFor'); + +/** + * This function is like `baseFor` except that it iterates over properties + * in the opposite order. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ +var baseForRight = createBaseFor(true); + +module.exports = baseForRight; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFunctions.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFunctions.js new file mode 100644 index 000000000..d23bc9b47 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseFunctions.js @@ -0,0 +1,19 @@ +var arrayFilter = require('./_arrayFilter'), + isFunction = require('./isFunction'); + +/** + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from `props`. + * + * @private + * @param {Object} object The object to inspect. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the function names. + */ +function baseFunctions(object, props) { + return arrayFilter(props, function(key) { + return isFunction(object[key]); + }); +} + +module.exports = baseFunctions; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGet.js new file mode 100644 index 000000000..a194913d2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGet.js @@ -0,0 +1,24 @@ +var castPath = require('./_castPath'), + toKey = require('./_toKey'); + +/** + * The base implementation of `_.get` without support for default values. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @returns {*} Returns the resolved value. + */ +function baseGet(object, path) { + path = castPath(path, object); + + var index = 0, + length = path.length; + + while (object != null && index < length) { + object = object[toKey(path[index++])]; + } + return (index && index == length) ? object : undefined; +} + +module.exports = baseGet; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGetAllKeys.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGetAllKeys.js new file mode 100644 index 000000000..8ad204ea4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGetAllKeys.js @@ -0,0 +1,20 @@ +var arrayPush = require('./_arrayPush'), + isArray = require('./isArray'); + +/** + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. + */ +function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); +} + +module.exports = baseGetAllKeys; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGetTag.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGetTag.js new file mode 100644 index 000000000..b927ccc17 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGetTag.js @@ -0,0 +1,28 @@ +var Symbol = require('./_Symbol'), + getRawTag = require('./_getRawTag'), + objectToString = require('./_objectToString'); + +/** `Object#toString` result references. */ +var nullTag = '[object Null]', + undefinedTag = '[object Undefined]'; + +/** Built-in value references. */ +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + +/** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); +} + +module.exports = baseGetTag; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGt.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGt.js new file mode 100644 index 000000000..502d273ca --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseGt.js @@ -0,0 +1,14 @@ +/** + * The base implementation of `_.gt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + */ +function baseGt(value, other) { + return value > other; +} + +module.exports = baseGt; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseHas.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseHas.js new file mode 100644 index 000000000..1b730321c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseHas.js @@ -0,0 +1,19 @@ +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * The base implementation of `_.has` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ +function baseHas(object, key) { + return object != null && hasOwnProperty.call(object, key); +} + +module.exports = baseHas; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseHasIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseHasIn.js new file mode 100644 index 000000000..2e0d04269 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseHasIn.js @@ -0,0 +1,13 @@ +/** + * The base implementation of `_.hasIn` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ +function baseHasIn(object, key) { + return object != null && key in Object(object); +} + +module.exports = baseHasIn; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseInRange.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseInRange.js new file mode 100644 index 000000000..ec9566618 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseInRange.js @@ -0,0 +1,18 @@ +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max, + nativeMin = Math.min; + +/** + * The base implementation of `_.inRange` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to check. + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + */ +function baseInRange(number, start, end) { + return number >= nativeMin(start, end) && number < nativeMax(start, end); +} + +module.exports = baseInRange; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIndexOf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIndexOf.js new file mode 100644 index 000000000..167e706e7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIndexOf.js @@ -0,0 +1,20 @@ +var baseFindIndex = require('./_baseFindIndex'), + baseIsNaN = require('./_baseIsNaN'), + strictIndexOf = require('./_strictIndexOf'); + +/** + * The base implementation of `_.indexOf` without `fromIndex` bounds checks. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseIndexOf(array, value, fromIndex) { + return value === value + ? strictIndexOf(array, value, fromIndex) + : baseFindIndex(array, baseIsNaN, fromIndex); +} + +module.exports = baseIndexOf; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIndexOfWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIndexOfWith.js new file mode 100644 index 000000000..f815fe0dd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIndexOfWith.js @@ -0,0 +1,23 @@ +/** + * This function is like `baseIndexOf` except that it accepts a comparator. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @param {Function} comparator The comparator invoked per element. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseIndexOfWith(array, value, fromIndex, comparator) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (comparator(array[index], value)) { + return index; + } + } + return -1; +} + +module.exports = baseIndexOfWith; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIntersection.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIntersection.js new file mode 100644 index 000000000..c1d250c2a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIntersection.js @@ -0,0 +1,74 @@ +var SetCache = require('./_SetCache'), + arrayIncludes = require('./_arrayIncludes'), + arrayIncludesWith = require('./_arrayIncludesWith'), + arrayMap = require('./_arrayMap'), + baseUnary = require('./_baseUnary'), + cacheHas = require('./_cacheHas'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMin = Math.min; + +/** + * The base implementation of methods like `_.intersection`, without support + * for iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of shared values. + */ +function baseIntersection(arrays, iteratee, comparator) { + var includes = comparator ? arrayIncludesWith : arrayIncludes, + length = arrays[0].length, + othLength = arrays.length, + othIndex = othLength, + caches = Array(othLength), + maxLength = Infinity, + result = []; + + while (othIndex--) { + var array = arrays[othIndex]; + if (othIndex && iteratee) { + array = arrayMap(array, baseUnary(iteratee)); + } + maxLength = nativeMin(array.length, maxLength); + caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120)) + ? new SetCache(othIndex && array) + : undefined; + } + array = arrays[0]; + + var index = -1, + seen = caches[0]; + + outer: + while (++index < length && result.length < maxLength) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (!(seen + ? cacheHas(seen, computed) + : includes(result, computed, comparator) + )) { + othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if (!(cache + ? cacheHas(cache, computed) + : includes(arrays[othIndex], computed, comparator)) + ) { + continue outer; + } + } + if (seen) { + seen.push(computed); + } + result.push(value); + } + } + return result; +} + +module.exports = baseIntersection; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseInverter.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseInverter.js new file mode 100644 index 000000000..fbc337f01 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseInverter.js @@ -0,0 +1,21 @@ +var baseForOwn = require('./_baseForOwn'); + +/** + * The base implementation of `_.invert` and `_.invertBy` which inverts + * `object` with values transformed by `iteratee` and set by `setter`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform values. + * @param {Object} accumulator The initial inverted object. + * @returns {Function} Returns `accumulator`. + */ +function baseInverter(object, setter, iteratee, accumulator) { + baseForOwn(object, function(value, key, object) { + setter(accumulator, iteratee(value), key, object); + }); + return accumulator; +} + +module.exports = baseInverter; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseInvoke.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseInvoke.js new file mode 100644 index 000000000..49bcf3c35 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseInvoke.js @@ -0,0 +1,24 @@ +var apply = require('./_apply'), + castPath = require('./_castPath'), + last = require('./last'), + parent = require('./_parent'), + toKey = require('./_toKey'); + +/** + * The base implementation of `_.invoke` without support for individual + * method arguments. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {Array} args The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + */ +function baseInvoke(object, path, args) { + path = castPath(path, object); + object = parent(object, path); + var func = object == null ? object : object[toKey(last(path))]; + return func == null ? undefined : apply(func, object, args); +} + +module.exports = baseInvoke; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsArguments.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsArguments.js new file mode 100644 index 000000000..b3562cca2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsArguments.js @@ -0,0 +1,18 @@ +var baseGetTag = require('./_baseGetTag'), + isObjectLike = require('./isObjectLike'); + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]'; + +/** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ +function baseIsArguments(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; +} + +module.exports = baseIsArguments; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsArrayBuffer.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsArrayBuffer.js new file mode 100644 index 000000000..a2c4f30a8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsArrayBuffer.js @@ -0,0 +1,17 @@ +var baseGetTag = require('./_baseGetTag'), + isObjectLike = require('./isObjectLike'); + +var arrayBufferTag = '[object ArrayBuffer]'; + +/** + * The base implementation of `_.isArrayBuffer` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + */ +function baseIsArrayBuffer(value) { + return isObjectLike(value) && baseGetTag(value) == arrayBufferTag; +} + +module.exports = baseIsArrayBuffer; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsDate.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsDate.js new file mode 100644 index 000000000..ba67c7857 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsDate.js @@ -0,0 +1,18 @@ +var baseGetTag = require('./_baseGetTag'), + isObjectLike = require('./isObjectLike'); + +/** `Object#toString` result references. */ +var dateTag = '[object Date]'; + +/** + * The base implementation of `_.isDate` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + */ +function baseIsDate(value) { + return isObjectLike(value) && baseGetTag(value) == dateTag; +} + +module.exports = baseIsDate; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsEqual.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsEqual.js new file mode 100644 index 000000000..00a68a4f5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsEqual.js @@ -0,0 +1,28 @@ +var baseIsEqualDeep = require('./_baseIsEqualDeep'), + isObjectLike = require('./isObjectLike'); + +/** + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {boolean} bitmask The bitmask flags. + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Function} [customizer] The function to customize comparisons. + * @param {Object} [stack] Tracks traversed `value` and `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ +function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); +} + +module.exports = baseIsEqual; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsEqualDeep.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsEqualDeep.js new file mode 100644 index 000000000..e3cfd6a8d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsEqualDeep.js @@ -0,0 +1,83 @@ +var Stack = require('./_Stack'), + equalArrays = require('./_equalArrays'), + equalByTag = require('./_equalByTag'), + equalObjects = require('./_equalObjects'), + getTag = require('./_getTag'), + isArray = require('./isArray'), + isBuffer = require('./isBuffer'), + isTypedArray = require('./isTypedArray'); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + objectTag = '[object Object]'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ +function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = objIsArr ? arrayTag : getTag(object), + othTag = othIsArr ? arrayTag : getTag(other); + + objTag = objTag == argsTag ? objectTag : objTag; + othTag = othTag == argsTag ? objectTag : othTag; + + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, + isSameTag = objTag == othTag; + + if (isSameTag && isBuffer(object)) { + if (!isBuffer(other)) { + return false; + } + objIsArr = true; + objIsObj = false; + } + if (isSameTag && !objIsObj) { + stack || (stack = new Stack); + return (objIsArr || isTypedArray(object)) + ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) + : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); + } + if (!(bitmask & COMPARE_PARTIAL_FLAG)) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + stack || (stack = new Stack); + return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack); + return equalObjects(object, other, bitmask, customizer, equalFunc, stack); +} + +module.exports = baseIsEqualDeep; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsMap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsMap.js new file mode 100644 index 000000000..02a4021ca --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsMap.js @@ -0,0 +1,18 @@ +var getTag = require('./_getTag'), + isObjectLike = require('./isObjectLike'); + +/** `Object#toString` result references. */ +var mapTag = '[object Map]'; + +/** + * The base implementation of `_.isMap` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + */ +function baseIsMap(value) { + return isObjectLike(value) && getTag(value) == mapTag; +} + +module.exports = baseIsMap; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsMatch.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsMatch.js new file mode 100644 index 000000000..72494bed4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsMatch.js @@ -0,0 +1,62 @@ +var Stack = require('./_Stack'), + baseIsEqual = require('./_baseIsEqual'); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + +/** + * The base implementation of `_.isMatch` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Array} matchData The property names, values, and compare flags to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + */ +function baseIsMatch(object, source, matchData, customizer) { + var index = matchData.length, + length = index, + noCustomizer = !customizer; + + if (object == null) { + return !length; + } + object = Object(object); + while (index--) { + var data = matchData[index]; + if ((noCustomizer && data[2]) + ? data[1] !== object[data[0]] + : !(data[0] in object) + ) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], + objValue = object[key], + srcValue = data[1]; + + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var stack = new Stack; + if (customizer) { + var result = customizer(objValue, srcValue, key, object, source, stack); + } + if (!(result === undefined + ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) + : result + )) { + return false; + } + } + } + return true; +} + +module.exports = baseIsMatch; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsNaN.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsNaN.js new file mode 100644 index 000000000..316f1eb1e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsNaN.js @@ -0,0 +1,12 @@ +/** + * The base implementation of `_.isNaN` without support for number objects. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + */ +function baseIsNaN(value) { + return value !== value; +} + +module.exports = baseIsNaN; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsNative.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsNative.js new file mode 100644 index 000000000..870233049 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsNative.js @@ -0,0 +1,47 @@ +var isFunction = require('./isFunction'), + isMasked = require('./_isMasked'), + isObject = require('./isObject'), + toSource = require('./_toSource'); + +/** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ +var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; + +/** Used to detect host constructors (Safari). */ +var reIsHostCtor = /^\[object .+?Constructor\]$/; + +/** Used for built-in method references. */ +var funcProto = Function.prototype, + objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' +); + +/** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ +function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); +} + +module.exports = baseIsNative; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsRegExp.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsRegExp.js new file mode 100644 index 000000000..6cd7c1aee --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsRegExp.js @@ -0,0 +1,18 @@ +var baseGetTag = require('./_baseGetTag'), + isObjectLike = require('./isObjectLike'); + +/** `Object#toString` result references. */ +var regexpTag = '[object RegExp]'; + +/** + * The base implementation of `_.isRegExp` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + */ +function baseIsRegExp(value) { + return isObjectLike(value) && baseGetTag(value) == regexpTag; +} + +module.exports = baseIsRegExp; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsSet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsSet.js new file mode 100644 index 000000000..6dee36716 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsSet.js @@ -0,0 +1,18 @@ +var getTag = require('./_getTag'), + isObjectLike = require('./isObjectLike'); + +/** `Object#toString` result references. */ +var setTag = '[object Set]'; + +/** + * The base implementation of `_.isSet` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + */ +function baseIsSet(value) { + return isObjectLike(value) && getTag(value) == setTag; +} + +module.exports = baseIsSet; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsTypedArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsTypedArray.js new file mode 100644 index 000000000..1edb32ff3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIsTypedArray.js @@ -0,0 +1,60 @@ +var baseGetTag = require('./_baseGetTag'), + isLength = require('./isLength'), + isObjectLike = require('./isObjectLike'); + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + weakMapTag = '[object WeakMap]'; + +var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + +/** Used to identify `toStringTag` values of typed arrays. */ +var typedArrayTags = {}; +typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = +typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = +typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = +typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = +typedArrayTags[uint32Tag] = true; +typedArrayTags[argsTag] = typedArrayTags[arrayTag] = +typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = +typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = +typedArrayTags[errorTag] = typedArrayTags[funcTag] = +typedArrayTags[mapTag] = typedArrayTags[numberTag] = +typedArrayTags[objectTag] = typedArrayTags[regexpTag] = +typedArrayTags[setTag] = typedArrayTags[stringTag] = +typedArrayTags[weakMapTag] = false; + +/** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ +function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; +} + +module.exports = baseIsTypedArray; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIteratee.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIteratee.js new file mode 100644 index 000000000..995c25756 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseIteratee.js @@ -0,0 +1,31 @@ +var baseMatches = require('./_baseMatches'), + baseMatchesProperty = require('./_baseMatchesProperty'), + identity = require('./identity'), + isArray = require('./isArray'), + property = require('./property'); + +/** + * The base implementation of `_.iteratee`. + * + * @private + * @param {*} [value=_.identity] The value to convert to an iteratee. + * @returns {Function} Returns the iteratee. + */ +function baseIteratee(value) { + // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. + // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. + if (typeof value == 'function') { + return value; + } + if (value == null) { + return identity; + } + if (typeof value == 'object') { + return isArray(value) + ? baseMatchesProperty(value[0], value[1]) + : baseMatches(value); + } + return property(value); +} + +module.exports = baseIteratee; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseKeys.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseKeys.js new file mode 100644 index 000000000..45e9e6f39 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseKeys.js @@ -0,0 +1,30 @@ +var isPrototype = require('./_isPrototype'), + nativeKeys = require('./_nativeKeys'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; +} + +module.exports = baseKeys; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseKeysIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseKeysIn.js new file mode 100644 index 000000000..ea8a0a174 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseKeysIn.js @@ -0,0 +1,33 @@ +var isObject = require('./isObject'), + isPrototype = require('./_isPrototype'), + nativeKeysIn = require('./_nativeKeysIn'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function baseKeysIn(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; +} + +module.exports = baseKeysIn; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseLodash.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseLodash.js new file mode 100644 index 000000000..f76c790e2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseLodash.js @@ -0,0 +1,10 @@ +/** + * The function whose prototype chain sequence wrappers inherit from. + * + * @private + */ +function baseLodash() { + // No operation performed. +} + +module.exports = baseLodash; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseLt.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseLt.js new file mode 100644 index 000000000..8674d2946 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseLt.js @@ -0,0 +1,14 @@ +/** + * The base implementation of `_.lt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + */ +function baseLt(value, other) { + return value < other; +} + +module.exports = baseLt; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMap.js new file mode 100644 index 000000000..0bf5cead5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMap.js @@ -0,0 +1,22 @@ +var baseEach = require('./_baseEach'), + isArrayLike = require('./isArrayLike'); + +/** + * The base implementation of `_.map` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ +function baseMap(collection, iteratee) { + var index = -1, + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; +} + +module.exports = baseMap; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMatches.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMatches.js new file mode 100644 index 000000000..e56582ad8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMatches.js @@ -0,0 +1,22 @@ +var baseIsMatch = require('./_baseIsMatch'), + getMatchData = require('./_getMatchData'), + matchesStrictComparable = require('./_matchesStrictComparable'); + +/** + * The base implementation of `_.matches` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new spec function. + */ +function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + return matchesStrictComparable(matchData[0][0], matchData[0][1]); + } + return function(object) { + return object === source || baseIsMatch(object, source, matchData); + }; +} + +module.exports = baseMatches; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMatchesProperty.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMatchesProperty.js new file mode 100644 index 000000000..24afd893d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMatchesProperty.js @@ -0,0 +1,33 @@ +var baseIsEqual = require('./_baseIsEqual'), + get = require('./get'), + hasIn = require('./hasIn'), + isKey = require('./_isKey'), + isStrictComparable = require('./_isStrictComparable'), + matchesStrictComparable = require('./_matchesStrictComparable'), + toKey = require('./_toKey'); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + +/** + * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. + * + * @private + * @param {string} path The path of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ +function baseMatchesProperty(path, srcValue) { + if (isKey(path) && isStrictComparable(srcValue)) { + return matchesStrictComparable(toKey(path), srcValue); + } + return function(object) { + var objValue = get(object, path); + return (objValue === undefined && objValue === srcValue) + ? hasIn(object, path) + : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG); + }; +} + +module.exports = baseMatchesProperty; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMean.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMean.js new file mode 100644 index 000000000..fa9e00a0a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMean.js @@ -0,0 +1,20 @@ +var baseSum = require('./_baseSum'); + +/** Used as references for various `Number` constants. */ +var NAN = 0 / 0; + +/** + * The base implementation of `_.mean` and `_.meanBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the mean. + */ +function baseMean(array, iteratee) { + var length = array == null ? 0 : array.length; + return length ? (baseSum(array, iteratee) / length) : NAN; +} + +module.exports = baseMean; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMerge.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMerge.js new file mode 100644 index 000000000..c98b5eb0b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMerge.js @@ -0,0 +1,42 @@ +var Stack = require('./_Stack'), + assignMergeValue = require('./_assignMergeValue'), + baseFor = require('./_baseFor'), + baseMergeDeep = require('./_baseMergeDeep'), + isObject = require('./isObject'), + keysIn = require('./keysIn'), + safeGet = require('./_safeGet'); + +/** + * The base implementation of `_.merge` without support for multiple sources. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {number} srcIndex The index of `source`. + * @param {Function} [customizer] The function to customize merged values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ +function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + baseFor(source, function(srcValue, key) { + stack || (stack = new Stack); + if (isObject(srcValue)) { + baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); + } + else { + var newValue = customizer + ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack) + : undefined; + + if (newValue === undefined) { + newValue = srcValue; + } + assignMergeValue(object, key, newValue); + } + }, keysIn); +} + +module.exports = baseMerge; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMergeDeep.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMergeDeep.js new file mode 100644 index 000000000..4679e8dce --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseMergeDeep.js @@ -0,0 +1,94 @@ +var assignMergeValue = require('./_assignMergeValue'), + cloneBuffer = require('./_cloneBuffer'), + cloneTypedArray = require('./_cloneTypedArray'), + copyArray = require('./_copyArray'), + initCloneObject = require('./_initCloneObject'), + isArguments = require('./isArguments'), + isArray = require('./isArray'), + isArrayLikeObject = require('./isArrayLikeObject'), + isBuffer = require('./isBuffer'), + isFunction = require('./isFunction'), + isObject = require('./isObject'), + isPlainObject = require('./isPlainObject'), + isTypedArray = require('./isTypedArray'), + safeGet = require('./_safeGet'), + toPlainObject = require('./toPlainObject'); + +/** + * A specialized version of `baseMerge` for arrays and objects which performs + * deep merges and tracks traversed objects enabling objects with circular + * references to be merged. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {string} key The key of the value to merge. + * @param {number} srcIndex The index of `source`. + * @param {Function} mergeFunc The function to merge values. + * @param {Function} [customizer] The function to customize assigned values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ +function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = safeGet(object, key), + srcValue = safeGet(source, key), + stacked = stack.get(srcValue); + + if (stacked) { + assignMergeValue(object, key, stacked); + return; + } + var newValue = customizer + ? customizer(objValue, srcValue, (key + ''), object, source, stack) + : undefined; + + var isCommon = newValue === undefined; + + if (isCommon) { + var isArr = isArray(srcValue), + isBuff = !isArr && isBuffer(srcValue), + isTyped = !isArr && !isBuff && isTypedArray(srcValue); + + newValue = srcValue; + if (isArr || isBuff || isTyped) { + if (isArray(objValue)) { + newValue = objValue; + } + else if (isArrayLikeObject(objValue)) { + newValue = copyArray(objValue); + } + else if (isBuff) { + isCommon = false; + newValue = cloneBuffer(srcValue, true); + } + else if (isTyped) { + isCommon = false; + newValue = cloneTypedArray(srcValue, true); + } + else { + newValue = []; + } + } + else if (isPlainObject(srcValue) || isArguments(srcValue)) { + newValue = objValue; + if (isArguments(objValue)) { + newValue = toPlainObject(objValue); + } + else if (!isObject(objValue) || isFunction(objValue)) { + newValue = initCloneObject(srcValue); + } + } + else { + isCommon = false; + } + } + if (isCommon) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, newValue); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack['delete'](srcValue); + } + assignMergeValue(object, key, newValue); +} + +module.exports = baseMergeDeep; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseNth.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseNth.js new file mode 100644 index 000000000..0403c2a36 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseNth.js @@ -0,0 +1,20 @@ +var isIndex = require('./_isIndex'); + +/** + * The base implementation of `_.nth` which doesn't coerce arguments. + * + * @private + * @param {Array} array The array to query. + * @param {number} n The index of the element to return. + * @returns {*} Returns the nth element of `array`. + */ +function baseNth(array, n) { + var length = array.length; + if (!length) { + return; + } + n += n < 0 ? length : 0; + return isIndex(n, length) ? array[n] : undefined; +} + +module.exports = baseNth; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseOrderBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseOrderBy.js new file mode 100644 index 000000000..775a01741 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseOrderBy.js @@ -0,0 +1,49 @@ +var arrayMap = require('./_arrayMap'), + baseGet = require('./_baseGet'), + baseIteratee = require('./_baseIteratee'), + baseMap = require('./_baseMap'), + baseSortBy = require('./_baseSortBy'), + baseUnary = require('./_baseUnary'), + compareMultiple = require('./_compareMultiple'), + identity = require('./identity'), + isArray = require('./isArray'); + +/** + * The base implementation of `_.orderBy` without param guards. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. + * @param {string[]} orders The sort orders of `iteratees`. + * @returns {Array} Returns the new sorted array. + */ +function baseOrderBy(collection, iteratees, orders) { + if (iteratees.length) { + iteratees = arrayMap(iteratees, function(iteratee) { + if (isArray(iteratee)) { + return function(value) { + return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee); + } + } + return iteratee; + }); + } else { + iteratees = [identity]; + } + + var index = -1; + iteratees = arrayMap(iteratees, baseUnary(baseIteratee)); + + var result = baseMap(collection, function(value, key, collection) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { 'criteria': criteria, 'index': ++index, 'value': value }; + }); + + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); +} + +module.exports = baseOrderBy; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePick.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePick.js new file mode 100644 index 000000000..09b458a60 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePick.js @@ -0,0 +1,19 @@ +var basePickBy = require('./_basePickBy'), + hasIn = require('./hasIn'); + +/** + * The base implementation of `_.pick` without support for individual + * property identifiers. + * + * @private + * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. + * @returns {Object} Returns the new object. + */ +function basePick(object, paths) { + return basePickBy(object, paths, function(value, path) { + return hasIn(object, path); + }); +} + +module.exports = basePick; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePickBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePickBy.js new file mode 100644 index 000000000..85be68c84 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePickBy.js @@ -0,0 +1,30 @@ +var baseGet = require('./_baseGet'), + baseSet = require('./_baseSet'), + castPath = require('./_castPath'); + +/** + * The base implementation of `_.pickBy` without support for iteratee shorthands. + * + * @private + * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. + * @param {Function} predicate The function invoked per property. + * @returns {Object} Returns the new object. + */ +function basePickBy(object, paths, predicate) { + var index = -1, + length = paths.length, + result = {}; + + while (++index < length) { + var path = paths[index], + value = baseGet(object, path); + + if (predicate(value, path)) { + baseSet(result, castPath(path, object), value); + } + } + return result; +} + +module.exports = basePickBy; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseProperty.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseProperty.js new file mode 100644 index 000000000..496281ec4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseProperty.js @@ -0,0 +1,14 @@ +/** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new accessor function. + */ +function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; +} + +module.exports = baseProperty; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePropertyDeep.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePropertyDeep.js new file mode 100644 index 000000000..1e5aae50c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePropertyDeep.js @@ -0,0 +1,16 @@ +var baseGet = require('./_baseGet'); + +/** + * A specialized version of `baseProperty` which supports deep paths. + * + * @private + * @param {Array|string} path The path of the property to get. + * @returns {Function} Returns the new accessor function. + */ +function basePropertyDeep(path) { + return function(object) { + return baseGet(object, path); + }; +} + +module.exports = basePropertyDeep; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePropertyOf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePropertyOf.js new file mode 100644 index 000000000..461739990 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePropertyOf.js @@ -0,0 +1,14 @@ +/** + * The base implementation of `_.propertyOf` without support for deep paths. + * + * @private + * @param {Object} object The object to query. + * @returns {Function} Returns the new accessor function. + */ +function basePropertyOf(object) { + return function(key) { + return object == null ? undefined : object[key]; + }; +} + +module.exports = basePropertyOf; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePullAll.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePullAll.js new file mode 100644 index 000000000..305720ede --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePullAll.js @@ -0,0 +1,51 @@ +var arrayMap = require('./_arrayMap'), + baseIndexOf = require('./_baseIndexOf'), + baseIndexOfWith = require('./_baseIndexOfWith'), + baseUnary = require('./_baseUnary'), + copyArray = require('./_copyArray'); + +/** Used for built-in method references. */ +var arrayProto = Array.prototype; + +/** Built-in value references. */ +var splice = arrayProto.splice; + +/** + * The base implementation of `_.pullAllBy` without support for iteratee + * shorthands. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + */ +function basePullAll(array, values, iteratee, comparator) { + var indexOf = comparator ? baseIndexOfWith : baseIndexOf, + index = -1, + length = values.length, + seen = array; + + if (array === values) { + values = copyArray(values); + } + if (iteratee) { + seen = arrayMap(array, baseUnary(iteratee)); + } + while (++index < length) { + var fromIndex = 0, + value = values[index], + computed = iteratee ? iteratee(value) : value; + + while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { + if (seen !== array) { + splice.call(seen, fromIndex, 1); + } + splice.call(array, fromIndex, 1); + } + } + return array; +} + +module.exports = basePullAll; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePullAt.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePullAt.js new file mode 100644 index 000000000..c3e9e7102 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_basePullAt.js @@ -0,0 +1,37 @@ +var baseUnset = require('./_baseUnset'), + isIndex = require('./_isIndex'); + +/** Used for built-in method references. */ +var arrayProto = Array.prototype; + +/** Built-in value references. */ +var splice = arrayProto.splice; + +/** + * The base implementation of `_.pullAt` without support for individual + * indexes or capturing the removed elements. + * + * @private + * @param {Array} array The array to modify. + * @param {number[]} indexes The indexes of elements to remove. + * @returns {Array} Returns `array`. + */ +function basePullAt(array, indexes) { + var length = array ? indexes.length : 0, + lastIndex = length - 1; + + while (length--) { + var index = indexes[length]; + if (length == lastIndex || index !== previous) { + var previous = index; + if (isIndex(index)) { + splice.call(array, index, 1); + } else { + baseUnset(array, index); + } + } + } + return array; +} + +module.exports = basePullAt; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRandom.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRandom.js new file mode 100644 index 000000000..94f76a766 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRandom.js @@ -0,0 +1,18 @@ +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeFloor = Math.floor, + nativeRandom = Math.random; + +/** + * The base implementation of `_.random` without support for returning + * floating-point numbers. + * + * @private + * @param {number} lower The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the random number. + */ +function baseRandom(lower, upper) { + return lower + nativeFloor(nativeRandom() * (upper - lower + 1)); +} + +module.exports = baseRandom; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRange.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRange.js new file mode 100644 index 000000000..0fb8e419f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRange.js @@ -0,0 +1,28 @@ +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeCeil = Math.ceil, + nativeMax = Math.max; + +/** + * The base implementation of `_.range` and `_.rangeRight` which doesn't + * coerce arguments. + * + * @private + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @param {number} step The value to increment or decrement by. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the range of numbers. + */ +function baseRange(start, end, step, fromRight) { + var index = -1, + length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), + result = Array(length); + + while (length--) { + result[fromRight ? length : ++index] = start; + start += step; + } + return result; +} + +module.exports = baseRange; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseReduce.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseReduce.js new file mode 100644 index 000000000..5a1f8b57f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseReduce.js @@ -0,0 +1,23 @@ +/** + * The base implementation of `_.reduce` and `_.reduceRight`, without support + * for iteratee shorthands, which iterates over `collection` using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} accumulator The initial value. + * @param {boolean} initAccum Specify using the first or last element of + * `collection` as the initial value. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the accumulated value. + */ +function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initAccum + ? (initAccum = false, value) + : iteratee(accumulator, value, index, collection); + }); + return accumulator; +} + +module.exports = baseReduce; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRepeat.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRepeat.js new file mode 100644 index 000000000..ee44c31ab --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRepeat.js @@ -0,0 +1,35 @@ +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeFloor = Math.floor; + +/** + * The base implementation of `_.repeat` which doesn't coerce arguments. + * + * @private + * @param {string} string The string to repeat. + * @param {number} n The number of times to repeat the string. + * @returns {string} Returns the repeated string. + */ +function baseRepeat(string, n) { + var result = ''; + if (!string || n < 1 || n > MAX_SAFE_INTEGER) { + return result; + } + // Leverage the exponentiation by squaring algorithm for a faster repeat. + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + if (n) { + string += string; + } + } while (n); + + return result; +} + +module.exports = baseRepeat; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRest.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRest.js new file mode 100644 index 000000000..d0dc4bdd1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseRest.js @@ -0,0 +1,17 @@ +var identity = require('./identity'), + overRest = require('./_overRest'), + setToString = require('./_setToString'); + +/** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ +function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ''); +} + +module.exports = baseRest; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSample.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSample.js new file mode 100644 index 000000000..58582b911 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSample.js @@ -0,0 +1,15 @@ +var arraySample = require('./_arraySample'), + values = require('./values'); + +/** + * The base implementation of `_.sample`. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + */ +function baseSample(collection) { + return arraySample(values(collection)); +} + +module.exports = baseSample; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSampleSize.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSampleSize.js new file mode 100644 index 000000000..5c90ec518 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSampleSize.js @@ -0,0 +1,18 @@ +var baseClamp = require('./_baseClamp'), + shuffleSelf = require('./_shuffleSelf'), + values = require('./values'); + +/** + * The base implementation of `_.sampleSize` without param guards. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ +function baseSampleSize(collection, n) { + var array = values(collection); + return shuffleSelf(array, baseClamp(n, 0, array.length)); +} + +module.exports = baseSampleSize; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSet.js new file mode 100644 index 000000000..99f4fbf9c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSet.js @@ -0,0 +1,51 @@ +var assignValue = require('./_assignValue'), + castPath = require('./_castPath'), + isIndex = require('./_isIndex'), + isObject = require('./isObject'), + toKey = require('./_toKey'); + +/** + * The base implementation of `_.set`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ +function baseSet(object, path, value, customizer) { + if (!isObject(object)) { + return object; + } + path = castPath(path, object); + + var index = -1, + length = path.length, + lastIndex = length - 1, + nested = object; + + while (nested != null && ++index < length) { + var key = toKey(path[index]), + newValue = value; + + if (key === '__proto__' || key === 'constructor' || key === 'prototype') { + return object; + } + + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : undefined; + if (newValue === undefined) { + newValue = isObject(objValue) + ? objValue + : (isIndex(path[index + 1]) ? [] : {}); + } + } + assignValue(nested, key, newValue); + nested = nested[key]; + } + return object; +} + +module.exports = baseSet; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSetData.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSetData.js new file mode 100644 index 000000000..c409947dd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSetData.js @@ -0,0 +1,17 @@ +var identity = require('./identity'), + metaMap = require('./_metaMap'); + +/** + * The base implementation of `setData` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ +var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; +}; + +module.exports = baseSetData; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSetToString.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSetToString.js new file mode 100644 index 000000000..89eaca38d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSetToString.js @@ -0,0 +1,22 @@ +var constant = require('./constant'), + defineProperty = require('./_defineProperty'), + identity = require('./identity'); + +/** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ +var baseSetToString = !defineProperty ? identity : function(func, string) { + return defineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant(string), + 'writable': true + }); +}; + +module.exports = baseSetToString; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseShuffle.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseShuffle.js new file mode 100644 index 000000000..023077ac4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseShuffle.js @@ -0,0 +1,15 @@ +var shuffleSelf = require('./_shuffleSelf'), + values = require('./values'); + +/** + * The base implementation of `_.shuffle`. + * + * @private + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + */ +function baseShuffle(collection) { + return shuffleSelf(values(collection)); +} + +module.exports = baseShuffle; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSlice.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSlice.js new file mode 100644 index 000000000..786f6c99e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSlice.js @@ -0,0 +1,31 @@ +/** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ +function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; +} + +module.exports = baseSlice; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSome.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSome.js new file mode 100644 index 000000000..58f3f447a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSome.js @@ -0,0 +1,22 @@ +var baseEach = require('./_baseEach'); + +/** + * The base implementation of `_.some` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ +function baseSome(collection, predicate) { + var result; + + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; +} + +module.exports = baseSome; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortBy.js new file mode 100644 index 000000000..a25c92eda --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortBy.js @@ -0,0 +1,21 @@ +/** + * The base implementation of `_.sortBy` which uses `comparer` to define the + * sort order of `array` and replaces criteria objects with their corresponding + * values. + * + * @private + * @param {Array} array The array to sort. + * @param {Function} comparer The function to define sort order. + * @returns {Array} Returns `array`. + */ +function baseSortBy(array, comparer) { + var length = array.length; + + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; +} + +module.exports = baseSortBy; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortedIndex.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortedIndex.js new file mode 100644 index 000000000..638c366c7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortedIndex.js @@ -0,0 +1,42 @@ +var baseSortedIndexBy = require('./_baseSortedIndexBy'), + identity = require('./identity'), + isSymbol = require('./isSymbol'); + +/** Used as references for the maximum length and index of an array. */ +var MAX_ARRAY_LENGTH = 4294967295, + HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + +/** + * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which + * performs a binary search of `array` to determine the index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ +function baseSortedIndex(array, value, retHighest) { + var low = 0, + high = array == null ? low : array.length; + + if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = (low + high) >>> 1, + computed = array[mid]; + + if (computed !== null && !isSymbol(computed) && + (retHighest ? (computed <= value) : (computed < value))) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return baseSortedIndexBy(array, value, identity, retHighest); +} + +module.exports = baseSortedIndex; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortedIndexBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortedIndexBy.js new file mode 100644 index 000000000..c247b377f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortedIndexBy.js @@ -0,0 +1,67 @@ +var isSymbol = require('./isSymbol'); + +/** Used as references for the maximum length and index of an array. */ +var MAX_ARRAY_LENGTH = 4294967295, + MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeFloor = Math.floor, + nativeMin = Math.min; + +/** + * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy` + * which invokes `iteratee` for `value` and each element of `array` to compute + * their sort ranking. The iteratee is invoked with one argument; (value). + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} iteratee The iteratee invoked per element. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ +function baseSortedIndexBy(array, value, iteratee, retHighest) { + var low = 0, + high = array == null ? 0 : array.length; + if (high === 0) { + return 0; + } + + value = iteratee(value); + var valIsNaN = value !== value, + valIsNull = value === null, + valIsSymbol = isSymbol(value), + valIsUndefined = value === undefined; + + while (low < high) { + var mid = nativeFloor((low + high) / 2), + computed = iteratee(array[mid]), + othIsDefined = computed !== undefined, + othIsNull = computed === null, + othIsReflexive = computed === computed, + othIsSymbol = isSymbol(computed); + + if (valIsNaN) { + var setLow = retHighest || othIsReflexive; + } else if (valIsUndefined) { + setLow = othIsReflexive && (retHighest || othIsDefined); + } else if (valIsNull) { + setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull); + } else if (valIsSymbol) { + setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol); + } else if (othIsNull || othIsSymbol) { + setLow = false; + } else { + setLow = retHighest ? (computed <= value) : (computed < value); + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); +} + +module.exports = baseSortedIndexBy; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortedUniq.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortedUniq.js new file mode 100644 index 000000000..802159a3d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSortedUniq.js @@ -0,0 +1,30 @@ +var eq = require('./eq'); + +/** + * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ +function baseSortedUniq(array, iteratee) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + if (!index || !eq(computed, seen)) { + var seen = computed; + result[resIndex++] = value === 0 ? 0 : value; + } + } + return result; +} + +module.exports = baseSortedUniq; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSum.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSum.js new file mode 100644 index 000000000..a9e84c13c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseSum.js @@ -0,0 +1,24 @@ +/** + * The base implementation of `_.sum` and `_.sumBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the sum. + */ +function baseSum(array, iteratee) { + var result, + index = -1, + length = array.length; + + while (++index < length) { + var current = iteratee(array[index]); + if (current !== undefined) { + result = result === undefined ? current : (result + current); + } + } + return result; +} + +module.exports = baseSum; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseTimes.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseTimes.js new file mode 100644 index 000000000..0603fc37e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseTimes.js @@ -0,0 +1,20 @@ +/** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ +function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; +} + +module.exports = baseTimes; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseToNumber.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseToNumber.js new file mode 100644 index 000000000..04859f391 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseToNumber.js @@ -0,0 +1,24 @@ +var isSymbol = require('./isSymbol'); + +/** Used as references for various `Number` constants. */ +var NAN = 0 / 0; + +/** + * The base implementation of `_.toNumber` which doesn't ensure correct + * conversions of binary, hexadecimal, or octal string values. + * + * @private + * @param {*} value The value to process. + * @returns {number} Returns the number. + */ +function baseToNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + return +value; +} + +module.exports = baseToNumber; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseToPairs.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseToPairs.js new file mode 100644 index 000000000..bff199128 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseToPairs.js @@ -0,0 +1,18 @@ +var arrayMap = require('./_arrayMap'); + +/** + * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array + * of key-value pairs for `object` corresponding to the property names of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the key-value pairs. + */ +function baseToPairs(object, props) { + return arrayMap(props, function(key) { + return [key, object[key]]; + }); +} + +module.exports = baseToPairs; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseToString.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseToString.js new file mode 100644 index 000000000..ada6ad298 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseToString.js @@ -0,0 +1,37 @@ +var Symbol = require('./_Symbol'), + arrayMap = require('./_arrayMap'), + isArray = require('./isArray'), + isSymbol = require('./isSymbol'); + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + +/** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ +function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray(value)) { + // Recursively convert values (susceptible to call stack limits). + return arrayMap(value, baseToString) + ''; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + +module.exports = baseToString; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseTrim.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseTrim.js new file mode 100644 index 000000000..3e2797d99 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseTrim.js @@ -0,0 +1,19 @@ +var trimmedEndIndex = require('./_trimmedEndIndex'); + +/** Used to match leading whitespace. */ +var reTrimStart = /^\s+/; + +/** + * The base implementation of `_.trim`. + * + * @private + * @param {string} string The string to trim. + * @returns {string} Returns the trimmed string. + */ +function baseTrim(string) { + return string + ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') + : string; +} + +module.exports = baseTrim; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUnary.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUnary.js new file mode 100644 index 000000000..98639e92f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUnary.js @@ -0,0 +1,14 @@ +/** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ +function baseUnary(func) { + return function(value) { + return func(value); + }; +} + +module.exports = baseUnary; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUniq.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUniq.js new file mode 100644 index 000000000..aea459dc7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUniq.js @@ -0,0 +1,72 @@ +var SetCache = require('./_SetCache'), + arrayIncludes = require('./_arrayIncludes'), + arrayIncludesWith = require('./_arrayIncludesWith'), + cacheHas = require('./_cacheHas'), + createSet = require('./_createSet'), + setToArray = require('./_setToArray'); + +/** Used as the size to enable large array optimizations. */ +var LARGE_ARRAY_SIZE = 200; + +/** + * The base implementation of `_.uniqBy` without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ +function baseUniq(array, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + length = array.length, + isCommon = true, + result = [], + seen = result; + + if (comparator) { + isCommon = false; + includes = arrayIncludesWith; + } + else if (length >= LARGE_ARRAY_SIZE) { + var set = iteratee ? null : createSet(array); + if (set) { + return setToArray(set); + } + isCommon = false; + includes = cacheHas; + seen = new SetCache; + } + else { + seen = iteratee ? [] : result; + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } + else if (!includes(seen, computed, comparator)) { + if (seen !== result) { + seen.push(computed); + } + result.push(value); + } + } + return result; +} + +module.exports = baseUniq; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUnset.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUnset.js new file mode 100644 index 000000000..eefc6e37d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUnset.js @@ -0,0 +1,20 @@ +var castPath = require('./_castPath'), + last = require('./last'), + parent = require('./_parent'), + toKey = require('./_toKey'); + +/** + * The base implementation of `_.unset`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The property path to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + */ +function baseUnset(object, path) { + path = castPath(path, object); + object = parent(object, path); + return object == null || delete object[toKey(last(path))]; +} + +module.exports = baseUnset; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUpdate.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUpdate.js new file mode 100644 index 000000000..92a623777 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseUpdate.js @@ -0,0 +1,18 @@ +var baseGet = require('./_baseGet'), + baseSet = require('./_baseSet'); + +/** + * The base implementation of `_.update`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to update. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ +function baseUpdate(object, path, updater, customizer) { + return baseSet(object, path, updater(baseGet(object, path)), customizer); +} + +module.exports = baseUpdate; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseValues.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseValues.js new file mode 100644 index 000000000..b95faadcf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseValues.js @@ -0,0 +1,19 @@ +var arrayMap = require('./_arrayMap'); + +/** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values corresponding to the property names + * of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the array of property values. + */ +function baseValues(object, props) { + return arrayMap(props, function(key) { + return object[key]; + }); +} + +module.exports = baseValues; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseWhile.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseWhile.js new file mode 100644 index 000000000..07eac61b9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseWhile.js @@ -0,0 +1,26 @@ +var baseSlice = require('./_baseSlice'); + +/** + * The base implementation of methods like `_.dropWhile` and `_.takeWhile` + * without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to query. + * @param {Function} predicate The function invoked per iteration. + * @param {boolean} [isDrop] Specify dropping elements instead of taking them. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the slice of `array`. + */ +function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length) && + predicate(array[index], index, array)) {} + + return isDrop + ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length)) + : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index)); +} + +module.exports = baseWhile; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseWrapperValue.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseWrapperValue.js new file mode 100644 index 000000000..443e0df5e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseWrapperValue.js @@ -0,0 +1,25 @@ +var LazyWrapper = require('./_LazyWrapper'), + arrayPush = require('./_arrayPush'), + arrayReduce = require('./_arrayReduce'); + +/** + * The base implementation of `wrapperValue` which returns the result of + * performing a sequence of actions on the unwrapped `value`, where each + * successive action is supplied the return value of the previous. + * + * @private + * @param {*} value The unwrapped value. + * @param {Array} actions Actions to perform to resolve the unwrapped value. + * @returns {*} Returns the resolved value. + */ +function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + return arrayReduce(actions, function(result, action) { + return action.func.apply(action.thisArg, arrayPush([result], action.args)); + }, result); +} + +module.exports = baseWrapperValue; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseXor.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseXor.js new file mode 100644 index 000000000..8e69338bf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseXor.js @@ -0,0 +1,36 @@ +var baseDifference = require('./_baseDifference'), + baseFlatten = require('./_baseFlatten'), + baseUniq = require('./_baseUniq'); + +/** + * The base implementation of methods like `_.xor`, without support for + * iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of values. + */ +function baseXor(arrays, iteratee, comparator) { + var length = arrays.length; + if (length < 2) { + return length ? baseUniq(arrays[0]) : []; + } + var index = -1, + result = Array(length); + + while (++index < length) { + var array = arrays[index], + othIndex = -1; + + while (++othIndex < length) { + if (othIndex != index) { + result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator); + } + } + } + return baseUniq(baseFlatten(result, 1), iteratee, comparator); +} + +module.exports = baseXor; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseZipObject.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseZipObject.js new file mode 100644 index 000000000..401f85be2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_baseZipObject.js @@ -0,0 +1,23 @@ +/** + * This base implementation of `_.zipObject` which assigns values using `assignFunc`. + * + * @private + * @param {Array} props The property identifiers. + * @param {Array} values The property values. + * @param {Function} assignFunc The function to assign values. + * @returns {Object} Returns the new object. + */ +function baseZipObject(props, values, assignFunc) { + var index = -1, + length = props.length, + valsLength = values.length, + result = {}; + + while (++index < length) { + var value = index < valsLength ? values[index] : undefined; + assignFunc(result, props[index], value); + } + return result; +} + +module.exports = baseZipObject; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cacheHas.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cacheHas.js new file mode 100644 index 000000000..2dec89268 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cacheHas.js @@ -0,0 +1,13 @@ +/** + * Checks if a `cache` value for `key` exists. + * + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function cacheHas(cache, key) { + return cache.has(key); +} + +module.exports = cacheHas; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castArrayLikeObject.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castArrayLikeObject.js new file mode 100644 index 000000000..92c75fa1a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castArrayLikeObject.js @@ -0,0 +1,14 @@ +var isArrayLikeObject = require('./isArrayLikeObject'); + +/** + * Casts `value` to an empty array if it's not an array like object. + * + * @private + * @param {*} value The value to inspect. + * @returns {Array|Object} Returns the cast array-like object. + */ +function castArrayLikeObject(value) { + return isArrayLikeObject(value) ? value : []; +} + +module.exports = castArrayLikeObject; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castFunction.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castFunction.js new file mode 100644 index 000000000..98c91ae63 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castFunction.js @@ -0,0 +1,14 @@ +var identity = require('./identity'); + +/** + * Casts `value` to `identity` if it's not a function. + * + * @private + * @param {*} value The value to inspect. + * @returns {Function} Returns cast function. + */ +function castFunction(value) { + return typeof value == 'function' ? value : identity; +} + +module.exports = castFunction; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castPath.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castPath.js new file mode 100644 index 000000000..017e4c1b4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castPath.js @@ -0,0 +1,21 @@ +var isArray = require('./isArray'), + isKey = require('./_isKey'), + stringToPath = require('./_stringToPath'), + toString = require('./toString'); + +/** + * Casts `value` to a path array if it's not one. + * + * @private + * @param {*} value The value to inspect. + * @param {Object} [object] The object to query keys on. + * @returns {Array} Returns the cast property path array. + */ +function castPath(value, object) { + if (isArray(value)) { + return value; + } + return isKey(value, object) ? [value] : stringToPath(toString(value)); +} + +module.exports = castPath; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castRest.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castRest.js new file mode 100644 index 000000000..213c66f19 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castRest.js @@ -0,0 +1,14 @@ +var baseRest = require('./_baseRest'); + +/** + * A `baseRest` alias which can be replaced with `identity` by module + * replacement plugins. + * + * @private + * @type {Function} + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ +var castRest = baseRest; + +module.exports = castRest; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castSlice.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castSlice.js new file mode 100644 index 000000000..071faeba5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_castSlice.js @@ -0,0 +1,18 @@ +var baseSlice = require('./_baseSlice'); + +/** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ +function castSlice(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : baseSlice(array, start, end); +} + +module.exports = castSlice; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_charsEndIndex.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_charsEndIndex.js new file mode 100644 index 000000000..07908ff3a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_charsEndIndex.js @@ -0,0 +1,19 @@ +var baseIndexOf = require('./_baseIndexOf'); + +/** + * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the last unmatched string symbol. + */ +function charsEndIndex(strSymbols, chrSymbols) { + var index = strSymbols.length; + + while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; +} + +module.exports = charsEndIndex; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_charsStartIndex.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_charsStartIndex.js new file mode 100644 index 000000000..b17afd254 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_charsStartIndex.js @@ -0,0 +1,20 @@ +var baseIndexOf = require('./_baseIndexOf'); + +/** + * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the first unmatched string symbol. + */ +function charsStartIndex(strSymbols, chrSymbols) { + var index = -1, + length = strSymbols.length; + + while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; +} + +module.exports = charsStartIndex; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneArrayBuffer.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneArrayBuffer.js new file mode 100644 index 000000000..c3d8f6e39 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneArrayBuffer.js @@ -0,0 +1,16 @@ +var Uint8Array = require('./_Uint8Array'); + +/** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ +function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(arrayBuffer)); + return result; +} + +module.exports = cloneArrayBuffer; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneBuffer.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneBuffer.js new file mode 100644 index 000000000..27c48109b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneBuffer.js @@ -0,0 +1,35 @@ +var root = require('./_root'); + +/** Detect free variable `exports`. */ +var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Built-in value references. */ +var Buffer = moduleExports ? root.Buffer : undefined, + allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined; + +/** + * Creates a clone of `buffer`. + * + * @private + * @param {Buffer} buffer The buffer to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Buffer} Returns the cloned buffer. + */ +function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; +} + +module.exports = cloneBuffer; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneDataView.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneDataView.js new file mode 100644 index 000000000..9c9b7b054 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneDataView.js @@ -0,0 +1,16 @@ +var cloneArrayBuffer = require('./_cloneArrayBuffer'); + +/** + * Creates a clone of `dataView`. + * + * @private + * @param {Object} dataView The data view to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned data view. + */ +function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); +} + +module.exports = cloneDataView; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneRegExp.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneRegExp.js new file mode 100644 index 000000000..64a30dfb4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneRegExp.js @@ -0,0 +1,17 @@ +/** Used to match `RegExp` flags from their coerced string values. */ +var reFlags = /\w*$/; + +/** + * Creates a clone of `regexp`. + * + * @private + * @param {Object} regexp The regexp to clone. + * @returns {Object} Returns the cloned regexp. + */ +function cloneRegExp(regexp) { + var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); + result.lastIndex = regexp.lastIndex; + return result; +} + +module.exports = cloneRegExp; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneSymbol.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneSymbol.js new file mode 100644 index 000000000..bede39f50 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneSymbol.js @@ -0,0 +1,18 @@ +var Symbol = require('./_Symbol'); + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined; + +/** + * Creates a clone of the `symbol` object. + * + * @private + * @param {Object} symbol The symbol object to clone. + * @returns {Object} Returns the cloned symbol object. + */ +function cloneSymbol(symbol) { + return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; +} + +module.exports = cloneSymbol; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneTypedArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneTypedArray.js new file mode 100644 index 000000000..7aad84d4f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_cloneTypedArray.js @@ -0,0 +1,16 @@ +var cloneArrayBuffer = require('./_cloneArrayBuffer'); + +/** + * Creates a clone of `typedArray`. + * + * @private + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. + */ +function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); +} + +module.exports = cloneTypedArray; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_compareAscending.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_compareAscending.js new file mode 100644 index 000000000..8dc279108 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_compareAscending.js @@ -0,0 +1,41 @@ +var isSymbol = require('./isSymbol'); + +/** + * Compares values to sort them in ascending order. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {number} Returns the sort order indicator for `value`. + */ +function compareAscending(value, other) { + if (value !== other) { + var valIsDefined = value !== undefined, + valIsNull = value === null, + valIsReflexive = value === value, + valIsSymbol = isSymbol(value); + + var othIsDefined = other !== undefined, + othIsNull = other === null, + othIsReflexive = other === other, + othIsSymbol = isSymbol(other); + + if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || + (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || + (valIsNull && othIsDefined && othIsReflexive) || + (!valIsDefined && othIsReflexive) || + !valIsReflexive) { + return 1; + } + if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || + (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || + (othIsNull && valIsDefined && valIsReflexive) || + (!othIsDefined && valIsReflexive) || + !othIsReflexive) { + return -1; + } + } + return 0; +} + +module.exports = compareAscending; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_compareMultiple.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_compareMultiple.js new file mode 100644 index 000000000..ad61f0fbc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_compareMultiple.js @@ -0,0 +1,44 @@ +var compareAscending = require('./_compareAscending'); + +/** + * Used by `_.orderBy` to compare multiple properties of a value to another + * and stable sort them. + * + * If `orders` is unspecified, all values are sorted in ascending order. Otherwise, + * specify an order of "desc" for descending or "asc" for ascending sort order + * of corresponding values. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {boolean[]|string[]} orders The order to sort by for each property. + * @returns {number} Returns the sort order indicator for `object`. + */ +function compareMultiple(object, other, orders) { + var index = -1, + objCriteria = object.criteria, + othCriteria = other.criteria, + length = objCriteria.length, + ordersLength = orders.length; + + while (++index < length) { + var result = compareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order == 'desc' ? -1 : 1); + } + } + // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications + // that causes it, under certain circumstances, to provide the same value for + // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 + // for more details. + // + // This also ensures a stable sort in V8 and other engines. + // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details. + return object.index - other.index; +} + +module.exports = compareMultiple; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_composeArgs.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_composeArgs.js new file mode 100644 index 000000000..1ce40f4f9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_composeArgs.js @@ -0,0 +1,39 @@ +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * Creates an array that is the composition of partially applied arguments, + * placeholders, and provided arguments into a single array of arguments. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to prepend to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ +function composeArgs(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersLength = holders.length, + leftIndex = -1, + leftLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(leftLength + rangeLength), + isUncurried = !isCurried; + + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + } + while (rangeLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; +} + +module.exports = composeArgs; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_composeArgsRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_composeArgsRight.js new file mode 100644 index 000000000..8dc588d0a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_composeArgsRight.js @@ -0,0 +1,41 @@ +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * This function is like `composeArgs` except that the arguments composition + * is tailored for `_.partialRight`. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to append to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ +function composeArgsRight(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersIndex = -1, + holdersLength = holders.length, + rightIndex = -1, + rightLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(rangeLength + rightLength), + isUncurried = !isCurried; + + while (++argsIndex < rangeLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + } + return result; +} + +module.exports = composeArgsRight; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copyArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copyArray.js new file mode 100644 index 000000000..cd94d5d09 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copyArray.js @@ -0,0 +1,20 @@ +/** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ +function copyArray(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; +} + +module.exports = copyArray; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copyObject.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copyObject.js new file mode 100644 index 000000000..2f2a5c23b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copyObject.js @@ -0,0 +1,40 @@ +var assignValue = require('./_assignValue'), + baseAssignValue = require('./_baseAssignValue'); + +/** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ +function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; +} + +module.exports = copyObject; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copySymbols.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copySymbols.js new file mode 100644 index 000000000..c35944ab5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copySymbols.js @@ -0,0 +1,16 @@ +var copyObject = require('./_copyObject'), + getSymbols = require('./_getSymbols'); + +/** + * Copies own symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ +function copySymbols(source, object) { + return copyObject(source, getSymbols(source), object); +} + +module.exports = copySymbols; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copySymbolsIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copySymbolsIn.js new file mode 100644 index 000000000..fdf20a73c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_copySymbolsIn.js @@ -0,0 +1,16 @@ +var copyObject = require('./_copyObject'), + getSymbolsIn = require('./_getSymbolsIn'); + +/** + * Copies own and inherited symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ +function copySymbolsIn(source, object) { + return copyObject(source, getSymbolsIn(source), object); +} + +module.exports = copySymbolsIn; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_coreJsData.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_coreJsData.js new file mode 100644 index 000000000..f8e5b4e34 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_coreJsData.js @@ -0,0 +1,6 @@ +var root = require('./_root'); + +/** Used to detect overreaching core-js shims. */ +var coreJsData = root['__core-js_shared__']; + +module.exports = coreJsData; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_countHolders.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_countHolders.js new file mode 100644 index 000000000..718fcdaa8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_countHolders.js @@ -0,0 +1,21 @@ +/** + * Gets the number of `placeholder` occurrences in `array`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} placeholder The placeholder to search for. + * @returns {number} Returns the placeholder count. + */ +function countHolders(array, placeholder) { + var length = array.length, + result = 0; + + while (length--) { + if (array[length] === placeholder) { + ++result; + } + } + return result; +} + +module.exports = countHolders; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createAggregator.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createAggregator.js new file mode 100644 index 000000000..0be42c41c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createAggregator.js @@ -0,0 +1,23 @@ +var arrayAggregator = require('./_arrayAggregator'), + baseAggregator = require('./_baseAggregator'), + baseIteratee = require('./_baseIteratee'), + isArray = require('./isArray'); + +/** + * Creates a function like `_.groupBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} [initializer] The accumulator object initializer. + * @returns {Function} Returns the new aggregator function. + */ +function createAggregator(setter, initializer) { + return function(collection, iteratee) { + var func = isArray(collection) ? arrayAggregator : baseAggregator, + accumulator = initializer ? initializer() : {}; + + return func(collection, setter, baseIteratee(iteratee, 2), accumulator); + }; +} + +module.exports = createAggregator; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createAssigner.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createAssigner.js new file mode 100644 index 000000000..1f904c51b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createAssigner.js @@ -0,0 +1,37 @@ +var baseRest = require('./_baseRest'), + isIterateeCall = require('./_isIterateeCall'); + +/** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ +function createAssigner(assigner) { + return baseRest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); +} + +module.exports = createAssigner; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createBaseEach.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createBaseEach.js new file mode 100644 index 000000000..d24fdd1bb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createBaseEach.js @@ -0,0 +1,32 @@ +var isArrayLike = require('./isArrayLike'); + +/** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ +function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + if (collection == null) { + return collection; + } + if (!isArrayLike(collection)) { + return eachFunc(collection, iteratee); + } + var length = collection.length, + index = fromRight ? length : -1, + iterable = Object(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; +} + +module.exports = createBaseEach; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createBaseFor.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createBaseFor.js new file mode 100644 index 000000000..94cbf297a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createBaseFor.js @@ -0,0 +1,25 @@ +/** + * Creates a base function for methods like `_.forIn` and `_.forOwn`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ +function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; +} + +module.exports = createBaseFor; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createBind.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createBind.js new file mode 100644 index 000000000..07cb99f4d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createBind.js @@ -0,0 +1,28 @@ +var createCtor = require('./_createCtor'), + root = require('./_root'); + +/** Used to compose bitmasks for function metadata. */ +var WRAP_BIND_FLAG = 1; + +/** + * Creates a function that wraps `func` to invoke it with the optional `this` + * binding of `thisArg`. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new wrapped function. + */ +function createBind(func, bitmask, thisArg) { + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return fn.apply(isBind ? thisArg : this, arguments); + } + return wrapper; +} + +module.exports = createBind; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCaseFirst.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCaseFirst.js new file mode 100644 index 000000000..fe8ea4830 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCaseFirst.js @@ -0,0 +1,33 @@ +var castSlice = require('./_castSlice'), + hasUnicode = require('./_hasUnicode'), + stringToArray = require('./_stringToArray'), + toString = require('./toString'); + +/** + * Creates a function like `_.lowerFirst`. + * + * @private + * @param {string} methodName The name of the `String` case method to use. + * @returns {Function} Returns the new case function. + */ +function createCaseFirst(methodName) { + return function(string) { + string = toString(string); + + var strSymbols = hasUnicode(string) + ? stringToArray(string) + : undefined; + + var chr = strSymbols + ? strSymbols[0] + : string.charAt(0); + + var trailing = strSymbols + ? castSlice(strSymbols, 1).join('') + : string.slice(1); + + return chr[methodName]() + trailing; + }; +} + +module.exports = createCaseFirst; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCompounder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCompounder.js new file mode 100644 index 000000000..8d4cee2cd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCompounder.js @@ -0,0 +1,24 @@ +var arrayReduce = require('./_arrayReduce'), + deburr = require('./deburr'), + words = require('./words'); + +/** Used to compose unicode capture groups. */ +var rsApos = "['\u2019]"; + +/** Used to match apostrophes. */ +var reApos = RegExp(rsApos, 'g'); + +/** + * Creates a function like `_.camelCase`. + * + * @private + * @param {Function} callback The function to combine each word. + * @returns {Function} Returns the new compounder function. + */ +function createCompounder(callback) { + return function(string) { + return arrayReduce(words(deburr(string).replace(reApos, '')), callback, ''); + }; +} + +module.exports = createCompounder; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCtor.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCtor.js new file mode 100644 index 000000000..9047aa5fa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCtor.js @@ -0,0 +1,37 @@ +var baseCreate = require('./_baseCreate'), + isObject = require('./isObject'); + +/** + * Creates a function that produces an instance of `Ctor` regardless of + * whether it was invoked as part of a `new` expression or by `call` or `apply`. + * + * @private + * @param {Function} Ctor The constructor to wrap. + * @returns {Function} Returns the new wrapped function. + */ +function createCtor(Ctor) { + return function() { + // Use a `switch` statement to work with class constructors. See + // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // for more details. + var args = arguments; + switch (args.length) { + case 0: return new Ctor; + case 1: return new Ctor(args[0]); + case 2: return new Ctor(args[0], args[1]); + case 3: return new Ctor(args[0], args[1], args[2]); + case 4: return new Ctor(args[0], args[1], args[2], args[3]); + case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); + case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), + result = Ctor.apply(thisBinding, args); + + // Mimic the constructor's `return` behavior. + // See https://es5.github.io/#x13.2.2 for more details. + return isObject(result) ? result : thisBinding; + }; +} + +module.exports = createCtor; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCurry.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCurry.js new file mode 100644 index 000000000..f06c2cdd8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createCurry.js @@ -0,0 +1,46 @@ +var apply = require('./_apply'), + createCtor = require('./_createCtor'), + createHybrid = require('./_createHybrid'), + createRecurry = require('./_createRecurry'), + getHolder = require('./_getHolder'), + replaceHolders = require('./_replaceHolders'), + root = require('./_root'); + +/** + * Creates a function that wraps `func` to enable currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {number} arity The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ +function createCurry(func, bitmask, arity) { + var Ctor = createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length, + placeholder = getHolder(wrapper); + + while (index--) { + args[index] = arguments[index]; + } + var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder) + ? [] + : replaceHolders(args, placeholder); + + length -= holders.length; + if (length < arity) { + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, undefined, + args, holders, undefined, undefined, arity - length); + } + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return apply(fn, this, args); + } + return wrapper; +} + +module.exports = createCurry; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createFind.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createFind.js new file mode 100644 index 000000000..8859ff89f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createFind.js @@ -0,0 +1,25 @@ +var baseIteratee = require('./_baseIteratee'), + isArrayLike = require('./isArrayLike'), + keys = require('./keys'); + +/** + * Creates a `_.find` or `_.findLast` function. + * + * @private + * @param {Function} findIndexFunc The function to find the collection index. + * @returns {Function} Returns the new find function. + */ +function createFind(findIndexFunc) { + return function(collection, predicate, fromIndex) { + var iterable = Object(collection); + if (!isArrayLike(collection)) { + var iteratee = baseIteratee(predicate, 3); + collection = keys(collection); + predicate = function(key) { return iteratee(iterable[key], key, iterable); }; + } + var index = findIndexFunc(collection, predicate, fromIndex); + return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; + }; +} + +module.exports = createFind; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createFlow.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createFlow.js new file mode 100644 index 000000000..baaddbf5e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createFlow.js @@ -0,0 +1,78 @@ +var LodashWrapper = require('./_LodashWrapper'), + flatRest = require('./_flatRest'), + getData = require('./_getData'), + getFuncName = require('./_getFuncName'), + isArray = require('./isArray'), + isLaziable = require('./_isLaziable'); + +/** Error message constants. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/** Used to compose bitmasks for function metadata. */ +var WRAP_CURRY_FLAG = 8, + WRAP_PARTIAL_FLAG = 32, + WRAP_ARY_FLAG = 128, + WRAP_REARG_FLAG = 256; + +/** + * Creates a `_.flow` or `_.flowRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new flow function. + */ +function createFlow(fromRight) { + return flatRest(function(funcs) { + var length = funcs.length, + index = length, + prereq = LodashWrapper.prototype.thru; + + if (fromRight) { + funcs.reverse(); + } + while (index--) { + var func = funcs[index]; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (prereq && !wrapper && getFuncName(func) == 'wrapper') { + var wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? index : length; + while (++index < length) { + func = funcs[index]; + + var funcName = getFuncName(func), + data = funcName == 'wrapper' ? getData(func) : undefined; + + if (data && isLaziable(data[0]) && + data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && + !data[4].length && data[9] == 1 + ) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = (func.length == 1 && isLaziable(func)) + ? wrapper[funcName]() + : wrapper.thru(func); + } + } + return function() { + var args = arguments, + value = args[0]; + + if (wrapper && args.length == 1 && isArray(value)) { + return wrapper.plant(value).value(); + } + var index = 0, + result = length ? funcs[index].apply(this, args) : value; + + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }); +} + +module.exports = createFlow; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createHybrid.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createHybrid.js new file mode 100644 index 000000000..b671bd11f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createHybrid.js @@ -0,0 +1,92 @@ +var composeArgs = require('./_composeArgs'), + composeArgsRight = require('./_composeArgsRight'), + countHolders = require('./_countHolders'), + createCtor = require('./_createCtor'), + createRecurry = require('./_createRecurry'), + getHolder = require('./_getHolder'), + reorder = require('./_reorder'), + replaceHolders = require('./_replaceHolders'), + root = require('./_root'); + +/** Used to compose bitmasks for function metadata. */ +var WRAP_BIND_FLAG = 1, + WRAP_BIND_KEY_FLAG = 2, + WRAP_CURRY_FLAG = 8, + WRAP_CURRY_RIGHT_FLAG = 16, + WRAP_ARY_FLAG = 128, + WRAP_FLIP_FLAG = 512; + +/** + * Creates a function that wraps `func` to invoke it with optional `this` + * binding of `thisArg`, partial application, and currying. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [partialsRight] The arguments to append to those provided + * to the new function. + * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ +function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & WRAP_ARY_FLAG, + isBind = bitmask & WRAP_BIND_FLAG, + isBindKey = bitmask & WRAP_BIND_KEY_FLAG, + isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), + isFlip = bitmask & WRAP_FLIP_FLAG, + Ctor = isBindKey ? undefined : createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length; + + while (index--) { + args[index] = arguments[index]; + } + if (isCurried) { + var placeholder = getHolder(wrapper), + holdersCount = countHolders(args, placeholder); + } + if (partials) { + args = composeArgs(args, partials, holders, isCurried); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight, isCurried); + } + length -= holdersCount; + if (isCurried && length < arity) { + var newHolders = replaceHolders(args, placeholder); + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, thisArg, + args, newHolders, argPos, ary, arity - length + ); + } + var thisBinding = isBind ? thisArg : this, + fn = isBindKey ? thisBinding[func] : func; + + length = args.length; + if (argPos) { + args = reorder(args, argPos); + } else if (isFlip && length > 1) { + args.reverse(); + } + if (isAry && ary < length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtor(fn); + } + return fn.apply(thisBinding, args); + } + return wrapper; +} + +module.exports = createHybrid; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createInverter.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createInverter.js new file mode 100644 index 000000000..6c0c56299 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createInverter.js @@ -0,0 +1,17 @@ +var baseInverter = require('./_baseInverter'); + +/** + * Creates a function like `_.invertBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} toIteratee The function to resolve iteratees. + * @returns {Function} Returns the new inverter function. + */ +function createInverter(setter, toIteratee) { + return function(object, iteratee) { + return baseInverter(object, setter, toIteratee(iteratee), {}); + }; +} + +module.exports = createInverter; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createMathOperation.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createMathOperation.js new file mode 100644 index 000000000..f1e238ac0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createMathOperation.js @@ -0,0 +1,38 @@ +var baseToNumber = require('./_baseToNumber'), + baseToString = require('./_baseToString'); + +/** + * Creates a function that performs a mathematical operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @param {number} [defaultValue] The value used for `undefined` arguments. + * @returns {Function} Returns the new mathematical operation function. + */ +function createMathOperation(operator, defaultValue) { + return function(value, other) { + var result; + if (value === undefined && other === undefined) { + return defaultValue; + } + if (value !== undefined) { + result = value; + } + if (other !== undefined) { + if (result === undefined) { + return other; + } + if (typeof value == 'string' || typeof other == 'string') { + value = baseToString(value); + other = baseToString(other); + } else { + value = baseToNumber(value); + other = baseToNumber(other); + } + result = operator(value, other); + } + return result; + }; +} + +module.exports = createMathOperation; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createOver.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createOver.js new file mode 100644 index 000000000..3b9455161 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createOver.js @@ -0,0 +1,27 @@ +var apply = require('./_apply'), + arrayMap = require('./_arrayMap'), + baseIteratee = require('./_baseIteratee'), + baseRest = require('./_baseRest'), + baseUnary = require('./_baseUnary'), + flatRest = require('./_flatRest'); + +/** + * Creates a function like `_.over`. + * + * @private + * @param {Function} arrayFunc The function to iterate over iteratees. + * @returns {Function} Returns the new over function. + */ +function createOver(arrayFunc) { + return flatRest(function(iteratees) { + iteratees = arrayMap(iteratees, baseUnary(baseIteratee)); + return baseRest(function(args) { + var thisArg = this; + return arrayFunc(iteratees, function(iteratee) { + return apply(iteratee, thisArg, args); + }); + }); + }); +} + +module.exports = createOver; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createPadding.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createPadding.js new file mode 100644 index 000000000..2124612b8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createPadding.js @@ -0,0 +1,33 @@ +var baseRepeat = require('./_baseRepeat'), + baseToString = require('./_baseToString'), + castSlice = require('./_castSlice'), + hasUnicode = require('./_hasUnicode'), + stringSize = require('./_stringSize'), + stringToArray = require('./_stringToArray'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeCeil = Math.ceil; + +/** + * Creates the padding for `string` based on `length`. The `chars` string + * is truncated if the number of characters exceeds `length`. + * + * @private + * @param {number} length The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padding for `string`. + */ +function createPadding(length, chars) { + chars = chars === undefined ? ' ' : baseToString(chars); + + var charsLength = chars.length; + if (charsLength < 2) { + return charsLength ? baseRepeat(chars, length) : chars; + } + var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); + return hasUnicode(chars) + ? castSlice(stringToArray(result), 0, length).join('') + : result.slice(0, length); +} + +module.exports = createPadding; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createPartial.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createPartial.js new file mode 100644 index 000000000..e16c248b5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createPartial.js @@ -0,0 +1,43 @@ +var apply = require('./_apply'), + createCtor = require('./_createCtor'), + root = require('./_root'); + +/** Used to compose bitmasks for function metadata. */ +var WRAP_BIND_FLAG = 1; + +/** + * Creates a function that wraps `func` to invoke it with the `this` binding + * of `thisArg` and `partials` prepended to the arguments it receives. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} partials The arguments to prepend to those provided to + * the new function. + * @returns {Function} Returns the new wrapped function. + */ +function createPartial(func, bitmask, thisArg, partials) { + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var argsIndex = -1, + argsLength = arguments.length, + leftIndex = -1, + leftLength = partials.length, + args = Array(leftLength + argsLength), + fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + return apply(fn, isBind ? thisArg : this, args); + } + return wrapper; +} + +module.exports = createPartial; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRange.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRange.js new file mode 100644 index 000000000..9f52c7793 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRange.js @@ -0,0 +1,30 @@ +var baseRange = require('./_baseRange'), + isIterateeCall = require('./_isIterateeCall'), + toFinite = require('./toFinite'); + +/** + * Creates a `_.range` or `_.rangeRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new range function. + */ +function createRange(fromRight) { + return function(start, end, step) { + if (step && typeof step != 'number' && isIterateeCall(start, end, step)) { + end = step = undefined; + } + // Ensure the sign of `-0` is preserved. + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + step = step === undefined ? (start < end ? 1 : -1) : toFinite(step); + return baseRange(start, end, step, fromRight); + }; +} + +module.exports = createRange; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRecurry.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRecurry.js new file mode 100644 index 000000000..eb29fb24c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRecurry.js @@ -0,0 +1,56 @@ +var isLaziable = require('./_isLaziable'), + setData = require('./_setData'), + setWrapToString = require('./_setWrapToString'); + +/** Used to compose bitmasks for function metadata. */ +var WRAP_BIND_FLAG = 1, + WRAP_BIND_KEY_FLAG = 2, + WRAP_CURRY_BOUND_FLAG = 4, + WRAP_CURRY_FLAG = 8, + WRAP_PARTIAL_FLAG = 32, + WRAP_PARTIAL_RIGHT_FLAG = 64; + +/** + * Creates a function that wraps `func` to continue currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {Function} wrapFunc The function to create the `func` wrapper. + * @param {*} placeholder The placeholder value. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ +function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { + var isCurry = bitmask & WRAP_CURRY_FLAG, + newHolders = isCurry ? holders : undefined, + newHoldersRight = isCurry ? undefined : holders, + newPartials = isCurry ? partials : undefined, + newPartialsRight = isCurry ? undefined : partials; + + bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG); + + if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) { + bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG); + } + var newData = [ + func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, + newHoldersRight, argPos, ary, arity + ]; + + var result = wrapFunc.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return setWrapToString(result, func, bitmask); +} + +module.exports = createRecurry; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRelationalOperation.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRelationalOperation.js new file mode 100644 index 000000000..a17c6b5e7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRelationalOperation.js @@ -0,0 +1,20 @@ +var toNumber = require('./toNumber'); + +/** + * Creates a function that performs a relational operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @returns {Function} Returns the new relational operation function. + */ +function createRelationalOperation(operator) { + return function(value, other) { + if (!(typeof value == 'string' && typeof other == 'string')) { + value = toNumber(value); + other = toNumber(other); + } + return operator(value, other); + }; +} + +module.exports = createRelationalOperation; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRound.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRound.js new file mode 100644 index 000000000..88be5df39 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createRound.js @@ -0,0 +1,35 @@ +var root = require('./_root'), + toInteger = require('./toInteger'), + toNumber = require('./toNumber'), + toString = require('./toString'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeIsFinite = root.isFinite, + nativeMin = Math.min; + +/** + * Creates a function like `_.round`. + * + * @private + * @param {string} methodName The name of the `Math` method to use when rounding. + * @returns {Function} Returns the new round function. + */ +function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + number = toNumber(number); + precision = precision == null ? 0 : nativeMin(toInteger(precision), 292); + if (precision && nativeIsFinite(number)) { + // Shift with exponential notation to avoid floating-point issues. + // See [MDN](https://mdn.io/round#Examples) for more details. + var pair = (toString(number) + 'e').split('e'), + value = func(pair[0] + 'e' + (+pair[1] + precision)); + + pair = (toString(value) + 'e').split('e'); + return +(pair[0] + 'e' + (+pair[1] - precision)); + } + return func(number); + }; +} + +module.exports = createRound; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createSet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createSet.js new file mode 100644 index 000000000..0f644eeae --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createSet.js @@ -0,0 +1,19 @@ +var Set = require('./_Set'), + noop = require('./noop'), + setToArray = require('./_setToArray'); + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** + * Creates a set object of `values`. + * + * @private + * @param {Array} values The values to add to the set. + * @returns {Object} Returns the new set. + */ +var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) { + return new Set(values); +}; + +module.exports = createSet; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createToPairs.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createToPairs.js new file mode 100644 index 000000000..568417afd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createToPairs.js @@ -0,0 +1,30 @@ +var baseToPairs = require('./_baseToPairs'), + getTag = require('./_getTag'), + mapToArray = require('./_mapToArray'), + setToPairs = require('./_setToPairs'); + +/** `Object#toString` result references. */ +var mapTag = '[object Map]', + setTag = '[object Set]'; + +/** + * Creates a `_.toPairs` or `_.toPairsIn` function. + * + * @private + * @param {Function} keysFunc The function to get the keys of a given object. + * @returns {Function} Returns the new pairs function. + */ +function createToPairs(keysFunc) { + return function(object) { + var tag = getTag(object); + if (tag == mapTag) { + return mapToArray(object); + } + if (tag == setTag) { + return setToPairs(object); + } + return baseToPairs(object, keysFunc(object)); + }; +} + +module.exports = createToPairs; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createWrap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createWrap.js new file mode 100644 index 000000000..33f0633e4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_createWrap.js @@ -0,0 +1,106 @@ +var baseSetData = require('./_baseSetData'), + createBind = require('./_createBind'), + createCurry = require('./_createCurry'), + createHybrid = require('./_createHybrid'), + createPartial = require('./_createPartial'), + getData = require('./_getData'), + mergeData = require('./_mergeData'), + setData = require('./_setData'), + setWrapToString = require('./_setWrapToString'), + toInteger = require('./toInteger'); + +/** Error message constants. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/** Used to compose bitmasks for function metadata. */ +var WRAP_BIND_FLAG = 1, + WRAP_BIND_KEY_FLAG = 2, + WRAP_CURRY_FLAG = 8, + WRAP_CURRY_RIGHT_FLAG = 16, + WRAP_PARTIAL_FLAG = 32, + WRAP_PARTIAL_RIGHT_FLAG = 64; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * Creates a function that either curries or invokes `func` with optional + * `this` binding and partially applied arguments. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` or `_.curryRight` of a bound function + * 8 - `_.curry` + * 16 - `_.curryRight` + * 32 - `_.partial` + * 64 - `_.partialRight` + * 128 - `_.rearg` + * 256 - `_.ary` + * 512 - `_.flip` + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to be partially applied. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ +function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & WRAP_BIND_KEY_FLAG; + if (!isBindKey && typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0); + arity = arity === undefined ? arity : toInteger(arity); + length -= holders ? holders.length : 0; + + if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, + holdersRight = holders; + + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func); + + var newData = [ + func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, + argPos, ary, arity + ]; + + if (data) { + mergeData(newData, data); + } + func = newData[0]; + bitmask = newData[1]; + thisArg = newData[2]; + partials = newData[3]; + holders = newData[4]; + arity = newData[9] = newData[9] === undefined + ? (isBindKey ? 0 : func.length) + : nativeMax(newData[9] - length, 0); + + if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) { + bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG); + } + if (!bitmask || bitmask == WRAP_BIND_FLAG) { + var result = createBind(func, bitmask, thisArg); + } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) { + result = createCurry(func, bitmask, arity); + } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) { + result = createPartial(func, bitmask, thisArg, partials); + } else { + result = createHybrid.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setWrapToString(setter(result, newData), func, bitmask); +} + +module.exports = createWrap; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_customDefaultsAssignIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_customDefaultsAssignIn.js new file mode 100644 index 000000000..1f49e6fc4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_customDefaultsAssignIn.js @@ -0,0 +1,29 @@ +var eq = require('./eq'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used by `_.defaults` to customize its `_.assignIn` use to assign properties + * of source objects to the destination object for all destination properties + * that resolve to `undefined`. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to assign. + * @param {Object} object The parent object of `objValue`. + * @returns {*} Returns the value to assign. + */ +function customDefaultsAssignIn(objValue, srcValue, key, object) { + if (objValue === undefined || + (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { + return srcValue; + } + return objValue; +} + +module.exports = customDefaultsAssignIn; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_customDefaultsMerge.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_customDefaultsMerge.js new file mode 100644 index 000000000..4cab31751 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_customDefaultsMerge.js @@ -0,0 +1,28 @@ +var baseMerge = require('./_baseMerge'), + isObject = require('./isObject'); + +/** + * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source + * objects into destination objects that are passed thru. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to merge. + * @param {Object} object The parent object of `objValue`. + * @param {Object} source The parent object of `srcValue`. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + * @returns {*} Returns the value to assign. + */ +function customDefaultsMerge(objValue, srcValue, key, object, source, stack) { + if (isObject(objValue) && isObject(srcValue)) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, objValue); + baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack); + stack['delete'](srcValue); + } + return objValue; +} + +module.exports = customDefaultsMerge; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_customOmitClone.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_customOmitClone.js new file mode 100644 index 000000000..968db2ef3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_customOmitClone.js @@ -0,0 +1,16 @@ +var isPlainObject = require('./isPlainObject'); + +/** + * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain + * objects. + * + * @private + * @param {*} value The value to inspect. + * @param {string} key The key of the property to inspect. + * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`. + */ +function customOmitClone(value) { + return isPlainObject(value) ? undefined : value; +} + +module.exports = customOmitClone; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_deburrLetter.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_deburrLetter.js new file mode 100644 index 000000000..3e531edcf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_deburrLetter.js @@ -0,0 +1,71 @@ +var basePropertyOf = require('./_basePropertyOf'); + +/** Used to map Latin Unicode letters to basic Latin letters. */ +var deburredLetters = { + // Latin-1 Supplement block. + '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', + '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', + '\xc7': 'C', '\xe7': 'c', + '\xd0': 'D', '\xf0': 'd', + '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', + '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', + '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', + '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', + '\xd1': 'N', '\xf1': 'n', + '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', + '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', + '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', + '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', + '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', + '\xc6': 'Ae', '\xe6': 'ae', + '\xde': 'Th', '\xfe': 'th', + '\xdf': 'ss', + // Latin Extended-A block. + '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', + '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', + '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', + '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', + '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', + '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', + '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', + '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', + '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', + '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', + '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', + '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', + '\u0134': 'J', '\u0135': 'j', + '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', + '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', + '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', + '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', + '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', + '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', + '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', + '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', + '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', + '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', + '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', + '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', + '\u0163': 't', '\u0165': 't', '\u0167': 't', + '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', + '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', + '\u0174': 'W', '\u0175': 'w', + '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', + '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', + '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', + '\u0132': 'IJ', '\u0133': 'ij', + '\u0152': 'Oe', '\u0153': 'oe', + '\u0149': "'n", '\u017f': 's' +}; + +/** + * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A + * letters to basic Latin letters. + * + * @private + * @param {string} letter The matched letter to deburr. + * @returns {string} Returns the deburred letter. + */ +var deburrLetter = basePropertyOf(deburredLetters); + +module.exports = deburrLetter; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_defineProperty.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_defineProperty.js new file mode 100644 index 000000000..b6116d92a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_defineProperty.js @@ -0,0 +1,11 @@ +var getNative = require('./_getNative'); + +var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} +}()); + +module.exports = defineProperty; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_equalArrays.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_equalArrays.js new file mode 100644 index 000000000..824228c78 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_equalArrays.js @@ -0,0 +1,84 @@ +var SetCache = require('./_SetCache'), + arraySome = require('./_arraySome'), + cacheHas = require('./_cacheHas'); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + +/** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ +function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + // Check that cyclic values are equal. + var arrStacked = stack.get(array); + var othStacked = stack.get(other); + if (arrStacked && othStacked) { + return arrStacked == other && othStacked == array; + } + var index = -1, + result = true, + seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; + + stack.set(array, other); + stack.set(other, array); + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, arrValue, index, other, array, stack) + : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!arraySome(other, function(othValue, othIndex) { + if (!cacheHas(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, bitmask, customizer, stack) + )) { + result = false; + break; + } + } + stack['delete'](array); + stack['delete'](other); + return result; +} + +module.exports = equalArrays; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_equalByTag.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_equalByTag.js new file mode 100644 index 000000000..71919e867 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_equalByTag.js @@ -0,0 +1,112 @@ +var Symbol = require('./_Symbol'), + Uint8Array = require('./_Uint8Array'), + eq = require('./eq'), + equalArrays = require('./_equalArrays'), + mapToArray = require('./_mapToArray'), + setToArray = require('./_setToArray'); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + +/** `Object#toString` result references. */ +var boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + mapTag = '[object Map]', + numberTag = '[object Number]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]'; + +var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]'; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined; + +/** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ +function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + case dataViewTag: + if ((object.byteLength != other.byteLength) || + (object.byteOffset != other.byteOffset)) { + return false; + } + object = object.buffer; + other = other.buffer; + + case arrayBufferTag: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; + + case boolTag: + case dateTag: + case numberTag: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); + + case errorTag: + return object.name == other.name && object.message == other.message; + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. + return object == (other + ''); + + case mapTag: + var convert = mapToArray; + + case setTag: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG; + convert || (convert = setToArray); + + if (object.size != other.size && !isPartial) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= COMPARE_UNORDERED_FLAG; + + // Recursively compare objects (susceptible to call stack limits). + stack.set(object, other); + var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); + stack['delete'](object); + return result; + + case symbolTag: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + return false; +} + +module.exports = equalByTag; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_equalObjects.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_equalObjects.js new file mode 100644 index 000000000..cdaacd2df --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_equalObjects.js @@ -0,0 +1,90 @@ +var getAllKeys = require('./_getAllKeys'); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ +function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + objProps = getAllKeys(object), + objLength = objProps.length, + othProps = getAllKeys(other), + othLength = othProps.length; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + // Check that cyclic values are equal. + var objStacked = stack.get(object); + var othStacked = stack.get(other); + if (objStacked && othStacked) { + return objStacked == other && othStacked == object; + } + var result = true; + stack.set(object, other); + stack.set(other, object); + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, objValue, key, other, object, stack) + : customizer(objValue, othValue, key, object, other, stack); + } + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } + } + stack['delete'](object); + stack['delete'](other); + return result; +} + +module.exports = equalObjects; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_escapeHtmlChar.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_escapeHtmlChar.js new file mode 100644 index 000000000..7ca68ee62 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_escapeHtmlChar.js @@ -0,0 +1,21 @@ +var basePropertyOf = require('./_basePropertyOf'); + +/** Used to map characters to HTML entities. */ +var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' +}; + +/** + * Used by `_.escape` to convert characters to HTML entities. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ +var escapeHtmlChar = basePropertyOf(htmlEscapes); + +module.exports = escapeHtmlChar; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_escapeStringChar.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_escapeStringChar.js new file mode 100644 index 000000000..44eca96ca --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_escapeStringChar.js @@ -0,0 +1,22 @@ +/** Used to escape characters for inclusion in compiled string literals. */ +var stringEscapes = { + '\\': '\\', + "'": "'", + '\n': 'n', + '\r': 'r', + '\u2028': 'u2028', + '\u2029': 'u2029' +}; + +/** + * Used by `_.template` to escape characters for inclusion in compiled string literals. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ +function escapeStringChar(chr) { + return '\\' + stringEscapes[chr]; +} + +module.exports = escapeStringChar; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_flatRest.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_flatRest.js new file mode 100644 index 000000000..94ab6cca7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_flatRest.js @@ -0,0 +1,16 @@ +var flatten = require('./flatten'), + overRest = require('./_overRest'), + setToString = require('./_setToString'); + +/** + * A specialized version of `baseRest` which flattens the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ +function flatRest(func) { + return setToString(overRest(func, undefined, flatten), func + ''); +} + +module.exports = flatRest; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_freeGlobal.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_freeGlobal.js new file mode 100644 index 000000000..bbec998fc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_freeGlobal.js @@ -0,0 +1,4 @@ +/** Detect free variable `global` from Node.js. */ +var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + +module.exports = freeGlobal; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getAllKeys.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getAllKeys.js new file mode 100644 index 000000000..a9ce6995a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getAllKeys.js @@ -0,0 +1,16 @@ +var baseGetAllKeys = require('./_baseGetAllKeys'), + getSymbols = require('./_getSymbols'), + keys = require('./keys'); + +/** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ +function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); +} + +module.exports = getAllKeys; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getAllKeysIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getAllKeysIn.js new file mode 100644 index 000000000..1b4667841 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getAllKeysIn.js @@ -0,0 +1,17 @@ +var baseGetAllKeys = require('./_baseGetAllKeys'), + getSymbolsIn = require('./_getSymbolsIn'), + keysIn = require('./keysIn'); + +/** + * Creates an array of own and inherited enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ +function getAllKeysIn(object) { + return baseGetAllKeys(object, keysIn, getSymbolsIn); +} + +module.exports = getAllKeysIn; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getData.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getData.js new file mode 100644 index 000000000..a1fe7b779 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getData.js @@ -0,0 +1,15 @@ +var metaMap = require('./_metaMap'), + noop = require('./noop'); + +/** + * Gets metadata for `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {*} Returns the metadata for `func`. + */ +var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); +}; + +module.exports = getData; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getFuncName.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getFuncName.js new file mode 100644 index 000000000..21e15b337 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getFuncName.js @@ -0,0 +1,31 @@ +var realNames = require('./_realNames'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Gets the name of `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {string} Returns the function name. + */ +function getFuncName(func) { + var result = (func.name + ''), + array = realNames[result], + length = hasOwnProperty.call(realNames, result) ? array.length : 0; + + while (length--) { + var data = array[length], + otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; +} + +module.exports = getFuncName; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getHolder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getHolder.js new file mode 100644 index 000000000..65e94b5c2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getHolder.js @@ -0,0 +1,13 @@ +/** + * Gets the argument placeholder value for `func`. + * + * @private + * @param {Function} func The function to inspect. + * @returns {*} Returns the placeholder value. + */ +function getHolder(func) { + var object = func; + return object.placeholder; +} + +module.exports = getHolder; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getMapData.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getMapData.js new file mode 100644 index 000000000..17f63032e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getMapData.js @@ -0,0 +1,18 @@ +var isKeyable = require('./_isKeyable'); + +/** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ +function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; +} + +module.exports = getMapData; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getMatchData.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getMatchData.js new file mode 100644 index 000000000..2cc70f917 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getMatchData.js @@ -0,0 +1,24 @@ +var isStrictComparable = require('./_isStrictComparable'), + keys = require('./keys'); + +/** + * Gets the property names, values, and compare flags of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the match data of `object`. + */ +function getMatchData(object) { + var result = keys(object), + length = result.length; + + while (length--) { + var key = result[length], + value = object[key]; + + result[length] = [key, value, isStrictComparable(value)]; + } + return result; +} + +module.exports = getMatchData; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getNative.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getNative.js new file mode 100644 index 000000000..97a622b83 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getNative.js @@ -0,0 +1,17 @@ +var baseIsNative = require('./_baseIsNative'), + getValue = require('./_getValue'); + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; +} + +module.exports = getNative; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getPrototype.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getPrototype.js new file mode 100644 index 000000000..e80861212 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getPrototype.js @@ -0,0 +1,6 @@ +var overArg = require('./_overArg'); + +/** Built-in value references. */ +var getPrototype = overArg(Object.getPrototypeOf, Object); + +module.exports = getPrototype; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getRawTag.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getRawTag.js new file mode 100644 index 000000000..49a95c9c6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getRawTag.js @@ -0,0 +1,46 @@ +var Symbol = require('./_Symbol'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** Built-in value references. */ +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + +/** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ +function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; +} + +module.exports = getRawTag; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getSymbols.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getSymbols.js new file mode 100644 index 000000000..7d6eafebb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getSymbols.js @@ -0,0 +1,30 @@ +var arrayFilter = require('./_arrayFilter'), + stubArray = require('./stubArray'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeGetSymbols = Object.getOwnPropertySymbols; + +/** + * Creates an array of the own enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ +var getSymbols = !nativeGetSymbols ? stubArray : function(object) { + if (object == null) { + return []; + } + object = Object(object); + return arrayFilter(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable.call(object, symbol); + }); +}; + +module.exports = getSymbols; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getSymbolsIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getSymbolsIn.js new file mode 100644 index 000000000..cec0855a4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getSymbolsIn.js @@ -0,0 +1,25 @@ +var arrayPush = require('./_arrayPush'), + getPrototype = require('./_getPrototype'), + getSymbols = require('./_getSymbols'), + stubArray = require('./stubArray'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeGetSymbols = Object.getOwnPropertySymbols; + +/** + * Creates an array of the own and inherited enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ +var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { + var result = []; + while (object) { + arrayPush(result, getSymbols(object)); + object = getPrototype(object); + } + return result; +}; + +module.exports = getSymbolsIn; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getTag.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getTag.js new file mode 100644 index 000000000..deaf89d58 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getTag.js @@ -0,0 +1,58 @@ +var DataView = require('./_DataView'), + Map = require('./_Map'), + Promise = require('./_Promise'), + Set = require('./_Set'), + WeakMap = require('./_WeakMap'), + baseGetTag = require('./_baseGetTag'), + toSource = require('./_toSource'); + +/** `Object#toString` result references. */ +var mapTag = '[object Map]', + objectTag = '[object Object]', + promiseTag = '[object Promise]', + setTag = '[object Set]', + weakMapTag = '[object WeakMap]'; + +var dataViewTag = '[object DataView]'; + +/** Used to detect maps, sets, and weakmaps. */ +var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map), + promiseCtorString = toSource(Promise), + setCtorString = toSource(Set), + weakMapCtorString = toSource(WeakMap); + +/** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +var getTag = baseGetTag; + +// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. +if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || + (Map && getTag(new Map) != mapTag) || + (Promise && getTag(Promise.resolve()) != promiseTag) || + (Set && getTag(new Set) != setTag) || + (WeakMap && getTag(new WeakMap) != weakMapTag)) { + getTag = function(value) { + var result = baseGetTag(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : ''; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag; + case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag; + case weakMapCtorString: return weakMapTag; + } + } + return result; + }; +} + +module.exports = getTag; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getValue.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getValue.js new file mode 100644 index 000000000..5f7d77367 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getValue.js @@ -0,0 +1,13 @@ +/** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ +function getValue(object, key) { + return object == null ? undefined : object[key]; +} + +module.exports = getValue; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getView.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getView.js new file mode 100644 index 000000000..df1e5d44b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getView.js @@ -0,0 +1,33 @@ +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max, + nativeMin = Math.min; + +/** + * Gets the view, applying any `transforms` to the `start` and `end` positions. + * + * @private + * @param {number} start The start of the view. + * @param {number} end The end of the view. + * @param {Array} transforms The transformations to apply to the view. + * @returns {Object} Returns an object containing the `start` and `end` + * positions of the view. + */ +function getView(start, end, transforms) { + var index = -1, + length = transforms.length; + + while (++index < length) { + var data = transforms[index], + size = data.size; + + switch (data.type) { + case 'drop': start += size; break; + case 'dropRight': end -= size; break; + case 'take': end = nativeMin(end, start + size); break; + case 'takeRight': start = nativeMax(start, end - size); break; + } + } + return { 'start': start, 'end': end }; +} + +module.exports = getView; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getWrapDetails.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getWrapDetails.js new file mode 100644 index 000000000..3bcc6e48a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_getWrapDetails.js @@ -0,0 +1,17 @@ +/** Used to match wrap detail comments. */ +var reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, + reSplitDetails = /,? & /; + +/** + * Extracts wrapper details from the `source` body comment. + * + * @private + * @param {string} source The source to inspect. + * @returns {Array} Returns the wrapper details. + */ +function getWrapDetails(source) { + var match = source.match(reWrapDetails); + return match ? match[1].split(reSplitDetails) : []; +} + +module.exports = getWrapDetails; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hasPath.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hasPath.js new file mode 100644 index 000000000..93dbde152 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hasPath.js @@ -0,0 +1,39 @@ +var castPath = require('./_castPath'), + isArguments = require('./isArguments'), + isArray = require('./isArray'), + isIndex = require('./_isIndex'), + isLength = require('./isLength'), + toKey = require('./_toKey'); + +/** + * Checks if `path` exists on `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @param {Function} hasFunc The function to check properties. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + */ +function hasPath(object, path, hasFunc) { + path = castPath(path, object); + + var index = -1, + length = path.length, + result = false; + + while (++index < length) { + var key = toKey(path[index]); + if (!(result = object != null && hasFunc(object, key))) { + break; + } + object = object[key]; + } + if (result || ++index != length) { + return result; + } + length = object == null ? 0 : object.length; + return !!length && isLength(length) && isIndex(key, length) && + (isArray(object) || isArguments(object)); +} + +module.exports = hasPath; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hasUnicode.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hasUnicode.js new file mode 100644 index 000000000..cb6ca15f6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hasUnicode.js @@ -0,0 +1,26 @@ +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f', + reComboHalfMarksRange = '\\ufe20-\\ufe2f', + rsComboSymbolsRange = '\\u20d0-\\u20ff', + rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, + rsVarRange = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsZWJ = '\\u200d'; + +/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ +var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); + +/** + * Checks if `string` contains Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a symbol is found, else `false`. + */ +function hasUnicode(string) { + return reHasUnicode.test(string); +} + +module.exports = hasUnicode; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hasUnicodeWord.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hasUnicodeWord.js new file mode 100644 index 000000000..95d52c444 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hasUnicodeWord.js @@ -0,0 +1,15 @@ +/** Used to detect strings that need a more robust regexp to match words. */ +var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + +/** + * Checks if `string` contains a word composed of Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a word is found, else `false`. + */ +function hasUnicodeWord(string) { + return reHasUnicodeWord.test(string); +} + +module.exports = hasUnicodeWord; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashClear.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashClear.js new file mode 100644 index 000000000..5d4b70cc4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashClear.js @@ -0,0 +1,15 @@ +var nativeCreate = require('./_nativeCreate'); + +/** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ +function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; +} + +module.exports = hashClear; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashDelete.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashDelete.js new file mode 100644 index 000000000..ea9dabf13 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashDelete.js @@ -0,0 +1,17 @@ +/** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; +} + +module.exports = hashDelete; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashGet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashGet.js new file mode 100644 index 000000000..1fc2f34b1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashGet.js @@ -0,0 +1,30 @@ +var nativeCreate = require('./_nativeCreate'); + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; +} + +module.exports = hashGet; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashHas.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashHas.js new file mode 100644 index 000000000..281a5517c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashHas.js @@ -0,0 +1,23 @@ +var nativeCreate = require('./_nativeCreate'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function hashHas(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); +} + +module.exports = hashHas; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashSet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashSet.js new file mode 100644 index 000000000..e1055283e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_hashSet.js @@ -0,0 +1,23 @@ +var nativeCreate = require('./_nativeCreate'); + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ +function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; +} + +module.exports = hashSet; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_initCloneArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_initCloneArray.js new file mode 100644 index 000000000..078c15af9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_initCloneArray.js @@ -0,0 +1,26 @@ +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Initializes an array clone. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the initialized clone. + */ +function initCloneArray(array) { + var length = array.length, + result = new array.constructor(length); + + // Add properties assigned by `RegExp#exec`. + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; +} + +module.exports = initCloneArray; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_initCloneByTag.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_initCloneByTag.js new file mode 100644 index 000000000..f69a008ca --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_initCloneByTag.js @@ -0,0 +1,77 @@ +var cloneArrayBuffer = require('./_cloneArrayBuffer'), + cloneDataView = require('./_cloneDataView'), + cloneRegExp = require('./_cloneRegExp'), + cloneSymbol = require('./_cloneSymbol'), + cloneTypedArray = require('./_cloneTypedArray'); + +/** `Object#toString` result references. */ +var boolTag = '[object Boolean]', + dateTag = '[object Date]', + mapTag = '[object Map]', + numberTag = '[object Number]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]'; + +var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + +/** + * Initializes an object clone based on its `toStringTag`. + * + * **Note:** This function only supports cloning values with tags of + * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`. + * + * @private + * @param {Object} object The object to clone. + * @param {string} tag The `toStringTag` of the object to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the initialized clone. + */ +function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return cloneArrayBuffer(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case dataViewTag: + return cloneDataView(object, isDeep); + + case float32Tag: case float64Tag: + case int8Tag: case int16Tag: case int32Tag: + case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: + return cloneTypedArray(object, isDeep); + + case mapTag: + return new Ctor; + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + return cloneRegExp(object); + + case setTag: + return new Ctor; + + case symbolTag: + return cloneSymbol(object); + } +} + +module.exports = initCloneByTag; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_initCloneObject.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_initCloneObject.js new file mode 100644 index 000000000..5a13e64a5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_initCloneObject.js @@ -0,0 +1,18 @@ +var baseCreate = require('./_baseCreate'), + getPrototype = require('./_getPrototype'), + isPrototype = require('./_isPrototype'); + +/** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ +function initCloneObject(object) { + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) + : {}; +} + +module.exports = initCloneObject; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_insertWrapDetails.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_insertWrapDetails.js new file mode 100644 index 000000000..e79080864 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_insertWrapDetails.js @@ -0,0 +1,23 @@ +/** Used to match wrap detail comments. */ +var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/; + +/** + * Inserts wrapper `details` in a comment at the top of the `source` body. + * + * @private + * @param {string} source The source to modify. + * @returns {Array} details The details to insert. + * @returns {string} Returns the modified source. + */ +function insertWrapDetails(source, details) { + var length = details.length; + if (!length) { + return source; + } + var lastIndex = length - 1; + details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; + details = details.join(length > 2 ? ', ' : ' '); + return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); +} + +module.exports = insertWrapDetails; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isFlattenable.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isFlattenable.js new file mode 100644 index 000000000..4cc2c249c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isFlattenable.js @@ -0,0 +1,20 @@ +var Symbol = require('./_Symbol'), + isArguments = require('./isArguments'), + isArray = require('./isArray'); + +/** Built-in value references. */ +var spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined; + +/** + * Checks if `value` is a flattenable `arguments` object or array. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. + */ +function isFlattenable(value) { + return isArray(value) || isArguments(value) || + !!(spreadableSymbol && value && value[spreadableSymbol]); +} + +module.exports = isFlattenable; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isIndex.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isIndex.js new file mode 100644 index 000000000..061cd390c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isIndex.js @@ -0,0 +1,25 @@ +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** Used to detect unsigned integer values. */ +var reIsUint = /^(?:0|[1-9]\d*)$/; + +/** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ +function isIndex(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + + return !!length && + (type == 'number' || + (type != 'symbol' && reIsUint.test(value))) && + (value > -1 && value % 1 == 0 && value < length); +} + +module.exports = isIndex; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isIterateeCall.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isIterateeCall.js new file mode 100644 index 000000000..a0bb5a9cf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isIterateeCall.js @@ -0,0 +1,30 @@ +var eq = require('./eq'), + isArrayLike = require('./isArrayLike'), + isIndex = require('./_isIndex'), + isObject = require('./isObject'); + +/** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ +function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; +} + +module.exports = isIterateeCall; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isKey.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isKey.js new file mode 100644 index 000000000..ff08b0680 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isKey.js @@ -0,0 +1,29 @@ +var isArray = require('./isArray'), + isSymbol = require('./isSymbol'); + +/** Used to match property names within property paths. */ +var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/; + +/** + * Checks if `value` is a property name and not a property path. + * + * @private + * @param {*} value The value to check. + * @param {Object} [object] The object to query keys on. + * @returns {boolean} Returns `true` if `value` is a property name, else `false`. + */ +function isKey(value, object) { + if (isArray(value)) { + return false; + } + var type = typeof value; + if (type == 'number' || type == 'symbol' || type == 'boolean' || + value == null || isSymbol(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object)); +} + +module.exports = isKey; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isKeyable.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isKeyable.js new file mode 100644 index 000000000..39f1828d4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isKeyable.js @@ -0,0 +1,15 @@ +/** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ +function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); +} + +module.exports = isKeyable; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isLaziable.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isLaziable.js new file mode 100644 index 000000000..a57c4f2dc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isLaziable.js @@ -0,0 +1,28 @@ +var LazyWrapper = require('./_LazyWrapper'), + getData = require('./_getData'), + getFuncName = require('./_getFuncName'), + lodash = require('./wrapperLodash'); + +/** + * Checks if `func` has a lazy counterpart. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` has a lazy counterpart, + * else `false`. + */ +function isLaziable(func) { + var funcName = getFuncName(func), + other = lodash[funcName]; + + if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; +} + +module.exports = isLaziable; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isMaskable.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isMaskable.js new file mode 100644 index 000000000..eb98d09f3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isMaskable.js @@ -0,0 +1,14 @@ +var coreJsData = require('./_coreJsData'), + isFunction = require('./isFunction'), + stubFalse = require('./stubFalse'); + +/** + * Checks if `func` is capable of being masked. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `func` is maskable, else `false`. + */ +var isMaskable = coreJsData ? isFunction : stubFalse; + +module.exports = isMaskable; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isMasked.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isMasked.js new file mode 100644 index 000000000..4b0f21ba8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isMasked.js @@ -0,0 +1,20 @@ +var coreJsData = require('./_coreJsData'); + +/** Used to detect methods masquerading as native. */ +var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; +}()); + +/** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ +function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); +} + +module.exports = isMasked; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isPrototype.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isPrototype.js new file mode 100644 index 000000000..0f29498d4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isPrototype.js @@ -0,0 +1,18 @@ +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ +function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; +} + +module.exports = isPrototype; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isStrictComparable.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isStrictComparable.js new file mode 100644 index 000000000..b59f40b85 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_isStrictComparable.js @@ -0,0 +1,15 @@ +var isObject = require('./isObject'); + +/** + * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` if suitable for strict + * equality comparisons, else `false`. + */ +function isStrictComparable(value) { + return value === value && !isObject(value); +} + +module.exports = isStrictComparable; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_iteratorToArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_iteratorToArray.js new file mode 100644 index 000000000..476856647 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_iteratorToArray.js @@ -0,0 +1,18 @@ +/** + * Converts `iterator` to an array. + * + * @private + * @param {Object} iterator The iterator to convert. + * @returns {Array} Returns the converted array. + */ +function iteratorToArray(iterator) { + var data, + result = []; + + while (!(data = iterator.next()).done) { + result.push(data.value); + } + return result; +} + +module.exports = iteratorToArray; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_lazyClone.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_lazyClone.js new file mode 100644 index 000000000..d8a51f870 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_lazyClone.js @@ -0,0 +1,23 @@ +var LazyWrapper = require('./_LazyWrapper'), + copyArray = require('./_copyArray'); + +/** + * Creates a clone of the lazy wrapper object. + * + * @private + * @name clone + * @memberOf LazyWrapper + * @returns {Object} Returns the cloned `LazyWrapper` object. + */ +function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = copyArray(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = copyArray(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = copyArray(this.__views__); + return result; +} + +module.exports = lazyClone; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_lazyReverse.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_lazyReverse.js new file mode 100644 index 000000000..c5b52190f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_lazyReverse.js @@ -0,0 +1,23 @@ +var LazyWrapper = require('./_LazyWrapper'); + +/** + * Reverses the direction of lazy iteration. + * + * @private + * @name reverse + * @memberOf LazyWrapper + * @returns {Object} Returns the new reversed `LazyWrapper` object. + */ +function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; +} + +module.exports = lazyReverse; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_lazyValue.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_lazyValue.js new file mode 100644 index 000000000..371ca8d22 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_lazyValue.js @@ -0,0 +1,69 @@ +var baseWrapperValue = require('./_baseWrapperValue'), + getView = require('./_getView'), + isArray = require('./isArray'); + +/** Used to indicate the type of lazy iteratees. */ +var LAZY_FILTER_FLAG = 1, + LAZY_MAP_FLAG = 2; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMin = Math.min; + +/** + * Extracts the unwrapped value from its lazy wrapper. + * + * @private + * @name value + * @memberOf LazyWrapper + * @returns {*} Returns the unwrapped value. + */ +function lazyValue() { + var array = this.__wrapped__.value(), + dir = this.__dir__, + isArr = isArray(array), + isRight = dir < 0, + arrLength = isArr ? array.length : 0, + view = getView(0, arrLength, this.__views__), + start = view.start, + end = view.end, + length = end - start, + index = isRight ? end : (start - 1), + iteratees = this.__iteratees__, + iterLength = iteratees.length, + resIndex = 0, + takeCount = nativeMin(length, this.__takeCount__); + + if (!isArr || (!isRight && arrLength == length && takeCount == length)) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + + outer: + while (length-- && resIndex < takeCount) { + index += dir; + + var iterIndex = -1, + value = array[index]; + + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], + iteratee = data.iteratee, + type = data.type, + computed = iteratee(value); + + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; +} + +module.exports = lazyValue; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheClear.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheClear.js new file mode 100644 index 000000000..acbe39a59 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheClear.js @@ -0,0 +1,13 @@ +/** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ +function listCacheClear() { + this.__data__ = []; + this.size = 0; +} + +module.exports = listCacheClear; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheDelete.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheDelete.js new file mode 100644 index 000000000..b1384ade9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheDelete.js @@ -0,0 +1,35 @@ +var assocIndexOf = require('./_assocIndexOf'); + +/** Used for built-in method references. */ +var arrayProto = Array.prototype; + +/** Built-in value references. */ +var splice = arrayProto.splice; + +/** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; +} + +module.exports = listCacheDelete; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheGet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheGet.js new file mode 100644 index 000000000..f8192fc38 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheGet.js @@ -0,0 +1,19 @@ +var assocIndexOf = require('./_assocIndexOf'); + +/** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; +} + +module.exports = listCacheGet; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheHas.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheHas.js new file mode 100644 index 000000000..2adf67146 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheHas.js @@ -0,0 +1,16 @@ +var assocIndexOf = require('./_assocIndexOf'); + +/** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; +} + +module.exports = listCacheHas; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheSet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheSet.js new file mode 100644 index 000000000..5855c95e4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_listCacheSet.js @@ -0,0 +1,26 @@ +var assocIndexOf = require('./_assocIndexOf'); + +/** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ +function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; +} + +module.exports = listCacheSet; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheClear.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheClear.js new file mode 100644 index 000000000..bc9ca204a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheClear.js @@ -0,0 +1,21 @@ +var Hash = require('./_Hash'), + ListCache = require('./_ListCache'), + Map = require('./_Map'); + +/** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ +function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; +} + +module.exports = mapCacheClear; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheDelete.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheDelete.js new file mode 100644 index 000000000..946ca3c93 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheDelete.js @@ -0,0 +1,18 @@ +var getMapData = require('./_getMapData'); + +/** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; +} + +module.exports = mapCacheDelete; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheGet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheGet.js new file mode 100644 index 000000000..f29f55cfd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheGet.js @@ -0,0 +1,16 @@ +var getMapData = require('./_getMapData'); + +/** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function mapCacheGet(key) { + return getMapData(this, key).get(key); +} + +module.exports = mapCacheGet; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheHas.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheHas.js new file mode 100644 index 000000000..a1214c028 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheHas.js @@ -0,0 +1,16 @@ +var getMapData = require('./_getMapData'); + +/** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function mapCacheHas(key) { + return getMapData(this, key).has(key); +} + +module.exports = mapCacheHas; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheSet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheSet.js new file mode 100644 index 000000000..734684927 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapCacheSet.js @@ -0,0 +1,22 @@ +var getMapData = require('./_getMapData'); + +/** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ +function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; +} + +module.exports = mapCacheSet; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapToArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapToArray.js new file mode 100644 index 000000000..fe3dd531a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mapToArray.js @@ -0,0 +1,18 @@ +/** + * Converts `map` to its key-value pairs. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. + */ +function mapToArray(map) { + var index = -1, + result = Array(map.size); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; +} + +module.exports = mapToArray; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_matchesStrictComparable.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_matchesStrictComparable.js new file mode 100644 index 000000000..f608af9ec --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_matchesStrictComparable.js @@ -0,0 +1,20 @@ +/** + * A specialized version of `matchesProperty` for source values suitable + * for strict equality comparisons, i.e. `===`. + * + * @private + * @param {string} key The key of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ +function matchesStrictComparable(key, srcValue) { + return function(object) { + if (object == null) { + return false; + } + return object[key] === srcValue && + (srcValue !== undefined || (key in Object(object))); + }; +} + +module.exports = matchesStrictComparable; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_memoizeCapped.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_memoizeCapped.js new file mode 100644 index 000000000..7f71c8fba --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_memoizeCapped.js @@ -0,0 +1,26 @@ +var memoize = require('./memoize'); + +/** Used as the maximum memoize cache size. */ +var MAX_MEMOIZE_SIZE = 500; + +/** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ +function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + + var cache = result.cache; + return result; +} + +module.exports = memoizeCapped; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mergeData.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mergeData.js new file mode 100644 index 000000000..cb570f976 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_mergeData.js @@ -0,0 +1,90 @@ +var composeArgs = require('./_composeArgs'), + composeArgsRight = require('./_composeArgsRight'), + replaceHolders = require('./_replaceHolders'); + +/** Used as the internal argument placeholder. */ +var PLACEHOLDER = '__lodash_placeholder__'; + +/** Used to compose bitmasks for function metadata. */ +var WRAP_BIND_FLAG = 1, + WRAP_BIND_KEY_FLAG = 2, + WRAP_CURRY_BOUND_FLAG = 4, + WRAP_CURRY_FLAG = 8, + WRAP_ARY_FLAG = 128, + WRAP_REARG_FLAG = 256; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMin = Math.min; + +/** + * Merges the function metadata of `source` into `data`. + * + * Merging metadata reduces the number of wrappers used to invoke a function. + * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` + * may be applied regardless of execution order. Methods like `_.ary` and + * `_.rearg` modify function arguments, making the order in which they are + * executed important, preventing the merging of metadata. However, we make + * an exception for a safe combined case where curried functions have `_.ary` + * and or `_.rearg` applied. + * + * @private + * @param {Array} data The destination metadata. + * @param {Array} source The source metadata. + * @returns {Array} Returns `data`. + */ +function mergeData(data, source) { + var bitmask = data[1], + srcBitmask = source[1], + newBitmask = bitmask | srcBitmask, + isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG); + + var isCombo = + ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) || + ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) || + ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG)); + + // Exit early if metadata can't be merged. + if (!(isCommon || isCombo)) { + return data; + } + // Use source `thisArg` if available. + if (srcBitmask & WRAP_BIND_FLAG) { + data[2] = source[2]; + // Set when currying a bound function. + newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG; + } + // Compose partial arguments. + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : value; + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4]; + } + // Compose partial right arguments. + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6]; + } + // Use source `argPos` if available. + value = source[7]; + if (value) { + data[7] = value; + } + // Use source `ary` if it's smaller. + if (srcBitmask & WRAP_ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + // Use source `arity` if one is not provided. + if (data[9] == null) { + data[9] = source[9]; + } + // Use source `func` and merge bitmasks. + data[0] = source[0]; + data[1] = newBitmask; + + return data; +} + +module.exports = mergeData; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_metaMap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_metaMap.js new file mode 100644 index 000000000..0157a0b09 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_metaMap.js @@ -0,0 +1,6 @@ +var WeakMap = require('./_WeakMap'); + +/** Used to store function metadata. */ +var metaMap = WeakMap && new WeakMap; + +module.exports = metaMap; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nativeCreate.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nativeCreate.js new file mode 100644 index 000000000..c7aede85b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nativeCreate.js @@ -0,0 +1,6 @@ +var getNative = require('./_getNative'); + +/* Built-in method references that are verified to be native. */ +var nativeCreate = getNative(Object, 'create'); + +module.exports = nativeCreate; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nativeKeys.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nativeKeys.js new file mode 100644 index 000000000..479a104a1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nativeKeys.js @@ -0,0 +1,6 @@ +var overArg = require('./_overArg'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeKeys = overArg(Object.keys, Object); + +module.exports = nativeKeys; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nativeKeysIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nativeKeysIn.js new file mode 100644 index 000000000..00ee50594 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nativeKeysIn.js @@ -0,0 +1,20 @@ +/** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; +} + +module.exports = nativeKeysIn; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nodeUtil.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nodeUtil.js new file mode 100644 index 000000000..983d78f75 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_nodeUtil.js @@ -0,0 +1,30 @@ +var freeGlobal = require('./_freeGlobal'); + +/** Detect free variable `exports`. */ +var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Detect free variable `process` from Node.js. */ +var freeProcess = moduleExports && freeGlobal.process; + +/** Used to access faster Node.js helpers. */ +var nodeUtil = (function() { + try { + // Use `util.types` for Node.js 10+. + var types = freeModule && freeModule.require && freeModule.require('util').types; + + if (types) { + return types; + } + + // Legacy `process.binding('util')` for Node.js < 10. + return freeProcess && freeProcess.binding && freeProcess.binding('util'); + } catch (e) {} +}()); + +module.exports = nodeUtil; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_objectToString.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_objectToString.js new file mode 100644 index 000000000..c614ec09b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_objectToString.js @@ -0,0 +1,22 @@ +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ +function objectToString(value) { + return nativeObjectToString.call(value); +} + +module.exports = objectToString; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_overArg.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_overArg.js new file mode 100644 index 000000000..651c5c55f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_overArg.js @@ -0,0 +1,15 @@ +/** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ +function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; +} + +module.exports = overArg; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_overRest.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_overRest.js new file mode 100644 index 000000000..c7cdef339 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_overRest.js @@ -0,0 +1,36 @@ +var apply = require('./_apply'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ +function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return apply(func, this, otherArgs); + }; +} + +module.exports = overRest; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_parent.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_parent.js new file mode 100644 index 000000000..f174328fc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_parent.js @@ -0,0 +1,16 @@ +var baseGet = require('./_baseGet'), + baseSlice = require('./_baseSlice'); + +/** + * Gets the parent value at `path` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} path The path to get the parent value of. + * @returns {*} Returns the parent value. + */ +function parent(object, path) { + return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1)); +} + +module.exports = parent; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reEscape.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reEscape.js new file mode 100644 index 000000000..7f47eda68 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reEscape.js @@ -0,0 +1,4 @@ +/** Used to match template delimiters. */ +var reEscape = /<%-([\s\S]+?)%>/g; + +module.exports = reEscape; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reEvaluate.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reEvaluate.js new file mode 100644 index 000000000..6adfc312c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reEvaluate.js @@ -0,0 +1,4 @@ +/** Used to match template delimiters. */ +var reEvaluate = /<%([\s\S]+?)%>/g; + +module.exports = reEvaluate; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reInterpolate.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reInterpolate.js new file mode 100644 index 000000000..d02ff0b29 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reInterpolate.js @@ -0,0 +1,4 @@ +/** Used to match template delimiters. */ +var reInterpolate = /<%=([\s\S]+?)%>/g; + +module.exports = reInterpolate; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_realNames.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_realNames.js new file mode 100644 index 000000000..aa0d52926 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_realNames.js @@ -0,0 +1,4 @@ +/** Used to lookup unminified function names. */ +var realNames = {}; + +module.exports = realNames; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reorder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reorder.js new file mode 100644 index 000000000..a3502b051 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_reorder.js @@ -0,0 +1,29 @@ +var copyArray = require('./_copyArray'), + isIndex = require('./_isIndex'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMin = Math.min; + +/** + * Reorder `array` according to the specified indexes where the element at + * the first index is assigned as the first element, the element at + * the second index is assigned as the second element, and so on. + * + * @private + * @param {Array} array The array to reorder. + * @param {Array} indexes The arranged array indexes. + * @returns {Array} Returns `array`. + */ +function reorder(array, indexes) { + var arrLength = array.length, + length = nativeMin(indexes.length, arrLength), + oldArray = copyArray(array); + + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; +} + +module.exports = reorder; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_replaceHolders.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_replaceHolders.js new file mode 100644 index 000000000..74360ec4d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_replaceHolders.js @@ -0,0 +1,29 @@ +/** Used as the internal argument placeholder. */ +var PLACEHOLDER = '__lodash_placeholder__'; + +/** + * Replaces all `placeholder` elements in `array` with an internal placeholder + * and returns an array of their indexes. + * + * @private + * @param {Array} array The array to modify. + * @param {*} placeholder The placeholder to replace. + * @returns {Array} Returns the new array of placeholder indexes. + */ +function replaceHolders(array, placeholder) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value === placeholder || value === PLACEHOLDER) { + array[index] = PLACEHOLDER; + result[resIndex++] = index; + } + } + return result; +} + +module.exports = replaceHolders; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_root.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_root.js new file mode 100644 index 000000000..d2852bed4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_root.js @@ -0,0 +1,9 @@ +var freeGlobal = require('./_freeGlobal'); + +/** Detect free variable `self`. */ +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + +/** Used as a reference to the global object. */ +var root = freeGlobal || freeSelf || Function('return this')(); + +module.exports = root; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_safeGet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_safeGet.js new file mode 100644 index 000000000..b070897db --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_safeGet.js @@ -0,0 +1,21 @@ +/** + * Gets the value at `key`, unless `key` is "__proto__" or "constructor". + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ +function safeGet(object, key) { + if (key === 'constructor' && typeof object[key] === 'function') { + return; + } + + if (key == '__proto__') { + return; + } + + return object[key]; +} + +module.exports = safeGet; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setCacheAdd.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setCacheAdd.js new file mode 100644 index 000000000..1081a7442 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setCacheAdd.js @@ -0,0 +1,19 @@ +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** + * Adds `value` to the array cache. + * + * @private + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. + */ +function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; +} + +module.exports = setCacheAdd; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setCacheHas.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setCacheHas.js new file mode 100644 index 000000000..9a492556e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setCacheHas.js @@ -0,0 +1,14 @@ +/** + * Checks if `value` is in the array cache. + * + * @private + * @name has + * @memberOf SetCache + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. + */ +function setCacheHas(value) { + return this.__data__.has(value); +} + +module.exports = setCacheHas; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setData.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setData.js new file mode 100644 index 000000000..e5cf3eb96 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setData.js @@ -0,0 +1,20 @@ +var baseSetData = require('./_baseSetData'), + shortOut = require('./_shortOut'); + +/** + * Sets metadata for `func`. + * + * **Note:** If this function becomes hot, i.e. is invoked a lot in a short + * period of time, it will trip its breaker and transition to an identity + * function to avoid garbage collection pauses in V8. See + * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070) + * for more details. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ +var setData = shortOut(baseSetData); + +module.exports = setData; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setToArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setToArray.js new file mode 100644 index 000000000..b87f07418 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setToArray.js @@ -0,0 +1,18 @@ +/** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ +function setToArray(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; +} + +module.exports = setToArray; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setToPairs.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setToPairs.js new file mode 100644 index 000000000..36ad37a05 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setToPairs.js @@ -0,0 +1,18 @@ +/** + * Converts `set` to its value-value pairs. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the value-value pairs. + */ +function setToPairs(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = [value, value]; + }); + return result; +} + +module.exports = setToPairs; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setToString.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setToString.js new file mode 100644 index 000000000..6ca841967 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setToString.js @@ -0,0 +1,14 @@ +var baseSetToString = require('./_baseSetToString'), + shortOut = require('./_shortOut'); + +/** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ +var setToString = shortOut(baseSetToString); + +module.exports = setToString; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setWrapToString.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setWrapToString.js new file mode 100644 index 000000000..decdc4499 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_setWrapToString.js @@ -0,0 +1,21 @@ +var getWrapDetails = require('./_getWrapDetails'), + insertWrapDetails = require('./_insertWrapDetails'), + setToString = require('./_setToString'), + updateWrapDetails = require('./_updateWrapDetails'); + +/** + * Sets the `toString` method of `wrapper` to mimic the source of `reference` + * with wrapper details in a comment at the top of the source body. + * + * @private + * @param {Function} wrapper The function to modify. + * @param {Function} reference The reference function. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Function} Returns `wrapper`. + */ +function setWrapToString(wrapper, reference, bitmask) { + var source = (reference + ''); + return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); +} + +module.exports = setWrapToString; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_shortOut.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_shortOut.js new file mode 100644 index 000000000..3300a0796 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_shortOut.js @@ -0,0 +1,37 @@ +/** Used to detect hot functions by number of calls within a span of milliseconds. */ +var HOT_COUNT = 800, + HOT_SPAN = 16; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeNow = Date.now; + +/** + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. + * + * @private + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. + */ +function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; +} + +module.exports = shortOut; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_shuffleSelf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_shuffleSelf.js new file mode 100644 index 000000000..8bcc4f5c3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_shuffleSelf.js @@ -0,0 +1,28 @@ +var baseRandom = require('./_baseRandom'); + +/** + * A specialized version of `_.shuffle` which mutates and sets the size of `array`. + * + * @private + * @param {Array} array The array to shuffle. + * @param {number} [size=array.length] The size of `array`. + * @returns {Array} Returns `array`. + */ +function shuffleSelf(array, size) { + var index = -1, + length = array.length, + lastIndex = length - 1; + + size = size === undefined ? length : size; + while (++index < size) { + var rand = baseRandom(index, lastIndex), + value = array[rand]; + + array[rand] = array[index]; + array[index] = value; + } + array.length = size; + return array; +} + +module.exports = shuffleSelf; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackClear.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackClear.js new file mode 100644 index 000000000..ce8e5a92f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackClear.js @@ -0,0 +1,15 @@ +var ListCache = require('./_ListCache'); + +/** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ +function stackClear() { + this.__data__ = new ListCache; + this.size = 0; +} + +module.exports = stackClear; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackDelete.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackDelete.js new file mode 100644 index 000000000..ff9887ab6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackDelete.js @@ -0,0 +1,18 @@ +/** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; +} + +module.exports = stackDelete; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackGet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackGet.js new file mode 100644 index 000000000..1cdf00409 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackGet.js @@ -0,0 +1,14 @@ +/** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function stackGet(key) { + return this.__data__.get(key); +} + +module.exports = stackGet; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackHas.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackHas.js new file mode 100644 index 000000000..16a3ad11b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackHas.js @@ -0,0 +1,14 @@ +/** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function stackHas(key) { + return this.__data__.has(key); +} + +module.exports = stackHas; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackSet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackSet.js new file mode 100644 index 000000000..b790ac5f4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stackSet.js @@ -0,0 +1,34 @@ +var ListCache = require('./_ListCache'), + Map = require('./_Map'), + MapCache = require('./_MapCache'); + +/** Used as the size to enable large array optimizations. */ +var LARGE_ARRAY_SIZE = 200; + +/** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ +function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; +} + +module.exports = stackSet; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_strictIndexOf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_strictIndexOf.js new file mode 100644 index 000000000..0486a4956 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_strictIndexOf.js @@ -0,0 +1,23 @@ +/** + * A specialized version of `_.indexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; +} + +module.exports = strictIndexOf; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_strictLastIndexOf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_strictLastIndexOf.js new file mode 100644 index 000000000..d7310dcc2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_strictLastIndexOf.js @@ -0,0 +1,21 @@ +/** + * A specialized version of `_.lastIndexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function strictLastIndexOf(array, value, fromIndex) { + var index = fromIndex + 1; + while (index--) { + if (array[index] === value) { + return index; + } + } + return index; +} + +module.exports = strictLastIndexOf; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stringSize.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stringSize.js new file mode 100644 index 000000000..17ef462a6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stringSize.js @@ -0,0 +1,18 @@ +var asciiSize = require('./_asciiSize'), + hasUnicode = require('./_hasUnicode'), + unicodeSize = require('./_unicodeSize'); + +/** + * Gets the number of symbols in `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the string size. + */ +function stringSize(string) { + return hasUnicode(string) + ? unicodeSize(string) + : asciiSize(string); +} + +module.exports = stringSize; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stringToArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stringToArray.js new file mode 100644 index 000000000..d161158c6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stringToArray.js @@ -0,0 +1,18 @@ +var asciiToArray = require('./_asciiToArray'), + hasUnicode = require('./_hasUnicode'), + unicodeToArray = require('./_unicodeToArray'); + +/** + * Converts `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function stringToArray(string) { + return hasUnicode(string) + ? unicodeToArray(string) + : asciiToArray(string); +} + +module.exports = stringToArray; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stringToPath.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stringToPath.js new file mode 100644 index 000000000..8f39f8a29 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_stringToPath.js @@ -0,0 +1,27 @@ +var memoizeCapped = require('./_memoizeCapped'); + +/** Used to match property names within property paths. */ +var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + +/** Used to match backslashes in property paths. */ +var reEscapeChar = /\\(\\)?/g; + +/** + * Converts `string` to a property path array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the property path array. + */ +var stringToPath = memoizeCapped(function(string) { + var result = []; + if (string.charCodeAt(0) === 46 /* . */) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, subString) { + result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match)); + }); + return result; +}); + +module.exports = stringToPath; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_toKey.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_toKey.js new file mode 100644 index 000000000..c6d645c4d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_toKey.js @@ -0,0 +1,21 @@ +var isSymbol = require('./isSymbol'); + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** + * Converts `value` to a string key if it's not a string or symbol. + * + * @private + * @param {*} value The value to inspect. + * @returns {string|symbol} Returns the key. + */ +function toKey(value) { + if (typeof value == 'string' || isSymbol(value)) { + return value; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + +module.exports = toKey; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_toSource.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_toSource.js new file mode 100644 index 000000000..a020b386c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_toSource.js @@ -0,0 +1,26 @@ +/** Used for built-in method references. */ +var funcProto = Function.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ +function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; +} + +module.exports = toSource; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_trimmedEndIndex.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_trimmedEndIndex.js new file mode 100644 index 000000000..139439ad4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_trimmedEndIndex.js @@ -0,0 +1,19 @@ +/** Used to match a single whitespace character. */ +var reWhitespace = /\s/; + +/** + * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace + * character of `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the last non-whitespace character. + */ +function trimmedEndIndex(string) { + var index = string.length; + + while (index-- && reWhitespace.test(string.charAt(index))) {} + return index; +} + +module.exports = trimmedEndIndex; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unescapeHtmlChar.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unescapeHtmlChar.js new file mode 100644 index 000000000..a71fecb3f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unescapeHtmlChar.js @@ -0,0 +1,21 @@ +var basePropertyOf = require('./_basePropertyOf'); + +/** Used to map HTML entities to characters. */ +var htmlUnescapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + ''': "'" +}; + +/** + * Used by `_.unescape` to convert HTML entities to characters. + * + * @private + * @param {string} chr The matched character to unescape. + * @returns {string} Returns the unescaped character. + */ +var unescapeHtmlChar = basePropertyOf(htmlUnescapes); + +module.exports = unescapeHtmlChar; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unicodeSize.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unicodeSize.js new file mode 100644 index 000000000..68137ec2c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unicodeSize.js @@ -0,0 +1,44 @@ +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f', + reComboHalfMarksRange = '\\ufe20-\\ufe2f', + rsComboSymbolsRange = '\\u20d0-\\u20ff', + rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, + rsVarRange = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsAstral = '[' + rsAstralRange + ']', + rsCombo = '[' + rsComboRange + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsZWJ = '\\u200d'; + +/** Used to compose unicode regexes. */ +var reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + +/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ +var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); + +/** + * Gets the size of a Unicode `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ +function unicodeSize(string) { + var result = reUnicode.lastIndex = 0; + while (reUnicode.test(string)) { + ++result; + } + return result; +} + +module.exports = unicodeSize; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unicodeToArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unicodeToArray.js new file mode 100644 index 000000000..2a725c062 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unicodeToArray.js @@ -0,0 +1,40 @@ +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f', + reComboHalfMarksRange = '\\ufe20-\\ufe2f', + rsComboSymbolsRange = '\\u20d0-\\u20ff', + rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, + rsVarRange = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsAstral = '[' + rsAstralRange + ']', + rsCombo = '[' + rsComboRange + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsZWJ = '\\u200d'; + +/** Used to compose unicode regexes. */ +var reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + +/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ +var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); + +/** + * Converts a Unicode `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function unicodeToArray(string) { + return string.match(reUnicode) || []; +} + +module.exports = unicodeToArray; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unicodeWords.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unicodeWords.js new file mode 100644 index 000000000..e72e6e0f9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_unicodeWords.js @@ -0,0 +1,69 @@ +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f', + reComboHalfMarksRange = '\\ufe20-\\ufe2f', + rsComboSymbolsRange = '\\u20d0-\\u20ff', + rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, + rsDingbatRange = '\\u2700-\\u27bf', + rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', + rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', + rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', + rsPunctuationRange = '\\u2000-\\u206f', + rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', + rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', + rsVarRange = '\\ufe0e\\ufe0f', + rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; + +/** Used to compose unicode capture groups. */ +var rsApos = "['\u2019]", + rsBreak = '[' + rsBreakRange + ']', + rsCombo = '[' + rsComboRange + ']', + rsDigits = '\\d+', + rsDingbat = '[' + rsDingbatRange + ']', + rsLower = '[' + rsLowerRange + ']', + rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsUpper = '[' + rsUpperRange + ']', + rsZWJ = '\\u200d'; + +/** Used to compose unicode regexes. */ +var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')', + rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')', + rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', + rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', + reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])', + rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq; + +/** Used to match complex or compound words. */ +var reUnicodeWord = RegExp([ + rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', + rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')', + rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower, + rsUpper + '+' + rsOptContrUpper, + rsOrdUpper, + rsOrdLower, + rsDigits, + rsEmoji +].join('|'), 'g'); + +/** + * Splits a Unicode `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ +function unicodeWords(string) { + return string.match(reUnicodeWord) || []; +} + +module.exports = unicodeWords; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_updateWrapDetails.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_updateWrapDetails.js new file mode 100644 index 000000000..8759fbdf7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_updateWrapDetails.js @@ -0,0 +1,46 @@ +var arrayEach = require('./_arrayEach'), + arrayIncludes = require('./_arrayIncludes'); + +/** Used to compose bitmasks for function metadata. */ +var WRAP_BIND_FLAG = 1, + WRAP_BIND_KEY_FLAG = 2, + WRAP_CURRY_FLAG = 8, + WRAP_CURRY_RIGHT_FLAG = 16, + WRAP_PARTIAL_FLAG = 32, + WRAP_PARTIAL_RIGHT_FLAG = 64, + WRAP_ARY_FLAG = 128, + WRAP_REARG_FLAG = 256, + WRAP_FLIP_FLAG = 512; + +/** Used to associate wrap methods with their bit flags. */ +var wrapFlags = [ + ['ary', WRAP_ARY_FLAG], + ['bind', WRAP_BIND_FLAG], + ['bindKey', WRAP_BIND_KEY_FLAG], + ['curry', WRAP_CURRY_FLAG], + ['curryRight', WRAP_CURRY_RIGHT_FLAG], + ['flip', WRAP_FLIP_FLAG], + ['partial', WRAP_PARTIAL_FLAG], + ['partialRight', WRAP_PARTIAL_RIGHT_FLAG], + ['rearg', WRAP_REARG_FLAG] +]; + +/** + * Updates wrapper `details` based on `bitmask` flags. + * + * @private + * @returns {Array} details The details to modify. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Array} Returns `details`. + */ +function updateWrapDetails(details, bitmask) { + arrayEach(wrapFlags, function(pair) { + var value = '_.' + pair[0]; + if ((bitmask & pair[1]) && !arrayIncludes(details, value)) { + details.push(value); + } + }); + return details.sort(); +} + +module.exports = updateWrapDetails; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_wrapperClone.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_wrapperClone.js new file mode 100644 index 000000000..7bb58a2e8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/_wrapperClone.js @@ -0,0 +1,23 @@ +var LazyWrapper = require('./_LazyWrapper'), + LodashWrapper = require('./_LodashWrapper'), + copyArray = require('./_copyArray'); + +/** + * Creates a clone of `wrapper`. + * + * @private + * @param {Object} wrapper The wrapper to clone. + * @returns {Object} Returns the cloned wrapper. + */ +function wrapperClone(wrapper) { + if (wrapper instanceof LazyWrapper) { + return wrapper.clone(); + } + var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); + result.__actions__ = copyArray(wrapper.__actions__); + result.__index__ = wrapper.__index__; + result.__values__ = wrapper.__values__; + return result; +} + +module.exports = wrapperClone; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/add.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/add.js new file mode 100644 index 000000000..f06951564 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/add.js @@ -0,0 +1,22 @@ +var createMathOperation = require('./_createMathOperation'); + +/** + * Adds two numbers. + * + * @static + * @memberOf _ + * @since 3.4.0 + * @category Math + * @param {number} augend The first number in an addition. + * @param {number} addend The second number in an addition. + * @returns {number} Returns the total. + * @example + * + * _.add(6, 4); + * // => 10 + */ +var add = createMathOperation(function(augend, addend) { + return augend + addend; +}, 0); + +module.exports = add; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/after.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/after.js new file mode 100644 index 000000000..3900c979a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/after.js @@ -0,0 +1,42 @@ +var toInteger = require('./toInteger'); + +/** Error message constants. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/** + * The opposite of `_.before`; this method creates a function that invokes + * `func` once it's called `n` or more times. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {number} n The number of calls before `func` is invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var saves = ['profile', 'settings']; + * + * var done = _.after(saves.length, function() { + * console.log('done saving!'); + * }); + * + * _.forEach(saves, function(type) { + * asyncSave({ 'type': type, 'complete': done }); + * }); + * // => Logs 'done saving!' after the two async saves have completed. + */ +function after(n, func) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; +} + +module.exports = after; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/array.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/array.js new file mode 100644 index 000000000..af688d3ee --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/array.js @@ -0,0 +1,67 @@ +module.exports = { + 'chunk': require('./chunk'), + 'compact': require('./compact'), + 'concat': require('./concat'), + 'difference': require('./difference'), + 'differenceBy': require('./differenceBy'), + 'differenceWith': require('./differenceWith'), + 'drop': require('./drop'), + 'dropRight': require('./dropRight'), + 'dropRightWhile': require('./dropRightWhile'), + 'dropWhile': require('./dropWhile'), + 'fill': require('./fill'), + 'findIndex': require('./findIndex'), + 'findLastIndex': require('./findLastIndex'), + 'first': require('./first'), + 'flatten': require('./flatten'), + 'flattenDeep': require('./flattenDeep'), + 'flattenDepth': require('./flattenDepth'), + 'fromPairs': require('./fromPairs'), + 'head': require('./head'), + 'indexOf': require('./indexOf'), + 'initial': require('./initial'), + 'intersection': require('./intersection'), + 'intersectionBy': require('./intersectionBy'), + 'intersectionWith': require('./intersectionWith'), + 'join': require('./join'), + 'last': require('./last'), + 'lastIndexOf': require('./lastIndexOf'), + 'nth': require('./nth'), + 'pull': require('./pull'), + 'pullAll': require('./pullAll'), + 'pullAllBy': require('./pullAllBy'), + 'pullAllWith': require('./pullAllWith'), + 'pullAt': require('./pullAt'), + 'remove': require('./remove'), + 'reverse': require('./reverse'), + 'slice': require('./slice'), + 'sortedIndex': require('./sortedIndex'), + 'sortedIndexBy': require('./sortedIndexBy'), + 'sortedIndexOf': require('./sortedIndexOf'), + 'sortedLastIndex': require('./sortedLastIndex'), + 'sortedLastIndexBy': require('./sortedLastIndexBy'), + 'sortedLastIndexOf': require('./sortedLastIndexOf'), + 'sortedUniq': require('./sortedUniq'), + 'sortedUniqBy': require('./sortedUniqBy'), + 'tail': require('./tail'), + 'take': require('./take'), + 'takeRight': require('./takeRight'), + 'takeRightWhile': require('./takeRightWhile'), + 'takeWhile': require('./takeWhile'), + 'union': require('./union'), + 'unionBy': require('./unionBy'), + 'unionWith': require('./unionWith'), + 'uniq': require('./uniq'), + 'uniqBy': require('./uniqBy'), + 'uniqWith': require('./uniqWith'), + 'unzip': require('./unzip'), + 'unzipWith': require('./unzipWith'), + 'without': require('./without'), + 'xor': require('./xor'), + 'xorBy': require('./xorBy'), + 'xorWith': require('./xorWith'), + 'zip': require('./zip'), + 'zipObject': require('./zipObject'), + 'zipObjectDeep': require('./zipObjectDeep'), + 'zipWith': require('./zipWith') +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/ary.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/ary.js new file mode 100644 index 000000000..70c87d094 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/ary.js @@ -0,0 +1,29 @@ +var createWrap = require('./_createWrap'); + +/** Used to compose bitmasks for function metadata. */ +var WRAP_ARY_FLAG = 128; + +/** + * Creates a function that invokes `func`, with up to `n` arguments, + * ignoring any additional arguments. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to cap arguments for. + * @param {number} [n=func.length] The arity cap. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new capped function. + * @example + * + * _.map(['6', '8', '10'], _.ary(parseInt, 1)); + * // => [6, 8, 10] + */ +function ary(func, n, guard) { + n = guard ? undefined : n; + n = (func && n == null) ? func.length : n; + return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n); +} + +module.exports = ary; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assign.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assign.js new file mode 100644 index 000000000..909db26a3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assign.js @@ -0,0 +1,58 @@ +var assignValue = require('./_assignValue'), + copyObject = require('./_copyObject'), + createAssigner = require('./_createAssigner'), + isArrayLike = require('./isArrayLike'), + isPrototype = require('./_isPrototype'), + keys = require('./keys'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Assigns own enumerable string keyed properties of source objects to the + * destination object. Source objects are applied from left to right. + * Subsequent sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object` and is loosely based on + * [`Object.assign`](https://mdn.io/Object/assign). + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assignIn + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assign({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'c': 3 } + */ +var assign = createAssigner(function(object, source) { + if (isPrototype(source) || isArrayLike(source)) { + copyObject(source, keys(source), object); + return; + } + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + assignValue(object, key, source[key]); + } + } +}); + +module.exports = assign; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assignIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assignIn.js new file mode 100644 index 000000000..e663473a0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assignIn.js @@ -0,0 +1,40 @@ +var copyObject = require('./_copyObject'), + createAssigner = require('./_createAssigner'), + keysIn = require('./keysIn'); + +/** + * This method is like `_.assign` except that it iterates over own and + * inherited source properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extend + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assign + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assignIn({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } + */ +var assignIn = createAssigner(function(object, source) { + copyObject(source, keysIn(source), object); +}); + +module.exports = assignIn; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assignInWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assignInWith.js new file mode 100644 index 000000000..68fcc0b03 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assignInWith.js @@ -0,0 +1,38 @@ +var copyObject = require('./_copyObject'), + createAssigner = require('./_createAssigner'), + keysIn = require('./keysIn'); + +/** + * This method is like `_.assignIn` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extendWith + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignInWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ +var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keysIn(source), object, customizer); +}); + +module.exports = assignInWith; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assignWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assignWith.js new file mode 100644 index 000000000..7dc6c761b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/assignWith.js @@ -0,0 +1,37 @@ +var copyObject = require('./_copyObject'), + createAssigner = require('./_createAssigner'), + keys = require('./keys'); + +/** + * This method is like `_.assign` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignInWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ +var assignWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keys(source), object, customizer); +}); + +module.exports = assignWith; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/at.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/at.js new file mode 100644 index 000000000..781ee9e5f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/at.js @@ -0,0 +1,23 @@ +var baseAt = require('./_baseAt'), + flatRest = require('./_flatRest'); + +/** + * Creates an array of values corresponding to `paths` of `object`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Array} Returns the picked values. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _.at(object, ['a[0].b.c', 'a[1]']); + * // => [3, 4] + */ +var at = flatRest(baseAt); + +module.exports = at; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/attempt.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/attempt.js new file mode 100644 index 000000000..624d01524 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/attempt.js @@ -0,0 +1,35 @@ +var apply = require('./_apply'), + baseRest = require('./_baseRest'), + isError = require('./isError'); + +/** + * Attempts to invoke `func`, returning either the result or the caught error + * object. Any additional arguments are provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Util + * @param {Function} func The function to attempt. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {*} Returns the `func` result or error object. + * @example + * + * // Avoid throwing errors for invalid selectors. + * var elements = _.attempt(function(selector) { + * return document.querySelectorAll(selector); + * }, '>_>'); + * + * if (_.isError(elements)) { + * elements = []; + * } + */ +var attempt = baseRest(function(func, args) { + try { + return apply(func, undefined, args); + } catch (e) { + return isError(e) ? e : new Error(e); + } +}); + +module.exports = attempt; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/before.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/before.js new file mode 100644 index 000000000..a3e0a16c7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/before.js @@ -0,0 +1,40 @@ +var toInteger = require('./toInteger'); + +/** Error message constants. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/** + * Creates a function that invokes `func`, with the `this` binding and arguments + * of the created function, while it's called less than `n` times. Subsequent + * calls to the created function return the result of the last `func` invocation. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {number} n The number of calls at which `func` is no longer invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * jQuery(element).on('click', _.before(5, addContactToList)); + * // => Allows adding up to 4 contacts to the list. + */ +function before(n, func) { + var result; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; +} + +module.exports = before; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/bind.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/bind.js new file mode 100644 index 000000000..b1076e93e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/bind.js @@ -0,0 +1,57 @@ +var baseRest = require('./_baseRest'), + createWrap = require('./_createWrap'), + getHolder = require('./_getHolder'), + replaceHolders = require('./_replaceHolders'); + +/** Used to compose bitmasks for function metadata. */ +var WRAP_BIND_FLAG = 1, + WRAP_PARTIAL_FLAG = 32; + +/** + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and `partials` prepended to the arguments it receives. + * + * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for partially applied arguments. + * + * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" + * property of bound functions. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * function greet(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * + * var object = { 'user': 'fred' }; + * + * var bound = _.bind(greet, object, 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * // Bound with placeholders. + * var bound = _.bind(greet, object, _, '!'); + * bound('hi'); + * // => 'hi fred!' + */ +var bind = baseRest(function(func, thisArg, partials) { + var bitmask = WRAP_BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bind)); + bitmask |= WRAP_PARTIAL_FLAG; + } + return createWrap(func, bitmask, thisArg, partials, holders); +}); + +// Assign default placeholders. +bind.placeholder = {}; + +module.exports = bind; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/bindAll.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/bindAll.js new file mode 100644 index 000000000..a35706dee --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/bindAll.js @@ -0,0 +1,41 @@ +var arrayEach = require('./_arrayEach'), + baseAssignValue = require('./_baseAssignValue'), + bind = require('./bind'), + flatRest = require('./_flatRest'), + toKey = require('./_toKey'); + +/** + * Binds methods of an object to the object itself, overwriting the existing + * method. + * + * **Note:** This method doesn't set the "length" property of bound functions. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {Object} object The object to bind and assign the bound methods to. + * @param {...(string|string[])} methodNames The object method names to bind. + * @returns {Object} Returns `object`. + * @example + * + * var view = { + * 'label': 'docs', + * 'click': function() { + * console.log('clicked ' + this.label); + * } + * }; + * + * _.bindAll(view, ['click']); + * jQuery(element).on('click', view.click); + * // => Logs 'clicked docs' when clicked. + */ +var bindAll = flatRest(function(object, methodNames) { + arrayEach(methodNames, function(key) { + key = toKey(key); + baseAssignValue(object, key, bind(object[key], object)); + }); + return object; +}); + +module.exports = bindAll; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/bindKey.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/bindKey.js new file mode 100644 index 000000000..f7fd64cd4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/bindKey.js @@ -0,0 +1,68 @@ +var baseRest = require('./_baseRest'), + createWrap = require('./_createWrap'), + getHolder = require('./_getHolder'), + replaceHolders = require('./_replaceHolders'); + +/** Used to compose bitmasks for function metadata. */ +var WRAP_BIND_FLAG = 1, + WRAP_BIND_KEY_FLAG = 2, + WRAP_PARTIAL_FLAG = 32; + +/** + * Creates a function that invokes the method at `object[key]` with `partials` + * prepended to the arguments it receives. + * + * This method differs from `_.bind` by allowing bound functions to reference + * methods that may be redefined or don't yet exist. See + * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern) + * for more details. + * + * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Function + * @param {Object} object The object to invoke the method on. + * @param {string} key The key of the method. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var object = { + * 'user': 'fred', + * 'greet': function(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * }; + * + * var bound = _.bindKey(object, 'greet', 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * object.greet = function(greeting, punctuation) { + * return greeting + 'ya ' + this.user + punctuation; + * }; + * + * bound('!'); + * // => 'hiya fred!' + * + * // Bound with placeholders. + * var bound = _.bindKey(object, 'greet', _, '!'); + * bound('hi'); + * // => 'hiya fred!' + */ +var bindKey = baseRest(function(object, key, partials) { + var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bindKey)); + bitmask |= WRAP_PARTIAL_FLAG; + } + return createWrap(key, bitmask, object, partials, holders); +}); + +// Assign default placeholders. +bindKey.placeholder = {}; + +module.exports = bindKey; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/camelCase.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/camelCase.js new file mode 100644 index 000000000..d7390def5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/camelCase.js @@ -0,0 +1,29 @@ +var capitalize = require('./capitalize'), + createCompounder = require('./_createCompounder'); + +/** + * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the camel cased string. + * @example + * + * _.camelCase('Foo Bar'); + * // => 'fooBar' + * + * _.camelCase('--foo-bar--'); + * // => 'fooBar' + * + * _.camelCase('__FOO_BAR__'); + * // => 'fooBar' + */ +var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? capitalize(word) : word); +}); + +module.exports = camelCase; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/capitalize.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/capitalize.js new file mode 100644 index 000000000..3e1600e7d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/capitalize.js @@ -0,0 +1,23 @@ +var toString = require('./toString'), + upperFirst = require('./upperFirst'); + +/** + * Converts the first character of `string` to upper case and the remaining + * to lower case. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to capitalize. + * @returns {string} Returns the capitalized string. + * @example + * + * _.capitalize('FRED'); + * // => 'Fred' + */ +function capitalize(string) { + return upperFirst(toString(string).toLowerCase()); +} + +module.exports = capitalize; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/castArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/castArray.js new file mode 100644 index 000000000..e470bdb9b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/castArray.js @@ -0,0 +1,44 @@ +var isArray = require('./isArray'); + +/** + * Casts `value` as an array if it's not one. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Lang + * @param {*} value The value to inspect. + * @returns {Array} Returns the cast array. + * @example + * + * _.castArray(1); + * // => [1] + * + * _.castArray({ 'a': 1 }); + * // => [{ 'a': 1 }] + * + * _.castArray('abc'); + * // => ['abc'] + * + * _.castArray(null); + * // => [null] + * + * _.castArray(undefined); + * // => [undefined] + * + * _.castArray(); + * // => [] + * + * var array = [1, 2, 3]; + * console.log(_.castArray(array) === array); + * // => true + */ +function castArray() { + if (!arguments.length) { + return []; + } + var value = arguments[0]; + return isArray(value) ? value : [value]; +} + +module.exports = castArray; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/ceil.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/ceil.js new file mode 100644 index 000000000..56c8722cf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/ceil.js @@ -0,0 +1,26 @@ +var createRound = require('./_createRound'); + +/** + * Computes `number` rounded up to `precision`. + * + * @static + * @memberOf _ + * @since 3.10.0 + * @category Math + * @param {number} number The number to round up. + * @param {number} [precision=0] The precision to round up to. + * @returns {number} Returns the rounded up number. + * @example + * + * _.ceil(4.006); + * // => 5 + * + * _.ceil(6.004, 2); + * // => 6.01 + * + * _.ceil(6040, -2); + * // => 6100 + */ +var ceil = createRound('ceil'); + +module.exports = ceil; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/chain.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/chain.js new file mode 100644 index 000000000..f6cd6475f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/chain.js @@ -0,0 +1,38 @@ +var lodash = require('./wrapperLodash'); + +/** + * Creates a `lodash` wrapper instance that wraps `value` with explicit method + * chain sequences enabled. The result of such sequences must be unwrapped + * with `_#value`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Seq + * @param {*} value The value to wrap. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'pebbles', 'age': 1 } + * ]; + * + * var youngest = _ + * .chain(users) + * .sortBy('age') + * .map(function(o) { + * return o.user + ' is ' + o.age; + * }) + * .head() + * .value(); + * // => 'pebbles is 1' + */ +function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; +} + +module.exports = chain; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/chunk.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/chunk.js new file mode 100644 index 000000000..5b562fef3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/chunk.js @@ -0,0 +1,50 @@ +var baseSlice = require('./_baseSlice'), + isIterateeCall = require('./_isIterateeCall'), + toInteger = require('./toInteger'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeCeil = Math.ceil, + nativeMax = Math.max; + +/** + * Creates an array of elements split into groups the length of `size`. + * If `array` can't be split evenly, the final chunk will be the remaining + * elements. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to process. + * @param {number} [size=1] The length of each chunk + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the new array of chunks. + * @example + * + * _.chunk(['a', 'b', 'c', 'd'], 2); + * // => [['a', 'b'], ['c', 'd']] + * + * _.chunk(['a', 'b', 'c', 'd'], 3); + * // => [['a', 'b', 'c'], ['d']] + */ +function chunk(array, size, guard) { + if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) { + size = 1; + } else { + size = nativeMax(toInteger(size), 0); + } + var length = array == null ? 0 : array.length; + if (!length || size < 1) { + return []; + } + var index = 0, + resIndex = 0, + result = Array(nativeCeil(length / size)); + + while (index < length) { + result[resIndex++] = baseSlice(array, index, (index += size)); + } + return result; +} + +module.exports = chunk; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/clamp.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/clamp.js new file mode 100644 index 000000000..91a72c978 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/clamp.js @@ -0,0 +1,39 @@ +var baseClamp = require('./_baseClamp'), + toNumber = require('./toNumber'); + +/** + * Clamps `number` within the inclusive `lower` and `upper` bounds. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Number + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + * @example + * + * _.clamp(-10, -5, 5); + * // => -5 + * + * _.clamp(10, -5, 5); + * // => 5 + */ +function clamp(number, lower, upper) { + if (upper === undefined) { + upper = lower; + lower = undefined; + } + if (upper !== undefined) { + upper = toNumber(upper); + upper = upper === upper ? upper : 0; + } + if (lower !== undefined) { + lower = toNumber(lower); + lower = lower === lower ? lower : 0; + } + return baseClamp(toNumber(number), lower, upper); +} + +module.exports = clamp; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/clone.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/clone.js new file mode 100644 index 000000000..dd439d639 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/clone.js @@ -0,0 +1,36 @@ +var baseClone = require('./_baseClone'); + +/** Used to compose bitmasks for cloning. */ +var CLONE_SYMBOLS_FLAG = 4; + +/** + * Creates a shallow clone of `value`. + * + * **Note:** This method is loosely based on the + * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) + * and supports cloning arrays, array buffers, booleans, date objects, maps, + * numbers, `Object` objects, regexes, sets, strings, symbols, and typed + * arrays. The own enumerable properties of `arguments` objects are cloned + * as plain objects. An empty object is returned for uncloneable values such + * as error objects, functions, DOM nodes, and WeakMaps. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to clone. + * @returns {*} Returns the cloned value. + * @see _.cloneDeep + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var shallow = _.clone(objects); + * console.log(shallow[0] === objects[0]); + * // => true + */ +function clone(value) { + return baseClone(value, CLONE_SYMBOLS_FLAG); +} + +module.exports = clone; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cloneDeep.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cloneDeep.js new file mode 100644 index 000000000..4425fbe8b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cloneDeep.js @@ -0,0 +1,29 @@ +var baseClone = require('./_baseClone'); + +/** Used to compose bitmasks for cloning. */ +var CLONE_DEEP_FLAG = 1, + CLONE_SYMBOLS_FLAG = 4; + +/** + * This method is like `_.clone` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @returns {*} Returns the deep cloned value. + * @see _.clone + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var deep = _.cloneDeep(objects); + * console.log(deep[0] === objects[0]); + * // => false + */ +function cloneDeep(value) { + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG); +} + +module.exports = cloneDeep; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cloneDeepWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cloneDeepWith.js new file mode 100644 index 000000000..fd9c6c050 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cloneDeepWith.js @@ -0,0 +1,40 @@ +var baseClone = require('./_baseClone'); + +/** Used to compose bitmasks for cloning. */ +var CLONE_DEEP_FLAG = 1, + CLONE_SYMBOLS_FLAG = 4; + +/** + * This method is like `_.cloneWith` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the deep cloned value. + * @see _.cloneWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(true); + * } + * } + * + * var el = _.cloneDeepWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 20 + */ +function cloneDeepWith(value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer); +} + +module.exports = cloneDeepWith; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cloneWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cloneWith.js new file mode 100644 index 000000000..d2f4e756d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cloneWith.js @@ -0,0 +1,42 @@ +var baseClone = require('./_baseClone'); + +/** Used to compose bitmasks for cloning. */ +var CLONE_SYMBOLS_FLAG = 4; + +/** + * This method is like `_.clone` except that it accepts `customizer` which + * is invoked to produce the cloned value. If `customizer` returns `undefined`, + * cloning is handled by the method instead. The `customizer` is invoked with + * up to four arguments; (value [, index|key, object, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the cloned value. + * @see _.cloneDeepWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(false); + * } + * } + * + * var el = _.cloneWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 0 + */ +function cloneWith(value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseClone(value, CLONE_SYMBOLS_FLAG, customizer); +} + +module.exports = cloneWith; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/collection.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/collection.js new file mode 100644 index 000000000..77fe837f3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/collection.js @@ -0,0 +1,30 @@ +module.exports = { + 'countBy': require('./countBy'), + 'each': require('./each'), + 'eachRight': require('./eachRight'), + 'every': require('./every'), + 'filter': require('./filter'), + 'find': require('./find'), + 'findLast': require('./findLast'), + 'flatMap': require('./flatMap'), + 'flatMapDeep': require('./flatMapDeep'), + 'flatMapDepth': require('./flatMapDepth'), + 'forEach': require('./forEach'), + 'forEachRight': require('./forEachRight'), + 'groupBy': require('./groupBy'), + 'includes': require('./includes'), + 'invokeMap': require('./invokeMap'), + 'keyBy': require('./keyBy'), + 'map': require('./map'), + 'orderBy': require('./orderBy'), + 'partition': require('./partition'), + 'reduce': require('./reduce'), + 'reduceRight': require('./reduceRight'), + 'reject': require('./reject'), + 'sample': require('./sample'), + 'sampleSize': require('./sampleSize'), + 'shuffle': require('./shuffle'), + 'size': require('./size'), + 'some': require('./some'), + 'sortBy': require('./sortBy') +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/commit.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/commit.js new file mode 100644 index 000000000..fe4db7178 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/commit.js @@ -0,0 +1,33 @@ +var LodashWrapper = require('./_LodashWrapper'); + +/** + * Executes the chain sequence and returns the wrapped result. + * + * @name commit + * @memberOf _ + * @since 3.2.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2]; + * var wrapped = _(array).push(3); + * + * console.log(array); + * // => [1, 2] + * + * wrapped = wrapped.commit(); + * console.log(array); + * // => [1, 2, 3] + * + * wrapped.last(); + * // => 3 + * + * console.log(array); + * // => [1, 2, 3] + */ +function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); +} + +module.exports = wrapperCommit; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/compact.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/compact.js new file mode 100644 index 000000000..031fab4e6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/compact.js @@ -0,0 +1,31 @@ +/** + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are falsey. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to compact. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ +function compact(array) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value) { + result[resIndex++] = value; + } + } + return result; +} + +module.exports = compact; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/concat.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/concat.js new file mode 100644 index 000000000..1da48a4fc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/concat.js @@ -0,0 +1,43 @@ +var arrayPush = require('./_arrayPush'), + baseFlatten = require('./_baseFlatten'), + copyArray = require('./_copyArray'), + isArray = require('./isArray'); + +/** + * Creates a new array concatenating `array` with any additional arrays + * and/or values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to concatenate. + * @param {...*} [values] The values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1]; + * var other = _.concat(array, 2, [3], [[4]]); + * + * console.log(other); + * // => [1, 2, 3, [4]] + * + * console.log(array); + * // => [1] + */ +function concat() { + var length = arguments.length; + if (!length) { + return []; + } + var args = Array(length - 1), + array = arguments[0], + index = length; + + while (index--) { + args[index - 1] = arguments[index]; + } + return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); +} + +module.exports = concat; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cond.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cond.js new file mode 100644 index 000000000..64555986a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/cond.js @@ -0,0 +1,60 @@ +var apply = require('./_apply'), + arrayMap = require('./_arrayMap'), + baseIteratee = require('./_baseIteratee'), + baseRest = require('./_baseRest'); + +/** Error message constants. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/** + * Creates a function that iterates over `pairs` and invokes the corresponding + * function of the first predicate to return truthy. The predicate-function + * pairs are invoked with the `this` binding and arguments of the created + * function. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Util + * @param {Array} pairs The predicate-function pairs. + * @returns {Function} Returns the new composite function. + * @example + * + * var func = _.cond([ + * [_.matches({ 'a': 1 }), _.constant('matches A')], + * [_.conforms({ 'b': _.isNumber }), _.constant('matches B')], + * [_.stubTrue, _.constant('no match')] + * ]); + * + * func({ 'a': 1, 'b': 2 }); + * // => 'matches A' + * + * func({ 'a': 0, 'b': 1 }); + * // => 'matches B' + * + * func({ 'a': '1', 'b': '2' }); + * // => 'no match' + */ +function cond(pairs) { + var length = pairs == null ? 0 : pairs.length, + toIteratee = baseIteratee; + + pairs = !length ? [] : arrayMap(pairs, function(pair) { + if (typeof pair[1] != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return [toIteratee(pair[0]), pair[1]]; + }); + + return baseRest(function(args) { + var index = -1; + while (++index < length) { + var pair = pairs[index]; + if (apply(pair[0], this, args)) { + return apply(pair[1], this, args); + } + } + }); +} + +module.exports = cond; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/conforms.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/conforms.js new file mode 100644 index 000000000..5501a949a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/conforms.js @@ -0,0 +1,35 @@ +var baseClone = require('./_baseClone'), + baseConforms = require('./_baseConforms'); + +/** Used to compose bitmasks for cloning. */ +var CLONE_DEEP_FLAG = 1; + +/** + * Creates a function that invokes the predicate properties of `source` with + * the corresponding property values of a given object, returning `true` if + * all predicates return truthy, else `false`. + * + * **Note:** The created function is equivalent to `_.conformsTo` with + * `source` partially applied. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Util + * @param {Object} source The object of property predicates to conform to. + * @returns {Function} Returns the new spec function. + * @example + * + * var objects = [ + * { 'a': 2, 'b': 1 }, + * { 'a': 1, 'b': 2 } + * ]; + * + * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } })); + * // => [{ 'a': 1, 'b': 2 }] + */ +function conforms(source) { + return baseConforms(baseClone(source, CLONE_DEEP_FLAG)); +} + +module.exports = conforms; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/conformsTo.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/conformsTo.js new file mode 100644 index 000000000..b8a93ebf4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/conformsTo.js @@ -0,0 +1,32 @@ +var baseConformsTo = require('./_baseConformsTo'), + keys = require('./keys'); + +/** + * Checks if `object` conforms to `source` by invoking the predicate + * properties of `source` with the corresponding property values of `object`. + * + * **Note:** This method is equivalent to `_.conforms` when `source` is + * partially applied. + * + * @static + * @memberOf _ + * @since 4.14.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.conformsTo(object, { 'b': function(n) { return n > 1; } }); + * // => true + * + * _.conformsTo(object, { 'b': function(n) { return n > 2; } }); + * // => false + */ +function conformsTo(object, source) { + return source == null || baseConformsTo(object, source, keys(source)); +} + +module.exports = conformsTo; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/constant.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/constant.js new file mode 100644 index 000000000..655ece3fb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/constant.js @@ -0,0 +1,26 @@ +/** + * Creates a function that returns `value`. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Util + * @param {*} value The value to return from the new function. + * @returns {Function} Returns the new constant function. + * @example + * + * var objects = _.times(2, _.constant({ 'a': 1 })); + * + * console.log(objects); + * // => [{ 'a': 1 }, { 'a': 1 }] + * + * console.log(objects[0] === objects[1]); + * // => true + */ +function constant(value) { + return function() { + return value; + }; +} + +module.exports = constant; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/core.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/core.js new file mode 100644 index 000000000..be1d567d6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/core.js @@ -0,0 +1,3877 @@ +/** + * @license + * Lodash (Custom Build) + * Build: `lodash core -o ./dist/lodash.core.js` + * Copyright OpenJS Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ +;(function() { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** Used as the semantic version number. */ + var VERSION = '4.17.21'; + + /** Error message constants. */ + var FUNC_ERROR_TEXT = 'Expected a function'; + + /** Used to compose bitmasks for value comparisons. */ + var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG = 1, + WRAP_PARTIAL_FLAG = 32; + + /** Used as references for various `Number` constants. */ + var INFINITY = 1 / 0, + MAX_SAFE_INTEGER = 9007199254740991; + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + asyncTag = '[object AsyncFunction]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + numberTag = '[object Number]', + objectTag = '[object Object]', + proxyTag = '[object Proxy]', + regexpTag = '[object RegExp]', + stringTag = '[object String]'; + + /** Used to match HTML entities and HTML characters. */ + var reUnescapedHtml = /[&<>"']/g, + reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + + /** Used to detect unsigned integer values. */ + var reIsUint = /^(?:0|[1-9]\d*)$/; + + /** Used to map characters to HTML entities. */ + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + /** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + + /** Used as a reference to the global object. */ + var root = freeGlobal || freeSelf || Function('return this')(); + + /** Detect free variable `exports`. */ + var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + + /** Detect free variable `module`. */ + var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + + /*--------------------------------------------------------------------------*/ + + /** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ + function arrayPush(array, values) { + array.push.apply(array, values); + return array; + } + + /** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.propertyOf` without support for deep paths. + * + * @private + * @param {Object} object The object to query. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyOf(object) { + return function(key) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.reduce` and `_.reduceRight`, without support + * for iteratee shorthands, which iterates over `collection` using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} accumulator The initial value. + * @param {boolean} initAccum Specify using the first or last element of + * `collection` as the initial value. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the accumulated value. + */ + function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initAccum + ? (initAccum = false, value) + : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values corresponding to the property names + * of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the array of property values. + */ + function baseValues(object, props) { + return baseMap(props, function(key) { + return object[key]; + }); + } + + /** + * Used by `_.escape` to convert characters to HTML entities. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + var escapeHtmlChar = basePropertyOf(htmlEscapes); + + /** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ + function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; + } + + /*--------------------------------------------------------------------------*/ + + /** Used for built-in method references. */ + var arrayProto = Array.prototype, + objectProto = Object.prototype; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to generate unique IDs. */ + var idCounter = 0; + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var nativeObjectToString = objectProto.toString; + + /** Used to restore the original `_` reference in `_.noConflict`. */ + var oldDash = root._; + + /** Built-in value references. */ + var objectCreate = Object.create, + propertyIsEnumerable = objectProto.propertyIsEnumerable; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeIsFinite = root.isFinite, + nativeKeys = overArg(Object.keys, Object), + nativeMax = Math.max; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` object which wraps `value` to enable implicit method + * chain sequences. Methods that operate on and return arrays, collections, + * and functions can be chained together. Methods that retrieve a single value + * or may return a primitive value will automatically end the chain sequence + * and return the unwrapped value. Otherwise, the value must be unwrapped + * with `_#value`. + * + * Explicit chain sequences, which must be unwrapped with `_#value`, may be + * enabled using `_.chain`. + * + * The execution of chained methods is lazy, that is, it's deferred until + * `_#value` is implicitly or explicitly called. + * + * Lazy evaluation allows several methods to support shortcut fusion. + * Shortcut fusion is an optimization to merge iteratee calls; this avoids + * the creation of intermediate arrays and can greatly reduce the number of + * iteratee executions. Sections of a chain sequence qualify for shortcut + * fusion if the section is applied to an array and iteratees accept only + * one argument. The heuristic for whether a section qualifies for shortcut + * fusion is subject to change. + * + * Chaining is supported in custom builds as long as the `_#value` method is + * directly or indirectly included in the build. + * + * In addition to lodash methods, wrappers have `Array` and `String` methods. + * + * The wrapper `Array` methods are: + * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` + * + * The wrapper `String` methods are: + * `replace` and `split` + * + * The wrapper methods that support shortcut fusion are: + * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, + * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, + * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` + * + * The chainable wrapper methods are: + * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, + * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, + * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, + * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, + * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, + * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, + * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, + * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, + * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, + * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, + * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, + * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, + * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, + * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, + * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, + * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, + * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, + * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, + * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, + * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, + * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, + * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, + * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, + * `zipObject`, `zipObjectDeep`, and `zipWith` + * + * The wrapper methods that are **not** chainable by default are: + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, + * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, + * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, + * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, + * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, + * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, + * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, + * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, + * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, + * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, + * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, + * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, + * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, + * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, + * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, + * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, + * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, + * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, + * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, + * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, + * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, + * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, + * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, + * `upperFirst`, `value`, and `words` + * + * @name _ + * @constructor + * @category Seq + * @param {*} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2, 3]); + * + * // Returns an unwrapped value. + * wrapped.reduce(_.add); + * // => 6 + * + * // Returns a wrapped value. + * var squares = wrapped.map(square); + * + * _.isArray(squares); + * // => false + * + * _.isArray(squares.value()); + * // => true + */ + function lodash(value) { + return value instanceof LodashWrapper + ? value + : new LodashWrapper(value); + } + + /** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ + var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; + }()); + + /** + * The base constructor for creating `lodash` wrapper objects. + * + * @private + * @param {*} value The value to wrap. + * @param {boolean} [chainAll] Enable explicit method chain sequences. + */ + function LodashWrapper(value, chainAll) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__chain__ = !!chainAll; + } + + LodashWrapper.prototype = baseCreate(lodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function baseAssignValue(object, key, value) { + object[key] = value; + } + + /** + * The base implementation of `_.delay` and `_.defer` which accepts `args` + * to provide to `func`. + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {Array} args The arguments to provide to `func`. + * @returns {number|Object} Returns the timer id or timeout object. + */ + function baseDelay(func, wait, args) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { func.apply(undefined, args); }, wait); + } + + /** + * The base implementation of `_.forEach` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEach = createBaseEach(baseForOwn); + + /** + * The base implementation of `_.every` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false` + */ + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + + /** + * The base implementation of methods like `_.max` and `_.min` which accepts a + * `comparator` to determine the extremum value. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The iteratee invoked per iteration. + * @param {Function} comparator The comparator used to compare values. + * @returns {*} Returns the extremum value. + */ + function baseExtremum(array, iteratee, comparator) { + var index = -1, + length = array.length; + + while (++index < length) { + var value = array[index], + current = iteratee(value); + + if (current != null && (computed === undefined + ? (current === current && !false) + : comparator(current, computed) + )) { + var computed = current, + result = value; + } + } + return result; + } + + /** + * The base implementation of `_.filter` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + + /** + * The base implementation of `_.flatten` with support for restricting flattening. + * + * @private + * @param {Array} array The array to flatten. + * @param {number} depth The maximum recursion depth. + * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. + * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. + * @param {Array} [result=[]] The initial result value. + * @returns {Array} Returns the new flattened array. + */ + function baseFlatten(array, depth, predicate, isStrict, result) { + var index = -1, + length = array.length; + + predicate || (predicate = isFlattenable); + result || (result = []); + + while (++index < length) { + var value = array[index]; + if (depth > 0 && predicate(value)) { + if (depth > 1) { + // Recursively flatten arrays (susceptible to call stack limits). + baseFlatten(value, depth - 1, predicate, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + + /** + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseFor = createBaseFor(); + + /** + * The base implementation of `_.forOwn` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwn(object, iteratee) { + return object && baseFor(object, iteratee, keys); + } + + /** + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from `props`. + * + * @private + * @param {Object} object The object to inspect. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the function names. + */ + function baseFunctions(object, props) { + return baseFilter(props, function(key) { + return isFunction(object[key]); + }); + } + + /** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + function baseGetTag(value) { + return objectToString(value); + } + + /** + * The base implementation of `_.gt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + */ + function baseGt(value, other) { + return value > other; + } + + /** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ + var baseIsArguments = noop; + + /** + * The base implementation of `_.isDate` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + */ + function baseIsDate(value) { + return isObjectLike(value) && baseGetTag(value) == dateTag; + } + + /** + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {boolean} bitmask The bitmask flags. + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Function} [customizer] The function to customize comparisons. + * @param {Object} [stack] Tracks traversed `value` and `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ + function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); + } + + /** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = objIsArr ? arrayTag : baseGetTag(object), + othTag = othIsArr ? arrayTag : baseGetTag(other); + + objTag = objTag == argsTag ? objectTag : objTag; + othTag = othTag == argsTag ? objectTag : othTag; + + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, + isSameTag = objTag == othTag; + + stack || (stack = []); + var objStack = find(stack, function(entry) { + return entry[0] == object; + }); + var othStack = find(stack, function(entry) { + return entry[0] == other; + }); + if (objStack && othStack) { + return objStack[1] == other; + } + stack.push([object, other]); + stack.push([other, object]); + if (isSameTag && !objIsObj) { + var result = (objIsArr) + ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) + : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); + stack.pop(); + return result; + } + if (!(bitmask & COMPARE_PARTIAL_FLAG)) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + var result = equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); + stack.pop(); + return result; + } + } + if (!isSameTag) { + return false; + } + var result = equalObjects(object, other, bitmask, customizer, equalFunc, stack); + stack.pop(); + return result; + } + + /** + * The base implementation of `_.isRegExp` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + */ + function baseIsRegExp(value) { + return isObjectLike(value) && baseGetTag(value) == regexpTag; + } + + /** + * The base implementation of `_.iteratee`. + * + * @private + * @param {*} [value=_.identity] The value to convert to an iteratee. + * @returns {Function} Returns the iteratee. + */ + function baseIteratee(func) { + if (typeof func == 'function') { + return func; + } + if (func == null) { + return identity; + } + return (typeof func == 'object' ? baseMatches : baseProperty)(func); + } + + /** + * The base implementation of `_.lt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + */ + function baseLt(value, other) { + return value < other; + } + + /** + * The base implementation of `_.map` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function baseMap(collection, iteratee) { + var index = -1, + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + + /** + * The base implementation of `_.matches` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatches(source) { + var props = nativeKeys(source); + return function(object) { + var length = props.length; + if (object == null) { + return !length; + } + object = Object(object); + while (length--) { + var key = props[length]; + if (!(key in object && + baseIsEqual(source[key], object[key], COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG) + )) { + return false; + } + } + return true; + }; + } + + /** + * The base implementation of `_.pick` without support for individual + * property identifiers. + * + * @private + * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. + * @returns {Object} Returns the new object. + */ + function basePick(object, props) { + object = Object(object); + return reduce(props, function(result, key) { + if (key in object) { + result[key] = object[key]; + } + return result; + }, {}); + } + + /** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ + function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ''); + } + + /** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + + /** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ + function copyArray(source) { + return baseSlice(source, 0, source.length); + } + + /** + * The base implementation of `_.some` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function baseSome(collection, predicate) { + var result; + + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + + /** + * The base implementation of `wrapperValue` which returns the result of + * performing a sequence of actions on the unwrapped `value`, where each + * successive action is supplied the return value of the previous. + * + * @private + * @param {*} value The unwrapped value. + * @param {Array} actions Actions to perform to resolve the unwrapped value. + * @returns {*} Returns the resolved value. + */ + function baseWrapperValue(value, actions) { + var result = value; + return reduce(actions, function(result, action) { + return action.func.apply(action.thisArg, arrayPush([result], action.args)); + }, result); + } + + /** + * Compares values to sort them in ascending order. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {number} Returns the sort order indicator for `value`. + */ + function compareAscending(value, other) { + if (value !== other) { + var valIsDefined = value !== undefined, + valIsNull = value === null, + valIsReflexive = value === value, + valIsSymbol = false; + + var othIsDefined = other !== undefined, + othIsNull = other === null, + othIsReflexive = other === other, + othIsSymbol = false; + + if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || + (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || + (valIsNull && othIsDefined && othIsReflexive) || + (!valIsDefined && othIsReflexive) || + !valIsReflexive) { + return 1; + } + if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || + (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || + (othIsNull && valIsDefined && valIsReflexive) || + (!othIsDefined && valIsReflexive) || + !othIsReflexive) { + return -1; + } + } + return 0; + } + + /** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ + function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; + } + + /** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ + function createAssigner(assigner) { + return baseRest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); + } + + /** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + if (collection == null) { + return collection; + } + if (!isArrayLike(collection)) { + return eachFunc(collection, iteratee); + } + var length = collection.length, + index = fromRight ? length : -1, + iterable = Object(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + + /** + * Creates a base function for methods like `_.forIn` and `_.forOwn`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + + /** + * Creates a function that produces an instance of `Ctor` regardless of + * whether it was invoked as part of a `new` expression or by `call` or `apply`. + * + * @private + * @param {Function} Ctor The constructor to wrap. + * @returns {Function} Returns the new wrapped function. + */ + function createCtor(Ctor) { + return function() { + // Use a `switch` statement to work with class constructors. See + // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // for more details. + var args = arguments; + var thisBinding = baseCreate(Ctor.prototype), + result = Ctor.apply(thisBinding, args); + + // Mimic the constructor's `return` behavior. + // See https://es5.github.io/#x13.2.2 for more details. + return isObject(result) ? result : thisBinding; + }; + } + + /** + * Creates a `_.find` or `_.findLast` function. + * + * @private + * @param {Function} findIndexFunc The function to find the collection index. + * @returns {Function} Returns the new find function. + */ + function createFind(findIndexFunc) { + return function(collection, predicate, fromIndex) { + var iterable = Object(collection); + if (!isArrayLike(collection)) { + var iteratee = baseIteratee(predicate, 3); + collection = keys(collection); + predicate = function(key) { return iteratee(iterable[key], key, iterable); }; + } + var index = findIndexFunc(collection, predicate, fromIndex); + return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; + }; + } + + /** + * Creates a function that wraps `func` to invoke it with the `this` binding + * of `thisArg` and `partials` prepended to the arguments it receives. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} partials The arguments to prepend to those provided to + * the new function. + * @returns {Function} Returns the new wrapped function. + */ + function createPartial(func, bitmask, thisArg, partials) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var argsIndex = -1, + argsLength = arguments.length, + leftIndex = -1, + leftLength = partials.length, + args = Array(leftLength + argsLength), + fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; + } + + /** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ + function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + // Check that cyclic values are equal. + var arrStacked = stack.get(array); + var othStacked = stack.get(other); + if (arrStacked && othStacked) { + return arrStacked == other && othStacked == array; + } + var index = -1, + result = true, + seen = (bitmask & COMPARE_UNORDERED_FLAG) ? [] : undefined; + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + var compared; + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!baseSome(other, function(othValue, othIndex) { + if (!indexOf(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, bitmask, customizer, stack) + )) { + result = false; + break; + } + } + return result; + } + + /** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + + case boolTag: + case dateTag: + case numberTag: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); + + case errorTag: + return object.name == other.name && object.message == other.message; + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. + return object == (other + ''); + + } + return false; + } + + /** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + objProps = keys(object), + objLength = objProps.length, + othProps = keys(other), + othLength = othProps.length; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + // Check that cyclic values are equal. + var objStacked = stack.get(object); + var othStacked = stack.get(other); + if (objStacked && othStacked) { + return objStacked == other && othStacked == object; + } + var result = true; + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + var compared; + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } + } + return result; + } + + /** + * A specialized version of `baseRest` which flattens the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + function flatRest(func) { + return setToString(overRest(func, undefined, flatten), func + ''); + } + + /** + * Checks if `value` is a flattenable `arguments` object or array. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. + */ + function isFlattenable(value) { + return isArray(value) || isArguments(value); + } + + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + + return !!length && + (type == 'number' || + (type != 'symbol' && reIsUint.test(value))) && + (value > -1 && value % 1 == 0 && value < length); + } + + /** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; + } + + /** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; + } + + /** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ + function objectToString(value) { + return nativeObjectToString.call(value); + } + + /** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ + function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return func.apply(this, otherArgs); + }; + } + + /** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var setToString = identity; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are falsey. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to compact. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ + function compact(array) { + return baseFilter(array, Boolean); + } + + /** + * Creates a new array concatenating `array` with any additional arrays + * and/or values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to concatenate. + * @param {...*} [values] The values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1]; + * var other = _.concat(array, 2, [3], [[4]]); + * + * console.log(other); + * // => [1, 2, 3, [4]] + * + * console.log(array); + * // => [1] + */ + function concat() { + var length = arguments.length; + if (!length) { + return []; + } + var args = Array(length - 1), + array = arguments[0], + index = length; + + while (index--) { + args[index - 1] = arguments[index]; + } + return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); + } + + /** + * This method is like `_.find` except that it returns the index of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.findIndex(users, function(o) { return o.user == 'barney'; }); + * // => 0 + * + * // The `_.matches` iteratee shorthand. + * _.findIndex(users, { 'user': 'fred', 'active': false }); + * // => 1 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findIndex(users, ['active', false]); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.findIndex(users, 'active'); + * // => 2 + */ + function findIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseFindIndex(array, baseIteratee(predicate, 3), index); + } + + /** + * Flattens `array` a single level deep. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flatten([1, [2, [3, [4]], 5]]); + * // => [1, 2, [3, [4]], 5] + */ + function flatten(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, 1) : []; + } + + /** + * Recursively flattens `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flattenDeep([1, [2, [3, [4]], 5]]); + * // => [1, 2, 3, 4, 5] + */ + function flattenDeep(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, INFINITY) : []; + } + + /** + * Gets the first element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias first + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the first element of `array`. + * @example + * + * _.head([1, 2, 3]); + * // => 1 + * + * _.head([]); + * // => undefined + */ + function head(array) { + return (array && array.length) ? array[0] : undefined; + } + + /** + * Gets the index at which the first occurrence of `value` is found in `array` + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. If `fromIndex` is negative, it's used as the + * offset from the end of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.indexOf([1, 2, 1, 2], 2); + * // => 1 + * + * // Search from the `fromIndex`. + * _.indexOf([1, 2, 1, 2], 2, 2); + * // => 3 + */ + function indexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (typeof fromIndex == 'number') { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else { + fromIndex = 0; + } + var index = (fromIndex || 0) - 1, + isReflexive = value === value; + + while (++index < length) { + var other = array[index]; + if ((isReflexive ? other === value : other !== other)) { + return index; + } + } + return -1; + } + + /** + * Gets the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the last element of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + */ + function last(array) { + var length = array == null ? 0 : array.length; + return length ? array[length - 1] : undefined; + } + + /** + * Creates a slice of `array` from `start` up to, but not including, `end`. + * + * **Note:** This method is used instead of + * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are + * returned. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function slice(array, start, end) { + var length = array == null ? 0 : array.length; + start = start == null ? 0 : +start; + end = end === undefined ? length : +end; + return length ? baseSlice(array, start, end) : []; + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` wrapper instance that wraps `value` with explicit method + * chain sequences enabled. The result of such sequences must be unwrapped + * with `_#value`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Seq + * @param {*} value The value to wrap. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'pebbles', 'age': 1 } + * ]; + * + * var youngest = _ + * .chain(users) + * .sortBy('age') + * .map(function(o) { + * return o.user + ' is ' + o.age; + * }) + * .head() + * .value(); + * // => 'pebbles is 1' + */ + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + + /** + * This method invokes `interceptor` and returns `value`. The interceptor + * is invoked with one argument; (value). The purpose of this method is to + * "tap into" a method chain sequence in order to modify intermediate results. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns `value`. + * @example + * + * _([1, 2, 3]) + * .tap(function(array) { + * // Mutate input array. + * array.pop(); + * }) + * .reverse() + * .value(); + * // => [2, 1] + */ + function tap(value, interceptor) { + interceptor(value); + return value; + } + + /** + * This method is like `_.tap` except that it returns the result of `interceptor`. + * The purpose of this method is to "pass thru" values replacing intermediate + * results in a method chain sequence. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns the result of `interceptor`. + * @example + * + * _(' abc ') + * .chain() + * .trim() + * .thru(function(value) { + * return [value]; + * }) + * .value(); + * // => ['abc'] + */ + function thru(value, interceptor) { + return interceptor(value); + } + + /** + * Creates a `lodash` wrapper instance with explicit method chain sequences enabled. + * + * @name chain + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * // A sequence without explicit chaining. + * _(users).head(); + * // => { 'user': 'barney', 'age': 36 } + * + * // A sequence with explicit chaining. + * _(users) + * .chain() + * .head() + * .pick('user') + * .value(); + * // => { 'user': 'barney' } + */ + function wrapperChain() { + return chain(this); + } + + /** + * Executes the chain sequence to resolve the unwrapped value. + * + * @name value + * @memberOf _ + * @since 0.1.0 + * @alias toJSON, valueOf + * @category Seq + * @returns {*} Returns the resolved unwrapped value. + * @example + * + * _([1, 2, 3]).value(); + * // => [1, 2, 3] + */ + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + + /*------------------------------------------------------------------------*/ + + /** + * Checks if `predicate` returns truthy for **all** elements of `collection`. + * Iteration is stopped once `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * **Note:** This method returns `true` for + * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because + * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of + * elements of empty collections. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.every(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.every(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.every(users, 'active'); + * // => false + */ + function every(collection, predicate, guard) { + predicate = guard ? undefined : predicate; + return baseEvery(collection, baseIteratee(predicate)); + } + + /** + * Iterates over elements of `collection`, returning an array of all elements + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * **Note:** Unlike `_.remove`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.reject + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * _.filter(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.filter(users, { 'age': 36, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.filter(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.filter(users, 'active'); + * // => objects for ['barney'] + * + * // Combining several predicates using `_.overEvery` or `_.overSome`. + * _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]])); + * // => objects for ['fred', 'barney'] + */ + function filter(collection, predicate) { + return baseFilter(collection, baseIteratee(predicate)); + } + + /** + * Iterates over elements of `collection`, returning the first element + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false }, + * { 'user': 'pebbles', 'age': 1, 'active': true } + * ]; + * + * _.find(users, function(o) { return o.age < 40; }); + * // => object for 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.find(users, { 'age': 1, 'active': true }); + * // => object for 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.find(users, ['active', false]); + * // => object for 'fred' + * + * // The `_.property` iteratee shorthand. + * _.find(users, 'active'); + * // => object for 'barney' + */ + var find = createFind(findIndex); + + /** + * Iterates over elements of `collection` and invokes `iteratee` for each element. + * The iteratee is invoked with three arguments: (value, index|key, collection). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * **Note:** As with other "Collections" methods, objects with a "length" + * property are iterated like arrays. To avoid this behavior use `_.forIn` + * or `_.forOwn` for object iteration. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias each + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEachRight + * @example + * + * _.forEach([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `1` then `2`. + * + * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forEach(collection, iteratee) { + return baseEach(collection, baseIteratee(iteratee)); + } + + /** + * Creates an array of values by running each element in `collection` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. + * + * The guarded methods are: + * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, + * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, + * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, + * `template`, `trim`, `trimEnd`, `trimStart`, and `words` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + * @example + * + * function square(n) { + * return n * n; + * } + * + * _.map([4, 8], square); + * // => [16, 64] + * + * _.map({ 'a': 4, 'b': 8 }, square); + * // => [16, 64] (iteration order is not guaranteed) + * + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * // The `_.property` iteratee shorthand. + * _.map(users, 'user'); + * // => ['barney', 'fred'] + */ + function map(collection, iteratee) { + return baseMap(collection, baseIteratee(iteratee)); + } + + /** + * Reduces `collection` to a value which is the accumulated result of running + * each element in `collection` thru `iteratee`, where each successive + * invocation is supplied the return value of the previous. If `accumulator` + * is not given, the first element of `collection` is used as the initial + * value. The iteratee is invoked with four arguments: + * (accumulator, value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.reduce`, `_.reduceRight`, and `_.transform`. + * + * The guarded methods are: + * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, + * and `sortBy` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduceRight + * @example + * + * _.reduce([1, 2], function(sum, n) { + * return sum + n; + * }, 0); + * // => 3 + * + * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * return result; + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) + */ + function reduce(collection, iteratee, accumulator) { + return baseReduce(collection, baseIteratee(iteratee), accumulator, arguments.length < 3, baseEach); + } + + /** + * Gets the size of `collection` by returning its length for array-like + * values or the number of own enumerable string keyed properties for objects. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @returns {number} Returns the collection size. + * @example + * + * _.size([1, 2, 3]); + * // => 3 + * + * _.size({ 'a': 1, 'b': 2 }); + * // => 2 + * + * _.size('pebbles'); + * // => 7 + */ + function size(collection) { + if (collection == null) { + return 0; + } + collection = isArrayLike(collection) ? collection : nativeKeys(collection); + return collection.length; + } + + /** + * Checks if `predicate` returns truthy for **any** element of `collection`. + * Iteration is stopped once `predicate` returns truthy. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + * @example + * + * _.some([null, 0, 'yes', false], Boolean); + * // => true + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.some(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.some(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.some(users, 'active'); + * // => true + */ + function some(collection, predicate, guard) { + predicate = guard ? undefined : predicate; + return baseSome(collection, baseIteratee(predicate)); + } + + /** + * Creates an array of elements, sorted in ascending order by the results of + * running each element in a collection thru each iteratee. This method + * performs a stable sort, that is, it preserves the original sort order of + * equal elements. The iteratees are invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {...(Function|Function[])} [iteratees=[_.identity]] + * The iteratees to sort by. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 30 }, + * { 'user': 'barney', 'age': 34 } + * ]; + * + * _.sortBy(users, [function(o) { return o.user; }]); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]] + * + * _.sortBy(users, ['user', 'age']); + * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]] + */ + function sortBy(collection, iteratee) { + var index = 0; + iteratee = baseIteratee(iteratee); + + return baseMap(baseMap(collection, function(value, key, collection) { + return { 'value': value, 'index': index++, 'criteria': iteratee(value, key, collection) }; + }).sort(function(object, other) { + return compareAscending(object.criteria, other.criteria) || (object.index - other.index); + }), baseProperty('value')); + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates a function that invokes `func`, with the `this` binding and arguments + * of the created function, while it's called less than `n` times. Subsequent + * calls to the created function return the result of the last `func` invocation. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {number} n The number of calls at which `func` is no longer invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * jQuery(element).on('click', _.before(5, addContactToList)); + * // => Allows adding up to 4 contacts to the list. + */ + function before(n, func) { + var result; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + + /** + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and `partials` prepended to the arguments it receives. + * + * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for partially applied arguments. + * + * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" + * property of bound functions. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * function greet(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * + * var object = { 'user': 'fred' }; + * + * var bound = _.bind(greet, object, 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * // Bound with placeholders. + * var bound = _.bind(greet, object, _, '!'); + * bound('hi'); + * // => 'hi fred!' + */ + var bind = baseRest(function(func, thisArg, partials) { + return createPartial(func, WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG, thisArg, partials); + }); + + /** + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to defer. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.defer(function(text) { + * console.log(text); + * }, 'deferred'); + * // => Logs 'deferred' after one millisecond. + */ + var defer = baseRest(function(func, args) { + return baseDelay(func, 1, args); + }); + + /** + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.delay(function(text) { + * console.log(text); + * }, 1000, 'later'); + * // => Logs 'later' after one second. + */ + var delay = baseRest(function(func, wait, args) { + return baseDelay(func, toNumber(wait) || 0, args); + }); + + /** + * Creates a function that negates the result of the predicate `func`. The + * `func` predicate is invoked with the `this` binding and arguments of the + * created function. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} predicate The predicate to negate. + * @returns {Function} Returns the new negated function. + * @example + * + * function isEven(n) { + * return n % 2 == 0; + * } + * + * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); + * // => [1, 3, 5] + */ + function negate(predicate) { + if (typeof predicate != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var args = arguments; + return !predicate.apply(this, args); + }; + } + + /** + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first invocation. The `func` is + * invoked with the `this` binding and arguments of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // => `createApplication` is invoked once + */ + function once(func) { + return before(2, func); + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates a shallow clone of `value`. + * + * **Note:** This method is loosely based on the + * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) + * and supports cloning arrays, array buffers, booleans, date objects, maps, + * numbers, `Object` objects, regexes, sets, strings, symbols, and typed + * arrays. The own enumerable properties of `arguments` objects are cloned + * as plain objects. An empty object is returned for uncloneable values such + * as error objects, functions, DOM nodes, and WeakMaps. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to clone. + * @returns {*} Returns the cloned value. + * @see _.cloneDeep + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var shallow = _.clone(objects); + * console.log(shallow[0] === objects[0]); + * // => true + */ + function clone(value) { + if (!isObject(value)) { + return value; + } + return isArray(value) ? copyArray(value) : copyObject(value, nativeKeys(value)); + } + + /** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ + function eq(value, other) { + return value === other || (value !== value && other !== other); + } + + /** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); + }; + + /** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ + var isArray = Array.isArray; + + /** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ + function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); + } + + /** + * Checks if `value` is classified as a boolean primitive or object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a boolean, else `false`. + * @example + * + * _.isBoolean(false); + * // => true + * + * _.isBoolean(null); + * // => false + */ + function isBoolean(value) { + return value === true || value === false || + (isObjectLike(value) && baseGetTag(value) == boolTag); + } + + /** + * Checks if `value` is classified as a `Date` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + * @example + * + * _.isDate(new Date); + * // => true + * + * _.isDate('Mon April 23 2012'); + * // => false + */ + var isDate = baseIsDate; + + /** + * Checks if `value` is an empty object, collection, map, or set. + * + * Objects are considered empty if they have no own enumerable string keyed + * properties. + * + * Array-like values such as `arguments` objects, arrays, buffers, strings, or + * jQuery-like collections are considered empty if they have a `length` of `0`. + * Similarly, maps and sets are considered empty if they have a `size` of `0`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. + * @example + * + * _.isEmpty(null); + * // => true + * + * _.isEmpty(true); + * // => true + * + * _.isEmpty(1); + * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false + */ + function isEmpty(value) { + if (isArrayLike(value) && + (isArray(value) || isString(value) || + isFunction(value.splice) || isArguments(value))) { + return !value.length; + } + return !nativeKeys(value).length; + } + + /** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are compared by strict equality, i.e. `===`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ + function isEqual(value, other) { + return baseIsEqual(value, other); + } + + /** + * Checks if `value` is a finite primitive number. + * + * **Note:** This method is based on + * [`Number.isFinite`](https://mdn.io/Number/isFinite). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. + * @example + * + * _.isFinite(3); + * // => true + * + * _.isFinite(Number.MIN_VALUE); + * // => true + * + * _.isFinite(Infinity); + * // => false + * + * _.isFinite('3'); + * // => false + */ + function isFinite(value) { + return typeof value == 'number' && nativeIsFinite(value); + } + + /** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ + function isFunction(value) { + if (!isObject(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; + } + + /** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ + function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); + } + + /** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ + function isObjectLike(value) { + return value != null && typeof value == 'object'; + } + + /** + * Checks if `value` is `NaN`. + * + * **Note:** This method is based on + * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as + * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for + * `undefined` and other non-number values. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ + function isNaN(value) { + // An `NaN` primitive is the only value that is not equal to itself. + // Perform the `toStringTag` check first to avoid errors with some + // ActiveX objects in IE. + return isNumber(value) && value != +value; + } + + /** + * Checks if `value` is `null`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `null`, else `false`. + * @example + * + * _.isNull(null); + * // => true + * + * _.isNull(void 0); + * // => false + */ + function isNull(value) { + return value === null; + } + + /** + * Checks if `value` is classified as a `Number` primitive or object. + * + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are + * classified as numbers, use the `_.isFinite` method. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a number, else `false`. + * @example + * + * _.isNumber(3); + * // => true + * + * _.isNumber(Number.MIN_VALUE); + * // => true + * + * _.isNumber(Infinity); + * // => true + * + * _.isNumber('3'); + * // => false + */ + function isNumber(value) { + return typeof value == 'number' || + (isObjectLike(value) && baseGetTag(value) == numberTag); + } + + /** + * Checks if `value` is classified as a `RegExp` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + * @example + * + * _.isRegExp(/abc/); + * // => true + * + * _.isRegExp('/abc/'); + * // => false + */ + var isRegExp = baseIsRegExp; + + /** + * Checks if `value` is classified as a `String` primitive or object. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a string, else `false`. + * @example + * + * _.isString('abc'); + * // => true + * + * _.isString(1); + * // => false + */ + function isString(value) { + return typeof value == 'string' || + (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); + } + + /** + * Checks if `value` is `undefined`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + * + * _.isUndefined(null); + * // => false + */ + function isUndefined(value) { + return value === undefined; + } + + /** + * Converts `value` to an array. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @returns {Array} Returns the converted array. + * @example + * + * _.toArray({ 'a': 1, 'b': 2 }); + * // => [1, 2] + * + * _.toArray('abc'); + * // => ['a', 'b', 'c'] + * + * _.toArray(1); + * // => [] + * + * _.toArray(null); + * // => [] + */ + function toArray(value) { + if (!isArrayLike(value)) { + return values(value); + } + return value.length ? copyArray(value) : []; + } + + /** + * Converts `value` to an integer. + * + * **Note:** This method is loosely based on + * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3.2); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3.2'); + * // => 3 + */ + var toInteger = Number; + + /** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3.2); + * // => 3.2 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3.2'); + * // => 3.2 + */ + var toNumber = Number; + + /** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ + function toString(value) { + if (typeof value == 'string') { + return value; + } + return value == null ? '' : (value + ''); + } + + /*------------------------------------------------------------------------*/ + + /** + * Assigns own enumerable string keyed properties of source objects to the + * destination object. Source objects are applied from left to right. + * Subsequent sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object` and is loosely based on + * [`Object.assign`](https://mdn.io/Object/assign). + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assignIn + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assign({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'c': 3 } + */ + var assign = createAssigner(function(object, source) { + copyObject(source, nativeKeys(source), object); + }); + + /** + * This method is like `_.assign` except that it iterates over own and + * inherited source properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extend + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assign + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assignIn({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } + */ + var assignIn = createAssigner(function(object, source) { + copyObject(source, nativeKeysIn(source), object); + }); + + /** + * Creates an object that inherits from the `prototype` object. If a + * `properties` object is given, its own enumerable string keyed properties + * are assigned to the created object. + * + * @static + * @memberOf _ + * @since 2.3.0 + * @category Object + * @param {Object} prototype The object to inherit from. + * @param {Object} [properties] The properties to assign to the object. + * @returns {Object} Returns the new object. + * @example + * + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * function Circle() { + * Shape.call(this); + * } + * + * Circle.prototype = _.create(Shape.prototype, { + * 'constructor': Circle + * }); + * + * var circle = new Circle; + * circle instanceof Circle; + * // => true + * + * circle instanceof Shape; + * // => true + */ + function create(prototype, properties) { + var result = baseCreate(prototype); + return properties == null ? result : assign(result, properties); + } + + /** + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaultsDeep + * @example + * + * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var defaults = baseRest(function(object, sources) { + object = Object(object); + + var index = -1; + var length = sources.length; + var guard = length > 2 ? sources[2] : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + length = 1; + } + + while (++index < length) { + var source = sources[index]; + var props = keysIn(source); + var propsIndex = -1; + var propsLength = props.length; + + while (++propsIndex < propsLength) { + var key = props[propsIndex]; + var value = object[key]; + + if (value === undefined || + (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) { + object[key] = source[key]; + } + } + } + + return object; + }); + + /** + * Checks if `path` is a direct property of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = { 'a': { 'b': 2 } }; + * var other = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.has(object, 'a'); + * // => true + * + * _.has(object, 'a.b'); + * // => true + * + * _.has(object, ['a', 'b']); + * // => true + * + * _.has(other, 'a'); + * // => false + */ + function has(object, path) { + return object != null && hasOwnProperty.call(object, path); + } + + /** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ + var keys = nativeKeys; + + /** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ + var keysIn = nativeKeysIn; + + /** + * Creates an object composed of the picked `object` properties. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pick(object, ['a', 'c']); + * // => { 'a': 1, 'c': 3 } + */ + var pick = flatRest(function(object, paths) { + return object == null ? {} : basePick(object, paths); + }); + + /** + * This method is like `_.get` except that if the resolved value is a + * function it's invoked with the `this` binding of its parent object and + * its result is returned. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to resolve. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] }; + * + * _.result(object, 'a[0].b.c1'); + * // => 3 + * + * _.result(object, 'a[0].b.c2'); + * // => 4 + * + * _.result(object, 'a[0].b.c3', 'default'); + * // => 'default' + * + * _.result(object, 'a[0].b.c3', _.constant('default')); + * // => 'default' + */ + function result(object, path, defaultValue) { + var value = object == null ? undefined : object[path]; + if (value === undefined) { + value = defaultValue; + } + return isFunction(value) ? value.call(object) : value; + } + + /** + * Creates an array of the own enumerable string keyed property values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.values(new Foo); + * // => [1, 2] (iteration order is not guaranteed) + * + * _.values('hi'); + * // => ['h', 'i'] + */ + function values(object) { + return object == null ? [] : baseValues(object, keys(object)); + } + + /*------------------------------------------------------------------------*/ + + /** + * Converts the characters "&", "<", ">", '"', and "'" in `string` to their + * corresponding HTML entities. + * + * **Note:** No other characters are escaped. To escape additional + * characters use a third-party library like [_he_](https://mths.be/he). + * + * Though the ">" character is escaped for symmetry, characters like + * ">" and "/" don't need escaping in HTML and have no special meaning + * unless they're part of a tag or unquoted attribute value. See + * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * (under "semi-related fun fact") for more details. + * + * When working with HTML you should always + * [quote attribute values](http://wonko.com/post/html-escaping) to reduce + * XSS vectors. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' + */ + function escape(string) { + string = toString(string); + return (string && reHasUnescapedHtml.test(string)) + ? string.replace(reUnescapedHtml, escapeHtmlChar) + : string; + } + + /*------------------------------------------------------------------------*/ + + /** + * This method returns the first argument it receives. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {*} value Any value. + * @returns {*} Returns `value`. + * @example + * + * var object = { 'a': 1 }; + * + * console.log(_.identity(object) === object); + * // => true + */ + function identity(value) { + return value; + } + + /** + * Creates a function that invokes `func` with the arguments of the created + * function. If `func` is a property name, the created function returns the + * property value for a given element. If `func` is an array or object, the + * created function returns `true` for elements that contain the equivalent + * source properties, otherwise it returns `false`. + * + * @static + * @since 4.0.0 + * @memberOf _ + * @category Util + * @param {*} [func=_.identity] The value to convert to a callback. + * @returns {Function} Returns the callback. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true })); + * // => [{ 'user': 'barney', 'age': 36, 'active': true }] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.filter(users, _.iteratee(['user', 'fred'])); + * // => [{ 'user': 'fred', 'age': 40 }] + * + * // The `_.property` iteratee shorthand. + * _.map(users, _.iteratee('user')); + * // => ['barney', 'fred'] + * + * // Create custom iteratee shorthands. + * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) { + * return !_.isRegExp(func) ? iteratee(func) : function(string) { + * return func.test(string); + * }; + * }); + * + * _.filter(['abc', 'def'], /ef/); + * // => ['def'] + */ + var iteratee = baseIteratee; + + /** + * Creates a function that performs a partial deep comparison between a given + * object and `source`, returning `true` if the given object has equivalent + * property values, else `false`. + * + * **Note:** The created function is equivalent to `_.isMatch` with `source` + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. + * + * **Note:** Multiple values can be checked by combining several matchers + * using `_.overSome` + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Util + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new spec function. + * @example + * + * var objects = [ + * { 'a': 1, 'b': 2, 'c': 3 }, + * { 'a': 4, 'b': 5, 'c': 6 } + * ]; + * + * _.filter(objects, _.matches({ 'a': 4, 'c': 6 })); + * // => [{ 'a': 4, 'b': 5, 'c': 6 }] + * + * // Checking for several possible values + * _.filter(objects, _.overSome([_.matches({ 'a': 1 }), _.matches({ 'a': 4 })])); + * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }] + */ + function matches(source) { + return baseMatches(assign({}, source)); + } + + /** + * Adds all own enumerable string keyed function properties of a source + * object to the destination object. If `object` is a function, then methods + * are added to its prototype as well. + * + * **Note:** Use `_.runInContext` to create a pristine `lodash` function to + * avoid conflicts caused by modifying the original. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {Function|Object} [object=lodash] The destination object. + * @param {Object} source The object of functions to add. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.chain=true] Specify whether mixins are chainable. + * @returns {Function|Object} Returns `object`. + * @example + * + * function vowels(string) { + * return _.filter(string, function(v) { + * return /[aeiou]/i.test(v); + * }); + * } + * + * _.mixin({ 'vowels': vowels }); + * _.vowels('fred'); + * // => ['e'] + * + * _('fred').vowels().value(); + * // => ['e'] + * + * _.mixin({ 'vowels': vowels }, { 'chain': false }); + * _('fred').vowels(); + * // => ['e'] + */ + function mixin(object, source, options) { + var props = keys(source), + methodNames = baseFunctions(source, props); + + if (options == null && + !(isObject(source) && (methodNames.length || !props.length))) { + options = source; + source = object; + object = this; + methodNames = baseFunctions(source, keys(source)); + } + var chain = !(isObject(options) && 'chain' in options) || !!options.chain, + isFunc = isFunction(object); + + baseEach(methodNames, function(methodName) { + var func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), + actions = result.__actions__ = copyArray(this.__actions__); + + actions.push({ 'func': func, 'args': arguments, 'thisArg': object }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([this.value()], arguments)); + }; + } + }); + + return object; + } + + /** + * Reverts the `_` variable to its previous value and returns a reference to + * the `lodash` function. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @returns {Function} Returns the `lodash` function. + * @example + * + * var lodash = _.noConflict(); + */ + function noConflict() { + if (root._ === this) { + root._ = oldDash; + } + return this; + } + + /** + * This method returns `undefined`. + * + * @static + * @memberOf _ + * @since 2.3.0 + * @category Util + * @example + * + * _.times(2, _.noop); + * // => [undefined, undefined] + */ + function noop() { + // No operation performed. + } + + /** + * Generates a unique ID. If `prefix` is given, the ID is appended to it. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {string} [prefix=''] The value to prefix the ID with. + * @returns {string} Returns the unique ID. + * @example + * + * _.uniqueId('contact_'); + * // => 'contact_104' + * + * _.uniqueId(); + * // => '105' + */ + function uniqueId(prefix) { + var id = ++idCounter; + return toString(prefix) + id; + } + + /*------------------------------------------------------------------------*/ + + /** + * Computes the maximum value of `array`. If `array` is empty or falsey, + * `undefined` is returned. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Math + * @param {Array} array The array to iterate over. + * @returns {*} Returns the maximum value. + * @example + * + * _.max([4, 2, 8, 6]); + * // => 8 + * + * _.max([]); + * // => undefined + */ + function max(array) { + return (array && array.length) + ? baseExtremum(array, identity, baseGt) + : undefined; + } + + /** + * Computes the minimum value of `array`. If `array` is empty or falsey, + * `undefined` is returned. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Math + * @param {Array} array The array to iterate over. + * @returns {*} Returns the minimum value. + * @example + * + * _.min([4, 2, 8, 6]); + * // => 2 + * + * _.min([]); + * // => undefined + */ + function min(array) { + return (array && array.length) + ? baseExtremum(array, identity, baseLt) + : undefined; + } + + /*------------------------------------------------------------------------*/ + + // Add methods that return wrapped values in chain sequences. + lodash.assignIn = assignIn; + lodash.before = before; + lodash.bind = bind; + lodash.chain = chain; + lodash.compact = compact; + lodash.concat = concat; + lodash.create = create; + lodash.defaults = defaults; + lodash.defer = defer; + lodash.delay = delay; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.iteratee = iteratee; + lodash.keys = keys; + lodash.map = map; + lodash.matches = matches; + lodash.mixin = mixin; + lodash.negate = negate; + lodash.once = once; + lodash.pick = pick; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.tap = tap; + lodash.thru = thru; + lodash.toArray = toArray; + lodash.values = values; + + // Add aliases. + lodash.extend = assignIn; + + // Add methods to `lodash.prototype`. + mixin(lodash, lodash); + + /*------------------------------------------------------------------------*/ + + // Add methods that return unwrapped values in chain sequences. + lodash.clone = clone; + lodash.escape = escape; + lodash.every = every; + lodash.find = find; + lodash.forEach = forEach; + lodash.has = has; + lodash.head = head; + lodash.identity = identity; + lodash.indexOf = indexOf; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isNaN = isNaN; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isUndefined = isUndefined; + lodash.last = last; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.reduce = reduce; + lodash.result = result; + lodash.size = size; + lodash.some = some; + lodash.uniqueId = uniqueId; + + // Add aliases. + lodash.each = forEach; + lodash.first = head; + + mixin(lodash, (function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!hasOwnProperty.call(lodash.prototype, methodName)) { + source[methodName] = func; + } + }); + return source; + }()), { 'chain': false }); + + /*------------------------------------------------------------------------*/ + + /** + * The semantic version number. + * + * @static + * @memberOf _ + * @type {string} + */ + lodash.VERSION = VERSION; + + // Add `Array` methods to `lodash.prototype`. + baseEach(['pop', 'join', 'replace', 'reverse', 'split', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? String.prototype : arrayProto)[methodName], + chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru', + retUnwrapped = /^(?:pop|join|replace|shift)$/.test(methodName); + + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + var value = this.value(); + return func.apply(isArray(value) ? value : [], args); + } + return this[chainName](function(value) { + return func.apply(isArray(value) ? value : [], args); + }); + }; + }); + + // Add chain sequence methods to the `lodash` wrapper. + lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + + /*--------------------------------------------------------------------------*/ + + // Some AMD build optimizers, like r.js, check for condition patterns like: + if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { + // Expose Lodash on the global object to prevent errors when Lodash is + // loaded by a script tag in the presence of an AMD loader. + // See http://requirejs.org/docs/errors.html#mismatch for more details. + // Use `_.noConflict` to remove Lodash from the global object. + root._ = lodash; + + // Define as an anonymous module so, through path mapping, it can be + // referenced as the "underscore" module. + define(function() { + return lodash; + }); + } + // Check for `exports` after `define` in case a build optimizer adds it. + else if (freeModule) { + // Export for Node.js. + (freeModule.exports = lodash)._ = lodash; + // Export for CommonJS support. + freeExports._ = lodash; + } + else { + // Export to the global object. + root._ = lodash; + } +}.call(this)); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/core.min.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/core.min.js new file mode 100644 index 000000000..e425e4d4f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/core.min.js @@ -0,0 +1,29 @@ +/** + * @license + * Lodash (Custom Build) lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE + * Build: `lodash core -o ./dist/lodash.core.js` + */ +;(function(){function n(n){return H(n)&&pn.call(n,"callee")&&!yn.call(n,"callee")}function t(n,t){return n.push.apply(n,t),n}function r(n){return function(t){return null==t?Z:t[n]}}function e(n,t,r,e,u){return u(n,function(n,u,o){r=e?(e=false,n):t(r,n,u,o)}),r}function u(n,t){return j(t,function(t){return n[t]})}function o(n){return n instanceof i?n:new i(n)}function i(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t}function c(n,t,r){if(typeof n!="function")throw new TypeError("Expected a function"); +return setTimeout(function(){n.apply(Z,r)},t)}function f(n,t){var r=true;return mn(n,function(n,e,u){return r=!!t(n,e,u)}),r}function a(n,t,r){for(var e=-1,u=n.length;++et}function b(n,t,r,e,u){return n===t||(null==n||null==t||!H(n)&&!H(t)?n!==n&&t!==t:y(n,t,r,e,b,u))}function y(n,t,r,e,u,o){var i=Nn(n),c=Nn(t),f=i?"[object Array]":hn.call(n),a=c?"[object Array]":hn.call(t),f="[object Arguments]"==f?"[object Object]":f,a="[object Arguments]"==a?"[object Object]":a,l="[object Object]"==f,c="[object Object]"==a,a=f==a;o||(o=[]);var p=An(o,function(t){return t[0]==n}),s=An(o,function(n){ +return n[0]==t});if(p&&s)return p[1]==t;if(o.push([n,t]),o.push([t,n]),a&&!l){if(i)r=T(n,t,r,e,u,o);else n:{switch(f){case"[object Boolean]":case"[object Date]":case"[object Number]":r=J(+n,+t);break n;case"[object Error]":r=n.name==t.name&&n.message==t.message;break n;case"[object RegExp]":case"[object String]":r=n==t+"";break n}r=false}return o.pop(),r}return 1&r||(i=l&&pn.call(n,"__wrapped__"),f=c&&pn.call(t,"__wrapped__"),!i&&!f)?!!a&&(r=B(n,t,r,e,u,o),o.pop(),r):(i=i?n.value():n,f=f?t.value():t, +r=u(i,f,r,e,o),o.pop(),r)}function g(n){return typeof n=="function"?n:null==n?X:(typeof n=="object"?d:r)(n)}function _(n,t){return nt&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Array(u);++ei))return false;var c=o.get(n),f=o.get(t);if(c&&f)return c==t&&f==n;for(var c=-1,f=true,a=2&r?[]:Z;++cr?jn(e+r,0):r:0,r=(r||0)-1;for(var u=t===t;++rarguments.length,mn); +}function G(n,t){var r;if(typeof t!="function")throw new TypeError("Expected a function");return n=Fn(n),function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=Z),r}}function J(n,t){return n===t||n!==n&&t!==t}function M(n){var t;return(t=null!=n)&&(t=n.length,t=typeof t=="number"&&-1=t),t&&!U(n)}function U(n){return!!V(n)&&(n=hn.call(n),"[object Function]"==n||"[object GeneratorFunction]"==n||"[object AsyncFunction]"==n||"[object Proxy]"==n)}function V(n){var t=typeof n; +return null!=n&&("object"==t||"function"==t)}function H(n){return null!=n&&typeof n=="object"}function K(n){return typeof n=="number"||H(n)&&"[object Number]"==hn.call(n)}function L(n){return typeof n=="string"||!Nn(n)&&H(n)&&"[object String]"==hn.call(n)}function Q(n){return typeof n=="string"?n:null==n?"":n+""}function W(n){return null==n?[]:u(n,Dn(n))}function X(n){return n}function Y(n,r,e){var u=Dn(r),o=h(r,u);null!=e||V(r)&&(o.length||!u.length)||(e=r,r=n,n=this,o=h(r,Dn(r)));var i=!(V(e)&&"chain"in e&&!e.chain),c=U(n); +return mn(o,function(e){var u=r[e];n[e]=u,c&&(n.prototype[e]=function(){var r=this.__chain__;if(i||r){var e=n(this.__wrapped__);return(e.__actions__=A(this.__actions__)).push({func:u,args:arguments,thisArg:n}),e.__chain__=r,e}return u.apply(n,t([this.value()],arguments))})}),n}var Z,nn=1/0,tn=/[&<>"']/g,rn=RegExp(tn.source),en=/^(?:0|[1-9]\d*)$/,un=typeof self=="object"&&self&&self.Object===Object&&self,on=typeof global=="object"&&global&&global.Object===Object&&global||un||Function("return this")(),cn=(un=typeof exports=="object"&&exports&&!exports.nodeType&&exports)&&typeof module=="object"&&module&&!module.nodeType&&module,fn=function(n){ +return function(t){return null==n?Z:n[t]}}({"&":"&","<":"<",">":">",'"':""","'":"'"}),an=Array.prototype,ln=Object.prototype,pn=ln.hasOwnProperty,sn=0,hn=ln.toString,vn=on._,bn=Object.create,yn=ln.propertyIsEnumerable,gn=on.isFinite,_n=function(n,t){return function(r){return n(t(r))}}(Object.keys,Object),jn=Math.max,dn=function(){function n(){}return function(t){return V(t)?bn?bn(t):(n.prototype=t,t=new n,n.prototype=Z,t):{}}}();i.prototype=dn(o.prototype),i.prototype.constructor=i; +var mn=function(n,t){return function(r,e){if(null==r)return r;if(!M(r))return n(r,e);for(var u=r.length,o=t?u:-1,i=Object(r);(t?o--:++or&&(r=jn(e+r,0));n:{for(t=g(t),e=n.length,r+=-1;++re||o&&c&&a||!u&&a||!i){r=1;break n}if(!o&&r { '4': 1, '6': 2 } + * + * // The `_.property` iteratee shorthand. + * _.countBy(['one', 'two', 'three'], 'length'); + * // => { '3': 2, '5': 1 } + */ +var countBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + ++result[key]; + } else { + baseAssignValue(result, key, 1); + } +}); + +module.exports = countBy; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/create.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/create.js new file mode 100644 index 000000000..919edb850 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/create.js @@ -0,0 +1,43 @@ +var baseAssign = require('./_baseAssign'), + baseCreate = require('./_baseCreate'); + +/** + * Creates an object that inherits from the `prototype` object. If a + * `properties` object is given, its own enumerable string keyed properties + * are assigned to the created object. + * + * @static + * @memberOf _ + * @since 2.3.0 + * @category Object + * @param {Object} prototype The object to inherit from. + * @param {Object} [properties] The properties to assign to the object. + * @returns {Object} Returns the new object. + * @example + * + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * function Circle() { + * Shape.call(this); + * } + * + * Circle.prototype = _.create(Shape.prototype, { + * 'constructor': Circle + * }); + * + * var circle = new Circle; + * circle instanceof Circle; + * // => true + * + * circle instanceof Shape; + * // => true + */ +function create(prototype, properties) { + var result = baseCreate(prototype); + return properties == null ? result : baseAssign(result, properties); +} + +module.exports = create; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/curry.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/curry.js new file mode 100644 index 000000000..918db1a4a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/curry.js @@ -0,0 +1,57 @@ +var createWrap = require('./_createWrap'); + +/** Used to compose bitmasks for function metadata. */ +var WRAP_CURRY_FLAG = 8; + +/** + * Creates a function that accepts arguments of `func` and either invokes + * `func` returning its result, if at least `arity` number of arguments have + * been provided, or returns a function that accepts the remaining `func` + * arguments, and so on. The arity of `func` may be specified if `func.length` + * is not sufficient. + * + * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curry(abc); + * + * curried(1)(2)(3); + * // => [1, 2, 3] + * + * curried(1, 2)(3); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(1)(_, 3)(2); + * // => [1, 2, 3] + */ +function curry(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curry.placeholder; + return result; +} + +// Assign default placeholders. +curry.placeholder = {}; + +module.exports = curry; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/curryRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/curryRight.js new file mode 100644 index 000000000..c85b6f339 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/curryRight.js @@ -0,0 +1,54 @@ +var createWrap = require('./_createWrap'); + +/** Used to compose bitmasks for function metadata. */ +var WRAP_CURRY_RIGHT_FLAG = 16; + +/** + * This method is like `_.curry` except that arguments are applied to `func` + * in the manner of `_.partialRight` instead of `_.partial`. + * + * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curryRight(abc); + * + * curried(3)(2)(1); + * // => [1, 2, 3] + * + * curried(2, 3)(1); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(3)(1, _)(2); + * // => [1, 2, 3] + */ +function curryRight(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryRight.placeholder; + return result; +} + +// Assign default placeholders. +curryRight.placeholder = {}; + +module.exports = curryRight; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/date.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/date.js new file mode 100644 index 000000000..cbf5b4109 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/date.js @@ -0,0 +1,3 @@ +module.exports = { + 'now': require('./now') +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/debounce.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/debounce.js new file mode 100644 index 000000000..8f751d53d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/debounce.js @@ -0,0 +1,191 @@ +var isObject = require('./isObject'), + now = require('./now'), + toNumber = require('./toNumber'); + +/** Error message constants. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max, + nativeMin = Math.min; + +/** + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked. The debounced function comes with a `cancel` method to cancel + * delayed `func` invocations and a `flush` method to immediately invoke them. + * Provide `options` to indicate whether `func` should be invoked on the + * leading and/or trailing edge of the `wait` timeout. The `func` is invoked + * with the last arguments provided to the debounced function. Subsequent + * calls to the debounced function return the result of the last `func` + * invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the debounced function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.debounce` and `_.throttle`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to debounce. + * @param {number} [wait=0] The number of milliseconds to delay. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=false] + * Specify invoking on the leading edge of the timeout. + * @param {number} [options.maxWait] + * The maximum time `func` is allowed to be delayed before it's invoked. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * // Avoid costly calculations while the window size is in flux. + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); + * + * // Invoke `sendMail` when clicked, debouncing subsequent calls. + * jQuery(element).on('click', _.debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * })); + * + * // Ensure `batchLog` is invoked once after 1 second of debounced calls. + * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); + * var source = new EventSource('/stream'); + * jQuery(source).on('message', debounced); + * + * // Cancel the trailing debounced invocation. + * jQuery(window).on('popstate', debounced.cancel); + */ +function debounce(func, wait, options) { + var lastArgs, + lastThis, + maxWait, + result, + timerId, + lastCallTime, + lastInvokeTime = 0, + leading = false, + maxing = false, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = toNumber(wait) || 0; + if (isObject(options)) { + leading = !!options.leading; + maxing = 'maxWait' in options; + maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + + function invokeFunc(time) { + var args = lastArgs, + thisArg = lastThis; + + lastArgs = lastThis = undefined; + lastInvokeTime = time; + result = func.apply(thisArg, args); + return result; + } + + function leadingEdge(time) { + // Reset any `maxWait` timer. + lastInvokeTime = time; + // Start the timer for the trailing edge. + timerId = setTimeout(timerExpired, wait); + // Invoke the leading edge. + return leading ? invokeFunc(time) : result; + } + + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime, + timeWaiting = wait - timeSinceLastCall; + + return maxing + ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) + : timeWaiting; + } + + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime; + + // Either this is the first call, activity has stopped and we're at the + // trailing edge, the system time has gone backwards and we're treating + // it as the trailing edge, or we've hit the `maxWait` limit. + return (lastCallTime === undefined || (timeSinceLastCall >= wait) || + (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); + } + + function timerExpired() { + var time = now(); + if (shouldInvoke(time)) { + return trailingEdge(time); + } + // Restart the timer. + timerId = setTimeout(timerExpired, remainingWait(time)); + } + + function trailingEdge(time) { + timerId = undefined; + + // Only invoke if we have `lastArgs` which means `func` has been + // debounced at least once. + if (trailing && lastArgs) { + return invokeFunc(time); + } + lastArgs = lastThis = undefined; + return result; + } + + function cancel() { + if (timerId !== undefined) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = undefined; + } + + function flush() { + return timerId === undefined ? result : trailingEdge(now()); + } + + function debounced() { + var time = now(), + isInvoking = shouldInvoke(time); + + lastArgs = arguments; + lastThis = this; + lastCallTime = time; + + if (isInvoking) { + if (timerId === undefined) { + return leadingEdge(lastCallTime); + } + if (maxing) { + // Handle invocations in a tight loop. + clearTimeout(timerId); + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); + } + } + if (timerId === undefined) { + timerId = setTimeout(timerExpired, wait); + } + return result; + } + debounced.cancel = cancel; + debounced.flush = flush; + return debounced; +} + +module.exports = debounce; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/deburr.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/deburr.js new file mode 100644 index 000000000..f85e314a0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/deburr.js @@ -0,0 +1,45 @@ +var deburrLetter = require('./_deburrLetter'), + toString = require('./toString'); + +/** Used to match Latin Unicode letters (excluding mathematical operators). */ +var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; + +/** Used to compose unicode character classes. */ +var rsComboMarksRange = '\\u0300-\\u036f', + reComboHalfMarksRange = '\\ufe20-\\ufe2f', + rsComboSymbolsRange = '\\u20d0-\\u20ff', + rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange; + +/** Used to compose unicode capture groups. */ +var rsCombo = '[' + rsComboRange + ']'; + +/** + * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and + * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). + */ +var reComboMark = RegExp(rsCombo, 'g'); + +/** + * Deburrs `string` by converting + * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) + * letters to basic Latin letters and removing + * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to deburr. + * @returns {string} Returns the deburred string. + * @example + * + * _.deburr('déjà vu'); + * // => 'deja vu' + */ +function deburr(string) { + string = toString(string); + return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); +} + +module.exports = deburr; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defaultTo.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defaultTo.js new file mode 100644 index 000000000..5b333592e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defaultTo.js @@ -0,0 +1,25 @@ +/** + * Checks `value` to determine whether a default value should be returned in + * its place. The `defaultValue` is returned if `value` is `NaN`, `null`, + * or `undefined`. + * + * @static + * @memberOf _ + * @since 4.14.0 + * @category Util + * @param {*} value The value to check. + * @param {*} defaultValue The default value. + * @returns {*} Returns the resolved value. + * @example + * + * _.defaultTo(1, 10); + * // => 1 + * + * _.defaultTo(undefined, 10); + * // => 10 + */ +function defaultTo(value, defaultValue) { + return (value == null || value !== value) ? defaultValue : value; +} + +module.exports = defaultTo; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defaults.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defaults.js new file mode 100644 index 000000000..c74df044c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defaults.js @@ -0,0 +1,64 @@ +var baseRest = require('./_baseRest'), + eq = require('./eq'), + isIterateeCall = require('./_isIterateeCall'), + keysIn = require('./keysIn'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaultsDeep + * @example + * + * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ +var defaults = baseRest(function(object, sources) { + object = Object(object); + + var index = -1; + var length = sources.length; + var guard = length > 2 ? sources[2] : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + length = 1; + } + + while (++index < length) { + var source = sources[index]; + var props = keysIn(source); + var propsIndex = -1; + var propsLength = props.length; + + while (++propsIndex < propsLength) { + var key = props[propsIndex]; + var value = object[key]; + + if (value === undefined || + (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) { + object[key] = source[key]; + } + } + } + + return object; +}); + +module.exports = defaults; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defaultsDeep.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defaultsDeep.js new file mode 100644 index 000000000..9b5fa3ee2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defaultsDeep.js @@ -0,0 +1,30 @@ +var apply = require('./_apply'), + baseRest = require('./_baseRest'), + customDefaultsMerge = require('./_customDefaultsMerge'), + mergeWith = require('./mergeWith'); + +/** + * This method is like `_.defaults` except that it recursively assigns + * default properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaults + * @example + * + * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } }); + * // => { 'a': { 'b': 2, 'c': 3 } } + */ +var defaultsDeep = baseRest(function(args) { + args.push(undefined, customDefaultsMerge); + return apply(mergeWith, undefined, args); +}); + +module.exports = defaultsDeep; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defer.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defer.js new file mode 100644 index 000000000..f6d6c6fa6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/defer.js @@ -0,0 +1,26 @@ +var baseDelay = require('./_baseDelay'), + baseRest = require('./_baseRest'); + +/** + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to defer. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.defer(function(text) { + * console.log(text); + * }, 'deferred'); + * // => Logs 'deferred' after one millisecond. + */ +var defer = baseRest(function(func, args) { + return baseDelay(func, 1, args); +}); + +module.exports = defer; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/delay.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/delay.js new file mode 100644 index 000000000..bd554796f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/delay.js @@ -0,0 +1,28 @@ +var baseDelay = require('./_baseDelay'), + baseRest = require('./_baseRest'), + toNumber = require('./toNumber'); + +/** + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.delay(function(text) { + * console.log(text); + * }, 1000, 'later'); + * // => Logs 'later' after one second. + */ +var delay = baseRest(function(func, wait, args) { + return baseDelay(func, toNumber(wait) || 0, args); +}); + +module.exports = delay; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/difference.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/difference.js new file mode 100644 index 000000000..fa28bb301 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/difference.js @@ -0,0 +1,33 @@ +var baseDifference = require('./_baseDifference'), + baseFlatten = require('./_baseFlatten'), + baseRest = require('./_baseRest'), + isArrayLikeObject = require('./isArrayLikeObject'); + +/** + * Creates an array of `array` values not included in the other given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * **Note:** Unlike `_.pullAll`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.without, _.xor + * @example + * + * _.difference([2, 1], [2, 3]); + * // => [1] + */ +var difference = baseRest(function(array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) + : []; +}); + +module.exports = difference; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/differenceBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/differenceBy.js new file mode 100644 index 000000000..2cd63e7ec --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/differenceBy.js @@ -0,0 +1,44 @@ +var baseDifference = require('./_baseDifference'), + baseFlatten = require('./_baseFlatten'), + baseIteratee = require('./_baseIteratee'), + baseRest = require('./_baseRest'), + isArrayLikeObject = require('./isArrayLikeObject'), + last = require('./last'); + +/** + * This method is like `_.difference` except that it accepts `iteratee` which + * is invoked for each element of `array` and `values` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * **Note:** Unlike `_.pullAllBy`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2] + * + * // The `_.property` iteratee shorthand. + * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ +var differenceBy = baseRest(function(array, values) { + var iteratee = last(values); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), baseIteratee(iteratee, 2)) + : []; +}); + +module.exports = differenceBy; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/differenceWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/differenceWith.js new file mode 100644 index 000000000..c0233f4b9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/differenceWith.js @@ -0,0 +1,40 @@ +var baseDifference = require('./_baseDifference'), + baseFlatten = require('./_baseFlatten'), + baseRest = require('./_baseRest'), + isArrayLikeObject = require('./isArrayLikeObject'), + last = require('./last'); + +/** + * This method is like `_.difference` except that it accepts `comparator` + * which is invoked to compare elements of `array` to `values`. The order and + * references of result values are determined by the first array. The comparator + * is invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.pullAllWith`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * + * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual); + * // => [{ 'x': 2, 'y': 1 }] + */ +var differenceWith = baseRest(function(array, values) { + var comparator = last(values); + if (isArrayLikeObject(comparator)) { + comparator = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator) + : []; +}); + +module.exports = differenceWith; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/divide.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/divide.js new file mode 100644 index 000000000..8cae0cd1b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/divide.js @@ -0,0 +1,22 @@ +var createMathOperation = require('./_createMathOperation'); + +/** + * Divide two numbers. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Math + * @param {number} dividend The first number in a division. + * @param {number} divisor The second number in a division. + * @returns {number} Returns the quotient. + * @example + * + * _.divide(6, 4); + * // => 1.5 + */ +var divide = createMathOperation(function(dividend, divisor) { + return dividend / divisor; +}, 1); + +module.exports = divide; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/drop.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/drop.js new file mode 100644 index 000000000..d5c3cbaa4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/drop.js @@ -0,0 +1,38 @@ +var baseSlice = require('./_baseSlice'), + toInteger = require('./toInteger'); + +/** + * Creates a slice of `array` with `n` elements dropped from the beginning. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.drop([1, 2, 3]); + * // => [2, 3] + * + * _.drop([1, 2, 3], 2); + * // => [3] + * + * _.drop([1, 2, 3], 5); + * // => [] + * + * _.drop([1, 2, 3], 0); + * // => [1, 2, 3] + */ +function drop(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, n < 0 ? 0 : n, length); +} + +module.exports = drop; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/dropRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/dropRight.js new file mode 100644 index 000000000..441fe9968 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/dropRight.js @@ -0,0 +1,39 @@ +var baseSlice = require('./_baseSlice'), + toInteger = require('./toInteger'); + +/** + * Creates a slice of `array` with `n` elements dropped from the end. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.dropRight([1, 2, 3]); + * // => [1, 2] + * + * _.dropRight([1, 2, 3], 2); + * // => [1] + * + * _.dropRight([1, 2, 3], 5); + * // => [] + * + * _.dropRight([1, 2, 3], 0); + * // => [1, 2, 3] + */ +function dropRight(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, 0, n < 0 ? 0 : n); +} + +module.exports = dropRight; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/dropRightWhile.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/dropRightWhile.js new file mode 100644 index 000000000..9ad36a044 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/dropRightWhile.js @@ -0,0 +1,45 @@ +var baseIteratee = require('./_baseIteratee'), + baseWhile = require('./_baseWhile'); + +/** + * Creates a slice of `array` excluding elements dropped from the end. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.dropRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney'] + * + * // The `_.matches` iteratee shorthand. + * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['barney', 'fred'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropRightWhile(users, ['active', false]); + * // => objects for ['barney'] + * + * // The `_.property` iteratee shorthand. + * _.dropRightWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ +function dropRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, baseIteratee(predicate, 3), true, true) + : []; +} + +module.exports = dropRightWhile; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/dropWhile.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/dropWhile.js new file mode 100644 index 000000000..903ef568c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/dropWhile.js @@ -0,0 +1,45 @@ +var baseIteratee = require('./_baseIteratee'), + baseWhile = require('./_baseWhile'); + +/** + * Creates a slice of `array` excluding elements dropped from the beginning. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.dropWhile(users, function(o) { return !o.active; }); + * // => objects for ['pebbles'] + * + * // The `_.matches` iteratee shorthand. + * _.dropWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropWhile(users, ['active', false]); + * // => objects for ['pebbles'] + * + * // The `_.property` iteratee shorthand. + * _.dropWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ +function dropWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, baseIteratee(predicate, 3), true) + : []; +} + +module.exports = dropWhile; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/each.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/each.js new file mode 100644 index 000000000..8800f4204 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/each.js @@ -0,0 +1 @@ +module.exports = require('./forEach'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/eachRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/eachRight.js new file mode 100644 index 000000000..3252b2aba --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/eachRight.js @@ -0,0 +1 @@ +module.exports = require('./forEachRight'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/endsWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/endsWith.js new file mode 100644 index 000000000..76fc866e3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/endsWith.js @@ -0,0 +1,43 @@ +var baseClamp = require('./_baseClamp'), + baseToString = require('./_baseToString'), + toInteger = require('./toInteger'), + toString = require('./toString'); + +/** + * Checks if `string` ends with the given target string. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {string} [target] The string to search for. + * @param {number} [position=string.length] The position to search up to. + * @returns {boolean} Returns `true` if `string` ends with `target`, + * else `false`. + * @example + * + * _.endsWith('abc', 'c'); + * // => true + * + * _.endsWith('abc', 'b'); + * // => false + * + * _.endsWith('abc', 'b', 2); + * // => true + */ +function endsWith(string, target, position) { + string = toString(string); + target = baseToString(target); + + var length = string.length; + position = position === undefined + ? length + : baseClamp(toInteger(position), 0, length); + + var end = position; + position -= target.length; + return position >= 0 && string.slice(position, end) == target; +} + +module.exports = endsWith; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/entries.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/entries.js new file mode 100644 index 000000000..7a88df204 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/entries.js @@ -0,0 +1 @@ +module.exports = require('./toPairs'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/entriesIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/entriesIn.js new file mode 100644 index 000000000..f6c6331c1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/entriesIn.js @@ -0,0 +1 @@ +module.exports = require('./toPairsIn'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/eq.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/eq.js new file mode 100644 index 000000000..a94068805 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/eq.js @@ -0,0 +1,37 @@ +/** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ +function eq(value, other) { + return value === other || (value !== value && other !== other); +} + +module.exports = eq; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/escape.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/escape.js new file mode 100644 index 000000000..9247e0029 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/escape.js @@ -0,0 +1,43 @@ +var escapeHtmlChar = require('./_escapeHtmlChar'), + toString = require('./toString'); + +/** Used to match HTML entities and HTML characters. */ +var reUnescapedHtml = /[&<>"']/g, + reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + +/** + * Converts the characters "&", "<", ">", '"', and "'" in `string` to their + * corresponding HTML entities. + * + * **Note:** No other characters are escaped. To escape additional + * characters use a third-party library like [_he_](https://mths.be/he). + * + * Though the ">" character is escaped for symmetry, characters like + * ">" and "/" don't need escaping in HTML and have no special meaning + * unless they're part of a tag or unquoted attribute value. See + * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * (under "semi-related fun fact") for more details. + * + * When working with HTML you should always + * [quote attribute values](http://wonko.com/post/html-escaping) to reduce + * XSS vectors. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' + */ +function escape(string) { + string = toString(string); + return (string && reHasUnescapedHtml.test(string)) + ? string.replace(reUnescapedHtml, escapeHtmlChar) + : string; +} + +module.exports = escape; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/escapeRegExp.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/escapeRegExp.js new file mode 100644 index 000000000..0a58c69fc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/escapeRegExp.js @@ -0,0 +1,32 @@ +var toString = require('./toString'); + +/** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ +var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, + reHasRegExpChar = RegExp(reRegExpChar.source); + +/** + * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+", + * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escapeRegExp('[lodash](https://lodash.com/)'); + * // => '\[lodash\]\(https://lodash\.com/\)' + */ +function escapeRegExp(string) { + string = toString(string); + return (string && reHasRegExpChar.test(string)) + ? string.replace(reRegExpChar, '\\$&') + : string; +} + +module.exports = escapeRegExp; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/every.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/every.js new file mode 100644 index 000000000..25080dac4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/every.js @@ -0,0 +1,56 @@ +var arrayEvery = require('./_arrayEvery'), + baseEvery = require('./_baseEvery'), + baseIteratee = require('./_baseIteratee'), + isArray = require('./isArray'), + isIterateeCall = require('./_isIterateeCall'); + +/** + * Checks if `predicate` returns truthy for **all** elements of `collection`. + * Iteration is stopped once `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * **Note:** This method returns `true` for + * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because + * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of + * elements of empty collections. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.every(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.every(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.every(users, 'active'); + * // => false + */ +function every(collection, predicate, guard) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, baseIteratee(predicate, 3)); +} + +module.exports = every; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/extend.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/extend.js new file mode 100644 index 000000000..e00166c20 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/extend.js @@ -0,0 +1 @@ +module.exports = require('./assignIn'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/extendWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/extendWith.js new file mode 100644 index 000000000..dbdcb3b4e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/extendWith.js @@ -0,0 +1 @@ +module.exports = require('./assignInWith'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fill.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fill.js new file mode 100644 index 000000000..ae13aa1c9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fill.js @@ -0,0 +1,45 @@ +var baseFill = require('./_baseFill'), + isIterateeCall = require('./_isIterateeCall'); + +/** + * Fills elements of `array` with `value` from `start` up to, but not + * including, `end`. + * + * **Note:** This method mutates `array`. + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Array + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.fill(array, 'a'); + * console.log(array); + * // => ['a', 'a', 'a'] + * + * _.fill(Array(3), 2); + * // => [2, 2, 2] + * + * _.fill([4, 6, 8, 10], '*', 1, 3); + * // => [4, '*', '*', 10] + */ +function fill(array, value, start, end) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + if (start && typeof start != 'number' && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); +} + +module.exports = fill; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/filter.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/filter.js new file mode 100644 index 000000000..89e0c8c48 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/filter.js @@ -0,0 +1,52 @@ +var arrayFilter = require('./_arrayFilter'), + baseFilter = require('./_baseFilter'), + baseIteratee = require('./_baseIteratee'), + isArray = require('./isArray'); + +/** + * Iterates over elements of `collection`, returning an array of all elements + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * **Note:** Unlike `_.remove`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.reject + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * _.filter(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.filter(users, { 'age': 36, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.filter(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.filter(users, 'active'); + * // => objects for ['barney'] + * + * // Combining several predicates using `_.overEvery` or `_.overSome`. + * _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]])); + * // => objects for ['fred', 'barney'] + */ +function filter(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, baseIteratee(predicate, 3)); +} + +module.exports = filter; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/find.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/find.js new file mode 100644 index 000000000..de732ccb4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/find.js @@ -0,0 +1,42 @@ +var createFind = require('./_createFind'), + findIndex = require('./findIndex'); + +/** + * Iterates over elements of `collection`, returning the first element + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false }, + * { 'user': 'pebbles', 'age': 1, 'active': true } + * ]; + * + * _.find(users, function(o) { return o.age < 40; }); + * // => object for 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.find(users, { 'age': 1, 'active': true }); + * // => object for 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.find(users, ['active', false]); + * // => object for 'fred' + * + * // The `_.property` iteratee shorthand. + * _.find(users, 'active'); + * // => object for 'barney' + */ +var find = createFind(findIndex); + +module.exports = find; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findIndex.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findIndex.js new file mode 100644 index 000000000..4689069f8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findIndex.js @@ -0,0 +1,55 @@ +var baseFindIndex = require('./_baseFindIndex'), + baseIteratee = require('./_baseIteratee'), + toInteger = require('./toInteger'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * This method is like `_.find` except that it returns the index of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.findIndex(users, function(o) { return o.user == 'barney'; }); + * // => 0 + * + * // The `_.matches` iteratee shorthand. + * _.findIndex(users, { 'user': 'fred', 'active': false }); + * // => 1 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findIndex(users, ['active', false]); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.findIndex(users, 'active'); + * // => 2 + */ +function findIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseFindIndex(array, baseIteratee(predicate, 3), index); +} + +module.exports = findIndex; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findKey.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findKey.js new file mode 100644 index 000000000..cac0248a9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findKey.js @@ -0,0 +1,44 @@ +var baseFindKey = require('./_baseFindKey'), + baseForOwn = require('./_baseForOwn'), + baseIteratee = require('./_baseIteratee'); + +/** + * This method is like `_.find` except that it returns the key of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findKey(users, function(o) { return o.age < 40; }); + * // => 'barney' (iteration order is not guaranteed) + * + * // The `_.matches` iteratee shorthand. + * _.findKey(users, { 'age': 1, 'active': true }); + * // => 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findKey(users, 'active'); + * // => 'barney' + */ +function findKey(object, predicate) { + return baseFindKey(object, baseIteratee(predicate, 3), baseForOwn); +} + +module.exports = findKey; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findLast.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findLast.js new file mode 100644 index 000000000..70b4271dc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findLast.js @@ -0,0 +1,25 @@ +var createFind = require('./_createFind'), + findLastIndex = require('./findLastIndex'); + +/** + * This method is like `_.find` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=collection.length-1] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * _.findLast([1, 2, 3, 4], function(n) { + * return n % 2 == 1; + * }); + * // => 3 + */ +var findLast = createFind(findLastIndex); + +module.exports = findLast; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findLastIndex.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findLastIndex.js new file mode 100644 index 000000000..7da3431f6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findLastIndex.js @@ -0,0 +1,59 @@ +var baseFindIndex = require('./_baseFindIndex'), + baseIteratee = require('./_baseIteratee'), + toInteger = require('./toInteger'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max, + nativeMin = Math.min; + +/** + * This method is like `_.findIndex` except that it iterates over elements + * of `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; }); + * // => 2 + * + * // The `_.matches` iteratee shorthand. + * _.findLastIndex(users, { 'user': 'barney', 'active': true }); + * // => 0 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastIndex(users, ['active', false]); + * // => 2 + * + * // The `_.property` iteratee shorthand. + * _.findLastIndex(users, 'active'); + * // => 0 + */ +function findLastIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = length - 1; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = fromIndex < 0 + ? nativeMax(length + index, 0) + : nativeMin(index, length - 1); + } + return baseFindIndex(array, baseIteratee(predicate, 3), index, true); +} + +module.exports = findLastIndex; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findLastKey.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findLastKey.js new file mode 100644 index 000000000..66fb9fbce --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/findLastKey.js @@ -0,0 +1,44 @@ +var baseFindKey = require('./_baseFindKey'), + baseForOwnRight = require('./_baseForOwnRight'), + baseIteratee = require('./_baseIteratee'); + +/** + * This method is like `_.findKey` except that it iterates over elements of + * a collection in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findLastKey(users, function(o) { return o.age < 40; }); + * // => returns 'pebbles' assuming `_.findKey` returns 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.findLastKey(users, { 'age': 36, 'active': true }); + * // => 'barney' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findLastKey(users, 'active'); + * // => 'pebbles' + */ +function findLastKey(object, predicate) { + return baseFindKey(object, baseIteratee(predicate, 3), baseForOwnRight); +} + +module.exports = findLastKey; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/first.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/first.js new file mode 100644 index 000000000..53f4ad13e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/first.js @@ -0,0 +1 @@ +module.exports = require('./head'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flake.lock b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flake.lock new file mode 100644 index 000000000..dd0325218 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flake.lock @@ -0,0 +1,40 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1613582597, + "narHash": "sha256-6LvipIvFuhyorHpUqK3HjySC5Y6gshXHFBhU9EJ4DoM=", + "path": "/nix/store/srvplqq673sqd9vyfhyc5w1p88y1gfm4-source", + "rev": "6b1057b452c55bb3b463f0d7055bc4ec3fd1f381", + "type": "path" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "utils": "utils" + } + }, + "utils": { + "locked": { + "lastModified": 1610051610, + "narHash": "sha256-U9rPz/usA1/Aohhk7Cmc2gBrEEKRzcW4nwPWMPwja4Y=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3982c9903e93927c2164caa727cd3f6a0e6d14cc", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flake.nix b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flake.nix new file mode 100644 index 000000000..15a451c6f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flake.nix @@ -0,0 +1,20 @@ +{ + inputs = { + utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, utils }: + utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages."${system}"; + in rec { + devShell = pkgs.mkShell { + nativeBuildInputs = with pkgs; [ + yarn + nodejs-14_x + nodePackages.typescript-language-server + nodePackages.eslint + ]; + }; + }); +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatMap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatMap.js new file mode 100644 index 000000000..e6685068f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatMap.js @@ -0,0 +1,29 @@ +var baseFlatten = require('./_baseFlatten'), + map = require('./map'); + +/** + * Creates a flattened array of values by running each element in `collection` + * thru `iteratee` and flattening the mapped results. The iteratee is invoked + * with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [n, n]; + * } + * + * _.flatMap([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ +function flatMap(collection, iteratee) { + return baseFlatten(map(collection, iteratee), 1); +} + +module.exports = flatMap; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatMapDeep.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatMapDeep.js new file mode 100644 index 000000000..4653d6033 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatMapDeep.js @@ -0,0 +1,31 @@ +var baseFlatten = require('./_baseFlatten'), + map = require('./map'); + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDeep([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ +function flatMapDeep(collection, iteratee) { + return baseFlatten(map(collection, iteratee), INFINITY); +} + +module.exports = flatMapDeep; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatMapDepth.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatMapDepth.js new file mode 100644 index 000000000..6d72005c9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatMapDepth.js @@ -0,0 +1,31 @@ +var baseFlatten = require('./_baseFlatten'), + map = require('./map'), + toInteger = require('./toInteger'); + +/** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDepth([1, 2], duplicate, 2); + * // => [[1, 1], [2, 2]] + */ +function flatMapDepth(collection, iteratee, depth) { + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(map(collection, iteratee), depth); +} + +module.exports = flatMapDepth; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatten.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatten.js new file mode 100644 index 000000000..3f09f7f77 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flatten.js @@ -0,0 +1,22 @@ +var baseFlatten = require('./_baseFlatten'); + +/** + * Flattens `array` a single level deep. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flatten([1, [2, [3, [4]], 5]]); + * // => [1, 2, [3, [4]], 5] + */ +function flatten(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, 1) : []; +} + +module.exports = flatten; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flattenDeep.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flattenDeep.js new file mode 100644 index 000000000..8ad585cf4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flattenDeep.js @@ -0,0 +1,25 @@ +var baseFlatten = require('./_baseFlatten'); + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** + * Recursively flattens `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flattenDeep([1, [2, [3, [4]], 5]]); + * // => [1, 2, 3, 4, 5] + */ +function flattenDeep(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, INFINITY) : []; +} + +module.exports = flattenDeep; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flattenDepth.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flattenDepth.js new file mode 100644 index 000000000..441fdcc22 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flattenDepth.js @@ -0,0 +1,33 @@ +var baseFlatten = require('./_baseFlatten'), + toInteger = require('./toInteger'); + +/** + * Recursively flatten `array` up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Array + * @param {Array} array The array to flatten. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * var array = [1, [2, [3, [4]], 5]]; + * + * _.flattenDepth(array, 1); + * // => [1, 2, [3, [4]], 5] + * + * _.flattenDepth(array, 2); + * // => [1, 2, 3, [4], 5] + */ +function flattenDepth(array, depth) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(array, depth); +} + +module.exports = flattenDepth; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flip.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flip.js new file mode 100644 index 000000000..c28dd7896 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flip.js @@ -0,0 +1,28 @@ +var createWrap = require('./_createWrap'); + +/** Used to compose bitmasks for function metadata. */ +var WRAP_FLIP_FLAG = 512; + +/** + * Creates a function that invokes `func` with arguments reversed. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to flip arguments for. + * @returns {Function} Returns the new flipped function. + * @example + * + * var flipped = _.flip(function() { + * return _.toArray(arguments); + * }); + * + * flipped('a', 'b', 'c', 'd'); + * // => ['d', 'c', 'b', 'a'] + */ +function flip(func) { + return createWrap(func, WRAP_FLIP_FLAG); +} + +module.exports = flip; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/floor.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/floor.js new file mode 100644 index 000000000..ab6dfa28a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/floor.js @@ -0,0 +1,26 @@ +var createRound = require('./_createRound'); + +/** + * Computes `number` rounded down to `precision`. + * + * @static + * @memberOf _ + * @since 3.10.0 + * @category Math + * @param {number} number The number to round down. + * @param {number} [precision=0] The precision to round down to. + * @returns {number} Returns the rounded down number. + * @example + * + * _.floor(4.006); + * // => 4 + * + * _.floor(0.046, 2); + * // => 0.04 + * + * _.floor(4060, -2); + * // => 4000 + */ +var floor = createRound('floor'); + +module.exports = floor; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flow.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flow.js new file mode 100644 index 000000000..74b6b62d4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flow.js @@ -0,0 +1,27 @@ +var createFlow = require('./_createFlow'); + +/** + * Creates a function that returns the result of invoking the given functions + * with the `this` binding of the created function, where each successive + * invocation is supplied the return value of the previous. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Util + * @param {...(Function|Function[])} [funcs] The functions to invoke. + * @returns {Function} Returns the new composite function. + * @see _.flowRight + * @example + * + * function square(n) { + * return n * n; + * } + * + * var addSquare = _.flow([_.add, square]); + * addSquare(1, 2); + * // => 9 + */ +var flow = createFlow(); + +module.exports = flow; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flowRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flowRight.js new file mode 100644 index 000000000..114614105 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/flowRight.js @@ -0,0 +1,26 @@ +var createFlow = require('./_createFlow'); + +/** + * This method is like `_.flow` except that it creates a function that + * invokes the given functions from right to left. + * + * @static + * @since 3.0.0 + * @memberOf _ + * @category Util + * @param {...(Function|Function[])} [funcs] The functions to invoke. + * @returns {Function} Returns the new composite function. + * @see _.flow + * @example + * + * function square(n) { + * return n * n; + * } + * + * var addSquare = _.flowRight([square, _.add]); + * addSquare(1, 2); + * // => 9 + */ +var flowRight = createFlow(true); + +module.exports = flowRight; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forEach.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forEach.js new file mode 100644 index 000000000..c64eaa73f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forEach.js @@ -0,0 +1,41 @@ +var arrayEach = require('./_arrayEach'), + baseEach = require('./_baseEach'), + castFunction = require('./_castFunction'), + isArray = require('./isArray'); + +/** + * Iterates over elements of `collection` and invokes `iteratee` for each element. + * The iteratee is invoked with three arguments: (value, index|key, collection). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * **Note:** As with other "Collections" methods, objects with a "length" + * property are iterated like arrays. To avoid this behavior use `_.forIn` + * or `_.forOwn` for object iteration. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias each + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEachRight + * @example + * + * _.forEach([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `1` then `2`. + * + * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ +function forEach(collection, iteratee) { + var func = isArray(collection) ? arrayEach : baseEach; + return func(collection, castFunction(iteratee)); +} + +module.exports = forEach; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forEachRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forEachRight.js new file mode 100644 index 000000000..7390ebaf8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forEachRight.js @@ -0,0 +1,31 @@ +var arrayEachRight = require('./_arrayEachRight'), + baseEachRight = require('./_baseEachRight'), + castFunction = require('./_castFunction'), + isArray = require('./isArray'); + +/** + * This method is like `_.forEach` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @alias eachRight + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEach + * @example + * + * _.forEachRight([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `2` then `1`. + */ +function forEachRight(collection, iteratee) { + var func = isArray(collection) ? arrayEachRight : baseEachRight; + return func(collection, castFunction(iteratee)); +} + +module.exports = forEachRight; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forIn.js new file mode 100644 index 000000000..583a59638 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forIn.js @@ -0,0 +1,39 @@ +var baseFor = require('./_baseFor'), + castFunction = require('./_castFunction'), + keysIn = require('./keysIn'); + +/** + * Iterates over own and inherited enumerable string keyed properties of an + * object and invokes `iteratee` for each property. The iteratee is invoked + * with three arguments: (value, key, object). Iteratee functions may exit + * iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forInRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forIn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed). + */ +function forIn(object, iteratee) { + return object == null + ? object + : baseFor(object, castFunction(iteratee), keysIn); +} + +module.exports = forIn; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forInRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forInRight.js new file mode 100644 index 000000000..4aedf58af --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forInRight.js @@ -0,0 +1,37 @@ +var baseForRight = require('./_baseForRight'), + castFunction = require('./_castFunction'), + keysIn = require('./keysIn'); + +/** + * This method is like `_.forIn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forIn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forInRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'. + */ +function forInRight(object, iteratee) { + return object == null + ? object + : baseForRight(object, castFunction(iteratee), keysIn); +} + +module.exports = forInRight; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forOwn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forOwn.js new file mode 100644 index 000000000..94eed8402 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forOwn.js @@ -0,0 +1,36 @@ +var baseForOwn = require('./_baseForOwn'), + castFunction = require('./_castFunction'); + +/** + * Iterates over own enumerable string keyed properties of an object and + * invokes `iteratee` for each property. The iteratee is invoked with three + * arguments: (value, key, object). Iteratee functions may exit iteration + * early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwnRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ +function forOwn(object, iteratee) { + return object && baseForOwn(object, castFunction(iteratee)); +} + +module.exports = forOwn; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forOwnRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forOwnRight.js new file mode 100644 index 000000000..86f338f03 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/forOwnRight.js @@ -0,0 +1,34 @@ +var baseForOwnRight = require('./_baseForOwnRight'), + castFunction = require('./_castFunction'); + +/** + * This method is like `_.forOwn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwnRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'. + */ +function forOwnRight(object, iteratee) { + return object && baseForOwnRight(object, castFunction(iteratee)); +} + +module.exports = forOwnRight; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp.js new file mode 100644 index 000000000..e372dbbdf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp.js @@ -0,0 +1,2 @@ +var _ = require('./lodash.min').runInContext(); +module.exports = require('./fp/_baseConvert')(_, _); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/F.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/F.js new file mode 100644 index 000000000..a05a63ad9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/F.js @@ -0,0 +1 @@ +module.exports = require('./stubFalse'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/T.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/T.js new file mode 100644 index 000000000..e2ba8ea56 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/T.js @@ -0,0 +1 @@ +module.exports = require('./stubTrue'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/__.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/__.js new file mode 100644 index 000000000..4af98deb4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/__.js @@ -0,0 +1 @@ +module.exports = require('./placeholder'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_baseConvert.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_baseConvert.js new file mode 100644 index 000000000..9baf8e190 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_baseConvert.js @@ -0,0 +1,569 @@ +var mapping = require('./_mapping'), + fallbackHolder = require('./placeholder'); + +/** Built-in value reference. */ +var push = Array.prototype.push; + +/** + * Creates a function, with an arity of `n`, that invokes `func` with the + * arguments it receives. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} n The arity of the new function. + * @returns {Function} Returns the new function. + */ +function baseArity(func, n) { + return n == 2 + ? function(a, b) { return func.apply(undefined, arguments); } + : function(a) { return func.apply(undefined, arguments); }; +} + +/** + * Creates a function that invokes `func`, with up to `n` arguments, ignoring + * any additional arguments. + * + * @private + * @param {Function} func The function to cap arguments for. + * @param {number} n The arity cap. + * @returns {Function} Returns the new function. + */ +function baseAry(func, n) { + return n == 2 + ? function(a, b) { return func(a, b); } + : function(a) { return func(a); }; +} + +/** + * Creates a clone of `array`. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the cloned array. + */ +function cloneArray(array) { + var length = array ? array.length : 0, + result = Array(length); + + while (length--) { + result[length] = array[length]; + } + return result; +} + +/** + * Creates a function that clones a given object using the assignment `func`. + * + * @private + * @param {Function} func The assignment function. + * @returns {Function} Returns the new cloner function. + */ +function createCloner(func) { + return function(object) { + return func({}, object); + }; +} + +/** + * A specialized version of `_.spread` which flattens the spread array into + * the arguments of the invoked `func`. + * + * @private + * @param {Function} func The function to spread arguments over. + * @param {number} start The start position of the spread. + * @returns {Function} Returns the new function. + */ +function flatSpread(func, start) { + return function() { + var length = arguments.length, + lastIndex = length - 1, + args = Array(length); + + while (length--) { + args[length] = arguments[length]; + } + var array = args[start], + otherArgs = args.slice(0, start); + + if (array) { + push.apply(otherArgs, array); + } + if (start != lastIndex) { + push.apply(otherArgs, args.slice(start + 1)); + } + return func.apply(this, otherArgs); + }; +} + +/** + * Creates a function that wraps `func` and uses `cloner` to clone the first + * argument it receives. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} cloner The function to clone arguments. + * @returns {Function} Returns the new immutable function. + */ +function wrapImmutable(func, cloner) { + return function() { + var length = arguments.length; + if (!length) { + return; + } + var args = Array(length); + while (length--) { + args[length] = arguments[length]; + } + var result = args[0] = cloner.apply(undefined, args); + func.apply(undefined, args); + return result; + }; +} + +/** + * The base implementation of `convert` which accepts a `util` object of methods + * required to perform conversions. + * + * @param {Object} util The util object. + * @param {string} name The name of the function to convert. + * @param {Function} func The function to convert. + * @param {Object} [options] The options object. + * @param {boolean} [options.cap=true] Specify capping iteratee arguments. + * @param {boolean} [options.curry=true] Specify currying. + * @param {boolean} [options.fixed=true] Specify fixed arity. + * @param {boolean} [options.immutable=true] Specify immutable operations. + * @param {boolean} [options.rearg=true] Specify rearranging arguments. + * @returns {Function|Object} Returns the converted function or object. + */ +function baseConvert(util, name, func, options) { + var isLib = typeof name == 'function', + isObj = name === Object(name); + + if (isObj) { + options = func; + func = name; + name = undefined; + } + if (func == null) { + throw new TypeError; + } + options || (options = {}); + + var config = { + 'cap': 'cap' in options ? options.cap : true, + 'curry': 'curry' in options ? options.curry : true, + 'fixed': 'fixed' in options ? options.fixed : true, + 'immutable': 'immutable' in options ? options.immutable : true, + 'rearg': 'rearg' in options ? options.rearg : true + }; + + var defaultHolder = isLib ? func : fallbackHolder, + forceCurry = ('curry' in options) && options.curry, + forceFixed = ('fixed' in options) && options.fixed, + forceRearg = ('rearg' in options) && options.rearg, + pristine = isLib ? func.runInContext() : undefined; + + var helpers = isLib ? func : { + 'ary': util.ary, + 'assign': util.assign, + 'clone': util.clone, + 'curry': util.curry, + 'forEach': util.forEach, + 'isArray': util.isArray, + 'isError': util.isError, + 'isFunction': util.isFunction, + 'isWeakMap': util.isWeakMap, + 'iteratee': util.iteratee, + 'keys': util.keys, + 'rearg': util.rearg, + 'toInteger': util.toInteger, + 'toPath': util.toPath + }; + + var ary = helpers.ary, + assign = helpers.assign, + clone = helpers.clone, + curry = helpers.curry, + each = helpers.forEach, + isArray = helpers.isArray, + isError = helpers.isError, + isFunction = helpers.isFunction, + isWeakMap = helpers.isWeakMap, + keys = helpers.keys, + rearg = helpers.rearg, + toInteger = helpers.toInteger, + toPath = helpers.toPath; + + var aryMethodKeys = keys(mapping.aryMethod); + + var wrappers = { + 'castArray': function(castArray) { + return function() { + var value = arguments[0]; + return isArray(value) + ? castArray(cloneArray(value)) + : castArray.apply(undefined, arguments); + }; + }, + 'iteratee': function(iteratee) { + return function() { + var func = arguments[0], + arity = arguments[1], + result = iteratee(func, arity), + length = result.length; + + if (config.cap && typeof arity == 'number') { + arity = arity > 2 ? (arity - 2) : 1; + return (length && length <= arity) ? result : baseAry(result, arity); + } + return result; + }; + }, + 'mixin': function(mixin) { + return function(source) { + var func = this; + if (!isFunction(func)) { + return mixin(func, Object(source)); + } + var pairs = []; + each(keys(source), function(key) { + if (isFunction(source[key])) { + pairs.push([key, func.prototype[key]]); + } + }); + + mixin(func, Object(source)); + + each(pairs, function(pair) { + var value = pair[1]; + if (isFunction(value)) { + func.prototype[pair[0]] = value; + } else { + delete func.prototype[pair[0]]; + } + }); + return func; + }; + }, + 'nthArg': function(nthArg) { + return function(n) { + var arity = n < 0 ? 1 : (toInteger(n) + 1); + return curry(nthArg(n), arity); + }; + }, + 'rearg': function(rearg) { + return function(func, indexes) { + var arity = indexes ? indexes.length : 0; + return curry(rearg(func, indexes), arity); + }; + }, + 'runInContext': function(runInContext) { + return function(context) { + return baseConvert(util, runInContext(context), options); + }; + } + }; + + /*--------------------------------------------------------------------------*/ + + /** + * Casts `func` to a function with an arity capped iteratee if needed. + * + * @private + * @param {string} name The name of the function to inspect. + * @param {Function} func The function to inspect. + * @returns {Function} Returns the cast function. + */ + function castCap(name, func) { + if (config.cap) { + var indexes = mapping.iterateeRearg[name]; + if (indexes) { + return iterateeRearg(func, indexes); + } + var n = !isLib && mapping.iterateeAry[name]; + if (n) { + return iterateeAry(func, n); + } + } + return func; + } + + /** + * Casts `func` to a curried function if needed. + * + * @private + * @param {string} name The name of the function to inspect. + * @param {Function} func The function to inspect. + * @param {number} n The arity of `func`. + * @returns {Function} Returns the cast function. + */ + function castCurry(name, func, n) { + return (forceCurry || (config.curry && n > 1)) + ? curry(func, n) + : func; + } + + /** + * Casts `func` to a fixed arity function if needed. + * + * @private + * @param {string} name The name of the function to inspect. + * @param {Function} func The function to inspect. + * @param {number} n The arity cap. + * @returns {Function} Returns the cast function. + */ + function castFixed(name, func, n) { + if (config.fixed && (forceFixed || !mapping.skipFixed[name])) { + var data = mapping.methodSpread[name], + start = data && data.start; + + return start === undefined ? ary(func, n) : flatSpread(func, start); + } + return func; + } + + /** + * Casts `func` to an rearged function if needed. + * + * @private + * @param {string} name The name of the function to inspect. + * @param {Function} func The function to inspect. + * @param {number} n The arity of `func`. + * @returns {Function} Returns the cast function. + */ + function castRearg(name, func, n) { + return (config.rearg && n > 1 && (forceRearg || !mapping.skipRearg[name])) + ? rearg(func, mapping.methodRearg[name] || mapping.aryRearg[n]) + : func; + } + + /** + * Creates a clone of `object` by `path`. + * + * @private + * @param {Object} object The object to clone. + * @param {Array|string} path The path to clone by. + * @returns {Object} Returns the cloned object. + */ + function cloneByPath(object, path) { + path = toPath(path); + + var index = -1, + length = path.length, + lastIndex = length - 1, + result = clone(Object(object)), + nested = result; + + while (nested != null && ++index < length) { + var key = path[index], + value = nested[key]; + + if (value != null && + !(isFunction(value) || isError(value) || isWeakMap(value))) { + nested[key] = clone(index == lastIndex ? value : Object(value)); + } + nested = nested[key]; + } + return result; + } + + /** + * Converts `lodash` to an immutable auto-curried iteratee-first data-last + * version with conversion `options` applied. + * + * @param {Object} [options] The options object. See `baseConvert` for more details. + * @returns {Function} Returns the converted `lodash`. + */ + function convertLib(options) { + return _.runInContext.convert(options)(undefined); + } + + /** + * Create a converter function for `func` of `name`. + * + * @param {string} name The name of the function to convert. + * @param {Function} func The function to convert. + * @returns {Function} Returns the new converter function. + */ + function createConverter(name, func) { + var realName = mapping.aliasToReal[name] || name, + methodName = mapping.remap[realName] || realName, + oldOptions = options; + + return function(options) { + var newUtil = isLib ? pristine : helpers, + newFunc = isLib ? pristine[methodName] : func, + newOptions = assign(assign({}, oldOptions), options); + + return baseConvert(newUtil, realName, newFunc, newOptions); + }; + } + + /** + * Creates a function that wraps `func` to invoke its iteratee, with up to `n` + * arguments, ignoring any additional arguments. + * + * @private + * @param {Function} func The function to cap iteratee arguments for. + * @param {number} n The arity cap. + * @returns {Function} Returns the new function. + */ + function iterateeAry(func, n) { + return overArg(func, function(func) { + return typeof func == 'function' ? baseAry(func, n) : func; + }); + } + + /** + * Creates a function that wraps `func` to invoke its iteratee with arguments + * arranged according to the specified `indexes` where the argument value at + * the first index is provided as the first argument, the argument value at + * the second index is provided as the second argument, and so on. + * + * @private + * @param {Function} func The function to rearrange iteratee arguments for. + * @param {number[]} indexes The arranged argument indexes. + * @returns {Function} Returns the new function. + */ + function iterateeRearg(func, indexes) { + return overArg(func, function(func) { + var n = indexes.length; + return baseArity(rearg(baseAry(func, n), indexes), n); + }); + } + + /** + * Creates a function that invokes `func` with its first argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ + function overArg(func, transform) { + return function() { + var length = arguments.length; + if (!length) { + return func(); + } + var args = Array(length); + while (length--) { + args[length] = arguments[length]; + } + var index = config.rearg ? 0 : (length - 1); + args[index] = transform(args[index]); + return func.apply(undefined, args); + }; + } + + /** + * Creates a function that wraps `func` and applys the conversions + * rules by `name`. + * + * @private + * @param {string} name The name of the function to wrap. + * @param {Function} func The function to wrap. + * @returns {Function} Returns the converted function. + */ + function wrap(name, func, placeholder) { + var result, + realName = mapping.aliasToReal[name] || name, + wrapped = func, + wrapper = wrappers[realName]; + + if (wrapper) { + wrapped = wrapper(func); + } + else if (config.immutable) { + if (mapping.mutate.array[realName]) { + wrapped = wrapImmutable(func, cloneArray); + } + else if (mapping.mutate.object[realName]) { + wrapped = wrapImmutable(func, createCloner(func)); + } + else if (mapping.mutate.set[realName]) { + wrapped = wrapImmutable(func, cloneByPath); + } + } + each(aryMethodKeys, function(aryKey) { + each(mapping.aryMethod[aryKey], function(otherName) { + if (realName == otherName) { + var data = mapping.methodSpread[realName], + afterRearg = data && data.afterRearg; + + result = afterRearg + ? castFixed(realName, castRearg(realName, wrapped, aryKey), aryKey) + : castRearg(realName, castFixed(realName, wrapped, aryKey), aryKey); + + result = castCap(realName, result); + result = castCurry(realName, result, aryKey); + return false; + } + }); + return !result; + }); + + result || (result = wrapped); + if (result == func) { + result = forceCurry ? curry(result, 1) : function() { + return func.apply(this, arguments); + }; + } + result.convert = createConverter(realName, func); + result.placeholder = func.placeholder = placeholder; + + return result; + } + + /*--------------------------------------------------------------------------*/ + + if (!isObj) { + return wrap(name, func, defaultHolder); + } + var _ = func; + + // Convert methods by ary cap. + var pairs = []; + each(aryMethodKeys, function(aryKey) { + each(mapping.aryMethod[aryKey], function(key) { + var func = _[mapping.remap[key] || key]; + if (func) { + pairs.push([key, wrap(key, func, _)]); + } + }); + }); + + // Convert remaining methods. + each(keys(_), function(key) { + var func = _[key]; + if (typeof func == 'function') { + var length = pairs.length; + while (length--) { + if (pairs[length][0] == key) { + return; + } + } + func.convert = createConverter(key, func); + pairs.push([key, func]); + } + }); + + // Assign to `_` leaving `_.prototype` unchanged to allow chaining. + each(pairs, function(pair) { + _[pair[0]] = pair[1]; + }); + + _.convert = convertLib; + _.placeholder = _; + + // Assign aliases. + each(keys(_), function(key) { + each(mapping.realToAlias[key] || [], function(alias) { + _[alias] = _[key]; + }); + }); + + return _; +} + +module.exports = baseConvert; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_convertBrowser.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_convertBrowser.js new file mode 100644 index 000000000..bde030dc0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_convertBrowser.js @@ -0,0 +1,18 @@ +var baseConvert = require('./_baseConvert'); + +/** + * Converts `lodash` to an immutable auto-curried iteratee-first data-last + * version with conversion `options` applied. + * + * @param {Function} lodash The lodash function to convert. + * @param {Object} [options] The options object. See `baseConvert` for more details. + * @returns {Function} Returns the converted `lodash`. + */ +function browserConvert(lodash, options) { + return baseConvert(lodash, lodash, options); +} + +if (typeof _ == 'function' && typeof _.runInContext == 'function') { + _ = browserConvert(_.runInContext()); +} +module.exports = browserConvert; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_falseOptions.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_falseOptions.js new file mode 100644 index 000000000..773235e34 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_falseOptions.js @@ -0,0 +1,7 @@ +module.exports = { + 'cap': false, + 'curry': false, + 'fixed': false, + 'immutable': false, + 'rearg': false +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_mapping.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_mapping.js new file mode 100644 index 000000000..a642ec058 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_mapping.js @@ -0,0 +1,358 @@ +/** Used to map aliases to their real names. */ +exports.aliasToReal = { + + // Lodash aliases. + 'each': 'forEach', + 'eachRight': 'forEachRight', + 'entries': 'toPairs', + 'entriesIn': 'toPairsIn', + 'extend': 'assignIn', + 'extendAll': 'assignInAll', + 'extendAllWith': 'assignInAllWith', + 'extendWith': 'assignInWith', + 'first': 'head', + + // Methods that are curried variants of others. + 'conforms': 'conformsTo', + 'matches': 'isMatch', + 'property': 'get', + + // Ramda aliases. + '__': 'placeholder', + 'F': 'stubFalse', + 'T': 'stubTrue', + 'all': 'every', + 'allPass': 'overEvery', + 'always': 'constant', + 'any': 'some', + 'anyPass': 'overSome', + 'apply': 'spread', + 'assoc': 'set', + 'assocPath': 'set', + 'complement': 'negate', + 'compose': 'flowRight', + 'contains': 'includes', + 'dissoc': 'unset', + 'dissocPath': 'unset', + 'dropLast': 'dropRight', + 'dropLastWhile': 'dropRightWhile', + 'equals': 'isEqual', + 'identical': 'eq', + 'indexBy': 'keyBy', + 'init': 'initial', + 'invertObj': 'invert', + 'juxt': 'over', + 'omitAll': 'omit', + 'nAry': 'ary', + 'path': 'get', + 'pathEq': 'matchesProperty', + 'pathOr': 'getOr', + 'paths': 'at', + 'pickAll': 'pick', + 'pipe': 'flow', + 'pluck': 'map', + 'prop': 'get', + 'propEq': 'matchesProperty', + 'propOr': 'getOr', + 'props': 'at', + 'symmetricDifference': 'xor', + 'symmetricDifferenceBy': 'xorBy', + 'symmetricDifferenceWith': 'xorWith', + 'takeLast': 'takeRight', + 'takeLastWhile': 'takeRightWhile', + 'unapply': 'rest', + 'unnest': 'flatten', + 'useWith': 'overArgs', + 'where': 'conformsTo', + 'whereEq': 'isMatch', + 'zipObj': 'zipObject' +}; + +/** Used to map ary to method names. */ +exports.aryMethod = { + '1': [ + 'assignAll', 'assignInAll', 'attempt', 'castArray', 'ceil', 'create', + 'curry', 'curryRight', 'defaultsAll', 'defaultsDeepAll', 'floor', 'flow', + 'flowRight', 'fromPairs', 'invert', 'iteratee', 'memoize', 'method', 'mergeAll', + 'methodOf', 'mixin', 'nthArg', 'over', 'overEvery', 'overSome','rest', 'reverse', + 'round', 'runInContext', 'spread', 'template', 'trim', 'trimEnd', 'trimStart', + 'uniqueId', 'words', 'zipAll' + ], + '2': [ + 'add', 'after', 'ary', 'assign', 'assignAllWith', 'assignIn', 'assignInAllWith', + 'at', 'before', 'bind', 'bindAll', 'bindKey', 'chunk', 'cloneDeepWith', + 'cloneWith', 'concat', 'conformsTo', 'countBy', 'curryN', 'curryRightN', + 'debounce', 'defaults', 'defaultsDeep', 'defaultTo', 'delay', 'difference', + 'divide', 'drop', 'dropRight', 'dropRightWhile', 'dropWhile', 'endsWith', 'eq', + 'every', 'filter', 'find', 'findIndex', 'findKey', 'findLast', 'findLastIndex', + 'findLastKey', 'flatMap', 'flatMapDeep', 'flattenDepth', 'forEach', + 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight', 'get', + 'groupBy', 'gt', 'gte', 'has', 'hasIn', 'includes', 'indexOf', 'intersection', + 'invertBy', 'invoke', 'invokeMap', 'isEqual', 'isMatch', 'join', 'keyBy', + 'lastIndexOf', 'lt', 'lte', 'map', 'mapKeys', 'mapValues', 'matchesProperty', + 'maxBy', 'meanBy', 'merge', 'mergeAllWith', 'minBy', 'multiply', 'nth', 'omit', + 'omitBy', 'overArgs', 'pad', 'padEnd', 'padStart', 'parseInt', 'partial', + 'partialRight', 'partition', 'pick', 'pickBy', 'propertyOf', 'pull', 'pullAll', + 'pullAt', 'random', 'range', 'rangeRight', 'rearg', 'reject', 'remove', + 'repeat', 'restFrom', 'result', 'sampleSize', 'some', 'sortBy', 'sortedIndex', + 'sortedIndexOf', 'sortedLastIndex', 'sortedLastIndexOf', 'sortedUniqBy', + 'split', 'spreadFrom', 'startsWith', 'subtract', 'sumBy', 'take', 'takeRight', + 'takeRightWhile', 'takeWhile', 'tap', 'throttle', 'thru', 'times', 'trimChars', + 'trimCharsEnd', 'trimCharsStart', 'truncate', 'union', 'uniqBy', 'uniqWith', + 'unset', 'unzipWith', 'without', 'wrap', 'xor', 'zip', 'zipObject', + 'zipObjectDeep' + ], + '3': [ + 'assignInWith', 'assignWith', 'clamp', 'differenceBy', 'differenceWith', + 'findFrom', 'findIndexFrom', 'findLastFrom', 'findLastIndexFrom', 'getOr', + 'includesFrom', 'indexOfFrom', 'inRange', 'intersectionBy', 'intersectionWith', + 'invokeArgs', 'invokeArgsMap', 'isEqualWith', 'isMatchWith', 'flatMapDepth', + 'lastIndexOfFrom', 'mergeWith', 'orderBy', 'padChars', 'padCharsEnd', + 'padCharsStart', 'pullAllBy', 'pullAllWith', 'rangeStep', 'rangeStepRight', + 'reduce', 'reduceRight', 'replace', 'set', 'slice', 'sortedIndexBy', + 'sortedLastIndexBy', 'transform', 'unionBy', 'unionWith', 'update', 'xorBy', + 'xorWith', 'zipWith' + ], + '4': [ + 'fill', 'setWith', 'updateWith' + ] +}; + +/** Used to map ary to rearg configs. */ +exports.aryRearg = { + '2': [1, 0], + '3': [2, 0, 1], + '4': [3, 2, 0, 1] +}; + +/** Used to map method names to their iteratee ary. */ +exports.iterateeAry = { + 'dropRightWhile': 1, + 'dropWhile': 1, + 'every': 1, + 'filter': 1, + 'find': 1, + 'findFrom': 1, + 'findIndex': 1, + 'findIndexFrom': 1, + 'findKey': 1, + 'findLast': 1, + 'findLastFrom': 1, + 'findLastIndex': 1, + 'findLastIndexFrom': 1, + 'findLastKey': 1, + 'flatMap': 1, + 'flatMapDeep': 1, + 'flatMapDepth': 1, + 'forEach': 1, + 'forEachRight': 1, + 'forIn': 1, + 'forInRight': 1, + 'forOwn': 1, + 'forOwnRight': 1, + 'map': 1, + 'mapKeys': 1, + 'mapValues': 1, + 'partition': 1, + 'reduce': 2, + 'reduceRight': 2, + 'reject': 1, + 'remove': 1, + 'some': 1, + 'takeRightWhile': 1, + 'takeWhile': 1, + 'times': 1, + 'transform': 2 +}; + +/** Used to map method names to iteratee rearg configs. */ +exports.iterateeRearg = { + 'mapKeys': [1], + 'reduceRight': [1, 0] +}; + +/** Used to map method names to rearg configs. */ +exports.methodRearg = { + 'assignInAllWith': [1, 0], + 'assignInWith': [1, 2, 0], + 'assignAllWith': [1, 0], + 'assignWith': [1, 2, 0], + 'differenceBy': [1, 2, 0], + 'differenceWith': [1, 2, 0], + 'getOr': [2, 1, 0], + 'intersectionBy': [1, 2, 0], + 'intersectionWith': [1, 2, 0], + 'isEqualWith': [1, 2, 0], + 'isMatchWith': [2, 1, 0], + 'mergeAllWith': [1, 0], + 'mergeWith': [1, 2, 0], + 'padChars': [2, 1, 0], + 'padCharsEnd': [2, 1, 0], + 'padCharsStart': [2, 1, 0], + 'pullAllBy': [2, 1, 0], + 'pullAllWith': [2, 1, 0], + 'rangeStep': [1, 2, 0], + 'rangeStepRight': [1, 2, 0], + 'setWith': [3, 1, 2, 0], + 'sortedIndexBy': [2, 1, 0], + 'sortedLastIndexBy': [2, 1, 0], + 'unionBy': [1, 2, 0], + 'unionWith': [1, 2, 0], + 'updateWith': [3, 1, 2, 0], + 'xorBy': [1, 2, 0], + 'xorWith': [1, 2, 0], + 'zipWith': [1, 2, 0] +}; + +/** Used to map method names to spread configs. */ +exports.methodSpread = { + 'assignAll': { 'start': 0 }, + 'assignAllWith': { 'start': 0 }, + 'assignInAll': { 'start': 0 }, + 'assignInAllWith': { 'start': 0 }, + 'defaultsAll': { 'start': 0 }, + 'defaultsDeepAll': { 'start': 0 }, + 'invokeArgs': { 'start': 2 }, + 'invokeArgsMap': { 'start': 2 }, + 'mergeAll': { 'start': 0 }, + 'mergeAllWith': { 'start': 0 }, + 'partial': { 'start': 1 }, + 'partialRight': { 'start': 1 }, + 'without': { 'start': 1 }, + 'zipAll': { 'start': 0 } +}; + +/** Used to identify methods which mutate arrays or objects. */ +exports.mutate = { + 'array': { + 'fill': true, + 'pull': true, + 'pullAll': true, + 'pullAllBy': true, + 'pullAllWith': true, + 'pullAt': true, + 'remove': true, + 'reverse': true + }, + 'object': { + 'assign': true, + 'assignAll': true, + 'assignAllWith': true, + 'assignIn': true, + 'assignInAll': true, + 'assignInAllWith': true, + 'assignInWith': true, + 'assignWith': true, + 'defaults': true, + 'defaultsAll': true, + 'defaultsDeep': true, + 'defaultsDeepAll': true, + 'merge': true, + 'mergeAll': true, + 'mergeAllWith': true, + 'mergeWith': true, + }, + 'set': { + 'set': true, + 'setWith': true, + 'unset': true, + 'update': true, + 'updateWith': true + } +}; + +/** Used to map real names to their aliases. */ +exports.realToAlias = (function() { + var hasOwnProperty = Object.prototype.hasOwnProperty, + object = exports.aliasToReal, + result = {}; + + for (var key in object) { + var value = object[key]; + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [key]; + } + } + return result; +}()); + +/** Used to map method names to other names. */ +exports.remap = { + 'assignAll': 'assign', + 'assignAllWith': 'assignWith', + 'assignInAll': 'assignIn', + 'assignInAllWith': 'assignInWith', + 'curryN': 'curry', + 'curryRightN': 'curryRight', + 'defaultsAll': 'defaults', + 'defaultsDeepAll': 'defaultsDeep', + 'findFrom': 'find', + 'findIndexFrom': 'findIndex', + 'findLastFrom': 'findLast', + 'findLastIndexFrom': 'findLastIndex', + 'getOr': 'get', + 'includesFrom': 'includes', + 'indexOfFrom': 'indexOf', + 'invokeArgs': 'invoke', + 'invokeArgsMap': 'invokeMap', + 'lastIndexOfFrom': 'lastIndexOf', + 'mergeAll': 'merge', + 'mergeAllWith': 'mergeWith', + 'padChars': 'pad', + 'padCharsEnd': 'padEnd', + 'padCharsStart': 'padStart', + 'propertyOf': 'get', + 'rangeStep': 'range', + 'rangeStepRight': 'rangeRight', + 'restFrom': 'rest', + 'spreadFrom': 'spread', + 'trimChars': 'trim', + 'trimCharsEnd': 'trimEnd', + 'trimCharsStart': 'trimStart', + 'zipAll': 'zip' +}; + +/** Used to track methods that skip fixing their arity. */ +exports.skipFixed = { + 'castArray': true, + 'flow': true, + 'flowRight': true, + 'iteratee': true, + 'mixin': true, + 'rearg': true, + 'runInContext': true +}; + +/** Used to track methods that skip rearranging arguments. */ +exports.skipRearg = { + 'add': true, + 'assign': true, + 'assignIn': true, + 'bind': true, + 'bindKey': true, + 'concat': true, + 'difference': true, + 'divide': true, + 'eq': true, + 'gt': true, + 'gte': true, + 'isEqual': true, + 'lt': true, + 'lte': true, + 'matchesProperty': true, + 'merge': true, + 'multiply': true, + 'overArgs': true, + 'partial': true, + 'partialRight': true, + 'propertyOf': true, + 'random': true, + 'range': true, + 'rangeRight': true, + 'subtract': true, + 'zip': true, + 'zipObject': true, + 'zipObjectDeep': true +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_util.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_util.js new file mode 100644 index 000000000..1dbf36f5d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/_util.js @@ -0,0 +1,16 @@ +module.exports = { + 'ary': require('../ary'), + 'assign': require('../_baseAssign'), + 'clone': require('../clone'), + 'curry': require('../curry'), + 'forEach': require('../_arrayEach'), + 'isArray': require('../isArray'), + 'isError': require('../isError'), + 'isFunction': require('../isFunction'), + 'isWeakMap': require('../isWeakMap'), + 'iteratee': require('../iteratee'), + 'keys': require('../_baseKeys'), + 'rearg': require('../rearg'), + 'toInteger': require('../toInteger'), + 'toPath': require('../toPath') +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/add.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/add.js new file mode 100644 index 000000000..816eeece3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/add.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('add', require('../add')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/after.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/after.js new file mode 100644 index 000000000..21a0167ab --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/after.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('after', require('../after')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/all.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/all.js new file mode 100644 index 000000000..d0839f77e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/all.js @@ -0,0 +1 @@ +module.exports = require('./every'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/allPass.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/allPass.js new file mode 100644 index 000000000..79b73ef84 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/allPass.js @@ -0,0 +1 @@ +module.exports = require('./overEvery'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/always.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/always.js new file mode 100644 index 000000000..988770307 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/always.js @@ -0,0 +1 @@ +module.exports = require('./constant'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/any.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/any.js new file mode 100644 index 000000000..900ac25e8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/any.js @@ -0,0 +1 @@ +module.exports = require('./some'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/anyPass.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/anyPass.js new file mode 100644 index 000000000..2774ab37a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/anyPass.js @@ -0,0 +1 @@ +module.exports = require('./overSome'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/apply.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/apply.js new file mode 100644 index 000000000..2b7571296 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/apply.js @@ -0,0 +1 @@ +module.exports = require('./spread'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/array.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/array.js new file mode 100644 index 000000000..fe939c2c2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/array.js @@ -0,0 +1,2 @@ +var convert = require('./convert'); +module.exports = convert(require('../array')); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/ary.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/ary.js new file mode 100644 index 000000000..8edf18778 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/ary.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('ary', require('../ary')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assign.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assign.js new file mode 100644 index 000000000..23f47af17 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assign.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('assign', require('../assign')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignAll.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignAll.js new file mode 100644 index 000000000..b1d36c7ef --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignAll.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('assignAll', require('../assign')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignAllWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignAllWith.js new file mode 100644 index 000000000..21e836e6f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignAllWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('assignAllWith', require('../assignWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignIn.js new file mode 100644 index 000000000..6e7c65fad --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignIn.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('assignIn', require('../assignIn')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignInAll.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignInAll.js new file mode 100644 index 000000000..7ba75dba1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignInAll.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('assignInAll', require('../assignIn')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignInAllWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignInAllWith.js new file mode 100644 index 000000000..e766903d4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignInAllWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('assignInAllWith', require('../assignInWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignInWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignInWith.js new file mode 100644 index 000000000..acb592367 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignInWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('assignInWith', require('../assignInWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignWith.js new file mode 100644 index 000000000..eb925212d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assignWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('assignWith', require('../assignWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assoc.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assoc.js new file mode 100644 index 000000000..7648820c9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assoc.js @@ -0,0 +1 @@ +module.exports = require('./set'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assocPath.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assocPath.js new file mode 100644 index 000000000..7648820c9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/assocPath.js @@ -0,0 +1 @@ +module.exports = require('./set'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/at.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/at.js new file mode 100644 index 000000000..cc39d257c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/at.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('at', require('../at')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/attempt.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/attempt.js new file mode 100644 index 000000000..26ca42ea0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/attempt.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('attempt', require('../attempt')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/before.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/before.js new file mode 100644 index 000000000..7a2de65d2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/before.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('before', require('../before')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/bind.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/bind.js new file mode 100644 index 000000000..5cbe4f302 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/bind.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('bind', require('../bind')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/bindAll.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/bindAll.js new file mode 100644 index 000000000..6b4a4a0f2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/bindAll.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('bindAll', require('../bindAll')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/bindKey.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/bindKey.js new file mode 100644 index 000000000..6a46c6b19 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/bindKey.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('bindKey', require('../bindKey')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/camelCase.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/camelCase.js new file mode 100644 index 000000000..87b77b493 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/camelCase.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('camelCase', require('../camelCase'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/capitalize.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/capitalize.js new file mode 100644 index 000000000..cac74e14f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/capitalize.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('capitalize', require('../capitalize'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/castArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/castArray.js new file mode 100644 index 000000000..8681c099e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/castArray.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('castArray', require('../castArray')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/ceil.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/ceil.js new file mode 100644 index 000000000..f416b7294 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/ceil.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('ceil', require('../ceil')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/chain.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/chain.js new file mode 100644 index 000000000..604fe398b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/chain.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('chain', require('../chain'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/chunk.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/chunk.js new file mode 100644 index 000000000..871ab0858 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/chunk.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('chunk', require('../chunk')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/clamp.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/clamp.js new file mode 100644 index 000000000..3b06c01ce --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/clamp.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('clamp', require('../clamp')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/clone.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/clone.js new file mode 100644 index 000000000..cadb59c91 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/clone.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('clone', require('../clone'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cloneDeep.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cloneDeep.js new file mode 100644 index 000000000..a6107aac9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cloneDeep.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('cloneDeep', require('../cloneDeep'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cloneDeepWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cloneDeepWith.js new file mode 100644 index 000000000..6f01e44a3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cloneDeepWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('cloneDeepWith', require('../cloneDeepWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cloneWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cloneWith.js new file mode 100644 index 000000000..aa8857810 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cloneWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('cloneWith', require('../cloneWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/collection.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/collection.js new file mode 100644 index 000000000..fc8b328a0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/collection.js @@ -0,0 +1,2 @@ +var convert = require('./convert'); +module.exports = convert(require('../collection')); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/commit.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/commit.js new file mode 100644 index 000000000..130a894f8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/commit.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('commit', require('../commit'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/compact.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/compact.js new file mode 100644 index 000000000..ce8f7a1ac --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/compact.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('compact', require('../compact'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/complement.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/complement.js new file mode 100644 index 000000000..93eb462b3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/complement.js @@ -0,0 +1 @@ +module.exports = require('./negate'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/compose.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/compose.js new file mode 100644 index 000000000..1954e9423 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/compose.js @@ -0,0 +1 @@ +module.exports = require('./flowRight'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/concat.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/concat.js new file mode 100644 index 000000000..e59346ad9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/concat.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('concat', require('../concat')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cond.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cond.js new file mode 100644 index 000000000..6a0120efd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/cond.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('cond', require('../cond'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/conforms.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/conforms.js new file mode 100644 index 000000000..3247f64a8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/conforms.js @@ -0,0 +1 @@ +module.exports = require('./conformsTo'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/conformsTo.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/conformsTo.js new file mode 100644 index 000000000..aa7f41ec0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/conformsTo.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('conformsTo', require('../conformsTo')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/constant.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/constant.js new file mode 100644 index 000000000..9e406fc09 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/constant.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('constant', require('../constant'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/contains.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/contains.js new file mode 100644 index 000000000..594722af5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/contains.js @@ -0,0 +1 @@ +module.exports = require('./includes'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/convert.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/convert.js new file mode 100644 index 000000000..4795dc424 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/convert.js @@ -0,0 +1,18 @@ +var baseConvert = require('./_baseConvert'), + util = require('./_util'); + +/** + * Converts `func` of `name` to an immutable auto-curried iteratee-first data-last + * version with conversion `options` applied. If `name` is an object its methods + * will be converted. + * + * @param {string} name The name of the function to wrap. + * @param {Function} [func] The function to wrap. + * @param {Object} [options] The options object. See `baseConvert` for more details. + * @returns {Function|Object} Returns the converted function or object. + */ +function convert(name, func, options) { + return baseConvert(util, name, func, options); +} + +module.exports = convert; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/countBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/countBy.js new file mode 100644 index 000000000..dfa464326 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/countBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('countBy', require('../countBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/create.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/create.js new file mode 100644 index 000000000..752025fb8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/create.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('create', require('../create')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curry.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curry.js new file mode 100644 index 000000000..b0b4168c5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curry.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('curry', require('../curry')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curryN.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curryN.js new file mode 100644 index 000000000..2ae7d00a6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curryN.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('curryN', require('../curry')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curryRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curryRight.js new file mode 100644 index 000000000..cb619eb5d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curryRight.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('curryRight', require('../curryRight')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curryRightN.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curryRightN.js new file mode 100644 index 000000000..2495afc89 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/curryRightN.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('curryRightN', require('../curryRight')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/date.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/date.js new file mode 100644 index 000000000..82cb952bc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/date.js @@ -0,0 +1,2 @@ +var convert = require('./convert'); +module.exports = convert(require('../date')); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/debounce.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/debounce.js new file mode 100644 index 000000000..26122293a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/debounce.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('debounce', require('../debounce')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/deburr.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/deburr.js new file mode 100644 index 000000000..96463ab88 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/deburr.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('deburr', require('../deburr'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultTo.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultTo.js new file mode 100644 index 000000000..d6b52a444 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultTo.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('defaultTo', require('../defaultTo')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaults.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaults.js new file mode 100644 index 000000000..e1a8e6e7d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaults.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('defaults', require('../defaults')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultsAll.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultsAll.js new file mode 100644 index 000000000..238fcc3c2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultsAll.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('defaultsAll', require('../defaults')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultsDeep.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultsDeep.js new file mode 100644 index 000000000..1f172ff94 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultsDeep.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('defaultsDeep', require('../defaultsDeep')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultsDeepAll.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultsDeepAll.js new file mode 100644 index 000000000..6835f2f07 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defaultsDeepAll.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('defaultsDeepAll', require('../defaultsDeep')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defer.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defer.js new file mode 100644 index 000000000..ec7990fe2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/defer.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('defer', require('../defer'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/delay.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/delay.js new file mode 100644 index 000000000..556dbd568 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/delay.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('delay', require('../delay')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/difference.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/difference.js new file mode 100644 index 000000000..2d0376542 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/difference.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('difference', require('../difference')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/differenceBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/differenceBy.js new file mode 100644 index 000000000..2f914910a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/differenceBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('differenceBy', require('../differenceBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/differenceWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/differenceWith.js new file mode 100644 index 000000000..bcf5ad2e1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/differenceWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('differenceWith', require('../differenceWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dissoc.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dissoc.js new file mode 100644 index 000000000..7ec7be190 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dissoc.js @@ -0,0 +1 @@ +module.exports = require('./unset'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dissocPath.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dissocPath.js new file mode 100644 index 000000000..7ec7be190 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dissocPath.js @@ -0,0 +1 @@ +module.exports = require('./unset'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/divide.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/divide.js new file mode 100644 index 000000000..82048c5e0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/divide.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('divide', require('../divide')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/drop.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/drop.js new file mode 100644 index 000000000..2fa9b4faa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/drop.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('drop', require('../drop')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropLast.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropLast.js new file mode 100644 index 000000000..174e52551 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropLast.js @@ -0,0 +1 @@ +module.exports = require('./dropRight'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropLastWhile.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropLastWhile.js new file mode 100644 index 000000000..be2a9d24a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropLastWhile.js @@ -0,0 +1 @@ +module.exports = require('./dropRightWhile'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropRight.js new file mode 100644 index 000000000..e98881fcd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropRight.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('dropRight', require('../dropRight')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropRightWhile.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropRightWhile.js new file mode 100644 index 000000000..cacaa7019 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropRightWhile.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('dropRightWhile', require('../dropRightWhile')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropWhile.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropWhile.js new file mode 100644 index 000000000..285f864d1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/dropWhile.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('dropWhile', require('../dropWhile')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/each.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/each.js new file mode 100644 index 000000000..8800f4204 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/each.js @@ -0,0 +1 @@ +module.exports = require('./forEach'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/eachRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/eachRight.js new file mode 100644 index 000000000..3252b2aba --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/eachRight.js @@ -0,0 +1 @@ +module.exports = require('./forEachRight'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/endsWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/endsWith.js new file mode 100644 index 000000000..17dc2a495 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/endsWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('endsWith', require('../endsWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/entries.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/entries.js new file mode 100644 index 000000000..7a88df204 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/entries.js @@ -0,0 +1 @@ +module.exports = require('./toPairs'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/entriesIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/entriesIn.js new file mode 100644 index 000000000..f6c6331c1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/entriesIn.js @@ -0,0 +1 @@ +module.exports = require('./toPairsIn'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/eq.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/eq.js new file mode 100644 index 000000000..9a3d21bf1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/eq.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('eq', require('../eq')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/equals.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/equals.js new file mode 100644 index 000000000..e6a5ce0ca --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/equals.js @@ -0,0 +1 @@ +module.exports = require('./isEqual'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/escape.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/escape.js new file mode 100644 index 000000000..52c1fbba6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/escape.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('escape', require('../escape'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/escapeRegExp.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/escapeRegExp.js new file mode 100644 index 000000000..369b2eff6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/escapeRegExp.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('escapeRegExp', require('../escapeRegExp'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/every.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/every.js new file mode 100644 index 000000000..95c2776c3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/every.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('every', require('../every')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extend.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extend.js new file mode 100644 index 000000000..e00166c20 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extend.js @@ -0,0 +1 @@ +module.exports = require('./assignIn'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extendAll.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extendAll.js new file mode 100644 index 000000000..cc55b64fc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extendAll.js @@ -0,0 +1 @@ +module.exports = require('./assignInAll'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extendAllWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extendAllWith.js new file mode 100644 index 000000000..6679d208b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extendAllWith.js @@ -0,0 +1 @@ +module.exports = require('./assignInAllWith'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extendWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extendWith.js new file mode 100644 index 000000000..dbdcb3b4e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/extendWith.js @@ -0,0 +1 @@ +module.exports = require('./assignInWith'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/fill.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/fill.js new file mode 100644 index 000000000..b2d47e84e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/fill.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('fill', require('../fill')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/filter.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/filter.js new file mode 100644 index 000000000..796d501ce --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/filter.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('filter', require('../filter')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/find.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/find.js new file mode 100644 index 000000000..f805d336a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/find.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('find', require('../find')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findFrom.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findFrom.js new file mode 100644 index 000000000..da8275e84 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findFrom.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('findFrom', require('../find')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findIndex.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findIndex.js new file mode 100644 index 000000000..8c15fd116 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findIndex.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('findIndex', require('../findIndex')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findIndexFrom.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findIndexFrom.js new file mode 100644 index 000000000..32e98cb95 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findIndexFrom.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('findIndexFrom', require('../findIndex')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findKey.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findKey.js new file mode 100644 index 000000000..475bcfa8a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findKey.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('findKey', require('../findKey')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLast.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLast.js new file mode 100644 index 000000000..093fe94e7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLast.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('findLast', require('../findLast')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastFrom.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastFrom.js new file mode 100644 index 000000000..76c38fbad --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastFrom.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('findLastFrom', require('../findLast')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastIndex.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastIndex.js new file mode 100644 index 000000000..36986df0b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastIndex.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('findLastIndex', require('../findLastIndex')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastIndexFrom.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastIndexFrom.js new file mode 100644 index 000000000..34c8176cf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastIndexFrom.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('findLastIndexFrom', require('../findLastIndex')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastKey.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastKey.js new file mode 100644 index 000000000..5f81b604e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/findLastKey.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('findLastKey', require('../findLastKey')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/first.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/first.js new file mode 100644 index 000000000..53f4ad13e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/first.js @@ -0,0 +1 @@ +module.exports = require('./head'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatMap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatMap.js new file mode 100644 index 000000000..d01dc4d04 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatMap.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('flatMap', require('../flatMap')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatMapDeep.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatMapDeep.js new file mode 100644 index 000000000..569c42eb9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatMapDeep.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('flatMapDeep', require('../flatMapDeep')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatMapDepth.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatMapDepth.js new file mode 100644 index 000000000..6eb68fdee --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatMapDepth.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('flatMapDepth', require('../flatMapDepth')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatten.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatten.js new file mode 100644 index 000000000..30425d896 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flatten.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('flatten', require('../flatten'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flattenDeep.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flattenDeep.js new file mode 100644 index 000000000..aed5db27c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flattenDeep.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('flattenDeep', require('../flattenDeep'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flattenDepth.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flattenDepth.js new file mode 100644 index 000000000..ad65e378e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flattenDepth.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('flattenDepth', require('../flattenDepth')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flip.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flip.js new file mode 100644 index 000000000..0547e7b4e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flip.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('flip', require('../flip'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/floor.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/floor.js new file mode 100644 index 000000000..a6cf3358e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/floor.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('floor', require('../floor')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flow.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flow.js new file mode 100644 index 000000000..cd83677a6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flow.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('flow', require('../flow')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flowRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flowRight.js new file mode 100644 index 000000000..972a5b9b1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/flowRight.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('flowRight', require('../flowRight')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forEach.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forEach.js new file mode 100644 index 000000000..2f494521c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forEach.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('forEach', require('../forEach')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forEachRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forEachRight.js new file mode 100644 index 000000000..3ff97336b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forEachRight.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('forEachRight', require('../forEachRight')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forIn.js new file mode 100644 index 000000000..9341749b1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forIn.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('forIn', require('../forIn')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forInRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forInRight.js new file mode 100644 index 000000000..cecf8bbfa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forInRight.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('forInRight', require('../forInRight')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forOwn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forOwn.js new file mode 100644 index 000000000..246449e9a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forOwn.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('forOwn', require('../forOwn')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forOwnRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forOwnRight.js new file mode 100644 index 000000000..c5e826e0d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/forOwnRight.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('forOwnRight', require('../forOwnRight')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/fromPairs.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/fromPairs.js new file mode 100644 index 000000000..f8cc5968c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/fromPairs.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('fromPairs', require('../fromPairs')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/function.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/function.js new file mode 100644 index 000000000..dfe69b1fa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/function.js @@ -0,0 +1,2 @@ +var convert = require('./convert'); +module.exports = convert(require('../function')); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/functions.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/functions.js new file mode 100644 index 000000000..09d1bb1ba --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/functions.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('functions', require('../functions'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/functionsIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/functionsIn.js new file mode 100644 index 000000000..2cfeb83eb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/functionsIn.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('functionsIn', require('../functionsIn'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/get.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/get.js new file mode 100644 index 000000000..6d3a32863 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/get.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('get', require('../get')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/getOr.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/getOr.js new file mode 100644 index 000000000..7dbf771f0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/getOr.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('getOr', require('../get')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/groupBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/groupBy.js new file mode 100644 index 000000000..fc0bc78a5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/groupBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('groupBy', require('../groupBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/gt.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/gt.js new file mode 100644 index 000000000..9e57c8085 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/gt.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('gt', require('../gt')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/gte.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/gte.js new file mode 100644 index 000000000..458478638 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/gte.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('gte', require('../gte')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/has.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/has.js new file mode 100644 index 000000000..b90129839 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/has.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('has', require('../has')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/hasIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/hasIn.js new file mode 100644 index 000000000..b3c3d1a3f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/hasIn.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('hasIn', require('../hasIn')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/head.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/head.js new file mode 100644 index 000000000..2694f0a21 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/head.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('head', require('../head'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/identical.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/identical.js new file mode 100644 index 000000000..85563f4a4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/identical.js @@ -0,0 +1 @@ +module.exports = require('./eq'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/identity.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/identity.js new file mode 100644 index 000000000..096415a5d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/identity.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('identity', require('../identity'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/inRange.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/inRange.js new file mode 100644 index 000000000..202d940ba --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/inRange.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('inRange', require('../inRange')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/includes.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/includes.js new file mode 100644 index 000000000..11467805c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/includes.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('includes', require('../includes')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/includesFrom.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/includesFrom.js new file mode 100644 index 000000000..683afdb46 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/includesFrom.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('includesFrom', require('../includes')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/indexBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/indexBy.js new file mode 100644 index 000000000..7e64bc0fc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/indexBy.js @@ -0,0 +1 @@ +module.exports = require('./keyBy'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/indexOf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/indexOf.js new file mode 100644 index 000000000..524658eb9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/indexOf.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('indexOf', require('../indexOf')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/indexOfFrom.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/indexOfFrom.js new file mode 100644 index 000000000..d99c822f4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/indexOfFrom.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('indexOfFrom', require('../indexOf')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/init.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/init.js new file mode 100644 index 000000000..2f88d8b0e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/init.js @@ -0,0 +1 @@ +module.exports = require('./initial'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/initial.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/initial.js new file mode 100644 index 000000000..b732ba0bd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/initial.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('initial', require('../initial'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/intersection.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/intersection.js new file mode 100644 index 000000000..52936d560 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/intersection.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('intersection', require('../intersection')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/intersectionBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/intersectionBy.js new file mode 100644 index 000000000..72629f277 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/intersectionBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('intersectionBy', require('../intersectionBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/intersectionWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/intersectionWith.js new file mode 100644 index 000000000..e064f400f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/intersectionWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('intersectionWith', require('../intersectionWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invert.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invert.js new file mode 100644 index 000000000..2d5d1f0d4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invert.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('invert', require('../invert')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invertBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invertBy.js new file mode 100644 index 000000000..63ca97ecb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invertBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('invertBy', require('../invertBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invertObj.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invertObj.js new file mode 100644 index 000000000..f1d842e49 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invertObj.js @@ -0,0 +1 @@ +module.exports = require('./invert'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invoke.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invoke.js new file mode 100644 index 000000000..fcf17f0d5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invoke.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('invoke', require('../invoke')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invokeArgs.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invokeArgs.js new file mode 100644 index 000000000..d3f2953fa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invokeArgs.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('invokeArgs', require('../invoke')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invokeArgsMap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invokeArgsMap.js new file mode 100644 index 000000000..eaa9f84ff --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invokeArgsMap.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('invokeArgsMap', require('../invokeMap')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invokeMap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invokeMap.js new file mode 100644 index 000000000..6515fd73f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/invokeMap.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('invokeMap', require('../invokeMap')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArguments.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArguments.js new file mode 100644 index 000000000..1d93c9e59 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArguments.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isArguments', require('../isArguments'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArray.js new file mode 100644 index 000000000..ba7ade8dd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArray.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isArray', require('../isArray'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArrayBuffer.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArrayBuffer.js new file mode 100644 index 000000000..5088513fa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArrayBuffer.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isArrayBuffer', require('../isArrayBuffer'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArrayLike.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArrayLike.js new file mode 100644 index 000000000..8f1856bf6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArrayLike.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isArrayLike', require('../isArrayLike'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArrayLikeObject.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArrayLikeObject.js new file mode 100644 index 000000000..21084984b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isArrayLikeObject.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isArrayLikeObject', require('../isArrayLikeObject'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isBoolean.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isBoolean.js new file mode 100644 index 000000000..9339f75b1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isBoolean.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isBoolean', require('../isBoolean'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isBuffer.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isBuffer.js new file mode 100644 index 000000000..e60b12381 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isBuffer.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isBuffer', require('../isBuffer'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isDate.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isDate.js new file mode 100644 index 000000000..dc41d089e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isDate.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isDate', require('../isDate'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isElement.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isElement.js new file mode 100644 index 000000000..18ee039a2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isElement.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isElement', require('../isElement'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isEmpty.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isEmpty.js new file mode 100644 index 000000000..0f4ae841e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isEmpty.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isEmpty', require('../isEmpty'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isEqual.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isEqual.js new file mode 100644 index 000000000..41383865f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isEqual.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isEqual', require('../isEqual')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isEqualWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isEqualWith.js new file mode 100644 index 000000000..029ff5cda --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isEqualWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isEqualWith', require('../isEqualWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isError.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isError.js new file mode 100644 index 000000000..3dfd81ccc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isError.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isError', require('../isError'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isFinite.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isFinite.js new file mode 100644 index 000000000..0b647b841 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isFinite.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isFinite', require('../isFinite'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isFunction.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isFunction.js new file mode 100644 index 000000000..ff8e5c458 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isFunction.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isFunction', require('../isFunction'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isInteger.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isInteger.js new file mode 100644 index 000000000..67af4ff6d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isInteger.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isInteger', require('../isInteger'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isLength.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isLength.js new file mode 100644 index 000000000..fc101c5a6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isLength.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isLength', require('../isLength'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isMap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isMap.js new file mode 100644 index 000000000..a209aa66f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isMap.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isMap', require('../isMap'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isMatch.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isMatch.js new file mode 100644 index 000000000..6264ca17f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isMatch.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isMatch', require('../isMatch')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isMatchWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isMatchWith.js new file mode 100644 index 000000000..d95f31935 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isMatchWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isMatchWith', require('../isMatchWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNaN.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNaN.js new file mode 100644 index 000000000..66a978f11 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNaN.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isNaN', require('../isNaN'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNative.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNative.js new file mode 100644 index 000000000..3d775ba95 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNative.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isNative', require('../isNative'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNil.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNil.js new file mode 100644 index 000000000..5952c028a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNil.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isNil', require('../isNil'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNull.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNull.js new file mode 100644 index 000000000..f201a354b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNull.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isNull', require('../isNull'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNumber.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNumber.js new file mode 100644 index 000000000..a2b5fa049 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isNumber.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isNumber', require('../isNumber'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isObject.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isObject.js new file mode 100644 index 000000000..231ace03b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isObject.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isObject', require('../isObject'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isObjectLike.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isObjectLike.js new file mode 100644 index 000000000..f16082e6f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isObjectLike.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isObjectLike', require('../isObjectLike'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isPlainObject.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isPlainObject.js new file mode 100644 index 000000000..b5bea90d3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isPlainObject.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isPlainObject', require('../isPlainObject'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isRegExp.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isRegExp.js new file mode 100644 index 000000000..12a1a3d71 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isRegExp.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isRegExp', require('../isRegExp'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isSafeInteger.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isSafeInteger.js new file mode 100644 index 000000000..7230f5520 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isSafeInteger.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isSafeInteger', require('../isSafeInteger'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isSet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isSet.js new file mode 100644 index 000000000..35c01f6fa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isSet.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isSet', require('../isSet'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isString.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isString.js new file mode 100644 index 000000000..1fd0679ef --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isString.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isString', require('../isString'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isSymbol.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isSymbol.js new file mode 100644 index 000000000..38676956d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isSymbol.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isSymbol', require('../isSymbol'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isTypedArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isTypedArray.js new file mode 100644 index 000000000..856795387 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isTypedArray.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isTypedArray', require('../isTypedArray'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isUndefined.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isUndefined.js new file mode 100644 index 000000000..ddbca31ca --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isUndefined.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isUndefined', require('../isUndefined'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isWeakMap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isWeakMap.js new file mode 100644 index 000000000..ef60c613c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isWeakMap.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isWeakMap', require('../isWeakMap'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isWeakSet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isWeakSet.js new file mode 100644 index 000000000..c99bfaa6d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/isWeakSet.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('isWeakSet', require('../isWeakSet'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/iteratee.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/iteratee.js new file mode 100644 index 000000000..9f0f71738 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/iteratee.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('iteratee', require('../iteratee')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/join.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/join.js new file mode 100644 index 000000000..a220e003c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/join.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('join', require('../join')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/juxt.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/juxt.js new file mode 100644 index 000000000..f71e04e00 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/juxt.js @@ -0,0 +1 @@ +module.exports = require('./over'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/kebabCase.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/kebabCase.js new file mode 100644 index 000000000..60737f17c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/kebabCase.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('kebabCase', require('../kebabCase'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/keyBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/keyBy.js new file mode 100644 index 000000000..9a6a85d42 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/keyBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('keyBy', require('../keyBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/keys.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/keys.js new file mode 100644 index 000000000..e12bb07f1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/keys.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('keys', require('../keys'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/keysIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/keysIn.js new file mode 100644 index 000000000..f3eb36a8d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/keysIn.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('keysIn', require('../keysIn'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lang.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lang.js new file mode 100644 index 000000000..08cc9c14b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lang.js @@ -0,0 +1,2 @@ +var convert = require('./convert'); +module.exports = convert(require('../lang')); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/last.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/last.js new file mode 100644 index 000000000..0f716993f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/last.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('last', require('../last'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lastIndexOf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lastIndexOf.js new file mode 100644 index 000000000..ddf39c301 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lastIndexOf.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('lastIndexOf', require('../lastIndexOf')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lastIndexOfFrom.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lastIndexOfFrom.js new file mode 100644 index 000000000..1ff6a0b5a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lastIndexOfFrom.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('lastIndexOfFrom', require('../lastIndexOf')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lowerCase.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lowerCase.js new file mode 100644 index 000000000..ea64bc15d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lowerCase.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('lowerCase', require('../lowerCase'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lowerFirst.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lowerFirst.js new file mode 100644 index 000000000..539720a3d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lowerFirst.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('lowerFirst', require('../lowerFirst'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lt.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lt.js new file mode 100644 index 000000000..a31d21ecc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lt.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('lt', require('../lt')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lte.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lte.js new file mode 100644 index 000000000..d795d10ee --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/lte.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('lte', require('../lte')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/map.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/map.js new file mode 100644 index 000000000..cf9879436 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/map.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('map', require('../map')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mapKeys.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mapKeys.js new file mode 100644 index 000000000..168458709 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mapKeys.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('mapKeys', require('../mapKeys')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mapValues.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mapValues.js new file mode 100644 index 000000000..400497275 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mapValues.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('mapValues', require('../mapValues')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/matches.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/matches.js new file mode 100644 index 000000000..29d1e1e4f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/matches.js @@ -0,0 +1 @@ +module.exports = require('./isMatch'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/matchesProperty.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/matchesProperty.js new file mode 100644 index 000000000..4575bd243 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/matchesProperty.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('matchesProperty', require('../matchesProperty')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/math.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/math.js new file mode 100644 index 000000000..e8f50f792 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/math.js @@ -0,0 +1,2 @@ +var convert = require('./convert'); +module.exports = convert(require('../math')); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/max.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/max.js new file mode 100644 index 000000000..a66acac22 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/max.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('max', require('../max'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/maxBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/maxBy.js new file mode 100644 index 000000000..d083fd64f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/maxBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('maxBy', require('../maxBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mean.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mean.js new file mode 100644 index 000000000..31172460c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mean.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('mean', require('../mean'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/meanBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/meanBy.js new file mode 100644 index 000000000..556f25edf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/meanBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('meanBy', require('../meanBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/memoize.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/memoize.js new file mode 100644 index 000000000..638eec63b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/memoize.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('memoize', require('../memoize')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/merge.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/merge.js new file mode 100644 index 000000000..ac66adde1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/merge.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('merge', require('../merge')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mergeAll.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mergeAll.js new file mode 100644 index 000000000..a3674d671 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mergeAll.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('mergeAll', require('../merge')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mergeAllWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mergeAllWith.js new file mode 100644 index 000000000..4bd4206dc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mergeAllWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('mergeAllWith', require('../mergeWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mergeWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mergeWith.js new file mode 100644 index 000000000..00d44d5e1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mergeWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('mergeWith', require('../mergeWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/method.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/method.js new file mode 100644 index 000000000..f4060c687 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/method.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('method', require('../method')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/methodOf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/methodOf.js new file mode 100644 index 000000000..61399056f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/methodOf.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('methodOf', require('../methodOf')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/min.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/min.js new file mode 100644 index 000000000..d12c6b40d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/min.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('min', require('../min'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/minBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/minBy.js new file mode 100644 index 000000000..fdb9e24d8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/minBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('minBy', require('../minBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mixin.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mixin.js new file mode 100644 index 000000000..332e6fbfd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/mixin.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('mixin', require('../mixin')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/multiply.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/multiply.js new file mode 100644 index 000000000..4dcf0b0d4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/multiply.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('multiply', require('../multiply')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/nAry.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/nAry.js new file mode 100644 index 000000000..f262a76cc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/nAry.js @@ -0,0 +1 @@ +module.exports = require('./ary'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/negate.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/negate.js new file mode 100644 index 000000000..8b6dc7c5b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/negate.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('negate', require('../negate'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/next.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/next.js new file mode 100644 index 000000000..140155e23 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/next.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('next', require('../next'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/noop.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/noop.js new file mode 100644 index 000000000..b9e32cc8c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/noop.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('noop', require('../noop'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/now.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/now.js new file mode 100644 index 000000000..6de2068aa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/now.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('now', require('../now'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/nth.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/nth.js new file mode 100644 index 000000000..da4fda740 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/nth.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('nth', require('../nth')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/nthArg.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/nthArg.js new file mode 100644 index 000000000..fce316594 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/nthArg.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('nthArg', require('../nthArg')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/number.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/number.js new file mode 100644 index 000000000..5c10b8842 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/number.js @@ -0,0 +1,2 @@ +var convert = require('./convert'); +module.exports = convert(require('../number')); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/object.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/object.js new file mode 100644 index 000000000..ae39a1346 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/object.js @@ -0,0 +1,2 @@ +var convert = require('./convert'); +module.exports = convert(require('../object')); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/omit.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/omit.js new file mode 100644 index 000000000..fd685291e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/omit.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('omit', require('../omit')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/omitAll.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/omitAll.js new file mode 100644 index 000000000..144cf4b96 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/omitAll.js @@ -0,0 +1 @@ +module.exports = require('./omit'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/omitBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/omitBy.js new file mode 100644 index 000000000..90df73802 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/omitBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('omitBy', require('../omitBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/once.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/once.js new file mode 100644 index 000000000..f8f0a5c73 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/once.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('once', require('../once'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/orderBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/orderBy.js new file mode 100644 index 000000000..848e21075 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/orderBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('orderBy', require('../orderBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/over.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/over.js new file mode 100644 index 000000000..01eba7b98 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/over.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('over', require('../over')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/overArgs.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/overArgs.js new file mode 100644 index 000000000..738556f0c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/overArgs.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('overArgs', require('../overArgs')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/overEvery.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/overEvery.js new file mode 100644 index 000000000..9f5a032dc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/overEvery.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('overEvery', require('../overEvery')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/overSome.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/overSome.js new file mode 100644 index 000000000..15939d586 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/overSome.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('overSome', require('../overSome')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pad.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pad.js new file mode 100644 index 000000000..f1dea4a98 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pad.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('pad', require('../pad')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padChars.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padChars.js new file mode 100644 index 000000000..d6e0804cd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padChars.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('padChars', require('../pad')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padCharsEnd.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padCharsEnd.js new file mode 100644 index 000000000..d4ab79ad3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padCharsEnd.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('padCharsEnd', require('../padEnd')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padCharsStart.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padCharsStart.js new file mode 100644 index 000000000..a08a30000 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padCharsStart.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('padCharsStart', require('../padStart')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padEnd.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padEnd.js new file mode 100644 index 000000000..a8522ec36 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padEnd.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('padEnd', require('../padEnd')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padStart.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padStart.js new file mode 100644 index 000000000..f4ca79d4a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/padStart.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('padStart', require('../padStart')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/parseInt.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/parseInt.js new file mode 100644 index 000000000..27314ccbc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/parseInt.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('parseInt', require('../parseInt')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/partial.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/partial.js new file mode 100644 index 000000000..5d4601598 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/partial.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('partial', require('../partial')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/partialRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/partialRight.js new file mode 100644 index 000000000..7f05fed0a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/partialRight.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('partialRight', require('../partialRight')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/partition.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/partition.js new file mode 100644 index 000000000..2ebcacc1f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/partition.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('partition', require('../partition')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/path.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/path.js new file mode 100644 index 000000000..b29cfb213 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/path.js @@ -0,0 +1 @@ +module.exports = require('./get'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pathEq.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pathEq.js new file mode 100644 index 000000000..36c027a38 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pathEq.js @@ -0,0 +1 @@ +module.exports = require('./matchesProperty'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pathOr.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pathOr.js new file mode 100644 index 000000000..4ab582091 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pathOr.js @@ -0,0 +1 @@ +module.exports = require('./getOr'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/paths.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/paths.js new file mode 100644 index 000000000..1eb7950ac --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/paths.js @@ -0,0 +1 @@ +module.exports = require('./at'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pick.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pick.js new file mode 100644 index 000000000..197393de1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pick.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('pick', require('../pick')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pickAll.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pickAll.js new file mode 100644 index 000000000..a8ecd4613 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pickAll.js @@ -0,0 +1 @@ +module.exports = require('./pick'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pickBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pickBy.js new file mode 100644 index 000000000..d832d16b6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pickBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('pickBy', require('../pickBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pipe.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pipe.js new file mode 100644 index 000000000..b2e1e2cc8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pipe.js @@ -0,0 +1 @@ +module.exports = require('./flow'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/placeholder.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/placeholder.js new file mode 100644 index 000000000..1ce17393b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/placeholder.js @@ -0,0 +1,6 @@ +/** + * The default argument placeholder value for methods. + * + * @type {Object} + */ +module.exports = {}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/plant.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/plant.js new file mode 100644 index 000000000..eca8f32b4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/plant.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('plant', require('../plant'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pluck.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pluck.js new file mode 100644 index 000000000..0d1e1abfa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pluck.js @@ -0,0 +1 @@ +module.exports = require('./map'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/prop.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/prop.js new file mode 100644 index 000000000..b29cfb213 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/prop.js @@ -0,0 +1 @@ +module.exports = require('./get'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/propEq.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/propEq.js new file mode 100644 index 000000000..36c027a38 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/propEq.js @@ -0,0 +1 @@ +module.exports = require('./matchesProperty'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/propOr.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/propOr.js new file mode 100644 index 000000000..4ab582091 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/propOr.js @@ -0,0 +1 @@ +module.exports = require('./getOr'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/property.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/property.js new file mode 100644 index 000000000..b29cfb213 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/property.js @@ -0,0 +1 @@ +module.exports = require('./get'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/propertyOf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/propertyOf.js new file mode 100644 index 000000000..f6273ee47 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/propertyOf.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('propertyOf', require('../get')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/props.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/props.js new file mode 100644 index 000000000..1eb7950ac --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/props.js @@ -0,0 +1 @@ +module.exports = require('./at'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pull.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pull.js new file mode 100644 index 000000000..8d7084f07 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pull.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('pull', require('../pull')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAll.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAll.js new file mode 100644 index 000000000..98d5c9a73 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAll.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('pullAll', require('../pullAll')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAllBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAllBy.js new file mode 100644 index 000000000..876bc3bf1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAllBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('pullAllBy', require('../pullAllBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAllWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAllWith.js new file mode 100644 index 000000000..f71ba4d73 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAllWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('pullAllWith', require('../pullAllWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAt.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAt.js new file mode 100644 index 000000000..e8b3bb612 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/pullAt.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('pullAt', require('../pullAt')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/random.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/random.js new file mode 100644 index 000000000..99d852e4a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/random.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('random', require('../random')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/range.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/range.js new file mode 100644 index 000000000..a6bb59118 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/range.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('range', require('../range')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rangeRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rangeRight.js new file mode 100644 index 000000000..fdb712f94 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rangeRight.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('rangeRight', require('../rangeRight')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rangeStep.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rangeStep.js new file mode 100644 index 000000000..d72dfc200 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rangeStep.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('rangeStep', require('../range')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rangeStepRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rangeStepRight.js new file mode 100644 index 000000000..8b2a67bc6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rangeStepRight.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('rangeStepRight', require('../rangeRight')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rearg.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rearg.js new file mode 100644 index 000000000..678e02a32 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rearg.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('rearg', require('../rearg')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reduce.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reduce.js new file mode 100644 index 000000000..4cef0a008 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reduce.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('reduce', require('../reduce')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reduceRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reduceRight.js new file mode 100644 index 000000000..caf5bb515 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reduceRight.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('reduceRight', require('../reduceRight')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reject.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reject.js new file mode 100644 index 000000000..c16327386 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reject.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('reject', require('../reject')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/remove.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/remove.js new file mode 100644 index 000000000..e9d132736 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/remove.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('remove', require('../remove')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/repeat.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/repeat.js new file mode 100644 index 000000000..08470f247 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/repeat.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('repeat', require('../repeat')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/replace.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/replace.js new file mode 100644 index 000000000..2227db625 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/replace.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('replace', require('../replace')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rest.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rest.js new file mode 100644 index 000000000..c1f3d64bd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/rest.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('rest', require('../rest')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/restFrom.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/restFrom.js new file mode 100644 index 000000000..714e42b5d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/restFrom.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('restFrom', require('../rest')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/result.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/result.js new file mode 100644 index 000000000..f86ce0712 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/result.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('result', require('../result')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reverse.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reverse.js new file mode 100644 index 000000000..07c9f5e49 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/reverse.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('reverse', require('../reverse')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/round.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/round.js new file mode 100644 index 000000000..4c0e5c829 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/round.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('round', require('../round')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sample.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sample.js new file mode 100644 index 000000000..6bea1254d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sample.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('sample', require('../sample'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sampleSize.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sampleSize.js new file mode 100644 index 000000000..359ed6fcd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sampleSize.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('sampleSize', require('../sampleSize')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/seq.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/seq.js new file mode 100644 index 000000000..d8f42b0a4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/seq.js @@ -0,0 +1,2 @@ +var convert = require('./convert'); +module.exports = convert(require('../seq')); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/set.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/set.js new file mode 100644 index 000000000..0b56a56c8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/set.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('set', require('../set')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/setWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/setWith.js new file mode 100644 index 000000000..0b584952b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/setWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('setWith', require('../setWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/shuffle.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/shuffle.js new file mode 100644 index 000000000..aa3a1ca5b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/shuffle.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('shuffle', require('../shuffle'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/size.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/size.js new file mode 100644 index 000000000..7490136e1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/size.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('size', require('../size'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/slice.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/slice.js new file mode 100644 index 000000000..15945d321 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/slice.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('slice', require('../slice')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/snakeCase.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/snakeCase.js new file mode 100644 index 000000000..a0ff7808e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/snakeCase.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('snakeCase', require('../snakeCase'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/some.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/some.js new file mode 100644 index 000000000..a4fa2d006 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/some.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('some', require('../some')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortBy.js new file mode 100644 index 000000000..e0790ad5b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('sortBy', require('../sortBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedIndex.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedIndex.js new file mode 100644 index 000000000..364a05435 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedIndex.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('sortedIndex', require('../sortedIndex')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedIndexBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedIndexBy.js new file mode 100644 index 000000000..9593dbd13 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedIndexBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('sortedIndexBy', require('../sortedIndexBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedIndexOf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedIndexOf.js new file mode 100644 index 000000000..c9084cab6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedIndexOf.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('sortedIndexOf', require('../sortedIndexOf')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedLastIndex.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedLastIndex.js new file mode 100644 index 000000000..47fe241af --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedLastIndex.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('sortedLastIndex', require('../sortedLastIndex')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedLastIndexBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedLastIndexBy.js new file mode 100644 index 000000000..0f9a34732 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedLastIndexBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('sortedLastIndexBy', require('../sortedLastIndexBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedLastIndexOf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedLastIndexOf.js new file mode 100644 index 000000000..0d4d93278 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedLastIndexOf.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('sortedLastIndexOf', require('../sortedLastIndexOf')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedUniq.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedUniq.js new file mode 100644 index 000000000..882d28370 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedUniq.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('sortedUniq', require('../sortedUniq'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedUniqBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedUniqBy.js new file mode 100644 index 000000000..033db91ca --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sortedUniqBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('sortedUniqBy', require('../sortedUniqBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/split.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/split.js new file mode 100644 index 000000000..14de1a7ef --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/split.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('split', require('../split')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/spread.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/spread.js new file mode 100644 index 000000000..2d11b7072 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/spread.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('spread', require('../spread')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/spreadFrom.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/spreadFrom.js new file mode 100644 index 000000000..0b630df1b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/spreadFrom.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('spreadFrom', require('../spread')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/startCase.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/startCase.js new file mode 100644 index 000000000..ada98c943 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/startCase.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('startCase', require('../startCase'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/startsWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/startsWith.js new file mode 100644 index 000000000..985e2f294 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/startsWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('startsWith', require('../startsWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/string.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/string.js new file mode 100644 index 000000000..773b03704 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/string.js @@ -0,0 +1,2 @@ +var convert = require('./convert'); +module.exports = convert(require('../string')); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubArray.js new file mode 100644 index 000000000..cd604cb49 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubArray.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('stubArray', require('../stubArray'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubFalse.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubFalse.js new file mode 100644 index 000000000..329666454 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubFalse.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('stubFalse', require('../stubFalse'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubObject.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubObject.js new file mode 100644 index 000000000..c6c8ec472 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubObject.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('stubObject', require('../stubObject'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubString.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubString.js new file mode 100644 index 000000000..701051e8b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubString.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('stubString', require('../stubString'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubTrue.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubTrue.js new file mode 100644 index 000000000..9249082ce --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/stubTrue.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('stubTrue', require('../stubTrue'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/subtract.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/subtract.js new file mode 100644 index 000000000..d32b16d47 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/subtract.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('subtract', require('../subtract')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sum.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sum.js new file mode 100644 index 000000000..5cce12b32 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sum.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('sum', require('../sum'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sumBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sumBy.js new file mode 100644 index 000000000..c8826565f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/sumBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('sumBy', require('../sumBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/symmetricDifference.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/symmetricDifference.js new file mode 100644 index 000000000..78c16add6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/symmetricDifference.js @@ -0,0 +1 @@ +module.exports = require('./xor'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/symmetricDifferenceBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/symmetricDifferenceBy.js new file mode 100644 index 000000000..298fc7ff6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/symmetricDifferenceBy.js @@ -0,0 +1 @@ +module.exports = require('./xorBy'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/symmetricDifferenceWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/symmetricDifferenceWith.js new file mode 100644 index 000000000..70bc6faf2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/symmetricDifferenceWith.js @@ -0,0 +1 @@ +module.exports = require('./xorWith'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/tail.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/tail.js new file mode 100644 index 000000000..f122f0ac3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/tail.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('tail', require('../tail'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/take.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/take.js new file mode 100644 index 000000000..9af98a7bd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/take.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('take', require('../take')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeLast.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeLast.js new file mode 100644 index 000000000..e98c84a16 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeLast.js @@ -0,0 +1 @@ +module.exports = require('./takeRight'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeLastWhile.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeLastWhile.js new file mode 100644 index 000000000..5367968a3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeLastWhile.js @@ -0,0 +1 @@ +module.exports = require('./takeRightWhile'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeRight.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeRight.js new file mode 100644 index 000000000..b82950a69 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeRight.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('takeRight', require('../takeRight')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeRightWhile.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeRightWhile.js new file mode 100644 index 000000000..8ffb0a285 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeRightWhile.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('takeRightWhile', require('../takeRightWhile')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeWhile.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeWhile.js new file mode 100644 index 000000000..28136644f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/takeWhile.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('takeWhile', require('../takeWhile')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/tap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/tap.js new file mode 100644 index 000000000..d33ad6ec1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/tap.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('tap', require('../tap')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/template.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/template.js new file mode 100644 index 000000000..74857e1c8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/template.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('template', require('../template')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/templateSettings.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/templateSettings.js new file mode 100644 index 000000000..7bcc0a82b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/templateSettings.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('templateSettings', require('../templateSettings'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/throttle.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/throttle.js new file mode 100644 index 000000000..77fff1428 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/throttle.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('throttle', require('../throttle')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/thru.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/thru.js new file mode 100644 index 000000000..d42b3b1d8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/thru.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('thru', require('../thru')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/times.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/times.js new file mode 100644 index 000000000..0dab06dad --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/times.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('times', require('../times')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toArray.js new file mode 100644 index 000000000..f0c360aca --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toArray.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('toArray', require('../toArray'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toFinite.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toFinite.js new file mode 100644 index 000000000..3a47687d6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toFinite.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('toFinite', require('../toFinite'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toInteger.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toInteger.js new file mode 100644 index 000000000..e0af6a750 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toInteger.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('toInteger', require('../toInteger'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toIterator.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toIterator.js new file mode 100644 index 000000000..65e6baa9d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toIterator.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('toIterator', require('../toIterator'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toJSON.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toJSON.js new file mode 100644 index 000000000..2d718d0bc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toJSON.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('toJSON', require('../toJSON'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toLength.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toLength.js new file mode 100644 index 000000000..b97cdd935 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toLength.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('toLength', require('../toLength'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toLower.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toLower.js new file mode 100644 index 000000000..616ef36ad --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toLower.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('toLower', require('../toLower'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toNumber.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toNumber.js new file mode 100644 index 000000000..d0c6f4d3d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toNumber.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('toNumber', require('../toNumber'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPairs.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPairs.js new file mode 100644 index 000000000..af783786e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPairs.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('toPairs', require('../toPairs'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPairsIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPairsIn.js new file mode 100644 index 000000000..66504abf1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPairsIn.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('toPairsIn', require('../toPairsIn'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPath.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPath.js new file mode 100644 index 000000000..b4d5e50fb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPath.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('toPath', require('../toPath'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPlainObject.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPlainObject.js new file mode 100644 index 000000000..278bb8639 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toPlainObject.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('toPlainObject', require('../toPlainObject'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toSafeInteger.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toSafeInteger.js new file mode 100644 index 000000000..367a26fdd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toSafeInteger.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('toSafeInteger', require('../toSafeInteger'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toString.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toString.js new file mode 100644 index 000000000..cec4f8e22 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toString.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('toString', require('../toString'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toUpper.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toUpper.js new file mode 100644 index 000000000..54f9a5605 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/toUpper.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('toUpper', require('../toUpper'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/transform.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/transform.js new file mode 100644 index 000000000..759d088f1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/transform.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('transform', require('../transform')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trim.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trim.js new file mode 100644 index 000000000..e6319a741 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trim.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('trim', require('../trim')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimChars.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimChars.js new file mode 100644 index 000000000..c9294de48 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimChars.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('trimChars', require('../trim')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimCharsEnd.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimCharsEnd.js new file mode 100644 index 000000000..284bc2f81 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimCharsEnd.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('trimCharsEnd', require('../trimEnd')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimCharsStart.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimCharsStart.js new file mode 100644 index 000000000..ff0ee65df --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimCharsStart.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('trimCharsStart', require('../trimStart')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimEnd.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimEnd.js new file mode 100644 index 000000000..71908805f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimEnd.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('trimEnd', require('../trimEnd')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimStart.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimStart.js new file mode 100644 index 000000000..fda902c38 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/trimStart.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('trimStart', require('../trimStart')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/truncate.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/truncate.js new file mode 100644 index 000000000..d265c1dec --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/truncate.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('truncate', require('../truncate')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unapply.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unapply.js new file mode 100644 index 000000000..c5dfe779d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unapply.js @@ -0,0 +1 @@ +module.exports = require('./rest'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unary.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unary.js new file mode 100644 index 000000000..286c945fb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unary.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('unary', require('../unary'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unescape.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unescape.js new file mode 100644 index 000000000..fddcb46e2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unescape.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('unescape', require('../unescape'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/union.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/union.js new file mode 100644 index 000000000..ef8228d74 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/union.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('union', require('../union')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unionBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unionBy.js new file mode 100644 index 000000000..603687a18 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unionBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('unionBy', require('../unionBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unionWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unionWith.js new file mode 100644 index 000000000..65bb3a792 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unionWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('unionWith', require('../unionWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniq.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniq.js new file mode 100644 index 000000000..bc1852490 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniq.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('uniq', require('../uniq'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniqBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniqBy.js new file mode 100644 index 000000000..634c6a8bb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniqBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('uniqBy', require('../uniqBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniqWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniqWith.js new file mode 100644 index 000000000..0ec601a91 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniqWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('uniqWith', require('../uniqWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniqueId.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniqueId.js new file mode 100644 index 000000000..aa8fc2f73 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/uniqueId.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('uniqueId', require('../uniqueId')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unnest.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unnest.js new file mode 100644 index 000000000..5d34060aa --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unnest.js @@ -0,0 +1 @@ +module.exports = require('./flatten'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unset.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unset.js new file mode 100644 index 000000000..ea203a0f3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unset.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('unset', require('../unset')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unzip.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unzip.js new file mode 100644 index 000000000..cc364b3c5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unzip.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('unzip', require('../unzip'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unzipWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unzipWith.js new file mode 100644 index 000000000..182eaa104 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/unzipWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('unzipWith', require('../unzipWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/update.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/update.js new file mode 100644 index 000000000..b8ce2cc9e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/update.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('update', require('../update')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/updateWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/updateWith.js new file mode 100644 index 000000000..d5e8282d9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/updateWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('updateWith', require('../updateWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/upperCase.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/upperCase.js new file mode 100644 index 000000000..c886f2021 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/upperCase.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('upperCase', require('../upperCase'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/upperFirst.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/upperFirst.js new file mode 100644 index 000000000..d8c04df54 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/upperFirst.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('upperFirst', require('../upperFirst'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/useWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/useWith.js new file mode 100644 index 000000000..d8b3df5a4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/useWith.js @@ -0,0 +1 @@ +module.exports = require('./overArgs'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/util.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/util.js new file mode 100644 index 000000000..18c00baed --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/util.js @@ -0,0 +1,2 @@ +var convert = require('./convert'); +module.exports = convert(require('../util')); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/value.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/value.js new file mode 100644 index 000000000..555eec7a3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/value.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('value', require('../value'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/valueOf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/valueOf.js new file mode 100644 index 000000000..f968807d7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/valueOf.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('valueOf', require('../valueOf'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/values.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/values.js new file mode 100644 index 000000000..2dfc56136 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/values.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('values', require('../values'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/valuesIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/valuesIn.js new file mode 100644 index 000000000..a1b2bb872 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/valuesIn.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('valuesIn', require('../valuesIn'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/where.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/where.js new file mode 100644 index 000000000..3247f64a8 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/where.js @@ -0,0 +1 @@ +module.exports = require('./conformsTo'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/whereEq.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/whereEq.js new file mode 100644 index 000000000..29d1e1e4f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/whereEq.js @@ -0,0 +1 @@ +module.exports = require('./isMatch'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/without.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/without.js new file mode 100644 index 000000000..bad9e125b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/without.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('without', require('../without')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/words.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/words.js new file mode 100644 index 000000000..4a901414b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/words.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('words', require('../words')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrap.js new file mode 100644 index 000000000..e93bd8a1d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrap.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('wrap', require('../wrap')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperAt.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperAt.js new file mode 100644 index 000000000..8f0a310fe --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperAt.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('wrapperAt', require('../wrapperAt'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperChain.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperChain.js new file mode 100644 index 000000000..2a48ea2b5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperChain.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('wrapperChain', require('../wrapperChain'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperLodash.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperLodash.js new file mode 100644 index 000000000..a7162d084 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperLodash.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('wrapperLodash', require('../wrapperLodash'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperReverse.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperReverse.js new file mode 100644 index 000000000..e1481aab9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperReverse.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('wrapperReverse', require('../wrapperReverse'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperValue.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperValue.js new file mode 100644 index 000000000..8eb9112f6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/wrapperValue.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('wrapperValue', require('../wrapperValue'), require('./_falseOptions')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/xor.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/xor.js new file mode 100644 index 000000000..29e281948 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/xor.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('xor', require('../xor')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/xorBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/xorBy.js new file mode 100644 index 000000000..b355686db --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/xorBy.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('xorBy', require('../xorBy')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/xorWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/xorWith.js new file mode 100644 index 000000000..8e05739ad --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/xorWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('xorWith', require('../xorWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zip.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zip.js new file mode 100644 index 000000000..69e147a44 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zip.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('zip', require('../zip')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipAll.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipAll.js new file mode 100644 index 000000000..efa8ccbfb --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipAll.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('zipAll', require('../zip')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipObj.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipObj.js new file mode 100644 index 000000000..f4a34531b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipObj.js @@ -0,0 +1 @@ +module.exports = require('./zipObject'); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipObject.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipObject.js new file mode 100644 index 000000000..462dbb68c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipObject.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('zipObject', require('../zipObject')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipObjectDeep.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipObjectDeep.js new file mode 100644 index 000000000..53a5d3380 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipObjectDeep.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('zipObjectDeep', require('../zipObjectDeep')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipWith.js new file mode 100644 index 000000000..c5cf9e212 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fp/zipWith.js @@ -0,0 +1,5 @@ +var convert = require('./convert'), + func = convert('zipWith', require('../zipWith')); + +func.placeholder = require('./placeholder'); +module.exports = func; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fromPairs.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fromPairs.js new file mode 100644 index 000000000..ee7940d24 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/fromPairs.js @@ -0,0 +1,28 @@ +/** + * The inverse of `_.toPairs`; this method returns an object composed + * from key-value `pairs`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} pairs The key-value pairs. + * @returns {Object} Returns the new object. + * @example + * + * _.fromPairs([['a', 1], ['b', 2]]); + * // => { 'a': 1, 'b': 2 } + */ +function fromPairs(pairs) { + var index = -1, + length = pairs == null ? 0 : pairs.length, + result = {}; + + while (++index < length) { + var pair = pairs[index]; + result[pair[0]] = pair[1]; + } + return result; +} + +module.exports = fromPairs; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/function.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/function.js new file mode 100644 index 000000000..b0fc6d93e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/function.js @@ -0,0 +1,25 @@ +module.exports = { + 'after': require('./after'), + 'ary': require('./ary'), + 'before': require('./before'), + 'bind': require('./bind'), + 'bindKey': require('./bindKey'), + 'curry': require('./curry'), + 'curryRight': require('./curryRight'), + 'debounce': require('./debounce'), + 'defer': require('./defer'), + 'delay': require('./delay'), + 'flip': require('./flip'), + 'memoize': require('./memoize'), + 'negate': require('./negate'), + 'once': require('./once'), + 'overArgs': require('./overArgs'), + 'partial': require('./partial'), + 'partialRight': require('./partialRight'), + 'rearg': require('./rearg'), + 'rest': require('./rest'), + 'spread': require('./spread'), + 'throttle': require('./throttle'), + 'unary': require('./unary'), + 'wrap': require('./wrap') +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/functions.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/functions.js new file mode 100644 index 000000000..9722928f5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/functions.js @@ -0,0 +1,31 @@ +var baseFunctions = require('./_baseFunctions'), + keys = require('./keys'); + +/** + * Creates an array of function property names from own enumerable properties + * of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functionsIn + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functions(new Foo); + * // => ['a', 'b'] + */ +function functions(object) { + return object == null ? [] : baseFunctions(object, keys(object)); +} + +module.exports = functions; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/functionsIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/functionsIn.js new file mode 100644 index 000000000..f00345d06 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/functionsIn.js @@ -0,0 +1,31 @@ +var baseFunctions = require('./_baseFunctions'), + keysIn = require('./keysIn'); + +/** + * Creates an array of function property names from own and inherited + * enumerable properties of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functions + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functionsIn(new Foo); + * // => ['a', 'b', 'c'] + */ +function functionsIn(object) { + return object == null ? [] : baseFunctions(object, keysIn(object)); +} + +module.exports = functionsIn; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/get.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/get.js new file mode 100644 index 000000000..8805ff92c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/get.js @@ -0,0 +1,33 @@ +var baseGet = require('./_baseGet'); + +/** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.get(object, 'a[0].b.c'); + * // => 3 + * + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */ +function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, path); + return result === undefined ? defaultValue : result; +} + +module.exports = get; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/groupBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/groupBy.js new file mode 100644 index 000000000..babf4f6ba --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/groupBy.js @@ -0,0 +1,41 @@ +var baseAssignValue = require('./_baseAssignValue'), + createAggregator = require('./_createAggregator'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The order of grouped values + * is determined by the order they occur in `collection`. The corresponding + * value of each key is an array of elements responsible for generating the + * key. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.groupBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': [4.2], '6': [6.1, 6.3] } + * + * // The `_.property` iteratee shorthand. + * _.groupBy(['one', 'two', 'three'], 'length'); + * // => { '3': ['one', 'two'], '5': ['three'] } + */ +var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + baseAssignValue(result, key, [value]); + } +}); + +module.exports = groupBy; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/gt.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/gt.js new file mode 100644 index 000000000..3a6628288 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/gt.js @@ -0,0 +1,29 @@ +var baseGt = require('./_baseGt'), + createRelationalOperation = require('./_createRelationalOperation'); + +/** + * Checks if `value` is greater than `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + * @see _.lt + * @example + * + * _.gt(3, 1); + * // => true + * + * _.gt(3, 3); + * // => false + * + * _.gt(1, 3); + * // => false + */ +var gt = createRelationalOperation(baseGt); + +module.exports = gt; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/gte.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/gte.js new file mode 100644 index 000000000..4180a687d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/gte.js @@ -0,0 +1,30 @@ +var createRelationalOperation = require('./_createRelationalOperation'); + +/** + * Checks if `value` is greater than or equal to `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than or equal to + * `other`, else `false`. + * @see _.lte + * @example + * + * _.gte(3, 1); + * // => true + * + * _.gte(3, 3); + * // => true + * + * _.gte(1, 3); + * // => false + */ +var gte = createRelationalOperation(function(value, other) { + return value >= other; +}); + +module.exports = gte; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/has.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/has.js new file mode 100644 index 000000000..34df55e8e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/has.js @@ -0,0 +1,35 @@ +var baseHas = require('./_baseHas'), + hasPath = require('./_hasPath'); + +/** + * Checks if `path` is a direct property of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = { 'a': { 'b': 2 } }; + * var other = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.has(object, 'a'); + * // => true + * + * _.has(object, 'a.b'); + * // => true + * + * _.has(object, ['a', 'b']); + * // => true + * + * _.has(other, 'a'); + * // => false + */ +function has(object, path) { + return object != null && hasPath(object, path, baseHas); +} + +module.exports = has; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/hasIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/hasIn.js new file mode 100644 index 000000000..06a368654 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/hasIn.js @@ -0,0 +1,34 @@ +var baseHasIn = require('./_baseHasIn'), + hasPath = require('./_hasPath'); + +/** + * Checks if `path` is a direct or inherited property of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.hasIn(object, 'a'); + * // => true + * + * _.hasIn(object, 'a.b'); + * // => true + * + * _.hasIn(object, ['a', 'b']); + * // => true + * + * _.hasIn(object, 'b'); + * // => false + */ +function hasIn(object, path) { + return object != null && hasPath(object, path, baseHasIn); +} + +module.exports = hasIn; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/head.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/head.js new file mode 100644 index 000000000..dee9d1f1e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/head.js @@ -0,0 +1,23 @@ +/** + * Gets the first element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias first + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the first element of `array`. + * @example + * + * _.head([1, 2, 3]); + * // => 1 + * + * _.head([]); + * // => undefined + */ +function head(array) { + return (array && array.length) ? array[0] : undefined; +} + +module.exports = head; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/identity.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/identity.js new file mode 100644 index 000000000..2d5d963cd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/identity.js @@ -0,0 +1,21 @@ +/** + * This method returns the first argument it receives. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {*} value Any value. + * @returns {*} Returns `value`. + * @example + * + * var object = { 'a': 1 }; + * + * console.log(_.identity(object) === object); + * // => true + */ +function identity(value) { + return value; +} + +module.exports = identity; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/inRange.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/inRange.js new file mode 100644 index 000000000..f20728d92 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/inRange.js @@ -0,0 +1,55 @@ +var baseInRange = require('./_baseInRange'), + toFinite = require('./toFinite'), + toNumber = require('./toNumber'); + +/** + * Checks if `n` is between `start` and up to, but not including, `end`. If + * `end` is not specified, it's set to `start` with `start` then set to `0`. + * If `start` is greater than `end` the params are swapped to support + * negative ranges. + * + * @static + * @memberOf _ + * @since 3.3.0 + * @category Number + * @param {number} number The number to check. + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + * @see _.range, _.rangeRight + * @example + * + * _.inRange(3, 2, 4); + * // => true + * + * _.inRange(4, 8); + * // => true + * + * _.inRange(4, 2); + * // => false + * + * _.inRange(2, 2); + * // => false + * + * _.inRange(1.2, 2); + * // => true + * + * _.inRange(5.2, 4); + * // => false + * + * _.inRange(-3, -2, -6); + * // => true + */ +function inRange(number, start, end) { + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + number = toNumber(number); + return baseInRange(number, start, end); +} + +module.exports = inRange; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/includes.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/includes.js new file mode 100644 index 000000000..ae0deedc9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/includes.js @@ -0,0 +1,53 @@ +var baseIndexOf = require('./_baseIndexOf'), + isArrayLike = require('./isArrayLike'), + isString = require('./isString'), + toInteger = require('./toInteger'), + values = require('./values'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * Checks if `value` is in `collection`. If `collection` is a string, it's + * checked for a substring of `value`, otherwise + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * is used for equality comparisons. If `fromIndex` is negative, it's used as + * the offset from the end of `collection`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. + * @returns {boolean} Returns `true` if `value` is found, else `false`. + * @example + * + * _.includes([1, 2, 3], 1); + * // => true + * + * _.includes([1, 2, 3], 1, 2); + * // => false + * + * _.includes({ 'a': 1, 'b': 2 }, 1); + * // => true + * + * _.includes('abcd', 'bc'); + * // => true + */ +function includes(collection, value, fromIndex, guard) { + collection = isArrayLike(collection) ? collection : values(collection); + fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0; + + var length = collection.length; + if (fromIndex < 0) { + fromIndex = nativeMax(length + fromIndex, 0); + } + return isString(collection) + ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1) + : (!!length && baseIndexOf(collection, value, fromIndex) > -1); +} + +module.exports = includes; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/index.js new file mode 100644 index 000000000..5d063e21f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/index.js @@ -0,0 +1 @@ +module.exports = require('./lodash'); \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/indexOf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/indexOf.js new file mode 100644 index 000000000..3c644af2e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/indexOf.js @@ -0,0 +1,42 @@ +var baseIndexOf = require('./_baseIndexOf'), + toInteger = require('./toInteger'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * Gets the index at which the first occurrence of `value` is found in `array` + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. If `fromIndex` is negative, it's used as the + * offset from the end of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.indexOf([1, 2, 1, 2], 2); + * // => 1 + * + * // Search from the `fromIndex`. + * _.indexOf([1, 2, 1, 2], 2, 2); + * // => 3 + */ +function indexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseIndexOf(array, value, index); +} + +module.exports = indexOf; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/initial.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/initial.js new file mode 100644 index 000000000..f47fc5092 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/initial.js @@ -0,0 +1,22 @@ +var baseSlice = require('./_baseSlice'); + +/** + * Gets all but the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.initial([1, 2, 3]); + * // => [1, 2] + */ +function initial(array) { + var length = array == null ? 0 : array.length; + return length ? baseSlice(array, 0, -1) : []; +} + +module.exports = initial; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/intersection.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/intersection.js new file mode 100644 index 000000000..a94c13512 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/intersection.js @@ -0,0 +1,30 @@ +var arrayMap = require('./_arrayMap'), + baseIntersection = require('./_baseIntersection'), + baseRest = require('./_baseRest'), + castArrayLikeObject = require('./_castArrayLikeObject'); + +/** + * Creates an array of unique values that are included in all given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersection([2, 1], [2, 3]); + * // => [2] + */ +var intersection = baseRest(function(arrays) { + var mapped = arrayMap(arrays, castArrayLikeObject); + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped) + : []; +}); + +module.exports = intersection; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/intersectionBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/intersectionBy.js new file mode 100644 index 000000000..31461aae5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/intersectionBy.js @@ -0,0 +1,45 @@ +var arrayMap = require('./_arrayMap'), + baseIntersection = require('./_baseIntersection'), + baseIteratee = require('./_baseIteratee'), + baseRest = require('./_baseRest'), + castArrayLikeObject = require('./_castArrayLikeObject'), + last = require('./last'); + +/** + * This method is like `_.intersection` except that it accepts `iteratee` + * which is invoked for each element of each `arrays` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [2.1] + * + * // The `_.property` iteratee shorthand. + * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }] + */ +var intersectionBy = baseRest(function(arrays) { + var iteratee = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + if (iteratee === last(mapped)) { + iteratee = undefined; + } else { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, baseIteratee(iteratee, 2)) + : []; +}); + +module.exports = intersectionBy; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/intersectionWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/intersectionWith.js new file mode 100644 index 000000000..63cabfaa4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/intersectionWith.js @@ -0,0 +1,41 @@ +var arrayMap = require('./_arrayMap'), + baseIntersection = require('./_baseIntersection'), + baseRest = require('./_baseRest'), + castArrayLikeObject = require('./_castArrayLikeObject'), + last = require('./last'); + +/** + * This method is like `_.intersection` except that it accepts `comparator` + * which is invoked to compare elements of `arrays`. The order and references + * of result values are determined by the first array. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.intersectionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }] + */ +var intersectionWith = baseRest(function(arrays) { + var comparator = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + comparator = typeof comparator == 'function' ? comparator : undefined; + if (comparator) { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, undefined, comparator) + : []; +}); + +module.exports = intersectionWith; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invert.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invert.js new file mode 100644 index 000000000..8c4795097 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invert.js @@ -0,0 +1,42 @@ +var constant = require('./constant'), + createInverter = require('./_createInverter'), + identity = require('./identity'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** + * Creates an object composed of the inverted keys and values of `object`. + * If `object` contains duplicate values, subsequent values overwrite + * property assignments of previous values. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Object + * @param {Object} object The object to invert. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invert(object); + * // => { '1': 'c', '2': 'b' } + */ +var invert = createInverter(function(result, value, key) { + if (value != null && + typeof value.toString != 'function') { + value = nativeObjectToString.call(value); + } + + result[value] = key; +}, constant(identity)); + +module.exports = invert; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invertBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invertBy.js new file mode 100644 index 000000000..3f4f7e532 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invertBy.js @@ -0,0 +1,56 @@ +var baseIteratee = require('./_baseIteratee'), + createInverter = require('./_createInverter'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** + * This method is like `_.invert` except that the inverted object is generated + * from the results of running each element of `object` thru `iteratee`. The + * corresponding inverted value of each inverted key is an array of keys + * responsible for generating the inverted value. The iteratee is invoked + * with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.1.0 + * @category Object + * @param {Object} object The object to invert. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invertBy(object); + * // => { '1': ['a', 'c'], '2': ['b'] } + * + * _.invertBy(object, function(value) { + * return 'group' + value; + * }); + * // => { 'group1': ['a', 'c'], 'group2': ['b'] } + */ +var invertBy = createInverter(function(result, value, key) { + if (value != null && + typeof value.toString != 'function') { + value = nativeObjectToString.call(value); + } + + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [key]; + } +}, baseIteratee); + +module.exports = invertBy; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invoke.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invoke.js new file mode 100644 index 000000000..97d51eb5b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invoke.js @@ -0,0 +1,24 @@ +var baseInvoke = require('./_baseInvoke'), + baseRest = require('./_baseRest'); + +/** + * Invokes the method at `path` of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {...*} [args] The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + * @example + * + * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] }; + * + * _.invoke(object, 'a[0].b.c.slice', 1, 3); + * // => [2, 3] + */ +var invoke = baseRest(baseInvoke); + +module.exports = invoke; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invokeMap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invokeMap.js new file mode 100644 index 000000000..8da5126c6 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/invokeMap.js @@ -0,0 +1,41 @@ +var apply = require('./_apply'), + baseEach = require('./_baseEach'), + baseInvoke = require('./_baseInvoke'), + baseRest = require('./_baseRest'), + isArrayLike = require('./isArrayLike'); + +/** + * Invokes the method at `path` of each element in `collection`, returning + * an array of the results of each invoked method. Any additional arguments + * are provided to each invoked method. If `path` is a function, it's invoked + * for, and `this` bound to, each element in `collection`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Array|Function|string} path The path of the method to invoke or + * the function invoked per iteration. + * @param {...*} [args] The arguments to invoke each method with. + * @returns {Array} Returns the array of results. + * @example + * + * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort'); + * // => [[1, 5, 7], [1, 2, 3]] + * + * _.invokeMap([123, 456], String.prototype.split, ''); + * // => [['1', '2', '3'], ['4', '5', '6']] + */ +var invokeMap = baseRest(function(collection, path, args) { + var index = -1, + isFunc = typeof path == 'function', + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value) { + result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args); + }); + return result; +}); + +module.exports = invokeMap; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArguments.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArguments.js new file mode 100644 index 000000000..8b9ed66cd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArguments.js @@ -0,0 +1,36 @@ +var baseIsArguments = require('./_baseIsArguments'), + isObjectLike = require('./isObjectLike'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); +}; + +module.exports = isArguments; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArray.js new file mode 100644 index 000000000..88ab55fd0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArray.js @@ -0,0 +1,26 @@ +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ +var isArray = Array.isArray; + +module.exports = isArray; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArrayBuffer.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArrayBuffer.js new file mode 100644 index 000000000..12904a64b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArrayBuffer.js @@ -0,0 +1,27 @@ +var baseIsArrayBuffer = require('./_baseIsArrayBuffer'), + baseUnary = require('./_baseUnary'), + nodeUtil = require('./_nodeUtil'); + +/* Node.js helper references. */ +var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer; + +/** + * Checks if `value` is classified as an `ArrayBuffer` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + * @example + * + * _.isArrayBuffer(new ArrayBuffer(2)); + * // => true + * + * _.isArrayBuffer(new Array(2)); + * // => false + */ +var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer; + +module.exports = isArrayBuffer; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArrayLike.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArrayLike.js new file mode 100644 index 000000000..0f9668056 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArrayLike.js @@ -0,0 +1,33 @@ +var isFunction = require('./isFunction'), + isLength = require('./isLength'); + +/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ +function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); +} + +module.exports = isArrayLike; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArrayLikeObject.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArrayLikeObject.js new file mode 100644 index 000000000..6c4812a8d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isArrayLikeObject.js @@ -0,0 +1,33 @@ +var isArrayLike = require('./isArrayLike'), + isObjectLike = require('./isObjectLike'); + +/** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ +function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); +} + +module.exports = isArrayLikeObject; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isBoolean.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isBoolean.js new file mode 100644 index 000000000..a43ed4b8f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isBoolean.js @@ -0,0 +1,29 @@ +var baseGetTag = require('./_baseGetTag'), + isObjectLike = require('./isObjectLike'); + +/** `Object#toString` result references. */ +var boolTag = '[object Boolean]'; + +/** + * Checks if `value` is classified as a boolean primitive or object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a boolean, else `false`. + * @example + * + * _.isBoolean(false); + * // => true + * + * _.isBoolean(null); + * // => false + */ +function isBoolean(value) { + return value === true || value === false || + (isObjectLike(value) && baseGetTag(value) == boolTag); +} + +module.exports = isBoolean; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isBuffer.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isBuffer.js new file mode 100644 index 000000000..c103cc74e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isBuffer.js @@ -0,0 +1,38 @@ +var root = require('./_root'), + stubFalse = require('./stubFalse'); + +/** Detect free variable `exports`. */ +var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Built-in value references. */ +var Buffer = moduleExports ? root.Buffer : undefined; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined; + +/** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ +var isBuffer = nativeIsBuffer || stubFalse; + +module.exports = isBuffer; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isDate.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isDate.js new file mode 100644 index 000000000..7f0209fca --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isDate.js @@ -0,0 +1,27 @@ +var baseIsDate = require('./_baseIsDate'), + baseUnary = require('./_baseUnary'), + nodeUtil = require('./_nodeUtil'); + +/* Node.js helper references. */ +var nodeIsDate = nodeUtil && nodeUtil.isDate; + +/** + * Checks if `value` is classified as a `Date` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + * @example + * + * _.isDate(new Date); + * // => true + * + * _.isDate('Mon April 23 2012'); + * // => false + */ +var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate; + +module.exports = isDate; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isElement.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isElement.js new file mode 100644 index 000000000..76ae29c3b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isElement.js @@ -0,0 +1,25 @@ +var isObjectLike = require('./isObjectLike'), + isPlainObject = require('./isPlainObject'); + +/** + * Checks if `value` is likely a DOM element. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. + * @example + * + * _.isElement(document.body); + * // => true + * + * _.isElement(''); + * // => false + */ +function isElement(value) { + return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value); +} + +module.exports = isElement; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isEmpty.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isEmpty.js new file mode 100644 index 000000000..3597294a4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isEmpty.js @@ -0,0 +1,77 @@ +var baseKeys = require('./_baseKeys'), + getTag = require('./_getTag'), + isArguments = require('./isArguments'), + isArray = require('./isArray'), + isArrayLike = require('./isArrayLike'), + isBuffer = require('./isBuffer'), + isPrototype = require('./_isPrototype'), + isTypedArray = require('./isTypedArray'); + +/** `Object#toString` result references. */ +var mapTag = '[object Map]', + setTag = '[object Set]'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Checks if `value` is an empty object, collection, map, or set. + * + * Objects are considered empty if they have no own enumerable string keyed + * properties. + * + * Array-like values such as `arguments` objects, arrays, buffers, strings, or + * jQuery-like collections are considered empty if they have a `length` of `0`. + * Similarly, maps and sets are considered empty if they have a `size` of `0`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. + * @example + * + * _.isEmpty(null); + * // => true + * + * _.isEmpty(true); + * // => true + * + * _.isEmpty(1); + * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false + */ +function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && + (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || + isBuffer(value) || isTypedArray(value) || isArguments(value))) { + return !value.length; + } + var tag = getTag(value); + if (tag == mapTag || tag == setTag) { + return !value.size; + } + if (isPrototype(value)) { + return !baseKeys(value).length; + } + for (var key in value) { + if (hasOwnProperty.call(value, key)) { + return false; + } + } + return true; +} + +module.exports = isEmpty; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isEqual.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isEqual.js new file mode 100644 index 000000000..5e23e76c9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isEqual.js @@ -0,0 +1,35 @@ +var baseIsEqual = require('./_baseIsEqual'); + +/** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are compared by strict equality, i.e. `===`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ +function isEqual(value, other) { + return baseIsEqual(value, other); +} + +module.exports = isEqual; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isEqualWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isEqualWith.js new file mode 100644 index 000000000..21bdc7ffe --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isEqualWith.js @@ -0,0 +1,41 @@ +var baseIsEqual = require('./_baseIsEqual'); + +/** + * This method is like `_.isEqual` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with up to + * six arguments: (objValue, othValue [, index|key, object, other, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, othValue) { + * if (isGreeting(objValue) && isGreeting(othValue)) { + * return true; + * } + * } + * + * var array = ['hello', 'goodbye']; + * var other = ['hi', 'goodbye']; + * + * _.isEqualWith(array, other, customizer); + * // => true + */ +function isEqualWith(value, other, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result; +} + +module.exports = isEqualWith; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isError.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isError.js new file mode 100644 index 000000000..b4f41e000 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isError.js @@ -0,0 +1,36 @@ +var baseGetTag = require('./_baseGetTag'), + isObjectLike = require('./isObjectLike'), + isPlainObject = require('./isPlainObject'); + +/** `Object#toString` result references. */ +var domExcTag = '[object DOMException]', + errorTag = '[object Error]'; + +/** + * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, + * `SyntaxError`, `TypeError`, or `URIError` object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an error object, else `false`. + * @example + * + * _.isError(new Error); + * // => true + * + * _.isError(Error); + * // => false + */ +function isError(value) { + if (!isObjectLike(value)) { + return false; + } + var tag = baseGetTag(value); + return tag == errorTag || tag == domExcTag || + (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value)); +} + +module.exports = isError; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isFinite.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isFinite.js new file mode 100644 index 000000000..601842bc4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isFinite.js @@ -0,0 +1,36 @@ +var root = require('./_root'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeIsFinite = root.isFinite; + +/** + * Checks if `value` is a finite primitive number. + * + * **Note:** This method is based on + * [`Number.isFinite`](https://mdn.io/Number/isFinite). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. + * @example + * + * _.isFinite(3); + * // => true + * + * _.isFinite(Number.MIN_VALUE); + * // => true + * + * _.isFinite(Infinity); + * // => false + * + * _.isFinite('3'); + * // => false + */ +function isFinite(value) { + return typeof value == 'number' && nativeIsFinite(value); +} + +module.exports = isFinite; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isFunction.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isFunction.js new file mode 100644 index 000000000..907a8cd8b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isFunction.js @@ -0,0 +1,37 @@ +var baseGetTag = require('./_baseGetTag'), + isObject = require('./isObject'); + +/** `Object#toString` result references. */ +var asyncTag = '[object AsyncFunction]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + proxyTag = '[object Proxy]'; + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + if (!isObject(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; +} + +module.exports = isFunction; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isInteger.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isInteger.js new file mode 100644 index 000000000..66aa87d57 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isInteger.js @@ -0,0 +1,33 @@ +var toInteger = require('./toInteger'); + +/** + * Checks if `value` is an integer. + * + * **Note:** This method is based on + * [`Number.isInteger`](https://mdn.io/Number/isInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an integer, else `false`. + * @example + * + * _.isInteger(3); + * // => true + * + * _.isInteger(Number.MIN_VALUE); + * // => false + * + * _.isInteger(Infinity); + * // => false + * + * _.isInteger('3'); + * // => false + */ +function isInteger(value) { + return typeof value == 'number' && value == toInteger(value); +} + +module.exports = isInteger; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isLength.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isLength.js new file mode 100644 index 000000000..3a95caa96 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isLength.js @@ -0,0 +1,35 @@ +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ +function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +module.exports = isLength; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isMap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isMap.js new file mode 100644 index 000000000..44f8517ee --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isMap.js @@ -0,0 +1,27 @@ +var baseIsMap = require('./_baseIsMap'), + baseUnary = require('./_baseUnary'), + nodeUtil = require('./_nodeUtil'); + +/* Node.js helper references. */ +var nodeIsMap = nodeUtil && nodeUtil.isMap; + +/** + * Checks if `value` is classified as a `Map` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + * @example + * + * _.isMap(new Map); + * // => true + * + * _.isMap(new WeakMap); + * // => false + */ +var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; + +module.exports = isMap; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isMatch.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isMatch.js new file mode 100644 index 000000000..9773a18cd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isMatch.js @@ -0,0 +1,36 @@ +var baseIsMatch = require('./_baseIsMatch'), + getMatchData = require('./_getMatchData'); + +/** + * Performs a partial deep comparison between `object` and `source` to + * determine if `object` contains equivalent property values. + * + * **Note:** This method is equivalent to `_.matches` when `source` is + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.isMatch(object, { 'b': 2 }); + * // => true + * + * _.isMatch(object, { 'b': 1 }); + * // => false + */ +function isMatch(object, source) { + return object === source || baseIsMatch(object, source, getMatchData(source)); +} + +module.exports = isMatch; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isMatchWith.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isMatchWith.js new file mode 100644 index 000000000..187b6a61d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isMatchWith.js @@ -0,0 +1,41 @@ +var baseIsMatch = require('./_baseIsMatch'), + getMatchData = require('./_getMatchData'); + +/** + * This method is like `_.isMatch` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with five + * arguments: (objValue, srcValue, index|key, object, source). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, srcValue) { + * if (isGreeting(objValue) && isGreeting(srcValue)) { + * return true; + * } + * } + * + * var object = { 'greeting': 'hello' }; + * var source = { 'greeting': 'hi' }; + * + * _.isMatchWith(object, source, customizer); + * // => true + */ +function isMatchWith(object, source, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseIsMatch(object, source, getMatchData(source), customizer); +} + +module.exports = isMatchWith; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNaN.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNaN.js new file mode 100644 index 000000000..7d0d783ba --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNaN.js @@ -0,0 +1,38 @@ +var isNumber = require('./isNumber'); + +/** + * Checks if `value` is `NaN`. + * + * **Note:** This method is based on + * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as + * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for + * `undefined` and other non-number values. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ +function isNaN(value) { + // An `NaN` primitive is the only value that is not equal to itself. + // Perform the `toStringTag` check first to avoid errors with some + // ActiveX objects in IE. + return isNumber(value) && value != +value; +} + +module.exports = isNaN; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNative.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNative.js new file mode 100644 index 000000000..f0cb8d580 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNative.js @@ -0,0 +1,40 @@ +var baseIsNative = require('./_baseIsNative'), + isMaskable = require('./_isMaskable'); + +/** Error message constants. */ +var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.'; + +/** + * Checks if `value` is a pristine native function. + * + * **Note:** This method can't reliably detect native functions in the presence + * of the core-js package because core-js circumvents this kind of detection. + * Despite multiple requests, the core-js maintainer has made it clear: any + * attempt to fix the detection will be obstructed. As a result, we're left + * with little choice but to throw an error. Unfortunately, this also affects + * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill), + * which rely on core-js. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + * @example + * + * _.isNative(Array.prototype.push); + * // => true + * + * _.isNative(_); + * // => false + */ +function isNative(value) { + if (isMaskable(value)) { + throw new Error(CORE_ERROR_TEXT); + } + return baseIsNative(value); +} + +module.exports = isNative; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNil.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNil.js new file mode 100644 index 000000000..79f05052c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNil.js @@ -0,0 +1,25 @@ +/** + * Checks if `value` is `null` or `undefined`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is nullish, else `false`. + * @example + * + * _.isNil(null); + * // => true + * + * _.isNil(void 0); + * // => true + * + * _.isNil(NaN); + * // => false + */ +function isNil(value) { + return value == null; +} + +module.exports = isNil; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNull.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNull.js new file mode 100644 index 000000000..c0a374d7d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNull.js @@ -0,0 +1,22 @@ +/** + * Checks if `value` is `null`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `null`, else `false`. + * @example + * + * _.isNull(null); + * // => true + * + * _.isNull(void 0); + * // => false + */ +function isNull(value) { + return value === null; +} + +module.exports = isNull; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNumber.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNumber.js new file mode 100644 index 000000000..cd34ee464 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isNumber.js @@ -0,0 +1,38 @@ +var baseGetTag = require('./_baseGetTag'), + isObjectLike = require('./isObjectLike'); + +/** `Object#toString` result references. */ +var numberTag = '[object Number]'; + +/** + * Checks if `value` is classified as a `Number` primitive or object. + * + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are + * classified as numbers, use the `_.isFinite` method. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a number, else `false`. + * @example + * + * _.isNumber(3); + * // => true + * + * _.isNumber(Number.MIN_VALUE); + * // => true + * + * _.isNumber(Infinity); + * // => true + * + * _.isNumber('3'); + * // => false + */ +function isNumber(value) { + return typeof value == 'number' || + (isObjectLike(value) && baseGetTag(value) == numberTag); +} + +module.exports = isNumber; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isObject.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isObject.js new file mode 100644 index 000000000..1dc893918 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isObject.js @@ -0,0 +1,31 @@ +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); +} + +module.exports = isObject; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isObjectLike.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isObjectLike.js new file mode 100644 index 000000000..301716b5a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isObjectLike.js @@ -0,0 +1,29 @@ +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return value != null && typeof value == 'object'; +} + +module.exports = isObjectLike; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isPlainObject.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isPlainObject.js new file mode 100644 index 000000000..238737313 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isPlainObject.js @@ -0,0 +1,62 @@ +var baseGetTag = require('./_baseGetTag'), + getPrototype = require('./_getPrototype'), + isObjectLike = require('./isObjectLike'); + +/** `Object#toString` result references. */ +var objectTag = '[object Object]'; + +/** Used for built-in method references. */ +var funcProto = Function.prototype, + objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Used to infer the `Object` constructor. */ +var objectCtorString = funcToString.call(Object); + +/** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * @static + * @memberOf _ + * @since 0.8.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ +function isPlainObject(value) { + if (!isObjectLike(value) || baseGetTag(value) != objectTag) { + return false; + } + var proto = getPrototype(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; + return typeof Ctor == 'function' && Ctor instanceof Ctor && + funcToString.call(Ctor) == objectCtorString; +} + +module.exports = isPlainObject; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isRegExp.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isRegExp.js new file mode 100644 index 000000000..76c9b6e9c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isRegExp.js @@ -0,0 +1,27 @@ +var baseIsRegExp = require('./_baseIsRegExp'), + baseUnary = require('./_baseUnary'), + nodeUtil = require('./_nodeUtil'); + +/* Node.js helper references. */ +var nodeIsRegExp = nodeUtil && nodeUtil.isRegExp; + +/** + * Checks if `value` is classified as a `RegExp` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + * @example + * + * _.isRegExp(/abc/); + * // => true + * + * _.isRegExp('/abc/'); + * // => false + */ +var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp; + +module.exports = isRegExp; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isSafeInteger.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isSafeInteger.js new file mode 100644 index 000000000..2a48526e1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isSafeInteger.js @@ -0,0 +1,37 @@ +var isInteger = require('./isInteger'); + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754 + * double precision number which isn't the result of a rounded unsafe integer. + * + * **Note:** This method is based on + * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`. + * @example + * + * _.isSafeInteger(3); + * // => true + * + * _.isSafeInteger(Number.MIN_VALUE); + * // => false + * + * _.isSafeInteger(Infinity); + * // => false + * + * _.isSafeInteger('3'); + * // => false + */ +function isSafeInteger(value) { + return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER; +} + +module.exports = isSafeInteger; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isSet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isSet.js new file mode 100644 index 000000000..ab88bdf81 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isSet.js @@ -0,0 +1,27 @@ +var baseIsSet = require('./_baseIsSet'), + baseUnary = require('./_baseUnary'), + nodeUtil = require('./_nodeUtil'); + +/* Node.js helper references. */ +var nodeIsSet = nodeUtil && nodeUtil.isSet; + +/** + * Checks if `value` is classified as a `Set` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + * @example + * + * _.isSet(new Set); + * // => true + * + * _.isSet(new WeakSet); + * // => false + */ +var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; + +module.exports = isSet; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isString.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isString.js new file mode 100644 index 000000000..627eb9c38 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isString.js @@ -0,0 +1,30 @@ +var baseGetTag = require('./_baseGetTag'), + isArray = require('./isArray'), + isObjectLike = require('./isObjectLike'); + +/** `Object#toString` result references. */ +var stringTag = '[object String]'; + +/** + * Checks if `value` is classified as a `String` primitive or object. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a string, else `false`. + * @example + * + * _.isString('abc'); + * // => true + * + * _.isString(1); + * // => false + */ +function isString(value) { + return typeof value == 'string' || + (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); +} + +module.exports = isString; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isSymbol.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isSymbol.js new file mode 100644 index 000000000..dfb60b97f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isSymbol.js @@ -0,0 +1,29 @@ +var baseGetTag = require('./_baseGetTag'), + isObjectLike = require('./isObjectLike'); + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && baseGetTag(value) == symbolTag); +} + +module.exports = isSymbol; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isTypedArray.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isTypedArray.js new file mode 100644 index 000000000..da3f8dd19 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isTypedArray.js @@ -0,0 +1,27 @@ +var baseIsTypedArray = require('./_baseIsTypedArray'), + baseUnary = require('./_baseUnary'), + nodeUtil = require('./_nodeUtil'); + +/* Node.js helper references. */ +var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + +/** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ +var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + +module.exports = isTypedArray; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isUndefined.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isUndefined.js new file mode 100644 index 000000000..377d121ab --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isUndefined.js @@ -0,0 +1,22 @@ +/** + * Checks if `value` is `undefined`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + * + * _.isUndefined(null); + * // => false + */ +function isUndefined(value) { + return value === undefined; +} + +module.exports = isUndefined; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isWeakMap.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isWeakMap.js new file mode 100644 index 000000000..8d36f6638 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isWeakMap.js @@ -0,0 +1,28 @@ +var getTag = require('./_getTag'), + isObjectLike = require('./isObjectLike'); + +/** `Object#toString` result references. */ +var weakMapTag = '[object WeakMap]'; + +/** + * Checks if `value` is classified as a `WeakMap` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak map, else `false`. + * @example + * + * _.isWeakMap(new WeakMap); + * // => true + * + * _.isWeakMap(new Map); + * // => false + */ +function isWeakMap(value) { + return isObjectLike(value) && getTag(value) == weakMapTag; +} + +module.exports = isWeakMap; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isWeakSet.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isWeakSet.js new file mode 100644 index 000000000..e628b261c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/isWeakSet.js @@ -0,0 +1,28 @@ +var baseGetTag = require('./_baseGetTag'), + isObjectLike = require('./isObjectLike'); + +/** `Object#toString` result references. */ +var weakSetTag = '[object WeakSet]'; + +/** + * Checks if `value` is classified as a `WeakSet` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak set, else `false`. + * @example + * + * _.isWeakSet(new WeakSet); + * // => true + * + * _.isWeakSet(new Set); + * // => false + */ +function isWeakSet(value) { + return isObjectLike(value) && baseGetTag(value) == weakSetTag; +} + +module.exports = isWeakSet; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/iteratee.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/iteratee.js new file mode 100644 index 000000000..61b73a8c0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/iteratee.js @@ -0,0 +1,53 @@ +var baseClone = require('./_baseClone'), + baseIteratee = require('./_baseIteratee'); + +/** Used to compose bitmasks for cloning. */ +var CLONE_DEEP_FLAG = 1; + +/** + * Creates a function that invokes `func` with the arguments of the created + * function. If `func` is a property name, the created function returns the + * property value for a given element. If `func` is an array or object, the + * created function returns `true` for elements that contain the equivalent + * source properties, otherwise it returns `false`. + * + * @static + * @since 4.0.0 + * @memberOf _ + * @category Util + * @param {*} [func=_.identity] The value to convert to a callback. + * @returns {Function} Returns the callback. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true })); + * // => [{ 'user': 'barney', 'age': 36, 'active': true }] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.filter(users, _.iteratee(['user', 'fred'])); + * // => [{ 'user': 'fred', 'age': 40 }] + * + * // The `_.property` iteratee shorthand. + * _.map(users, _.iteratee('user')); + * // => ['barney', 'fred'] + * + * // Create custom iteratee shorthands. + * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) { + * return !_.isRegExp(func) ? iteratee(func) : function(string) { + * return func.test(string); + * }; + * }); + * + * _.filter(['abc', 'def'], /ef/); + * // => ['def'] + */ +function iteratee(func) { + return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG)); +} + +module.exports = iteratee; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/join.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/join.js new file mode 100644 index 000000000..45de079ff --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/join.js @@ -0,0 +1,26 @@ +/** Used for built-in method references. */ +var arrayProto = Array.prototype; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeJoin = arrayProto.join; + +/** + * Converts all elements in `array` into a string separated by `separator`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to convert. + * @param {string} [separator=','] The element separator. + * @returns {string} Returns the joined string. + * @example + * + * _.join(['a', 'b', 'c'], '~'); + * // => 'a~b~c' + */ +function join(array, separator) { + return array == null ? '' : nativeJoin.call(array, separator); +} + +module.exports = join; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/kebabCase.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/kebabCase.js new file mode 100644 index 000000000..8a52be645 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/kebabCase.js @@ -0,0 +1,28 @@ +var createCompounder = require('./_createCompounder'); + +/** + * Converts `string` to + * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the kebab cased string. + * @example + * + * _.kebabCase('Foo Bar'); + * // => 'foo-bar' + * + * _.kebabCase('fooBar'); + * // => 'foo-bar' + * + * _.kebabCase('__FOO_BAR__'); + * // => 'foo-bar' + */ +var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? '-' : '') + word.toLowerCase(); +}); + +module.exports = kebabCase; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/keyBy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/keyBy.js new file mode 100644 index 000000000..acc007a0a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/keyBy.js @@ -0,0 +1,36 @@ +var baseAssignValue = require('./_baseAssignValue'), + createAggregator = require('./_createAggregator'); + +/** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the last element responsible for generating the key. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * var array = [ + * { 'dir': 'left', 'code': 97 }, + * { 'dir': 'right', 'code': 100 } + * ]; + * + * _.keyBy(array, function(o) { + * return String.fromCharCode(o.code); + * }); + * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } + * + * _.keyBy(array, 'dir'); + * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } + */ +var keyBy = createAggregator(function(result, value, key) { + baseAssignValue(result, key, value); +}); + +module.exports = keyBy; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/keys.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/keys.js new file mode 100644 index 000000000..d143c7186 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/keys.js @@ -0,0 +1,37 @@ +var arrayLikeKeys = require('./_arrayLikeKeys'), + baseKeys = require('./_baseKeys'), + isArrayLike = require('./isArrayLike'); + +/** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ +function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); +} + +module.exports = keys; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/keysIn.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/keysIn.js new file mode 100644 index 000000000..a62308f2c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/keysIn.js @@ -0,0 +1,32 @@ +var arrayLikeKeys = require('./_arrayLikeKeys'), + baseKeysIn = require('./_baseKeysIn'), + isArrayLike = require('./isArrayLike'); + +/** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ +function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); +} + +module.exports = keysIn; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lang.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lang.js new file mode 100644 index 000000000..a3962169a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lang.js @@ -0,0 +1,58 @@ +module.exports = { + 'castArray': require('./castArray'), + 'clone': require('./clone'), + 'cloneDeep': require('./cloneDeep'), + 'cloneDeepWith': require('./cloneDeepWith'), + 'cloneWith': require('./cloneWith'), + 'conformsTo': require('./conformsTo'), + 'eq': require('./eq'), + 'gt': require('./gt'), + 'gte': require('./gte'), + 'isArguments': require('./isArguments'), + 'isArray': require('./isArray'), + 'isArrayBuffer': require('./isArrayBuffer'), + 'isArrayLike': require('./isArrayLike'), + 'isArrayLikeObject': require('./isArrayLikeObject'), + 'isBoolean': require('./isBoolean'), + 'isBuffer': require('./isBuffer'), + 'isDate': require('./isDate'), + 'isElement': require('./isElement'), + 'isEmpty': require('./isEmpty'), + 'isEqual': require('./isEqual'), + 'isEqualWith': require('./isEqualWith'), + 'isError': require('./isError'), + 'isFinite': require('./isFinite'), + 'isFunction': require('./isFunction'), + 'isInteger': require('./isInteger'), + 'isLength': require('./isLength'), + 'isMap': require('./isMap'), + 'isMatch': require('./isMatch'), + 'isMatchWith': require('./isMatchWith'), + 'isNaN': require('./isNaN'), + 'isNative': require('./isNative'), + 'isNil': require('./isNil'), + 'isNull': require('./isNull'), + 'isNumber': require('./isNumber'), + 'isObject': require('./isObject'), + 'isObjectLike': require('./isObjectLike'), + 'isPlainObject': require('./isPlainObject'), + 'isRegExp': require('./isRegExp'), + 'isSafeInteger': require('./isSafeInteger'), + 'isSet': require('./isSet'), + 'isString': require('./isString'), + 'isSymbol': require('./isSymbol'), + 'isTypedArray': require('./isTypedArray'), + 'isUndefined': require('./isUndefined'), + 'isWeakMap': require('./isWeakMap'), + 'isWeakSet': require('./isWeakSet'), + 'lt': require('./lt'), + 'lte': require('./lte'), + 'toArray': require('./toArray'), + 'toFinite': require('./toFinite'), + 'toInteger': require('./toInteger'), + 'toLength': require('./toLength'), + 'toNumber': require('./toNumber'), + 'toPlainObject': require('./toPlainObject'), + 'toSafeInteger': require('./toSafeInteger'), + 'toString': require('./toString') +}; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/last.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/last.js new file mode 100644 index 000000000..cad1eafaf --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/last.js @@ -0,0 +1,20 @@ +/** + * Gets the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the last element of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + */ +function last(array) { + var length = array == null ? 0 : array.length; + return length ? array[length - 1] : undefined; +} + +module.exports = last; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lastIndexOf.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lastIndexOf.js new file mode 100644 index 000000000..dabfb613a --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lastIndexOf.js @@ -0,0 +1,46 @@ +var baseFindIndex = require('./_baseFindIndex'), + baseIsNaN = require('./_baseIsNaN'), + strictLastIndexOf = require('./_strictLastIndexOf'), + toInteger = require('./toInteger'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max, + nativeMin = Math.min; + +/** + * This method is like `_.indexOf` except that it iterates over elements of + * `array` from right to left. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.lastIndexOf([1, 2, 1, 2], 2); + * // => 3 + * + * // Search from the `fromIndex`. + * _.lastIndexOf([1, 2, 1, 2], 2, 2); + * // => 1 + */ +function lastIndexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = length; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); + } + return value === value + ? strictLastIndexOf(array, value, index) + : baseFindIndex(array, baseIsNaN, index, true); +} + +module.exports = lastIndexOf; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lodash.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lodash.js new file mode 100644 index 000000000..4131e936c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/lodash/lodash.js @@ -0,0 +1,17209 @@ +/** + * @license + * Lodash + * Copyright OpenJS Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ +;(function() { + + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ + var undefined; + + /** Used as the semantic version number. */ + var VERSION = '4.17.21'; + + /** Used as the size to enable large array optimizations. */ + var LARGE_ARRAY_SIZE = 200; + + /** Error message constants. */ + var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.', + FUNC_ERROR_TEXT = 'Expected a function', + INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`'; + + /** Used to stand-in for `undefined` hash values. */ + var HASH_UNDEFINED = '__lodash_hash_undefined__'; + + /** Used as the maximum memoize cache size. */ + var MAX_MEMOIZE_SIZE = 500; + + /** Used as the internal argument placeholder. */ + var PLACEHOLDER = '__lodash_placeholder__'; + + /** Used to compose bitmasks for cloning. */ + var CLONE_DEEP_FLAG = 1, + CLONE_FLAT_FLAG = 2, + CLONE_SYMBOLS_FLAG = 4; + + /** Used to compose bitmasks for value comparisons. */ + var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + + /** Used to compose bitmasks for function metadata. */ + var WRAP_BIND_FLAG = 1, + WRAP_BIND_KEY_FLAG = 2, + WRAP_CURRY_BOUND_FLAG = 4, + WRAP_CURRY_FLAG = 8, + WRAP_CURRY_RIGHT_FLAG = 16, + WRAP_PARTIAL_FLAG = 32, + WRAP_PARTIAL_RIGHT_FLAG = 64, + WRAP_ARY_FLAG = 128, + WRAP_REARG_FLAG = 256, + WRAP_FLIP_FLAG = 512; + + /** Used as default options for `_.truncate`. */ + var DEFAULT_TRUNC_LENGTH = 30, + DEFAULT_TRUNC_OMISSION = '...'; + + /** Used to detect hot functions by number of calls within a span of milliseconds. */ + var HOT_COUNT = 800, + HOT_SPAN = 16; + + /** Used to indicate the type of lazy iteratees. */ + var LAZY_FILTER_FLAG = 1, + LAZY_MAP_FLAG = 2, + LAZY_WHILE_FLAG = 3; + + /** Used as references for various `Number` constants. */ + var INFINITY = 1 / 0, + MAX_SAFE_INTEGER = 9007199254740991, + MAX_INTEGER = 1.7976931348623157e+308, + NAN = 0 / 0; + + /** Used as references for the maximum length and index of an array. */ + var MAX_ARRAY_LENGTH = 4294967295, + MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, + HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + + /** Used to associate wrap methods with their bit flags. */ + var wrapFlags = [ + ['ary', WRAP_ARY_FLAG], + ['bind', WRAP_BIND_FLAG], + ['bindKey', WRAP_BIND_KEY_FLAG], + ['curry', WRAP_CURRY_FLAG], + ['curryRight', WRAP_CURRY_RIGHT_FLAG], + ['flip', WRAP_FLIP_FLAG], + ['partial', WRAP_PARTIAL_FLAG], + ['partialRight', WRAP_PARTIAL_RIGHT_FLAG], + ['rearg', WRAP_REARG_FLAG] + ]; + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + asyncTag = '[object AsyncFunction]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + domExcTag = '[object DOMException]', + errorTag = '[object Error]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + mapTag = '[object Map]', + numberTag = '[object Number]', + nullTag = '[object Null]', + objectTag = '[object Object]', + promiseTag = '[object Promise]', + proxyTag = '[object Proxy]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]', + undefinedTag = '[object Undefined]', + weakMapTag = '[object WeakMap]', + weakSetTag = '[object WeakSet]'; + + var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + + /** Used to match empty string literals in compiled template source. */ + var reEmptyStringLeading = /\b__p \+= '';/g, + reEmptyStringMiddle = /\b(__p \+=) '' \+/g, + reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + + /** Used to match HTML entities and HTML characters. */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, + reUnescapedHtml = /[&<>"']/g, + reHasEscapedHtml = RegExp(reEscapedHtml.source), + reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + + /** Used to match template delimiters. */ + var reEscape = /<%-([\s\S]+?)%>/g, + reEvaluate = /<%([\s\S]+?)%>/g, + reInterpolate = /<%=([\s\S]+?)%>/g; + + /** Used to match property names within property paths. */ + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/, + rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + + /** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ + var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, + reHasRegExpChar = RegExp(reRegExpChar.source); + + /** Used to match leading whitespace. */ + var reTrimStart = /^\s+/; + + /** Used to match a single whitespace character. */ + var reWhitespace = /\s/; + + /** Used to match wrap detail comments. */ + var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, + reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, + reSplitDetails = /,? & /; + + /** Used to match words composed of alphanumeric characters. */ + var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; + + /** + * Used to validate the `validate` option in `_.template` variable. + * + * Forbids characters which could potentially change the meaning of the function argument definition: + * - "()," (modification of function parameters) + * - "=" (default value) + * - "[]{}" (destructuring of function parameters) + * - "/" (beginning of a comment) + * - whitespace + */ + var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/; + + /** Used to match backslashes in property paths. */ + var reEscapeChar = /\\(\\)?/g; + + /** + * Used to match + * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components). + */ + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + + /** Used to match `RegExp` flags from their coerced string values. */ + var reFlags = /\w*$/; + + /** Used to detect bad signed hexadecimal string values. */ + var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; + + /** Used to detect binary string values. */ + var reIsBinary = /^0b[01]+$/i; + + /** Used to detect host constructors (Safari). */ + var reIsHostCtor = /^\[object .+?Constructor\]$/; + + /** Used to detect octal string values. */ + var reIsOctal = /^0o[0-7]+$/i; + + /** Used to detect unsigned integer values. */ + var reIsUint = /^(?:0|[1-9]\d*)$/; + + /** Used to match Latin Unicode letters (excluding mathematical operators). */ + var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; + + /** Used to ensure capturing order of template delimiters. */ + var reNoMatch = /($^)/; + + /** Used to match unescaped characters in compiled string literals. */ + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + + /** Used to compose unicode character classes. */ + var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f', + reComboHalfMarksRange = '\\ufe20-\\ufe2f', + rsComboSymbolsRange = '\\u20d0-\\u20ff', + rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, + rsDingbatRange = '\\u2700-\\u27bf', + rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', + rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', + rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', + rsPunctuationRange = '\\u2000-\\u206f', + rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', + rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', + rsVarRange = '\\ufe0e\\ufe0f', + rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; + + /** Used to compose unicode capture groups. */ + var rsApos = "['\u2019]", + rsAstral = '[' + rsAstralRange + ']', + rsBreak = '[' + rsBreakRange + ']', + rsCombo = '[' + rsComboRange + ']', + rsDigits = '\\d+', + rsDingbat = '[' + rsDingbatRange + ']', + rsLower = '[' + rsLowerRange + ']', + rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsUpper = '[' + rsUpperRange + ']', + rsZWJ = '\\u200d'; + + /** Used to compose unicode regexes. */ + var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')', + rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')', + rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', + rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', + reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])', + rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq, + rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + + /** Used to match apostrophes. */ + var reApos = RegExp(rsApos, 'g'); + + /** + * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and + * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). + */ + var reComboMark = RegExp(rsCombo, 'g'); + + /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ + var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); + + /** Used to match complex or compound words. */ + var reUnicodeWord = RegExp([ + rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', + rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')', + rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower, + rsUpper + '+' + rsOptContrUpper, + rsOrdUpper, + rsOrdLower, + rsDigits, + rsEmoji + ].join('|'), 'g'); + + /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ + var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); + + /** Used to detect strings that need a more robust regexp to match words. */ + var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + + /** Used to assign default `context` object properties. */ + var contextProps = [ + 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array', + 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object', + 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', + '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout' + ]; + + /** Used to make template sourceURLs easier to identify. */ + var templateCounter = -1; + + /** Used to identify `toStringTag` values of typed arrays. */ + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = + typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = + typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = + typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = + typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = + typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = + typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = + typedArrayTags[errorTag] = typedArrayTags[funcTag] = + typedArrayTags[mapTag] = typedArrayTags[numberTag] = + typedArrayTags[objectTag] = typedArrayTags[regexpTag] = + typedArrayTags[setTag] = typedArrayTags[stringTag] = + typedArrayTags[weakMapTag] = false; + + /** Used to identify `toStringTag` values supported by `_.clone`. */ + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = + cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = + cloneableTags[boolTag] = cloneableTags[dateTag] = + cloneableTags[float32Tag] = cloneableTags[float64Tag] = + cloneableTags[int8Tag] = cloneableTags[int16Tag] = + cloneableTags[int32Tag] = cloneableTags[mapTag] = + cloneableTags[numberTag] = cloneableTags[objectTag] = + cloneableTags[regexpTag] = cloneableTags[setTag] = + cloneableTags[stringTag] = cloneableTags[symbolTag] = + cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = + cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = + cloneableTags[weakMapTag] = false; + + /** Used to map Latin Unicode letters to basic Latin letters. */ + var deburredLetters = { + // Latin-1 Supplement block. + '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', + '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', + '\xc7': 'C', '\xe7': 'c', + '\xd0': 'D', '\xf0': 'd', + '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', + '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', + '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', + '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', + '\xd1': 'N', '\xf1': 'n', + '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', + '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', + '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', + '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', + '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', + '\xc6': 'Ae', '\xe6': 'ae', + '\xde': 'Th', '\xfe': 'th', + '\xdf': 'ss', + // Latin Extended-A block. + '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', + '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', + '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', + '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', + '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', + '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', + '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', + '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', + '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', + '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', + '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', + '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', + '\u0134': 'J', '\u0135': 'j', + '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', + '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', + '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', + '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', + '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', + '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', + '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', + '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', + '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', + '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', + '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', + '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', + '\u0163': 't', '\u0165': 't', '\u0167': 't', + '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', + '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', + '\u0174': 'W', '\u0175': 'w', + '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', + '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', + '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', + '\u0132': 'IJ', '\u0133': 'ij', + '\u0152': 'Oe', '\u0153': 'oe', + '\u0149': "'n", '\u017f': 's' + }; + + /** Used to map characters to HTML entities. */ + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + /** Used to map HTML entities to characters. */ + var htmlUnescapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + ''': "'" + }; + + /** Used to escape characters for inclusion in compiled string literals. */ + var stringEscapes = { + '\\': '\\', + "'": "'", + '\n': 'n', + '\r': 'r', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + /** Built-in method references without a dependency on `root`. */ + var freeParseFloat = parseFloat, + freeParseInt = parseInt; + + /** Detect free variable `global` from Node.js. */ + var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + + /** Detect free variable `self`. */ + var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + + /** Used as a reference to the global object. */ + var root = freeGlobal || freeSelf || Function('return this')(); + + /** Detect free variable `exports`. */ + var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + + /** Detect free variable `module`. */ + var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports; + + /** Detect free variable `process` from Node.js. */ + var freeProcess = moduleExports && freeGlobal.process; + + /** Used to access faster Node.js helpers. */ + var nodeUtil = (function() { + try { + // Use `util.types` for Node.js 10+. + var types = freeModule && freeModule.require && freeModule.require('util').types; + + if (types) { + return types; + } + + // Legacy `process.binding('util')` for Node.js < 10. + return freeProcess && freeProcess.binding && freeProcess.binding('util'); + } catch (e) {} + }()); + + /* Node.js helper references. */ + var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, + nodeIsDate = nodeUtil && nodeUtil.isDate, + nodeIsMap = nodeUtil && nodeUtil.isMap, + nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, + nodeIsSet = nodeUtil && nodeUtil.isSet, + nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + + /*--------------------------------------------------------------------------*/ + + /** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ + function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); + } + + /** + * A specialized version of `baseAggregator` for arrays. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ + function arrayAggregator(array, setter, iteratee, accumulator) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + var value = array[index]; + setter(accumulator, value, iteratee(value), array); + } + return accumulator; + } + + /** + * A specialized version of `_.forEach` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEach(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + + /** + * A specialized version of `_.forEachRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ + function arrayEachRight(array, iteratee) { + var length = array == null ? 0 : array.length; + + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + + /** + * A specialized version of `_.every` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + */ + function arrayEvery(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + + /** + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function arrayFilter(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; + } + + /** + * A specialized version of `_.includes` for arrays without support for + * specifying an index to search from. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ + function arrayIncludes(array, value) { + var length = array == null ? 0 : array.length; + return !!length && baseIndexOf(array, value, 0) > -1; + } + + /** + * This function is like `arrayIncludes` except that it accepts a comparator. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @param {Function} comparator The comparator invoked per element. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ + function arrayIncludesWith(array, value, comparator) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (comparator(value, array[index])) { + return true; + } + } + return false; + } + + /** + * A specialized version of `_.map` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function arrayMap(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + + /** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ + function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + + /** + * A specialized version of `_.reduce` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the first element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduce(array, iteratee, accumulator, initAccum) { + var index = -1, + length = array == null ? 0 : array.length; + + if (initAccum && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + + /** + * A specialized version of `_.reduceRight` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initAccum] Specify using the last element of `array` as + * the initial value. + * @returns {*} Returns the accumulated value. + */ + function arrayReduceRight(array, iteratee, accumulator, initAccum) { + var length = array == null ? 0 : array.length; + if (initAccum && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + + /** + * A specialized version of `_.some` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function arraySome(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + + /** + * Gets the size of an ASCII `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + var asciiSize = baseProperty('length'); + + /** + * Converts an ASCII `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function asciiToArray(string) { + return string.split(''); + } + + /** + * Splits an ASCII `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function asciiWords(string) { + return string.match(reAsciiWord) || []; + } + + /** + * The base implementation of methods like `_.findKey` and `_.findLastKey`, + * without support for iteratee shorthands, which iterates over `collection` + * using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the found element or its key, else `undefined`. + */ + function baseFindKey(collection, predicate, eachFunc) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = key; + return false; + } + }); + return result; + } + + /** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.indexOf` without `fromIndex` bounds checks. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOf(array, value, fromIndex) { + return value === value + ? strictIndexOf(array, value, fromIndex) + : baseFindIndex(array, baseIsNaN, fromIndex); + } + + /** + * This function is like `baseIndexOf` except that it accepts a comparator. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @param {Function} comparator The comparator invoked per element. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function baseIndexOfWith(array, value, fromIndex, comparator) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (comparator(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * The base implementation of `_.isNaN` without support for number objects. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + */ + function baseIsNaN(value) { + return value !== value; + } + + /** + * The base implementation of `_.mean` and `_.meanBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the mean. + */ + function baseMean(array, iteratee) { + var length = array == null ? 0 : array.length; + return length ? (baseSum(array, iteratee) / length) : NAN; + } + + /** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.propertyOf` without support for deep paths. + * + * @private + * @param {Object} object The object to query. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyOf(object) { + return function(key) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.reduce` and `_.reduceRight`, without support + * for iteratee shorthands, which iterates over `collection` using `eachFunc`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} accumulator The initial value. + * @param {boolean} initAccum Specify using the first or last element of + * `collection` as the initial value. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the accumulated value. + */ + function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initAccum + ? (initAccum = false, value) + : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.sortBy` which uses `comparer` to define the + * sort order of `array` and replaces criteria objects with their corresponding + * values. + * + * @private + * @param {Array} array The array to sort. + * @param {Function} comparer The function to define sort order. + * @returns {Array} Returns `array`. + */ + function baseSortBy(array, comparer) { + var length = array.length; + + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + + /** + * The base implementation of `_.sum` and `_.sumBy` without support for + * iteratee shorthands. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {number} Returns the sum. + */ + function baseSum(array, iteratee) { + var result, + index = -1, + length = array.length; + + while (++index < length) { + var current = iteratee(array[index]); + if (current !== undefined) { + result = result === undefined ? current : (result + current); + } + } + return result; + } + + /** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ + function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; + } + + /** + * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array + * of key-value pairs for `object` corresponding to the property names of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the key-value pairs. + */ + function baseToPairs(object, props) { + return arrayMap(props, function(key) { + return [key, object[key]]; + }); + } + + /** + * The base implementation of `_.trim`. + * + * @private + * @param {string} string The string to trim. + * @returns {string} Returns the trimmed string. + */ + function baseTrim(string) { + return string + ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') + : string; + } + + /** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ + function baseUnary(func) { + return function(value) { + return func(value); + }; + } + + /** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values corresponding to the property names + * of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the array of property values. + */ + function baseValues(object, props) { + return arrayMap(props, function(key) { + return object[key]; + }); + } + + /** + * Checks if a `cache` value for `key` exists. + * + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function cacheHas(cache, key) { + return cache.has(key); + } + + /** + * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the first unmatched string symbol. + */ + function charsStartIndex(strSymbols, chrSymbols) { + var index = -1, + length = strSymbols.length; + + while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; + } + + /** + * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol + * that is not found in the character symbols. + * + * @private + * @param {Array} strSymbols The string symbols to inspect. + * @param {Array} chrSymbols The character symbols to find. + * @returns {number} Returns the index of the last unmatched string symbol. + */ + function charsEndIndex(strSymbols, chrSymbols) { + var index = strSymbols.length; + + while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} + return index; + } + + /** + * Gets the number of `placeholder` occurrences in `array`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} placeholder The placeholder to search for. + * @returns {number} Returns the placeholder count. + */ + function countHolders(array, placeholder) { + var length = array.length, + result = 0; + + while (length--) { + if (array[length] === placeholder) { + ++result; + } + } + return result; + } + + /** + * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A + * letters to basic Latin letters. + * + * @private + * @param {string} letter The matched letter to deburr. + * @returns {string} Returns the deburred letter. + */ + var deburrLetter = basePropertyOf(deburredLetters); + + /** + * Used by `_.escape` to convert characters to HTML entities. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + var escapeHtmlChar = basePropertyOf(htmlEscapes); + + /** + * Used by `_.template` to escape characters for inclusion in compiled string literals. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + function escapeStringChar(chr) { + return '\\' + stringEscapes[chr]; + } + + /** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function getValue(object, key) { + return object == null ? undefined : object[key]; + } + + /** + * Checks if `string` contains Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a symbol is found, else `false`. + */ + function hasUnicode(string) { + return reHasUnicode.test(string); + } + + /** + * Checks if `string` contains a word composed of Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a word is found, else `false`. + */ + function hasUnicodeWord(string) { + return reHasUnicodeWord.test(string); + } + + /** + * Converts `iterator` to an array. + * + * @private + * @param {Object} iterator The iterator to convert. + * @returns {Array} Returns the converted array. + */ + function iteratorToArray(iterator) { + var data, + result = []; + + while (!(data = iterator.next()).done) { + result.push(data.value); + } + return result; + } + + /** + * Converts `map` to its key-value pairs. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. + */ + function mapToArray(map) { + var index = -1, + result = Array(map.size); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; + } + + /** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ + function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; + } + + /** + * Replaces all `placeholder` elements in `array` with an internal placeholder + * and returns an array of their indexes. + * + * @private + * @param {Array} array The array to modify. + * @param {*} placeholder The placeholder to replace. + * @returns {Array} Returns the new array of placeholder indexes. + */ + function replaceHolders(array, placeholder) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value === placeholder || value === PLACEHOLDER) { + array[index] = PLACEHOLDER; + result[resIndex++] = index; + } + } + return result; + } + + /** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ + function setToArray(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; + } + + /** + * Converts `set` to its value-value pairs. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the value-value pairs. + */ + function setToPairs(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = [value, value]; + }); + return result; + } + + /** + * A specialized version of `_.indexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictIndexOf(array, value, fromIndex) { + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * A specialized version of `_.lastIndexOf` which performs strict equality + * comparisons of values, i.e. `===`. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function strictLastIndexOf(array, value, fromIndex) { + var index = fromIndex + 1; + while (index--) { + if (array[index] === value) { + return index; + } + } + return index; + } + + /** + * Gets the number of symbols in `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the string size. + */ + function stringSize(string) { + return hasUnicode(string) + ? unicodeSize(string) + : asciiSize(string); + } + + /** + * Converts `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function stringToArray(string) { + return hasUnicode(string) + ? unicodeToArray(string) + : asciiToArray(string); + } + + /** + * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace + * character of `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the last non-whitespace character. + */ + function trimmedEndIndex(string) { + var index = string.length; + + while (index-- && reWhitespace.test(string.charAt(index))) {} + return index; + } + + /** + * Used by `_.unescape` to convert HTML entities to characters. + * + * @private + * @param {string} chr The matched character to unescape. + * @returns {string} Returns the unescaped character. + */ + var unescapeHtmlChar = basePropertyOf(htmlUnescapes); + + /** + * Gets the size of a Unicode `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + function unicodeSize(string) { + var result = reUnicode.lastIndex = 0; + while (reUnicode.test(string)) { + ++result; + } + return result; + } + + /** + * Converts a Unicode `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function unicodeToArray(string) { + return string.match(reUnicode) || []; + } + + /** + * Splits a Unicode `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function unicodeWords(string) { + return string.match(reUnicodeWord) || []; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Create a new pristine `lodash` function using the `context` object. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Util + * @param {Object} [context=root] The context object. + * @returns {Function} Returns a new `lodash` function. + * @example + * + * _.mixin({ 'foo': _.constant('foo') }); + * + * var lodash = _.runInContext(); + * lodash.mixin({ 'bar': lodash.constant('bar') }); + * + * _.isFunction(_.foo); + * // => true + * _.isFunction(_.bar); + * // => false + * + * lodash.isFunction(lodash.foo); + * // => false + * lodash.isFunction(lodash.bar); + * // => true + * + * // Create a suped-up `defer` in Node.js. + * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; + */ + var runInContext = (function runInContext(context) { + context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps)); + + /** Built-in constructor references. */ + var Array = context.Array, + Date = context.Date, + Error = context.Error, + Function = context.Function, + Math = context.Math, + Object = context.Object, + RegExp = context.RegExp, + String = context.String, + TypeError = context.TypeError; + + /** Used for built-in method references. */ + var arrayProto = Array.prototype, + funcProto = Function.prototype, + objectProto = Object.prototype; + + /** Used to detect overreaching core-js shims. */ + var coreJsData = context['__core-js_shared__']; + + /** Used to resolve the decompiled source of functions. */ + var funcToString = funcProto.toString; + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to generate unique IDs. */ + var idCounter = 0; + + /** Used to detect methods masquerading as native. */ + var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; + }()); + + /** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ + var nativeObjectToString = objectProto.toString; + + /** Used to infer the `Object` constructor. */ + var objectCtorString = funcToString.call(Object); + + /** Used to restore the original `_` reference in `_.noConflict`. */ + var oldDash = root._; + + /** Used to detect if a method is native. */ + var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' + ); + + /** Built-in value references. */ + var Buffer = moduleExports ? context.Buffer : undefined, + Symbol = context.Symbol, + Uint8Array = context.Uint8Array, + allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined, + getPrototype = overArg(Object.getPrototypeOf, Object), + objectCreate = Object.create, + propertyIsEnumerable = objectProto.propertyIsEnumerable, + splice = arrayProto.splice, + spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined, + symIterator = Symbol ? Symbol.iterator : undefined, + symToStringTag = Symbol ? Symbol.toStringTag : undefined; + + var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} + }()); + + /** Mocked built-ins. */ + var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, + ctxNow = Date && Date.now !== root.Date.now && Date.now, + ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout; + + /* Built-in method references for those with the same name as other `lodash` methods. */ + var nativeCeil = Math.ceil, + nativeFloor = Math.floor, + nativeGetSymbols = Object.getOwnPropertySymbols, + nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, + nativeIsFinite = context.isFinite, + nativeJoin = arrayProto.join, + nativeKeys = overArg(Object.keys, Object), + nativeMax = Math.max, + nativeMin = Math.min, + nativeNow = Date.now, + nativeParseInt = context.parseInt, + nativeRandom = Math.random, + nativeReverse = arrayProto.reverse; + + /* Built-in method references that are verified to be native. */ + var DataView = getNative(context, 'DataView'), + Map = getNative(context, 'Map'), + Promise = getNative(context, 'Promise'), + Set = getNative(context, 'Set'), + WeakMap = getNative(context, 'WeakMap'), + nativeCreate = getNative(Object, 'create'); + + /** Used to store function metadata. */ + var metaMap = WeakMap && new WeakMap; + + /** Used to lookup unminified function names. */ + var realNames = {}; + + /** Used to detect maps, sets, and weakmaps. */ + var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map), + promiseCtorString = toSource(Promise), + setCtorString = toSource(Set), + weakMapCtorString = toSource(WeakMap); + + /** Used to convert symbols to primitives and strings. */ + var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` object which wraps `value` to enable implicit method + * chain sequences. Methods that operate on and return arrays, collections, + * and functions can be chained together. Methods that retrieve a single value + * or may return a primitive value will automatically end the chain sequence + * and return the unwrapped value. Otherwise, the value must be unwrapped + * with `_#value`. + * + * Explicit chain sequences, which must be unwrapped with `_#value`, may be + * enabled using `_.chain`. + * + * The execution of chained methods is lazy, that is, it's deferred until + * `_#value` is implicitly or explicitly called. + * + * Lazy evaluation allows several methods to support shortcut fusion. + * Shortcut fusion is an optimization to merge iteratee calls; this avoids + * the creation of intermediate arrays and can greatly reduce the number of + * iteratee executions. Sections of a chain sequence qualify for shortcut + * fusion if the section is applied to an array and iteratees accept only + * one argument. The heuristic for whether a section qualifies for shortcut + * fusion is subject to change. + * + * Chaining is supported in custom builds as long as the `_#value` method is + * directly or indirectly included in the build. + * + * In addition to lodash methods, wrappers have `Array` and `String` methods. + * + * The wrapper `Array` methods are: + * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` + * + * The wrapper `String` methods are: + * `replace` and `split` + * + * The wrapper methods that support shortcut fusion are: + * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, + * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, + * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` + * + * The chainable wrapper methods are: + * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, + * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, + * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, + * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, + * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, + * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, + * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, + * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, + * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, + * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, + * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, + * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, + * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, + * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, + * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, + * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, + * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, + * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, + * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, + * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, + * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, + * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, + * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, + * `zipObject`, `zipObjectDeep`, and `zipWith` + * + * The wrapper methods that are **not** chainable by default are: + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, + * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, + * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, + * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, + * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, + * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, + * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, + * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, + * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, + * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, + * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, + * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, + * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, + * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, + * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, + * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, + * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, + * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, + * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, + * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, + * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, + * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, + * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, + * `upperFirst`, `value`, and `words` + * + * @name _ + * @constructor + * @category Seq + * @param {*} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2, 3]); + * + * // Returns an unwrapped value. + * wrapped.reduce(_.add); + * // => 6 + * + * // Returns a wrapped value. + * var squares = wrapped.map(square); + * + * _.isArray(squares); + * // => false + * + * _.isArray(squares.value()); + * // => true + */ + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, '__wrapped__')) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + + /** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ + var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; + }()); + + /** + * The function whose prototype chain sequence wrappers inherit from. + * + * @private + */ + function baseLodash() { + // No operation performed. + } + + /** + * The base constructor for creating `lodash` wrapper objects. + * + * @private + * @param {*} value The value to wrap. + * @param {boolean} [chainAll] Enable explicit method chain sequences. + */ + function LodashWrapper(value, chainAll) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__chain__ = !!chainAll; + this.__index__ = 0; + this.__values__ = undefined; + } + + /** + * By default, the template delimiters used by lodash are like those in + * embedded Ruby (ERB) as well as ES2015 template strings. Change the + * following template settings to use alternative delimiters. + * + * @static + * @memberOf _ + * @type {Object} + */ + lodash.templateSettings = { + + /** + * Used to detect `data` property values to be HTML-escaped. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'escape': reEscape, + + /** + * Used to detect code to be evaluated. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'evaluate': reEvaluate, + + /** + * Used to detect `data` property values to inject. + * + * @memberOf _.templateSettings + * @type {RegExp} + */ + 'interpolate': reInterpolate, + + /** + * Used to reference the data object in the template text. + * + * @memberOf _.templateSettings + * @type {string} + */ + 'variable': '', + + /** + * Used to import variables into the compiled template. + * + * @memberOf _.templateSettings + * @type {Object} + */ + 'imports': { + + /** + * A reference to the `lodash` function. + * + * @memberOf _.templateSettings.imports + * @type {Function} + */ + '_': lodash + } + }; + + // Ensure wrappers are instances of `baseLodash`. + lodash.prototype = baseLodash.prototype; + lodash.prototype.constructor = lodash; + + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. + * + * @private + * @constructor + * @param {*} value The value to wrap. + */ + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = MAX_ARRAY_LENGTH; + this.__views__ = []; + } + + /** + * Creates a clone of the lazy wrapper object. + * + * @private + * @name clone + * @memberOf LazyWrapper + * @returns {Object} Returns the cloned `LazyWrapper` object. + */ + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = copyArray(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = copyArray(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = copyArray(this.__views__); + return result; + } + + /** + * Reverses the direction of lazy iteration. + * + * @private + * @name reverse + * @memberOf LazyWrapper + * @returns {Object} Returns the new reversed `LazyWrapper` object. + */ + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + + /** + * Extracts the unwrapped value from its lazy wrapper. + * + * @private + * @name value + * @memberOf LazyWrapper + * @returns {*} Returns the unwrapped value. + */ + function lazyValue() { + var array = this.__wrapped__.value(), + dir = this.__dir__, + isArr = isArray(array), + isRight = dir < 0, + arrLength = isArr ? array.length : 0, + view = getView(0, arrLength, this.__views__), + start = view.start, + end = view.end, + length = end - start, + index = isRight ? end : (start - 1), + iteratees = this.__iteratees__, + iterLength = iteratees.length, + resIndex = 0, + takeCount = nativeMin(length, this.__takeCount__); + + if (!isArr || (!isRight && arrLength == length && takeCount == length)) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + + outer: + while (length-- && resIndex < takeCount) { + index += dir; + + var iterIndex = -1, + value = array[index]; + + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], + iteratee = data.iteratee, + type = data.type, + computed = iteratee(value); + + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + + // Ensure `LazyWrapper` is an instance of `baseLodash`. + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Hash(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ + function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; + } + + /** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; + } + + /** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; + } + + /** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function hashHas(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); + } + + /** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ + function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; + } + + // Add methods to `Hash`. + Hash.prototype.clear = hashClear; + Hash.prototype['delete'] = hashDelete; + Hash.prototype.get = hashGet; + Hash.prototype.has = hashHas; + Hash.prototype.set = hashSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ + function listCacheClear() { + this.__data__ = []; + this.size = 0; + } + + /** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; + } + + /** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; + } + + /** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; + } + + /** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ + function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; + } + + // Add methods to `ListCache`. + ListCache.prototype.clear = listCacheClear; + ListCache.prototype['delete'] = listCacheDelete; + ListCache.prototype.get = listCacheGet; + ListCache.prototype.has = listCacheHas; + ListCache.prototype.set = listCacheSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function MapCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } + } + + /** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ + function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; + } + + /** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; + } + + /** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function mapCacheGet(key) { + return getMapData(this, key).get(key); + } + + /** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function mapCacheHas(key) { + return getMapData(this, key).has(key); + } + + /** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ + function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; + } + + // Add methods to `MapCache`. + MapCache.prototype.clear = mapCacheClear; + MapCache.prototype['delete'] = mapCacheDelete; + MapCache.prototype.get = mapCacheGet; + MapCache.prototype.has = mapCacheHas; + MapCache.prototype.set = mapCacheSet; + + /*------------------------------------------------------------------------*/ + + /** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ + function SetCache(values) { + var index = -1, + length = values == null ? 0 : values.length; + + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } + } + + /** + * Adds `value` to the array cache. + * + * @private + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. + */ + function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; + } + + /** + * Checks if `value` is in the array cache. + * + * @private + * @name has + * @memberOf SetCache + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. + */ + function setCacheHas(value) { + return this.__data__.has(value); + } + + // Add methods to `SetCache`. + SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; + SetCache.prototype.has = setCacheHas; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ + function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; + } + + /** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ + function stackClear() { + this.__data__ = new ListCache; + this.size = 0; + } + + /** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ + function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; + } + + /** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ + function stackGet(key) { + return this.__data__.get(key); + } + + /** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function stackHas(key) { + return this.__data__.has(key); + } + + /** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ + function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; + } + + // Add methods to `Stack`. + Stack.prototype.clear = stackClear; + Stack.prototype['delete'] = stackDelete; + Stack.prototype.get = stackGet; + Stack.prototype.has = stackHas; + Stack.prototype.set = stackSet; + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ + function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; + } + + /** + * A specialized version of `_.sample` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @returns {*} Returns the random element. + */ + function arraySample(array) { + var length = array.length; + return length ? array[baseRandom(0, length - 1)] : undefined; + } + + /** + * A specialized version of `_.sampleSize` for arrays. + * + * @private + * @param {Array} array The array to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function arraySampleSize(array, n) { + return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length)); + } + + /** + * A specialized version of `_.shuffle` for arrays. + * + * @private + * @param {Array} array The array to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function arrayShuffle(array) { + return shuffleSelf(copyArray(array)); + } + + /** + * This function is like `assignValue` except that it doesn't assign + * `undefined` values. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignMergeValue(object, key, value) { + if ((value !== undefined && !eq(object[key], value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } + } + + /** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ + function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; + } + + /** + * Aggregates elements of `collection` on `accumulator` with keys transformed + * by `iteratee` and values set by `setter`. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform keys. + * @param {Object} accumulator The initial aggregated object. + * @returns {Function} Returns `accumulator`. + */ + function baseAggregator(collection, setter, iteratee, accumulator) { + baseEach(collection, function(value, key, collection) { + setter(accumulator, value, iteratee(value), collection); + }); + return accumulator; + } + + /** + * The base implementation of `_.assign` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ + function baseAssign(object, source) { + return object && copyObject(source, keys(source), object); + } + + /** + * The base implementation of `_.assignIn` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ + function baseAssignIn(object, source) { + return object && copyObject(source, keysIn(source), object); + } + + /** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ + function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } + } + + /** + * The base implementation of `_.at` without support for individual paths. + * + * @private + * @param {Object} object The object to iterate over. + * @param {string[]} paths The property paths to pick. + * @returns {Array} Returns the picked elements. + */ + function baseAt(object, paths) { + var index = -1, + length = paths.length, + result = Array(length), + skip = object == null; + + while (++index < length) { + result[index] = skip ? undefined : get(object, paths[index]); + } + return result; + } + + /** + * The base implementation of `_.clamp` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + */ + function baseClamp(number, lower, upper) { + if (number === number) { + if (upper !== undefined) { + number = number <= upper ? number : upper; + } + if (lower !== undefined) { + number = number >= lower ? number : lower; + } + } + return number; + } + + /** + * The base implementation of `_.clone` and `_.cloneDeep` which tracks + * traversed objects. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} bitmask The bitmask flags. + * 1 - Deep clone + * 2 - Flatten inherited properties + * 4 - Clone symbols + * @param {Function} [customizer] The function to customize cloning. + * @param {string} [key] The key of `value`. + * @param {Object} [object] The parent object of `value`. + * @param {Object} [stack] Tracks traversed objects and their clone counterparts. + * @returns {*} Returns the cloned value. + */ + function baseClone(value, bitmask, customizer, key, object, stack) { + var result, + isDeep = bitmask & CLONE_DEEP_FLAG, + isFlat = bitmask & CLONE_FLAT_FLAG, + isFull = bitmask & CLONE_SYMBOLS_FLAG; + + if (customizer) { + result = object ? customizer(value, key, object, stack) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return copyArray(value, result); + } + } else { + var tag = getTag(value), + isFunc = tag == funcTag || tag == genTag; + + if (isBuffer(value)) { + return cloneBuffer(value, isDeep); + } + if (tag == objectTag || tag == argsTag || (isFunc && !object)) { + result = (isFlat || isFunc) ? {} : initCloneObject(value); + if (!isDeep) { + return isFlat + ? copySymbolsIn(value, baseAssignIn(result, value)) + : copySymbols(value, baseAssign(result, value)); + } + } else { + if (!cloneableTags[tag]) { + return object ? value : {}; + } + result = initCloneByTag(value, tag, isDeep); + } + } + // Check for circular references and return its corresponding clone. + stack || (stack = new Stack); + var stacked = stack.get(value); + if (stacked) { + return stacked; + } + stack.set(value, result); + + if (isSet(value)) { + value.forEach(function(subValue) { + result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack)); + }); + } else if (isMap(value)) { + value.forEach(function(subValue, key) { + result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + } + + var keysFunc = isFull + ? (isFlat ? getAllKeysIn : getAllKeys) + : (isFlat ? keysIn : keys); + + var props = isArr ? undefined : keysFunc(value); + arrayEach(props || value, function(subValue, key) { + if (props) { + key = subValue; + subValue = value[key]; + } + // Recursively populate clone (susceptible to call stack limits). + assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + return result; + } + + /** + * The base implementation of `_.conforms` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property predicates to conform to. + * @returns {Function} Returns the new spec function. + */ + function baseConforms(source) { + var props = keys(source); + return function(object) { + return baseConformsTo(object, source, props); + }; + } + + /** + * The base implementation of `_.conformsTo` which accepts `props` to check. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + */ + function baseConformsTo(object, source, props) { + var length = props.length; + if (object == null) { + return !length; + } + object = Object(object); + while (length--) { + var key = props[length], + predicate = source[key], + value = object[key]; + + if ((value === undefined && !(key in object)) || !predicate(value)) { + return false; + } + } + return true; + } + + /** + * The base implementation of `_.delay` and `_.defer` which accepts `args` + * to provide to `func`. + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {Array} args The arguments to provide to `func`. + * @returns {number|Object} Returns the timer id or timeout object. + */ + function baseDelay(func, wait, args) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { func.apply(undefined, args); }, wait); + } + + /** + * The base implementation of methods like `_.difference` without support + * for excluding multiple arrays or iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Array} values The values to exclude. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + */ + function baseDifference(array, values, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + isCommon = true, + length = array.length, + result = [], + valuesLength = values.length; + + if (!length) { + return result; + } + if (iteratee) { + values = arrayMap(values, baseUnary(iteratee)); + } + if (comparator) { + includes = arrayIncludesWith; + isCommon = false; + } + else if (values.length >= LARGE_ARRAY_SIZE) { + includes = cacheHas; + isCommon = false; + values = new SetCache(values); + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee == null ? value : iteratee(value); + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === computed) { + continue outer; + } + } + result.push(value); + } + else if (!includes(values, computed, comparator)) { + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.forEach` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEach = createBaseEach(baseForOwn); + + /** + * The base implementation of `_.forEachRight` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ + var baseEachRight = createBaseEach(baseForOwnRight, true); + + /** + * The base implementation of `_.every` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false` + */ + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + + /** + * The base implementation of methods like `_.max` and `_.min` which accepts a + * `comparator` to determine the extremum value. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The iteratee invoked per iteration. + * @param {Function} comparator The comparator used to compare values. + * @returns {*} Returns the extremum value. + */ + function baseExtremum(array, iteratee, comparator) { + var index = -1, + length = array.length; + + while (++index < length) { + var value = array[index], + current = iteratee(value); + + if (current != null && (computed === undefined + ? (current === current && !isSymbol(current)) + : comparator(current, computed) + )) { + var computed = current, + result = value; + } + } + return result; + } + + /** + * The base implementation of `_.fill` without an iteratee call guard. + * + * @private + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + */ + function baseFill(array, value, start, end) { + var length = array.length; + + start = toInteger(start); + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = (end === undefined || end > length) ? length : toInteger(end); + if (end < 0) { + end += length; + } + end = start > end ? 0 : toLength(end); + while (start < end) { + array[start++] = value; + } + return array; + } + + /** + * The base implementation of `_.filter` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + + /** + * The base implementation of `_.flatten` with support for restricting flattening. + * + * @private + * @param {Array} array The array to flatten. + * @param {number} depth The maximum recursion depth. + * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. + * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. + * @param {Array} [result=[]] The initial result value. + * @returns {Array} Returns the new flattened array. + */ + function baseFlatten(array, depth, predicate, isStrict, result) { + var index = -1, + length = array.length; + + predicate || (predicate = isFlattenable); + result || (result = []); + + while (++index < length) { + var value = array[index]; + if (depth > 0 && predicate(value)) { + if (depth > 1) { + // Recursively flatten arrays (susceptible to call stack limits). + baseFlatten(value, depth - 1, predicate, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + + /** + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseFor = createBaseFor(); + + /** + * This function is like `baseFor` except that it iterates over properties + * in the opposite order. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + var baseForRight = createBaseFor(true); + + /** + * The base implementation of `_.forOwn` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwn(object, iteratee) { + return object && baseFor(object, iteratee, keys); + } + + /** + * The base implementation of `_.forOwnRight` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwnRight(object, iteratee) { + return object && baseForRight(object, iteratee, keys); + } + + /** + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from `props`. + * + * @private + * @param {Object} object The object to inspect. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the function names. + */ + function baseFunctions(object, props) { + return arrayFilter(props, function(key) { + return isFunction(object[key]); + }); + } + + /** + * The base implementation of `_.get` without support for default values. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @returns {*} Returns the resolved value. + */ + function baseGet(object, path) { + path = castPath(path, object); + + var index = 0, + length = path.length; + + while (object != null && index < length) { + object = object[toKey(path[index++])]; + } + return (index && index == length) ? object : undefined; + } + + /** + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. + */ + function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); + } + + /** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); + } + + /** + * The base implementation of `_.gt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + */ + function baseGt(value, other) { + return value > other; + } + + /** + * The base implementation of `_.has` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ + function baseHas(object, key) { + return object != null && hasOwnProperty.call(object, key); + } + + /** + * The base implementation of `_.hasIn` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ + function baseHasIn(object, key) { + return object != null && key in Object(object); + } + + /** + * The base implementation of `_.inRange` which doesn't coerce arguments. + * + * @private + * @param {number} number The number to check. + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + */ + function baseInRange(number, start, end) { + return number >= nativeMin(start, end) && number < nativeMax(start, end); + } + + /** + * The base implementation of methods like `_.intersection`, without support + * for iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of shared values. + */ + function baseIntersection(arrays, iteratee, comparator) { + var includes = comparator ? arrayIncludesWith : arrayIncludes, + length = arrays[0].length, + othLength = arrays.length, + othIndex = othLength, + caches = Array(othLength), + maxLength = Infinity, + result = []; + + while (othIndex--) { + var array = arrays[othIndex]; + if (othIndex && iteratee) { + array = arrayMap(array, baseUnary(iteratee)); + } + maxLength = nativeMin(array.length, maxLength); + caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120)) + ? new SetCache(othIndex && array) + : undefined; + } + array = arrays[0]; + + var index = -1, + seen = caches[0]; + + outer: + while (++index < length && result.length < maxLength) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (!(seen + ? cacheHas(seen, computed) + : includes(result, computed, comparator) + )) { + othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if (!(cache + ? cacheHas(cache, computed) + : includes(arrays[othIndex], computed, comparator)) + ) { + continue outer; + } + } + if (seen) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.invert` and `_.invertBy` which inverts + * `object` with values transformed by `iteratee` and set by `setter`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} setter The function to set `accumulator` values. + * @param {Function} iteratee The iteratee to transform values. + * @param {Object} accumulator The initial inverted object. + * @returns {Function} Returns `accumulator`. + */ + function baseInverter(object, setter, iteratee, accumulator) { + baseForOwn(object, function(value, key, object) { + setter(accumulator, iteratee(value), key, object); + }); + return accumulator; + } + + /** + * The base implementation of `_.invoke` without support for individual + * method arguments. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {Array} args The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + */ + function baseInvoke(object, path, args) { + path = castPath(path, object); + object = parent(object, path); + var func = object == null ? object : object[toKey(last(path))]; + return func == null ? undefined : apply(func, object, args); + } + + /** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ + function baseIsArguments(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; + } + + /** + * The base implementation of `_.isArrayBuffer` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + */ + function baseIsArrayBuffer(value) { + return isObjectLike(value) && baseGetTag(value) == arrayBufferTag; + } + + /** + * The base implementation of `_.isDate` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + */ + function baseIsDate(value) { + return isObjectLike(value) && baseGetTag(value) == dateTag; + } + + /** + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {boolean} bitmask The bitmask flags. + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Function} [customizer] The function to customize comparisons. + * @param {Object} [stack] Tracks traversed `value` and `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ + function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); + } + + /** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = objIsArr ? arrayTag : getTag(object), + othTag = othIsArr ? arrayTag : getTag(other); + + objTag = objTag == argsTag ? objectTag : objTag; + othTag = othTag == argsTag ? objectTag : othTag; + + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, + isSameTag = objTag == othTag; + + if (isSameTag && isBuffer(object)) { + if (!isBuffer(other)) { + return false; + } + objIsArr = true; + objIsObj = false; + } + if (isSameTag && !objIsObj) { + stack || (stack = new Stack); + return (objIsArr || isTypedArray(object)) + ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) + : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); + } + if (!(bitmask & COMPARE_PARTIAL_FLAG)) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + stack || (stack = new Stack); + return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack); + return equalObjects(object, other, bitmask, customizer, equalFunc, stack); + } + + /** + * The base implementation of `_.isMap` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + */ + function baseIsMap(value) { + return isObjectLike(value) && getTag(value) == mapTag; + } + + /** + * The base implementation of `_.isMatch` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Array} matchData The property names, values, and compare flags to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + */ + function baseIsMatch(object, source, matchData, customizer) { + var index = matchData.length, + length = index, + noCustomizer = !customizer; + + if (object == null) { + return !length; + } + object = Object(object); + while (index--) { + var data = matchData[index]; + if ((noCustomizer && data[2]) + ? data[1] !== object[data[0]] + : !(data[0] in object) + ) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], + objValue = object[key], + srcValue = data[1]; + + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var stack = new Stack; + if (customizer) { + var result = customizer(objValue, srcValue, key, object, source, stack); + } + if (!(result === undefined + ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) + : result + )) { + return false; + } + } + } + return true; + } + + /** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ + function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); + } + + /** + * The base implementation of `_.isRegExp` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + */ + function baseIsRegExp(value) { + return isObjectLike(value) && baseGetTag(value) == regexpTag; + } + + /** + * The base implementation of `_.isSet` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + */ + function baseIsSet(value) { + return isObjectLike(value) && getTag(value) == setTag; + } + + /** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ + function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; + } + + /** + * The base implementation of `_.iteratee`. + * + * @private + * @param {*} [value=_.identity] The value to convert to an iteratee. + * @returns {Function} Returns the iteratee. + */ + function baseIteratee(value) { + // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. + // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. + if (typeof value == 'function') { + return value; + } + if (value == null) { + return identity; + } + if (typeof value == 'object') { + return isArray(value) + ? baseMatchesProperty(value[0], value[1]) + : baseMatches(value); + } + return property(value); + } + + /** + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; + } + + /** + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function baseKeysIn(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + + /** + * The base implementation of `_.lt` which doesn't coerce arguments. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + */ + function baseLt(value, other) { + return value < other; + } + + /** + * The base implementation of `_.map` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function baseMap(collection, iteratee) { + var index = -1, + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + + /** + * The base implementation of `_.matches` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + return matchesStrictComparable(matchData[0][0], matchData[0][1]); + } + return function(object) { + return object === source || baseIsMatch(object, source, matchData); + }; + } + + /** + * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. + * + * @private + * @param {string} path The path of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ + function baseMatchesProperty(path, srcValue) { + if (isKey(path) && isStrictComparable(srcValue)) { + return matchesStrictComparable(toKey(path), srcValue); + } + return function(object) { + var objValue = get(object, path); + return (objValue === undefined && objValue === srcValue) + ? hasIn(object, path) + : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG); + }; + } + + /** + * The base implementation of `_.merge` without support for multiple sources. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {number} srcIndex The index of `source`. + * @param {Function} [customizer] The function to customize merged values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + baseFor(source, function(srcValue, key) { + stack || (stack = new Stack); + if (isObject(srcValue)) { + baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); + } + else { + var newValue = customizer + ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack) + : undefined; + + if (newValue === undefined) { + newValue = srcValue; + } + assignMergeValue(object, key, newValue); + } + }, keysIn); + } + + /** + * A specialized version of `baseMerge` for arrays and objects which performs + * deep merges and tracks traversed objects enabling objects with circular + * references to be merged. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {string} key The key of the value to merge. + * @param {number} srcIndex The index of `source`. + * @param {Function} mergeFunc The function to merge values. + * @param {Function} [customizer] The function to customize assigned values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ + function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { + var objValue = safeGet(object, key), + srcValue = safeGet(source, key), + stacked = stack.get(srcValue); + + if (stacked) { + assignMergeValue(object, key, stacked); + return; + } + var newValue = customizer + ? customizer(objValue, srcValue, (key + ''), object, source, stack) + : undefined; + + var isCommon = newValue === undefined; + + if (isCommon) { + var isArr = isArray(srcValue), + isBuff = !isArr && isBuffer(srcValue), + isTyped = !isArr && !isBuff && isTypedArray(srcValue); + + newValue = srcValue; + if (isArr || isBuff || isTyped) { + if (isArray(objValue)) { + newValue = objValue; + } + else if (isArrayLikeObject(objValue)) { + newValue = copyArray(objValue); + } + else if (isBuff) { + isCommon = false; + newValue = cloneBuffer(srcValue, true); + } + else if (isTyped) { + isCommon = false; + newValue = cloneTypedArray(srcValue, true); + } + else { + newValue = []; + } + } + else if (isPlainObject(srcValue) || isArguments(srcValue)) { + newValue = objValue; + if (isArguments(objValue)) { + newValue = toPlainObject(objValue); + } + else if (!isObject(objValue) || isFunction(objValue)) { + newValue = initCloneObject(srcValue); + } + } + else { + isCommon = false; + } + } + if (isCommon) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, newValue); + mergeFunc(newValue, srcValue, srcIndex, customizer, stack); + stack['delete'](srcValue); + } + assignMergeValue(object, key, newValue); + } + + /** + * The base implementation of `_.nth` which doesn't coerce arguments. + * + * @private + * @param {Array} array The array to query. + * @param {number} n The index of the element to return. + * @returns {*} Returns the nth element of `array`. + */ + function baseNth(array, n) { + var length = array.length; + if (!length) { + return; + } + n += n < 0 ? length : 0; + return isIndex(n, length) ? array[n] : undefined; + } + + /** + * The base implementation of `_.orderBy` without param guards. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. + * @param {string[]} orders The sort orders of `iteratees`. + * @returns {Array} Returns the new sorted array. + */ + function baseOrderBy(collection, iteratees, orders) { + if (iteratees.length) { + iteratees = arrayMap(iteratees, function(iteratee) { + if (isArray(iteratee)) { + return function(value) { + return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee); + } + } + return iteratee; + }); + } else { + iteratees = [identity]; + } + + var index = -1; + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); + + var result = baseMap(collection, function(value, key, collection) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { 'criteria': criteria, 'index': ++index, 'value': value }; + }); + + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + + /** + * The base implementation of `_.pick` without support for individual + * property identifiers. + * + * @private + * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. + * @returns {Object} Returns the new object. + */ + function basePick(object, paths) { + return basePickBy(object, paths, function(value, path) { + return hasIn(object, path); + }); + } + + /** + * The base implementation of `_.pickBy` without support for iteratee shorthands. + * + * @private + * @param {Object} object The source object. + * @param {string[]} paths The property paths to pick. + * @param {Function} predicate The function invoked per property. + * @returns {Object} Returns the new object. + */ + function basePickBy(object, paths, predicate) { + var index = -1, + length = paths.length, + result = {}; + + while (++index < length) { + var path = paths[index], + value = baseGet(object, path); + + if (predicate(value, path)) { + baseSet(result, castPath(path, object), value); + } + } + return result; + } + + /** + * A specialized version of `baseProperty` which supports deep paths. + * + * @private + * @param {Array|string} path The path of the property to get. + * @returns {Function} Returns the new accessor function. + */ + function basePropertyDeep(path) { + return function(object) { + return baseGet(object, path); + }; + } + + /** + * The base implementation of `_.pullAllBy` without support for iteratee + * shorthands. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + */ + function basePullAll(array, values, iteratee, comparator) { + var indexOf = comparator ? baseIndexOfWith : baseIndexOf, + index = -1, + length = values.length, + seen = array; + + if (array === values) { + values = copyArray(values); + } + if (iteratee) { + seen = arrayMap(array, baseUnary(iteratee)); + } + while (++index < length) { + var fromIndex = 0, + value = values[index], + computed = iteratee ? iteratee(value) : value; + + while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { + if (seen !== array) { + splice.call(seen, fromIndex, 1); + } + splice.call(array, fromIndex, 1); + } + } + return array; + } + + /** + * The base implementation of `_.pullAt` without support for individual + * indexes or capturing the removed elements. + * + * @private + * @param {Array} array The array to modify. + * @param {number[]} indexes The indexes of elements to remove. + * @returns {Array} Returns `array`. + */ + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0, + lastIndex = length - 1; + + while (length--) { + var index = indexes[length]; + if (length == lastIndex || index !== previous) { + var previous = index; + if (isIndex(index)) { + splice.call(array, index, 1); + } else { + baseUnset(array, index); + } + } + } + return array; + } + + /** + * The base implementation of `_.random` without support for returning + * floating-point numbers. + * + * @private + * @param {number} lower The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the random number. + */ + function baseRandom(lower, upper) { + return lower + nativeFloor(nativeRandom() * (upper - lower + 1)); + } + + /** + * The base implementation of `_.range` and `_.rangeRight` which doesn't + * coerce arguments. + * + * @private + * @param {number} start The start of the range. + * @param {number} end The end of the range. + * @param {number} step The value to increment or decrement by. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the range of numbers. + */ + function baseRange(start, end, step, fromRight) { + var index = -1, + length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), + result = Array(length); + + while (length--) { + result[fromRight ? length : ++index] = start; + start += step; + } + return result; + } + + /** + * The base implementation of `_.repeat` which doesn't coerce arguments. + * + * @private + * @param {string} string The string to repeat. + * @param {number} n The number of times to repeat the string. + * @returns {string} Returns the repeated string. + */ + function baseRepeat(string, n) { + var result = ''; + if (!string || n < 1 || n > MAX_SAFE_INTEGER) { + return result; + } + // Leverage the exponentiation by squaring algorithm for a faster repeat. + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + if (n) { + string += string; + } + } while (n); + + return result; + } + + /** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ + function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ''); + } + + /** + * The base implementation of `_.sample`. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + */ + function baseSample(collection) { + return arraySample(values(collection)); + } + + /** + * The base implementation of `_.sampleSize` without param guards. + * + * @private + * @param {Array|Object} collection The collection to sample. + * @param {number} n The number of elements to sample. + * @returns {Array} Returns the random elements. + */ + function baseSampleSize(collection, n) { + var array = values(collection); + return shuffleSelf(array, baseClamp(n, 0, array.length)); + } + + /** + * The base implementation of `_.set`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ + function baseSet(object, path, value, customizer) { + if (!isObject(object)) { + return object; + } + path = castPath(path, object); + + var index = -1, + length = path.length, + lastIndex = length - 1, + nested = object; + + while (nested != null && ++index < length) { + var key = toKey(path[index]), + newValue = value; + + if (key === '__proto__' || key === 'constructor' || key === 'prototype') { + return object; + } + + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : undefined; + if (newValue === undefined) { + newValue = isObject(objValue) + ? objValue + : (isIndex(path[index + 1]) ? [] : {}); + } + } + assignValue(nested, key, newValue); + nested = nested[key]; + } + return object; + } + + /** + * The base implementation of `setData` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + + /** + * The base implementation of `setToString` without support for hot loop shorting. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var baseSetToString = !defineProperty ? identity : function(func, string) { + return defineProperty(func, 'toString', { + 'configurable': true, + 'enumerable': false, + 'value': constant(string), + 'writable': true + }); + }; + + /** + * The base implementation of `_.shuffle`. + * + * @private + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + */ + function baseShuffle(collection) { + return shuffleSelf(values(collection)); + } + + /** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = end > length ? length : end; + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + + /** + * The base implementation of `_.some` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function baseSome(collection, predicate) { + var result; + + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + + /** + * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which + * performs a binary search of `array` to determine the index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function baseSortedIndex(array, value, retHighest) { + var low = 0, + high = array == null ? low : array.length; + + if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = (low + high) >>> 1, + computed = array[mid]; + + if (computed !== null && !isSymbol(computed) && + (retHighest ? (computed <= value) : (computed < value))) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return baseSortedIndexBy(array, value, identity, retHighest); + } + + /** + * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy` + * which invokes `iteratee` for `value` and each element of `array` to compute + * their sort ranking. The iteratee is invoked with one argument; (value). + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} iteratee The iteratee invoked per element. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function baseSortedIndexBy(array, value, iteratee, retHighest) { + var low = 0, + high = array == null ? 0 : array.length; + if (high === 0) { + return 0; + } + + value = iteratee(value); + var valIsNaN = value !== value, + valIsNull = value === null, + valIsSymbol = isSymbol(value), + valIsUndefined = value === undefined; + + while (low < high) { + var mid = nativeFloor((low + high) / 2), + computed = iteratee(array[mid]), + othIsDefined = computed !== undefined, + othIsNull = computed === null, + othIsReflexive = computed === computed, + othIsSymbol = isSymbol(computed); + + if (valIsNaN) { + var setLow = retHighest || othIsReflexive; + } else if (valIsUndefined) { + setLow = othIsReflexive && (retHighest || othIsDefined); + } else if (valIsNull) { + setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull); + } else if (valIsSymbol) { + setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol); + } else if (othIsNull || othIsSymbol) { + setLow = false; + } else { + setLow = retHighest ? (computed <= value) : (computed < value); + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + + /** + * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ + function baseSortedUniq(array, iteratee) { + var index = -1, + length = array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + if (!index || !eq(computed, seen)) { + var seen = computed; + result[resIndex++] = value === 0 ? 0 : value; + } + } + return result; + } + + /** + * The base implementation of `_.toNumber` which doesn't ensure correct + * conversions of binary, hexadecimal, or octal string values. + * + * @private + * @param {*} value The value to process. + * @returns {number} Returns the number. + */ + function baseToNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + return +value; + } + + /** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ + function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray(value)) { + // Recursively convert values (susceptible to call stack limits). + return arrayMap(value, baseToString) + ''; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * The base implementation of `_.uniqBy` without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ + function baseUniq(array, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + length = array.length, + isCommon = true, + result = [], + seen = result; + + if (comparator) { + isCommon = false; + includes = arrayIncludesWith; + } + else if (length >= LARGE_ARRAY_SIZE) { + var set = iteratee ? null : createSet(array); + if (set) { + return setToArray(set); + } + isCommon = false; + includes = cacheHas; + seen = new SetCache; + } + else { + seen = iteratee ? [] : result; + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } + else if (!includes(seen, computed, comparator)) { + if (seen !== result) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.unset`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The property path to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + */ + function baseUnset(object, path) { + path = castPath(path, object); + object = parent(object, path); + return object == null || delete object[toKey(last(path))]; + } + + /** + * The base implementation of `_.update`. + * + * @private + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to update. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize path creation. + * @returns {Object} Returns `object`. + */ + function baseUpdate(object, path, updater, customizer) { + return baseSet(object, path, updater(baseGet(object, path)), customizer); + } + + /** + * The base implementation of methods like `_.dropWhile` and `_.takeWhile` + * without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to query. + * @param {Function} predicate The function invoked per iteration. + * @param {boolean} [isDrop] Specify dropping elements instead of taking them. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Array} Returns the slice of `array`. + */ + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length) && + predicate(array[index], index, array)) {} + + return isDrop + ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length)) + : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index)); + } + + /** + * The base implementation of `wrapperValue` which returns the result of + * performing a sequence of actions on the unwrapped `value`, where each + * successive action is supplied the return value of the previous. + * + * @private + * @param {*} value The unwrapped value. + * @param {Array} actions Actions to perform to resolve the unwrapped value. + * @returns {*} Returns the resolved value. + */ + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + return arrayReduce(actions, function(result, action) { + return action.func.apply(action.thisArg, arrayPush([result], action.args)); + }, result); + } + + /** + * The base implementation of methods like `_.xor`, without support for + * iteratee shorthands, that accepts an array of arrays to inspect. + * + * @private + * @param {Array} arrays The arrays to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of values. + */ + function baseXor(arrays, iteratee, comparator) { + var length = arrays.length; + if (length < 2) { + return length ? baseUniq(arrays[0]) : []; + } + var index = -1, + result = Array(length); + + while (++index < length) { + var array = arrays[index], + othIndex = -1; + + while (++othIndex < length) { + if (othIndex != index) { + result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator); + } + } + } + return baseUniq(baseFlatten(result, 1), iteratee, comparator); + } + + /** + * This base implementation of `_.zipObject` which assigns values using `assignFunc`. + * + * @private + * @param {Array} props The property identifiers. + * @param {Array} values The property values. + * @param {Function} assignFunc The function to assign values. + * @returns {Object} Returns the new object. + */ + function baseZipObject(props, values, assignFunc) { + var index = -1, + length = props.length, + valsLength = values.length, + result = {}; + + while (++index < length) { + var value = index < valsLength ? values[index] : undefined; + assignFunc(result, props[index], value); + } + return result; + } + + /** + * Casts `value` to an empty array if it's not an array like object. + * + * @private + * @param {*} value The value to inspect. + * @returns {Array|Object} Returns the cast array-like object. + */ + function castArrayLikeObject(value) { + return isArrayLikeObject(value) ? value : []; + } + + /** + * Casts `value` to `identity` if it's not a function. + * + * @private + * @param {*} value The value to inspect. + * @returns {Function} Returns cast function. + */ + function castFunction(value) { + return typeof value == 'function' ? value : identity; + } + + /** + * Casts `value` to a path array if it's not one. + * + * @private + * @param {*} value The value to inspect. + * @param {Object} [object] The object to query keys on. + * @returns {Array} Returns the cast property path array. + */ + function castPath(value, object) { + if (isArray(value)) { + return value; + } + return isKey(value, object) ? [value] : stringToPath(toString(value)); + } + + /** + * A `baseRest` alias which can be replaced with `identity` by module + * replacement plugins. + * + * @private + * @type {Function} + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + var castRest = baseRest; + + /** + * Casts `array` to a slice if it's needed. + * + * @private + * @param {Array} array The array to inspect. + * @param {number} start The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the cast slice. + */ + function castSlice(array, start, end) { + var length = array.length; + end = end === undefined ? length : end; + return (!start && end >= length) ? array : baseSlice(array, start, end); + } + + /** + * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout). + * + * @private + * @param {number|Object} id The timer id or timeout object of the timer to clear. + */ + var clearTimeout = ctxClearTimeout || function(id) { + return root.clearTimeout(id); + }; + + /** + * Creates a clone of `buffer`. + * + * @private + * @param {Buffer} buffer The buffer to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Buffer} Returns the cloned buffer. + */ + function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; + } + + /** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(arrayBuffer)); + return result; + } + + /** + * Creates a clone of `dataView`. + * + * @private + * @param {Object} dataView The data view to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned data view. + */ + function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); + } + + /** + * Creates a clone of `regexp`. + * + * @private + * @param {Object} regexp The regexp to clone. + * @returns {Object} Returns the cloned regexp. + */ + function cloneRegExp(regexp) { + var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); + result.lastIndex = regexp.lastIndex; + return result; + } + + /** + * Creates a clone of the `symbol` object. + * + * @private + * @param {Object} symbol The symbol object to clone. + * @returns {Object} Returns the cloned symbol object. + */ + function cloneSymbol(symbol) { + return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; + } + + /** + * Creates a clone of `typedArray`. + * + * @private + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. + */ + function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); + } + + /** + * Compares values to sort them in ascending order. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {number} Returns the sort order indicator for `value`. + */ + function compareAscending(value, other) { + if (value !== other) { + var valIsDefined = value !== undefined, + valIsNull = value === null, + valIsReflexive = value === value, + valIsSymbol = isSymbol(value); + + var othIsDefined = other !== undefined, + othIsNull = other === null, + othIsReflexive = other === other, + othIsSymbol = isSymbol(other); + + if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || + (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || + (valIsNull && othIsDefined && othIsReflexive) || + (!valIsDefined && othIsReflexive) || + !valIsReflexive) { + return 1; + } + if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || + (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || + (othIsNull && valIsDefined && valIsReflexive) || + (!othIsDefined && valIsReflexive) || + !othIsReflexive) { + return -1; + } + } + return 0; + } + + /** + * Used by `_.orderBy` to compare multiple properties of a value to another + * and stable sort them. + * + * If `orders` is unspecified, all values are sorted in ascending order. Otherwise, + * specify an order of "desc" for descending or "asc" for ascending sort order + * of corresponding values. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {boolean[]|string[]} orders The order to sort by for each property. + * @returns {number} Returns the sort order indicator for `object`. + */ + function compareMultiple(object, other, orders) { + var index = -1, + objCriteria = object.criteria, + othCriteria = other.criteria, + length = objCriteria.length, + ordersLength = orders.length; + + while (++index < length) { + var result = compareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order == 'desc' ? -1 : 1); + } + } + // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications + // that causes it, under certain circumstances, to provide the same value for + // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 + // for more details. + // + // This also ensures a stable sort in V8 and other engines. + // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details. + return object.index - other.index; + } + + /** + * Creates an array that is the composition of partially applied arguments, + * placeholders, and provided arguments into a single array of arguments. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to prepend to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgs(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersLength = holders.length, + leftIndex = -1, + leftLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(leftLength + rangeLength), + isUncurried = !isCurried; + + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + } + while (rangeLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + + /** + * This function is like `composeArgs` except that the arguments composition + * is tailored for `_.partialRight`. + * + * @private + * @param {Array} args The provided arguments. + * @param {Array} partials The arguments to append to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @params {boolean} [isCurried] Specify composing for a curried function. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgsRight(args, partials, holders, isCurried) { + var argsIndex = -1, + argsLength = args.length, + holdersIndex = -1, + holdersLength = holders.length, + rightIndex = -1, + rightLength = partials.length, + rangeLength = nativeMax(argsLength - holdersLength, 0), + result = Array(rangeLength + rightLength), + isUncurried = !isCurried; + + while (++argsIndex < rangeLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + if (isUncurried || argsIndex < argsLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + } + return result; + } + + /** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ + function copyArray(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + + /** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ + function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; + } + + /** + * Copies own symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ + function copySymbols(source, object) { + return copyObject(source, getSymbols(source), object); + } + + /** + * Copies own and inherited symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ + function copySymbolsIn(source, object) { + return copyObject(source, getSymbolsIn(source), object); + } + + /** + * Creates a function like `_.groupBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} [initializer] The accumulator object initializer. + * @returns {Function} Returns the new aggregator function. + */ + function createAggregator(setter, initializer) { + return function(collection, iteratee) { + var func = isArray(collection) ? arrayAggregator : baseAggregator, + accumulator = initializer ? initializer() : {}; + + return func(collection, setter, getIteratee(iteratee, 2), accumulator); + }; + } + + /** + * Creates a function like `_.assign`. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ + function createAssigner(assigner) { + return baseRest(function(object, sources) { + var index = -1, + length = sources.length, + customizer = length > 1 ? sources[length - 1] : undefined, + guard = length > 2 ? sources[2] : undefined; + + customizer = (assigner.length > 3 && typeof customizer == 'function') + ? (length--, customizer) + : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + object = Object(object); + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, index, customizer); + } + } + return object; + }); + } + + /** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + if (collection == null) { + return collection; + } + if (!isArrayLike(collection)) { + return eachFunc(collection, iteratee); + } + var length = collection.length, + index = fromRight ? length : -1, + iterable = Object(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + + /** + * Creates a base function for methods like `_.forIn` and `_.forOwn`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + + /** + * Creates a function that wraps `func` to invoke it with the optional `this` + * binding of `thisArg`. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createBind(func, bitmask, thisArg) { + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return fn.apply(isBind ? thisArg : this, arguments); + } + return wrapper; + } + + /** + * Creates a function like `_.lowerFirst`. + * + * @private + * @param {string} methodName The name of the `String` case method to use. + * @returns {Function} Returns the new case function. + */ + function createCaseFirst(methodName) { + return function(string) { + string = toString(string); + + var strSymbols = hasUnicode(string) + ? stringToArray(string) + : undefined; + + var chr = strSymbols + ? strSymbols[0] + : string.charAt(0); + + var trailing = strSymbols + ? castSlice(strSymbols, 1).join('') + : string.slice(1); + + return chr[methodName]() + trailing; + }; + } + + /** + * Creates a function like `_.camelCase`. + * + * @private + * @param {Function} callback The function to combine each word. + * @returns {Function} Returns the new compounder function. + */ + function createCompounder(callback) { + return function(string) { + return arrayReduce(words(deburr(string).replace(reApos, '')), callback, ''); + }; + } + + /** + * Creates a function that produces an instance of `Ctor` regardless of + * whether it was invoked as part of a `new` expression or by `call` or `apply`. + * + * @private + * @param {Function} Ctor The constructor to wrap. + * @returns {Function} Returns the new wrapped function. + */ + function createCtor(Ctor) { + return function() { + // Use a `switch` statement to work with class constructors. See + // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // for more details. + var args = arguments; + switch (args.length) { + case 0: return new Ctor; + case 1: return new Ctor(args[0]); + case 2: return new Ctor(args[0], args[1]); + case 3: return new Ctor(args[0], args[1], args[2]); + case 4: return new Ctor(args[0], args[1], args[2], args[3]); + case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); + case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), + result = Ctor.apply(thisBinding, args); + + // Mimic the constructor's `return` behavior. + // See https://es5.github.io/#x13.2.2 for more details. + return isObject(result) ? result : thisBinding; + }; + } + + /** + * Creates a function that wraps `func` to enable currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {number} arity The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createCurry(func, bitmask, arity) { + var Ctor = createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length, + placeholder = getHolder(wrapper); + + while (index--) { + args[index] = arguments[index]; + } + var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder) + ? [] + : replaceHolders(args, placeholder); + + length -= holders.length; + if (length < arity) { + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, undefined, + args, holders, undefined, undefined, arity - length); + } + var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + return apply(fn, this, args); + } + return wrapper; + } + + /** + * Creates a `_.find` or `_.findLast` function. + * + * @private + * @param {Function} findIndexFunc The function to find the collection index. + * @returns {Function} Returns the new find function. + */ + function createFind(findIndexFunc) { + return function(collection, predicate, fromIndex) { + var iterable = Object(collection); + if (!isArrayLike(collection)) { + var iteratee = getIteratee(predicate, 3); + collection = keys(collection); + predicate = function(key) { return iteratee(iterable[key], key, iterable); }; + } + var index = findIndexFunc(collection, predicate, fromIndex); + return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; + }; + } + + /** + * Creates a `_.flow` or `_.flowRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new flow function. + */ + function createFlow(fromRight) { + return flatRest(function(funcs) { + var length = funcs.length, + index = length, + prereq = LodashWrapper.prototype.thru; + + if (fromRight) { + funcs.reverse(); + } + while (index--) { + var func = funcs[index]; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (prereq && !wrapper && getFuncName(func) == 'wrapper') { + var wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? index : length; + while (++index < length) { + func = funcs[index]; + + var funcName = getFuncName(func), + data = funcName == 'wrapper' ? getData(func) : undefined; + + if (data && isLaziable(data[0]) && + data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && + !data[4].length && data[9] == 1 + ) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = (func.length == 1 && isLaziable(func)) + ? wrapper[funcName]() + : wrapper.thru(func); + } + } + return function() { + var args = arguments, + value = args[0]; + + if (wrapper && args.length == 1 && isArray(value)) { + return wrapper.plant(value).value(); + } + var index = 0, + result = length ? funcs[index].apply(this, args) : value; + + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }); + } + + /** + * Creates a function that wraps `func` to invoke it with optional `this` + * binding of `thisArg`, partial application, and currying. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [partialsRight] The arguments to append to those provided + * to the new function. + * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & WRAP_ARY_FLAG, + isBind = bitmask & WRAP_BIND_FLAG, + isBindKey = bitmask & WRAP_BIND_KEY_FLAG, + isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), + isFlip = bitmask & WRAP_FLIP_FLAG, + Ctor = isBindKey ? undefined : createCtor(func); + + function wrapper() { + var length = arguments.length, + args = Array(length), + index = length; + + while (index--) { + args[index] = arguments[index]; + } + if (isCurried) { + var placeholder = getHolder(wrapper), + holdersCount = countHolders(args, placeholder); + } + if (partials) { + args = composeArgs(args, partials, holders, isCurried); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight, isCurried); + } + length -= holdersCount; + if (isCurried && length < arity) { + var newHolders = replaceHolders(args, placeholder); + return createRecurry( + func, bitmask, createHybrid, wrapper.placeholder, thisArg, + args, newHolders, argPos, ary, arity - length + ); + } + var thisBinding = isBind ? thisArg : this, + fn = isBindKey ? thisBinding[func] : func; + + length = args.length; + if (argPos) { + args = reorder(args, argPos); + } else if (isFlip && length > 1) { + args.reverse(); + } + if (isAry && ary < length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtor(fn); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + + /** + * Creates a function like `_.invertBy`. + * + * @private + * @param {Function} setter The function to set accumulator values. + * @param {Function} toIteratee The function to resolve iteratees. + * @returns {Function} Returns the new inverter function. + */ + function createInverter(setter, toIteratee) { + return function(object, iteratee) { + return baseInverter(object, setter, toIteratee(iteratee), {}); + }; + } + + /** + * Creates a function that performs a mathematical operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @param {number} [defaultValue] The value used for `undefined` arguments. + * @returns {Function} Returns the new mathematical operation function. + */ + function createMathOperation(operator, defaultValue) { + return function(value, other) { + var result; + if (value === undefined && other === undefined) { + return defaultValue; + } + if (value !== undefined) { + result = value; + } + if (other !== undefined) { + if (result === undefined) { + return other; + } + if (typeof value == 'string' || typeof other == 'string') { + value = baseToString(value); + other = baseToString(other); + } else { + value = baseToNumber(value); + other = baseToNumber(other); + } + result = operator(value, other); + } + return result; + }; + } + + /** + * Creates a function like `_.over`. + * + * @private + * @param {Function} arrayFunc The function to iterate over iteratees. + * @returns {Function} Returns the new over function. + */ + function createOver(arrayFunc) { + return flatRest(function(iteratees) { + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); + return baseRest(function(args) { + var thisArg = this; + return arrayFunc(iteratees, function(iteratee) { + return apply(iteratee, thisArg, args); + }); + }); + }); + } + + /** + * Creates the padding for `string` based on `length`. The `chars` string + * is truncated if the number of characters exceeds `length`. + * + * @private + * @param {number} length The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padding for `string`. + */ + function createPadding(length, chars) { + chars = chars === undefined ? ' ' : baseToString(chars); + + var charsLength = chars.length; + if (charsLength < 2) { + return charsLength ? baseRepeat(chars, length) : chars; + } + var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); + return hasUnicode(chars) + ? castSlice(stringToArray(result), 0, length).join('') + : result.slice(0, length); + } + + /** + * Creates a function that wraps `func` to invoke it with the `this` binding + * of `thisArg` and `partials` prepended to the arguments it receives. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} partials The arguments to prepend to those provided to + * the new function. + * @returns {Function} Returns the new wrapped function. + */ + function createPartial(func, bitmask, thisArg, partials) { + var isBind = bitmask & WRAP_BIND_FLAG, + Ctor = createCtor(func); + + function wrapper() { + var argsIndex = -1, + argsLength = arguments.length, + leftIndex = -1, + leftLength = partials.length, + args = Array(leftLength + argsLength), + fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; + + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + return apply(fn, isBind ? thisArg : this, args); + } + return wrapper; + } + + /** + * Creates a `_.range` or `_.rangeRight` function. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new range function. + */ + function createRange(fromRight) { + return function(start, end, step) { + if (step && typeof step != 'number' && isIterateeCall(start, end, step)) { + end = step = undefined; + } + // Ensure the sign of `-0` is preserved. + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + step = step === undefined ? (start < end ? 1 : -1) : toFinite(step); + return baseRange(start, end, step, fromRight); + }; + } + + /** + * Creates a function that performs a relational operation on two values. + * + * @private + * @param {Function} operator The function to perform the operation. + * @returns {Function} Returns the new relational operation function. + */ + function createRelationalOperation(operator) { + return function(value, other) { + if (!(typeof value == 'string' && typeof other == 'string')) { + value = toNumber(value); + other = toNumber(other); + } + return operator(value, other); + }; + } + + /** + * Creates a function that wraps `func` to continue currying. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @param {Function} wrapFunc The function to create the `func` wrapper. + * @param {*} placeholder The placeholder value. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to + * the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { + var isCurry = bitmask & WRAP_CURRY_FLAG, + newHolders = isCurry ? holders : undefined, + newHoldersRight = isCurry ? undefined : holders, + newPartials = isCurry ? partials : undefined, + newPartialsRight = isCurry ? undefined : partials; + + bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG); + + if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) { + bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG); + } + var newData = [ + func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, + newHoldersRight, argPos, ary, arity + ]; + + var result = wrapFunc.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return setWrapToString(result, func, bitmask); + } + + /** + * Creates a function like `_.round`. + * + * @private + * @param {string} methodName The name of the `Math` method to use when rounding. + * @returns {Function} Returns the new round function. + */ + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + number = toNumber(number); + precision = precision == null ? 0 : nativeMin(toInteger(precision), 292); + if (precision && nativeIsFinite(number)) { + // Shift with exponential notation to avoid floating-point issues. + // See [MDN](https://mdn.io/round#Examples) for more details. + var pair = (toString(number) + 'e').split('e'), + value = func(pair[0] + 'e' + (+pair[1] + precision)); + + pair = (toString(value) + 'e').split('e'); + return +(pair[0] + 'e' + (+pair[1] - precision)); + } + return func(number); + }; + } + + /** + * Creates a set object of `values`. + * + * @private + * @param {Array} values The values to add to the set. + * @returns {Object} Returns the new set. + */ + var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) { + return new Set(values); + }; + + /** + * Creates a `_.toPairs` or `_.toPairsIn` function. + * + * @private + * @param {Function} keysFunc The function to get the keys of a given object. + * @returns {Function} Returns the new pairs function. + */ + function createToPairs(keysFunc) { + return function(object) { + var tag = getTag(object); + if (tag == mapTag) { + return mapToArray(object); + } + if (tag == setTag) { + return setToPairs(object); + } + return baseToPairs(object, keysFunc(object)); + }; + } + + /** + * Creates a function that either curries or invokes `func` with optional + * `this` binding and partially applied arguments. + * + * @private + * @param {Function|string} func The function or method name to wrap. + * @param {number} bitmask The bitmask flags. + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` or `_.curryRight` of a bound function + * 8 - `_.curry` + * 16 - `_.curryRight` + * 32 - `_.partial` + * 64 - `_.partialRight` + * 128 - `_.rearg` + * 256 - `_.ary` + * 512 - `_.flip` + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to be partially applied. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & WRAP_BIND_KEY_FLAG; + if (!isBindKey && typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0); + arity = arity === undefined ? arity : toInteger(arity); + length -= holders ? holders.length : 0; + + if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, + holdersRight = holders; + + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func); + + var newData = [ + func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, + argPos, ary, arity + ]; + + if (data) { + mergeData(newData, data); + } + func = newData[0]; + bitmask = newData[1]; + thisArg = newData[2]; + partials = newData[3]; + holders = newData[4]; + arity = newData[9] = newData[9] === undefined + ? (isBindKey ? 0 : func.length) + : nativeMax(newData[9] - length, 0); + + if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) { + bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG); + } + if (!bitmask || bitmask == WRAP_BIND_FLAG) { + var result = createBind(func, bitmask, thisArg); + } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) { + result = createCurry(func, bitmask, arity); + } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) { + result = createPartial(func, bitmask, thisArg, partials); + } else { + result = createHybrid.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setWrapToString(setter(result, newData), func, bitmask); + } + + /** + * Used by `_.defaults` to customize its `_.assignIn` use to assign properties + * of source objects to the destination object for all destination properties + * that resolve to `undefined`. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to assign. + * @param {Object} object The parent object of `objValue`. + * @returns {*} Returns the value to assign. + */ + function customDefaultsAssignIn(objValue, srcValue, key, object) { + if (objValue === undefined || + (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { + return srcValue; + } + return objValue; + } + + /** + * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source + * objects into destination objects that are passed thru. + * + * @private + * @param {*} objValue The destination value. + * @param {*} srcValue The source value. + * @param {string} key The key of the property to merge. + * @param {Object} object The parent object of `objValue`. + * @param {Object} source The parent object of `srcValue`. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + * @returns {*} Returns the value to assign. + */ + function customDefaultsMerge(objValue, srcValue, key, object, source, stack) { + if (isObject(objValue) && isObject(srcValue)) { + // Recursively merge objects and arrays (susceptible to call stack limits). + stack.set(srcValue, objValue); + baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack); + stack['delete'](srcValue); + } + return objValue; + } + + /** + * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain + * objects. + * + * @private + * @param {*} value The value to inspect. + * @param {string} key The key of the property to inspect. + * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`. + */ + function customOmitClone(value) { + return isPlainObject(value) ? undefined : value; + } + + /** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ + function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + // Check that cyclic values are equal. + var arrStacked = stack.get(array); + var othStacked = stack.get(other); + if (arrStacked && othStacked) { + return arrStacked == other && othStacked == array; + } + var index = -1, + result = true, + seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; + + stack.set(array, other); + stack.set(other, array); + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, arrValue, index, other, array, stack) + : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!arraySome(other, function(othValue, othIndex) { + if (!cacheHas(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, bitmask, customizer, stack) + )) { + result = false; + break; + } + } + stack['delete'](array); + stack['delete'](other); + return result; + } + + /** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + case dataViewTag: + if ((object.byteLength != other.byteLength) || + (object.byteOffset != other.byteOffset)) { + return false; + } + object = object.buffer; + other = other.buffer; + + case arrayBufferTag: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; + + case boolTag: + case dateTag: + case numberTag: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); + + case errorTag: + return object.name == other.name && object.message == other.message; + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. + return object == (other + ''); + + case mapTag: + var convert = mapToArray; + + case setTag: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG; + convert || (convert = setToArray); + + if (object.size != other.size && !isPartial) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= COMPARE_UNORDERED_FLAG; + + // Recursively compare objects (susceptible to call stack limits). + stack.set(object, other); + var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); + stack['delete'](object); + return result; + + case symbolTag: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + return false; + } + + /** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + objProps = getAllKeys(object), + objLength = objProps.length, + othProps = getAllKeys(other), + othLength = othProps.length; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + // Check that cyclic values are equal. + var objStacked = stack.get(object); + var othStacked = stack.get(other); + if (objStacked && othStacked) { + return objStacked == other && othStacked == object; + } + var result = true; + stack.set(object, other); + stack.set(other, object); + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, objValue, key, other, object, stack) + : customizer(objValue, othValue, key, object, other, stack); + } + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } + } + stack['delete'](object); + stack['delete'](other); + return result; + } + + /** + * A specialized version of `baseRest` which flattens the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @returns {Function} Returns the new function. + */ + function flatRest(func) { + return setToString(overRest(func, undefined, flatten), func + ''); + } + + /** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); + } + + /** + * Creates an array of own and inherited enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ + function getAllKeysIn(object) { + return baseGetAllKeys(object, keysIn, getSymbolsIn); + } + + /** + * Gets metadata for `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {*} Returns the metadata for `func`. + */ + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + + /** + * Gets the name of `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {string} Returns the function name. + */ + function getFuncName(func) { + var result = (func.name + ''), + array = realNames[result], + length = hasOwnProperty.call(realNames, result) ? array.length : 0; + + while (length--) { + var data = array[length], + otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + + /** + * Gets the argument placeholder value for `func`. + * + * @private + * @param {Function} func The function to inspect. + * @returns {*} Returns the placeholder value. + */ + function getHolder(func) { + var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func; + return object.placeholder; + } + + /** + * Gets the appropriate "iteratee" function. If `_.iteratee` is customized, + * this function returns the custom method, otherwise it returns `baseIteratee`. + * If arguments are provided, the chosen function is invoked with them and + * its result is returned. + * + * @private + * @param {*} [value] The value to convert to an iteratee. + * @param {number} [arity] The arity of the created iteratee. + * @returns {Function} Returns the chosen function or its result. + */ + function getIteratee() { + var result = lodash.iteratee || iteratee; + result = result === iteratee ? baseIteratee : result; + return arguments.length ? result(arguments[0], arguments[1]) : result; + } + + /** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ + function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; + } + + /** + * Gets the property names, values, and compare flags of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the match data of `object`. + */ + function getMatchData(object) { + var result = keys(object), + length = result.length; + + while (length--) { + var key = result[length], + value = object[key]; + + result[length] = [key, value, isStrictComparable(value)]; + } + return result; + } + + /** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ + function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; + } + + /** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ + function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; + } + + /** + * Creates an array of the own enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbols = !nativeGetSymbols ? stubArray : function(object) { + if (object == null) { + return []; + } + object = Object(object); + return arrayFilter(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable.call(object, symbol); + }); + }; + + /** + * Creates an array of the own and inherited enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ + var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { + var result = []; + while (object) { + arrayPush(result, getSymbols(object)); + object = getPrototype(object); + } + return result; + }; + + /** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + var getTag = baseGetTag; + + // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. + if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || + (Map && getTag(new Map) != mapTag) || + (Promise && getTag(Promise.resolve()) != promiseTag) || + (Set && getTag(new Set) != setTag) || + (WeakMap && getTag(new WeakMap) != weakMapTag)) { + getTag = function(value) { + var result = baseGetTag(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : ''; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag; + case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag; + case weakMapCtorString: return weakMapTag; + } + } + return result; + }; + } + + /** + * Gets the view, applying any `transforms` to the `start` and `end` positions. + * + * @private + * @param {number} start The start of the view. + * @param {number} end The end of the view. + * @param {Array} transforms The transformations to apply to the view. + * @returns {Object} Returns an object containing the `start` and `end` + * positions of the view. + */ + function getView(start, end, transforms) { + var index = -1, + length = transforms.length; + + while (++index < length) { + var data = transforms[index], + size = data.size; + + switch (data.type) { + case 'drop': start += size; break; + case 'dropRight': end -= size; break; + case 'take': end = nativeMin(end, start + size); break; + case 'takeRight': start = nativeMax(start, end - size); break; + } + } + return { 'start': start, 'end': end }; + } + + /** + * Extracts wrapper details from the `source` body comment. + * + * @private + * @param {string} source The source to inspect. + * @returns {Array} Returns the wrapper details. + */ + function getWrapDetails(source) { + var match = source.match(reWrapDetails); + return match ? match[1].split(reSplitDetails) : []; + } + + /** + * Checks if `path` exists on `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @param {Function} hasFunc The function to check properties. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + */ + function hasPath(object, path, hasFunc) { + path = castPath(path, object); + + var index = -1, + length = path.length, + result = false; + + while (++index < length) { + var key = toKey(path[index]); + if (!(result = object != null && hasFunc(object, key))) { + break; + } + object = object[key]; + } + if (result || ++index != length) { + return result; + } + length = object == null ? 0 : object.length; + return !!length && isLength(length) && isIndex(key, length) && + (isArray(object) || isArguments(object)); + } + + /** + * Initializes an array clone. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the initialized clone. + */ + function initCloneArray(array) { + var length = array.length, + result = new array.constructor(length); + + // Add properties assigned by `RegExp#exec`. + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; + } + + /** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneObject(object) { + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) + : {}; + } + + /** + * Initializes an object clone based on its `toStringTag`. + * + * **Note:** This function only supports cloning values with tags of + * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`. + * + * @private + * @param {Object} object The object to clone. + * @param {string} tag The `toStringTag` of the object to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return cloneArrayBuffer(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case dataViewTag: + return cloneDataView(object, isDeep); + + case float32Tag: case float64Tag: + case int8Tag: case int16Tag: case int32Tag: + case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: + return cloneTypedArray(object, isDeep); + + case mapTag: + return new Ctor; + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + return cloneRegExp(object); + + case setTag: + return new Ctor; + + case symbolTag: + return cloneSymbol(object); + } + } + + /** + * Inserts wrapper `details` in a comment at the top of the `source` body. + * + * @private + * @param {string} source The source to modify. + * @returns {Array} details The details to insert. + * @returns {string} Returns the modified source. + */ + function insertWrapDetails(source, details) { + var length = details.length; + if (!length) { + return source; + } + var lastIndex = length - 1; + details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; + details = details.join(length > 2 ? ', ' : ' '); + return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); + } + + /** + * Checks if `value` is a flattenable `arguments` object or array. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. + */ + function isFlattenable(value) { + return isArray(value) || isArguments(value) || + !!(spreadableSymbol && value && value[spreadableSymbol]); + } + + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + + return !!length && + (type == 'number' || + (type != 'symbol' && reIsUint.test(value))) && + (value > -1 && value % 1 == 0 && value < length); + } + + /** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; + } + + /** + * Checks if `value` is a property name and not a property path. + * + * @private + * @param {*} value The value to check. + * @param {Object} [object] The object to query keys on. + * @returns {boolean} Returns `true` if `value` is a property name, else `false`. + */ + function isKey(value, object) { + if (isArray(value)) { + return false; + } + var type = typeof value; + if (type == 'number' || type == 'symbol' || type == 'boolean' || + value == null || isSymbol(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object)); + } + + /** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ + function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); + } + + /** + * Checks if `func` has a lazy counterpart. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` has a lazy counterpart, + * else `false`. + */ + function isLaziable(func) { + var funcName = getFuncName(func), + other = lodash[funcName]; + + if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + + /** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ + function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); + } + + /** + * Checks if `func` is capable of being masked. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `func` is maskable, else `false`. + */ + var isMaskable = coreJsData ? isFunction : stubFalse; + + /** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ + function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; + } + + /** + * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` if suitable for strict + * equality comparisons, else `false`. + */ + function isStrictComparable(value) { + return value === value && !isObject(value); + } + + /** + * A specialized version of `matchesProperty` for source values suitable + * for strict equality comparisons, i.e. `===`. + * + * @private + * @param {string} key The key of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ + function matchesStrictComparable(key, srcValue) { + return function(object) { + if (object == null) { + return false; + } + return object[key] === srcValue && + (srcValue !== undefined || (key in Object(object))); + }; + } + + /** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ + function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + + var cache = result.cache; + return result; + } + + /** + * Merges the function metadata of `source` into `data`. + * + * Merging metadata reduces the number of wrappers used to invoke a function. + * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` + * may be applied regardless of execution order. Methods like `_.ary` and + * `_.rearg` modify function arguments, making the order in which they are + * executed important, preventing the merging of metadata. However, we make + * an exception for a safe combined case where curried functions have `_.ary` + * and or `_.rearg` applied. + * + * @private + * @param {Array} data The destination metadata. + * @param {Array} source The source metadata. + * @returns {Array} Returns `data`. + */ + function mergeData(data, source) { + var bitmask = data[1], + srcBitmask = source[1], + newBitmask = bitmask | srcBitmask, + isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG); + + var isCombo = + ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) || + ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) || + ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG)); + + // Exit early if metadata can't be merged. + if (!(isCommon || isCombo)) { + return data; + } + // Use source `thisArg` if available. + if (srcBitmask & WRAP_BIND_FLAG) { + data[2] = source[2]; + // Set when currying a bound function. + newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG; + } + // Compose partial arguments. + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : value; + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4]; + } + // Compose partial right arguments. + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6]; + } + // Use source `argPos` if available. + value = source[7]; + if (value) { + data[7] = value; + } + // Use source `ary` if it's smaller. + if (srcBitmask & WRAP_ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + // Use source `arity` if one is not provided. + if (data[9] == null) { + data[9] = source[9]; + } + // Use source `func` and merge bitmasks. + data[0] = source[0]; + data[1] = newBitmask; + + return data; + } + + /** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; + } + + /** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ + function objectToString(value) { + return nativeObjectToString.call(value); + } + + /** + * A specialized version of `baseRest` which transforms the rest array. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @param {Function} transform The rest array transform. + * @returns {Function} Returns the new function. + */ + function overRest(func, start, transform) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = transform(array); + return apply(func, this, otherArgs); + }; + } + + /** + * Gets the parent value at `path` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} path The path to get the parent value of. + * @returns {*} Returns the parent value. + */ + function parent(object, path) { + return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1)); + } + + /** + * Reorder `array` according to the specified indexes where the element at + * the first index is assigned as the first element, the element at + * the second index is assigned as the second element, and so on. + * + * @private + * @param {Array} array The array to reorder. + * @param {Array} indexes The arranged array indexes. + * @returns {Array} Returns `array`. + */ + function reorder(array, indexes) { + var arrLength = array.length, + length = nativeMin(indexes.length, arrLength), + oldArray = copyArray(array); + + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + + /** + * Gets the value at `key`, unless `key` is "__proto__" or "constructor". + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function safeGet(object, key) { + if (key === 'constructor' && typeof object[key] === 'function') { + return; + } + + if (key == '__proto__') { + return; + } + + return object[key]; + } + + /** + * Sets metadata for `func`. + * + * **Note:** If this function becomes hot, i.e. is invoked a lot in a short + * period of time, it will trip its breaker and transition to an identity + * function to avoid garbage collection pauses in V8. See + * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070) + * for more details. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var setData = shortOut(baseSetData); + + /** + * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout). + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @returns {number|Object} Returns the timer id or timeout object. + */ + var setTimeout = ctxSetTimeout || function(func, wait) { + return root.setTimeout(func, wait); + }; + + /** + * Sets the `toString` method of `func` to return `string`. + * + * @private + * @param {Function} func The function to modify. + * @param {Function} string The `toString` result. + * @returns {Function} Returns `func`. + */ + var setToString = shortOut(baseSetToString); + + /** + * Sets the `toString` method of `wrapper` to mimic the source of `reference` + * with wrapper details in a comment at the top of the source body. + * + * @private + * @param {Function} wrapper The function to modify. + * @param {Function} reference The reference function. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Function} Returns `wrapper`. + */ + function setWrapToString(wrapper, reference, bitmask) { + var source = (reference + ''); + return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); + } + + /** + * Creates a function that'll short out and invoke `identity` instead + * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` + * milliseconds. + * + * @private + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new shortable function. + */ + function shortOut(func) { + var count = 0, + lastCalled = 0; + + return function() { + var stamp = nativeNow(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return arguments[0]; + } + } else { + count = 0; + } + return func.apply(undefined, arguments); + }; + } + + /** + * A specialized version of `_.shuffle` which mutates and sets the size of `array`. + * + * @private + * @param {Array} array The array to shuffle. + * @param {number} [size=array.length] The size of `array`. + * @returns {Array} Returns `array`. + */ + function shuffleSelf(array, size) { + var index = -1, + length = array.length, + lastIndex = length - 1; + + size = size === undefined ? length : size; + while (++index < size) { + var rand = baseRandom(index, lastIndex), + value = array[rand]; + + array[rand] = array[index]; + array[index] = value; + } + array.length = size; + return array; + } + + /** + * Converts `string` to a property path array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the property path array. + */ + var stringToPath = memoizeCapped(function(string) { + var result = []; + if (string.charCodeAt(0) === 46 /* . */) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, subString) { + result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match)); + }); + return result; + }); + + /** + * Converts `value` to a string key if it's not a string or symbol. + * + * @private + * @param {*} value The value to inspect. + * @returns {string|symbol} Returns the key. + */ + function toKey(value) { + if (typeof value == 'string' || isSymbol(value)) { + return value; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; + } + + /** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ + function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; + } + + /** + * Updates wrapper `details` based on `bitmask` flags. + * + * @private + * @returns {Array} details The details to modify. + * @param {number} bitmask The bitmask flags. See `createWrap` for more details. + * @returns {Array} Returns `details`. + */ + function updateWrapDetails(details, bitmask) { + arrayEach(wrapFlags, function(pair) { + var value = '_.' + pair[0]; + if ((bitmask & pair[1]) && !arrayIncludes(details, value)) { + details.push(value); + } + }); + return details.sort(); + } + + /** + * Creates a clone of `wrapper`. + * + * @private + * @param {Object} wrapper The wrapper to clone. + * @returns {Object} Returns the cloned wrapper. + */ + function wrapperClone(wrapper) { + if (wrapper instanceof LazyWrapper) { + return wrapper.clone(); + } + var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); + result.__actions__ = copyArray(wrapper.__actions__); + result.__index__ = wrapper.__index__; + result.__values__ = wrapper.__values__; + return result; + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of elements split into groups the length of `size`. + * If `array` can't be split evenly, the final chunk will be the remaining + * elements. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to process. + * @param {number} [size=1] The length of each chunk + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the new array of chunks. + * @example + * + * _.chunk(['a', 'b', 'c', 'd'], 2); + * // => [['a', 'b'], ['c', 'd']] + * + * _.chunk(['a', 'b', 'c', 'd'], 3); + * // => [['a', 'b', 'c'], ['d']] + */ + function chunk(array, size, guard) { + if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) { + size = 1; + } else { + size = nativeMax(toInteger(size), 0); + } + var length = array == null ? 0 : array.length; + if (!length || size < 1) { + return []; + } + var index = 0, + resIndex = 0, + result = Array(nativeCeil(length / size)); + + while (index < length) { + result[resIndex++] = baseSlice(array, index, (index += size)); + } + return result; + } + + /** + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are falsey. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to compact. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ + function compact(array) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value) { + result[resIndex++] = value; + } + } + return result; + } + + /** + * Creates a new array concatenating `array` with any additional arrays + * and/or values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to concatenate. + * @param {...*} [values] The values to concatenate. + * @returns {Array} Returns the new concatenated array. + * @example + * + * var array = [1]; + * var other = _.concat(array, 2, [3], [[4]]); + * + * console.log(other); + * // => [1, 2, 3, [4]] + * + * console.log(array); + * // => [1] + */ + function concat() { + var length = arguments.length; + if (!length) { + return []; + } + var args = Array(length - 1), + array = arguments[0], + index = length; + + while (index--) { + args[index - 1] = arguments[index]; + } + return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); + } + + /** + * Creates an array of `array` values not included in the other given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * **Note:** Unlike `_.pullAll`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.without, _.xor + * @example + * + * _.difference([2, 1], [2, 3]); + * // => [1] + */ + var difference = baseRest(function(array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) + : []; + }); + + /** + * This method is like `_.difference` except that it accepts `iteratee` which + * is invoked for each element of `array` and `values` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * **Note:** Unlike `_.pullAllBy`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2] + * + * // The `_.property` iteratee shorthand. + * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ + var differenceBy = baseRest(function(array, values) { + var iteratee = last(values); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)) + : []; + }); + + /** + * This method is like `_.difference` except that it accepts `comparator` + * which is invoked to compare elements of `array` to `values`. The order and + * references of result values are determined by the first array. The comparator + * is invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.pullAllWith`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * + * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual); + * // => [{ 'x': 2, 'y': 1 }] + */ + var differenceWith = baseRest(function(array, values) { + var comparator = last(values); + if (isArrayLikeObject(comparator)) { + comparator = undefined; + } + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator) + : []; + }); + + /** + * Creates a slice of `array` with `n` elements dropped from the beginning. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.drop([1, 2, 3]); + * // => [2, 3] + * + * _.drop([1, 2, 3], 2); + * // => [3] + * + * _.drop([1, 2, 3], 5); + * // => [] + * + * _.drop([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function drop(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, n < 0 ? 0 : n, length); + } + + /** + * Creates a slice of `array` with `n` elements dropped from the end. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.dropRight([1, 2, 3]); + * // => [1, 2] + * + * _.dropRight([1, 2, 3], 2); + * // => [1] + * + * _.dropRight([1, 2, 3], 5); + * // => [] + * + * _.dropRight([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function dropRight(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` excluding elements dropped from the end. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.dropRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney'] + * + * // The `_.matches` iteratee shorthand. + * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['barney', 'fred'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropRightWhile(users, ['active', false]); + * // => objects for ['barney'] + * + * // The `_.property` iteratee shorthand. + * _.dropRightWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ + function dropRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), true, true) + : []; + } + + /** + * Creates a slice of `array` excluding elements dropped from the beginning. + * Elements are dropped until `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.dropWhile(users, function(o) { return !o.active; }); + * // => objects for ['pebbles'] + * + * // The `_.matches` iteratee shorthand. + * _.dropWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.dropWhile(users, ['active', false]); + * // => objects for ['pebbles'] + * + * // The `_.property` iteratee shorthand. + * _.dropWhile(users, 'active'); + * // => objects for ['barney', 'fred', 'pebbles'] + */ + function dropWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), true) + : []; + } + + /** + * Fills elements of `array` with `value` from `start` up to, but not + * including, `end`. + * + * **Note:** This method mutates `array`. + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Array + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.fill(array, 'a'); + * console.log(array); + * // => ['a', 'a', 'a'] + * + * _.fill(Array(3), 2); + * // => [2, 2, 2] + * + * _.fill([4, 6, 8, 10], '*', 1, 3); + * // => [4, '*', '*', 10] + */ + function fill(array, value, start, end) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + if (start && typeof start != 'number' && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + + /** + * This method is like `_.find` except that it returns the index of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.findIndex(users, function(o) { return o.user == 'barney'; }); + * // => 0 + * + * // The `_.matches` iteratee shorthand. + * _.findIndex(users, { 'user': 'fred', 'active': false }); + * // => 1 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findIndex(users, ['active', false]); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.findIndex(users, 'active'); + * // => 2 + */ + function findIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseFindIndex(array, getIteratee(predicate, 3), index); + } + + /** + * This method is like `_.findIndex` except that it iterates over elements + * of `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; }); + * // => 2 + * + * // The `_.matches` iteratee shorthand. + * _.findLastIndex(users, { 'user': 'barney', 'active': true }); + * // => 0 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastIndex(users, ['active', false]); + * // => 2 + * + * // The `_.property` iteratee shorthand. + * _.findLastIndex(users, 'active'); + * // => 0 + */ + function findLastIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = length - 1; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = fromIndex < 0 + ? nativeMax(length + index, 0) + : nativeMin(index, length - 1); + } + return baseFindIndex(array, getIteratee(predicate, 3), index, true); + } + + /** + * Flattens `array` a single level deep. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flatten([1, [2, [3, [4]], 5]]); + * // => [1, 2, [3, [4]], 5] + */ + function flatten(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, 1) : []; + } + + /** + * Recursively flattens `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flattenDeep([1, [2, [3, [4]], 5]]); + * // => [1, 2, 3, 4, 5] + */ + function flattenDeep(array) { + var length = array == null ? 0 : array.length; + return length ? baseFlatten(array, INFINITY) : []; + } + + /** + * Recursively flatten `array` up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Array + * @param {Array} array The array to flatten. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * var array = [1, [2, [3, [4]], 5]]; + * + * _.flattenDepth(array, 1); + * // => [1, 2, [3, [4]], 5] + * + * _.flattenDepth(array, 2); + * // => [1, 2, 3, [4], 5] + */ + function flattenDepth(array, depth) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(array, depth); + } + + /** + * The inverse of `_.toPairs`; this method returns an object composed + * from key-value `pairs`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} pairs The key-value pairs. + * @returns {Object} Returns the new object. + * @example + * + * _.fromPairs([['a', 1], ['b', 2]]); + * // => { 'a': 1, 'b': 2 } + */ + function fromPairs(pairs) { + var index = -1, + length = pairs == null ? 0 : pairs.length, + result = {}; + + while (++index < length) { + var pair = pairs[index]; + result[pair[0]] = pair[1]; + } + return result; + } + + /** + * Gets the first element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias first + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the first element of `array`. + * @example + * + * _.head([1, 2, 3]); + * // => 1 + * + * _.head([]); + * // => undefined + */ + function head(array) { + return (array && array.length) ? array[0] : undefined; + } + + /** + * Gets the index at which the first occurrence of `value` is found in `array` + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. If `fromIndex` is negative, it's used as the + * offset from the end of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.indexOf([1, 2, 1, 2], 2); + * // => 1 + * + * // Search from the `fromIndex`. + * _.indexOf([1, 2, 1, 2], 2, 2); + * // => 3 + */ + function indexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseIndexOf(array, value, index); + } + + /** + * Gets all but the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.initial([1, 2, 3]); + * // => [1, 2] + */ + function initial(array) { + var length = array == null ? 0 : array.length; + return length ? baseSlice(array, 0, -1) : []; + } + + /** + * Creates an array of unique values that are included in all given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order and references of result values are + * determined by the first array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersection([2, 1], [2, 3]); + * // => [2] + */ + var intersection = baseRest(function(arrays) { + var mapped = arrayMap(arrays, castArrayLikeObject); + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped) + : []; + }); + + /** + * This method is like `_.intersection` except that it accepts `iteratee` + * which is invoked for each element of each `arrays` to generate the criterion + * by which they're compared. The order and references of result values are + * determined by the first array. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [2.1] + * + * // The `_.property` iteratee shorthand. + * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }] + */ + var intersectionBy = baseRest(function(arrays) { + var iteratee = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + if (iteratee === last(mapped)) { + iteratee = undefined; + } else { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, getIteratee(iteratee, 2)) + : []; + }); + + /** + * This method is like `_.intersection` except that it accepts `comparator` + * which is invoked to compare elements of `arrays`. The order and references + * of result values are determined by the first array. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of intersecting values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.intersectionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }] + */ + var intersectionWith = baseRest(function(arrays) { + var comparator = last(arrays), + mapped = arrayMap(arrays, castArrayLikeObject); + + comparator = typeof comparator == 'function' ? comparator : undefined; + if (comparator) { + mapped.pop(); + } + return (mapped.length && mapped[0] === arrays[0]) + ? baseIntersection(mapped, undefined, comparator) + : []; + }); + + /** + * Converts all elements in `array` into a string separated by `separator`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to convert. + * @param {string} [separator=','] The element separator. + * @returns {string} Returns the joined string. + * @example + * + * _.join(['a', 'b', 'c'], '~'); + * // => 'a~b~c' + */ + function join(array, separator) { + return array == null ? '' : nativeJoin.call(array, separator); + } + + /** + * Gets the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the last element of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + */ + function last(array) { + var length = array == null ? 0 : array.length; + return length ? array[length - 1] : undefined; + } + + /** + * This method is like `_.indexOf` except that it iterates over elements of + * `array` from right to left. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=array.length-1] The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.lastIndexOf([1, 2, 1, 2], 2); + * // => 3 + * + * // Search from the `fromIndex`. + * _.lastIndexOf([1, 2, 1, 2], 2, 2); + * // => 1 + */ + function lastIndexOf(array, value, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = length; + if (fromIndex !== undefined) { + index = toInteger(fromIndex); + index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); + } + return value === value + ? strictLastIndexOf(array, value, index) + : baseFindIndex(array, baseIsNaN, index, true); + } + + /** + * Gets the element at index `n` of `array`. If `n` is negative, the nth + * element from the end is returned. + * + * @static + * @memberOf _ + * @since 4.11.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=0] The index of the element to return. + * @returns {*} Returns the nth element of `array`. + * @example + * + * var array = ['a', 'b', 'c', 'd']; + * + * _.nth(array, 1); + * // => 'b' + * + * _.nth(array, -2); + * // => 'c'; + */ + function nth(array, n) { + return (array && array.length) ? baseNth(array, toInteger(n)) : undefined; + } + + /** + * Removes all given values from `array` using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` + * to remove elements from an array by predicate. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...*} [values] The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pull(array, 'a', 'c'); + * console.log(array); + * // => ['b', 'b'] + */ + var pull = baseRest(pullAll); + + /** + * This method is like `_.pull` except that it accepts an array of values to remove. + * + * **Note:** Unlike `_.difference`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = ['a', 'b', 'c', 'a', 'b', 'c']; + * + * _.pullAll(array, ['a', 'c']); + * console.log(array); + * // => ['b', 'b'] + */ + function pullAll(array, values) { + return (array && array.length && values && values.length) + ? basePullAll(array, values) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `iteratee` which is + * invoked for each element of `array` and `values` to generate the criterion + * by which they're compared. The iteratee is invoked with one argument: (value). + * + * **Note:** Unlike `_.differenceBy`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }]; + * + * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x'); + * console.log(array); + * // => [{ 'x': 2 }] + */ + function pullAllBy(array, values, iteratee) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, getIteratee(iteratee, 2)) + : array; + } + + /** + * This method is like `_.pullAll` except that it accepts `comparator` which + * is invoked to compare elements of `array` to `values`. The comparator is + * invoked with two arguments: (arrVal, othVal). + * + * **Note:** Unlike `_.differenceWith`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Array} values The values to remove. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns `array`. + * @example + * + * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }]; + * + * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual); + * console.log(array); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }] + */ + function pullAllWith(array, values, comparator) { + return (array && array.length && values && values.length) + ? basePullAll(array, values, undefined, comparator) + : array; + } + + /** + * Removes elements from `array` corresponding to `indexes` and returns an + * array of removed elements. + * + * **Note:** Unlike `_.at`, this method mutates `array`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {...(number|number[])} [indexes] The indexes of elements to remove. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = ['a', 'b', 'c', 'd']; + * var pulled = _.pullAt(array, [1, 3]); + * + * console.log(array); + * // => ['a', 'c'] + * + * console.log(pulled); + * // => ['b', 'd'] + */ + var pullAt = flatRest(function(array, indexes) { + var length = array == null ? 0 : array.length, + result = baseAt(array, indexes); + + basePullAt(array, arrayMap(indexes, function(index) { + return isIndex(index, length) ? +index : index; + }).sort(compareAscending)); + + return result; + }); + + /** + * Removes all elements from `array` that `predicate` returns truthy for + * and returns an array of the removed elements. The predicate is invoked + * with three arguments: (value, index, array). + * + * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull` + * to pull elements from an array by value. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Array + * @param {Array} array The array to modify. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = [1, 2, 3, 4]; + * var evens = _.remove(array, function(n) { + * return n % 2 == 0; + * }); + * + * console.log(array); + * // => [1, 3] + * + * console.log(evens); + * // => [2, 4] + */ + function remove(array, predicate) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, + indexes = [], + length = array.length; + + predicate = getIteratee(predicate, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + + /** + * Reverses `array` so that the first element becomes the last, the second + * element becomes the second to last, and so on. + * + * **Note:** This method mutates `array` and is based on + * [`Array#reverse`](https://mdn.io/Array/reverse). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to modify. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3]; + * + * _.reverse(array); + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function reverse(array) { + return array == null ? array : nativeReverse.call(array); + } + + /** + * Creates a slice of `array` from `start` up to, but not including, `end`. + * + * **Note:** This method is used instead of + * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are + * returned. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function slice(array, start, end) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + if (end && typeof end != 'number' && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + else { + start = start == null ? 0 : toInteger(start); + end = end === undefined ? length : toInteger(end); + } + return baseSlice(array, start, end); + } + + /** + * Uses a binary search to determine the lowest index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedIndex([30, 50], 40); + * // => 1 + */ + function sortedIndex(array, value) { + return baseSortedIndex(array, value); + } + + /** + * This method is like `_.sortedIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * var objects = [{ 'x': 4 }, { 'x': 5 }]; + * + * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.sortedIndexBy(objects, { 'x': 4 }, 'x'); + * // => 0 + */ + function sortedIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2)); + } + + /** + * This method is like `_.indexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedIndexOf([4, 5, 5, 5, 6], 5); + * // => 1 + */ + function sortedIndexOf(array, value) { + var length = array == null ? 0 : array.length; + if (length) { + var index = baseSortedIndex(array, value); + if (index < length && eq(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * This method is like `_.sortedIndex` except that it returns the highest + * index at which `value` should be inserted into `array` in order to + * maintain its sort order. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedLastIndex([4, 5, 5, 5, 6], 5); + * // => 4 + */ + function sortedLastIndex(array, value) { + return baseSortedIndex(array, value, true); + } + + /** + * This method is like `_.sortedLastIndex` except that it accepts `iteratee` + * which is invoked for `value` and each element of `array` to compute their + * sort ranking. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * var objects = [{ 'x': 4 }, { 'x': 5 }]; + * + * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); + * // => 1 + * + * // The `_.property` iteratee shorthand. + * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x'); + * // => 1 + */ + function sortedLastIndexBy(array, value, iteratee) { + return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true); + } + + /** + * This method is like `_.lastIndexOf` except that it performs a binary + * search on a sorted `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5); + * // => 3 + */ + function sortedLastIndexOf(array, value) { + var length = array == null ? 0 : array.length; + if (length) { + var index = baseSortedIndex(array, value, true) - 1; + if (eq(array[index], value)) { + return index; + } + } + return -1; + } + + /** + * This method is like `_.uniq` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniq([1, 1, 2]); + * // => [1, 2] + */ + function sortedUniq(array) { + return (array && array.length) + ? baseSortedUniq(array) + : []; + } + + /** + * This method is like `_.uniqBy` except that it's designed and optimized + * for sorted arrays. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor); + * // => [1.1, 2.3] + */ + function sortedUniqBy(array, iteratee) { + return (array && array.length) + ? baseSortedUniq(array, getIteratee(iteratee, 2)) + : []; + } + + /** + * Gets all but the first element of `array`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.tail([1, 2, 3]); + * // => [2, 3] + */ + function tail(array) { + var length = array == null ? 0 : array.length; + return length ? baseSlice(array, 1, length) : []; + } + + /** + * Creates a slice of `array` with `n` elements taken from the beginning. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.take([1, 2, 3]); + * // => [1] + * + * _.take([1, 2, 3], 2); + * // => [1, 2] + * + * _.take([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.take([1, 2, 3], 0); + * // => [] + */ + function take(array, n, guard) { + if (!(array && array.length)) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` with `n` elements taken from the end. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.takeRight([1, 2, 3]); + * // => [3] + * + * _.takeRight([1, 2, 3], 2); + * // => [2, 3] + * + * _.takeRight([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.takeRight([1, 2, 3], 0); + * // => [] + */ + function takeRight(array, n, guard) { + var length = array == null ? 0 : array.length; + if (!length) { + return []; + } + n = (guard || n === undefined) ? 1 : toInteger(n); + n = length - n; + return baseSlice(array, n < 0 ? 0 : n, length); + } + + /** + * Creates a slice of `array` with elements taken from the end. Elements are + * taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.takeRightWhile(users, function(o) { return !o.active; }); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.matches` iteratee shorthand. + * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false }); + * // => objects for ['pebbles'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.takeRightWhile(users, ['active', false]); + * // => objects for ['fred', 'pebbles'] + * + * // The `_.property` iteratee shorthand. + * _.takeRightWhile(users, 'active'); + * // => [] + */ + function takeRightWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3), false, true) + : []; + } + + /** + * Creates a slice of `array` with elements taken from the beginning. Elements + * are taken until `predicate` returns falsey. The predicate is invoked with + * three arguments: (value, index, array). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Array + * @param {Array} array The array to query. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the slice of `array`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.takeWhile(users, function(o) { return !o.active; }); + * // => objects for ['barney', 'fred'] + * + * // The `_.matches` iteratee shorthand. + * _.takeWhile(users, { 'user': 'barney', 'active': false }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.takeWhile(users, ['active', false]); + * // => objects for ['barney', 'fred'] + * + * // The `_.property` iteratee shorthand. + * _.takeWhile(users, 'active'); + * // => [] + */ + function takeWhile(array, predicate) { + return (array && array.length) + ? baseWhile(array, getIteratee(predicate, 3)) + : []; + } + + /** + * Creates an array of unique values, in order, from all given arrays using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.union([2], [1, 2]); + * // => [2, 1] + */ + var union = baseRest(function(arrays) { + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); + }); + + /** + * This method is like `_.union` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by + * which uniqueness is computed. Result values are chosen from the first + * array in which the value occurs. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.unionBy([2.1], [1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // The `_.property` iteratee shorthand. + * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + var unionBy = baseRest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)); + }); + + /** + * This method is like `_.union` except that it accepts `comparator` which + * is invoked to compare elements of `arrays`. Result values are chosen from + * the first array in which the value occurs. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of combined values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.unionWith(objects, others, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ + var unionWith = baseRest(function(arrays) { + var comparator = last(arrays); + comparator = typeof comparator == 'function' ? comparator : undefined; + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator); + }); + + /** + * Creates a duplicate-free version of an array, using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons, in which only the first occurrence of each element + * is kept. The order of result values is determined by the order they occur + * in the array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniq([2, 1, 2]); + * // => [2, 1] + */ + function uniq(array) { + return (array && array.length) ? baseUniq(array) : []; + } + + /** + * This method is like `_.uniq` except that it accepts `iteratee` which is + * invoked for each element in `array` to generate the criterion by which + * uniqueness is computed. The order of result values is determined by the + * order they occur in the array. The iteratee is invoked with one argument: + * (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * _.uniqBy([2.1, 1.2, 2.3], Math.floor); + * // => [2.1, 1.2] + * + * // The `_.property` iteratee shorthand. + * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + function uniqBy(array, iteratee) { + return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : []; + } + + /** + * This method is like `_.uniq` except that it accepts `comparator` which + * is invoked to compare elements of `array`. The order of result values is + * determined by the order they occur in the array.The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.uniqWith(objects, _.isEqual); + * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }] + */ + function uniqWith(array, comparator) { + comparator = typeof comparator == 'function' ? comparator : undefined; + return (array && array.length) ? baseUniq(array, undefined, comparator) : []; + } + + /** + * This method is like `_.zip` except that it accepts an array of grouped + * elements and creates an array regrouping the elements to their pre-zip + * configuration. + * + * @static + * @memberOf _ + * @since 1.2.0 + * @category Array + * @param {Array} array The array of grouped elements to process. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] + * + * _.unzip(zipped); + * // => [['a', 'b'], [1, 2], [true, false]] + */ + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLikeObject(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + return baseTimes(length, function(index) { + return arrayMap(array, baseProperty(index)); + }); + } + + /** + * This method is like `_.unzip` except that it accepts `iteratee` to specify + * how regrouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Array + * @param {Array} array The array of grouped elements to process. + * @param {Function} [iteratee=_.identity] The function to combine + * regrouped values. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip([1, 2], [10, 20], [100, 200]); + * // => [[1, 10, 100], [2, 20, 200]] + * + * _.unzipWith(zipped, _.add); + * // => [3, 30, 300] + */ + function unzipWith(array, iteratee) { + if (!(array && array.length)) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + return arrayMap(result, function(group) { + return apply(iteratee, undefined, group); + }); + } + + /** + * Creates an array excluding all given values using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * **Note:** Unlike `_.pull`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...*} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.xor + * @example + * + * _.without([2, 1, 2, 3], 1, 2); + * // => [3] + */ + var without = baseRest(function(array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, values) + : []; + }); + + /** + * Creates an array of unique values that is the + * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) + * of the given arrays. The order of result values is determined by the order + * they occur in the arrays. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of filtered values. + * @see _.difference, _.without + * @example + * + * _.xor([2, 1], [2, 3]); + * // => [1, 3] + */ + var xor = baseRest(function(arrays) { + return baseXor(arrayFilter(arrays, isArrayLikeObject)); + }); + + /** + * This method is like `_.xor` except that it accepts `iteratee` which is + * invoked for each element of each `arrays` to generate the criterion by + * which by which they're compared. The order of result values is determined + * by the order they occur in the arrays. The iteratee is invoked with one + * argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor); + * // => [1.2, 3.4] + * + * // The `_.property` iteratee shorthand. + * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 2 }] + */ + var xorBy = baseRest(function(arrays) { + var iteratee = last(arrays); + if (isArrayLikeObject(iteratee)) { + iteratee = undefined; + } + return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2)); + }); + + /** + * This method is like `_.xor` except that it accepts `comparator` which is + * invoked to compare elements of `arrays`. The order of result values is + * determined by the order they occur in the arrays. The comparator is invoked + * with two arguments: (arrVal, othVal). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; + * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; + * + * _.xorWith(objects, others, _.isEqual); + * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] + */ + var xorWith = baseRest(function(arrays) { + var comparator = last(arrays); + comparator = typeof comparator == 'function' ? comparator : undefined; + return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator); + }); + + /** + * Creates an array of grouped elements, the first of which contains the + * first elements of the given arrays, the second of which contains the + * second elements of the given arrays, and so on. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zip(['a', 'b'], [1, 2], [true, false]); + * // => [['a', 1, true], ['b', 2, false]] + */ + var zip = baseRest(unzip); + + /** + * This method is like `_.fromPairs` except that it accepts two arrays, + * one of property identifiers and one of corresponding values. + * + * @static + * @memberOf _ + * @since 0.4.0 + * @category Array + * @param {Array} [props=[]] The property identifiers. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObject(['a', 'b'], [1, 2]); + * // => { 'a': 1, 'b': 2 } + */ + function zipObject(props, values) { + return baseZipObject(props || [], values || [], assignValue); + } + + /** + * This method is like `_.zipObject` except that it supports property paths. + * + * @static + * @memberOf _ + * @since 4.1.0 + * @category Array + * @param {Array} [props=[]] The property identifiers. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]); + * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } } + */ + function zipObjectDeep(props, values) { + return baseZipObject(props || [], values || [], baseSet); + } + + /** + * This method is like `_.zip` except that it accepts `iteratee` to specify + * how grouped values should be combined. The iteratee is invoked with the + * elements of each group: (...group). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @param {Function} [iteratee=_.identity] The function to combine + * grouped values. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) { + * return a + b + c; + * }); + * // => [111, 222] + */ + var zipWith = baseRest(function(arrays) { + var length = arrays.length, + iteratee = length > 1 ? arrays[length - 1] : undefined; + + iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined; + return unzipWith(arrays, iteratee); + }); + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` wrapper instance that wraps `value` with explicit method + * chain sequences enabled. The result of such sequences must be unwrapped + * with `_#value`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Seq + * @param {*} value The value to wrap. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'pebbles', 'age': 1 } + * ]; + * + * var youngest = _ + * .chain(users) + * .sortBy('age') + * .map(function(o) { + * return o.user + ' is ' + o.age; + * }) + * .head() + * .value(); + * // => 'pebbles is 1' + */ + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + + /** + * This method invokes `interceptor` and returns `value`. The interceptor + * is invoked with one argument; (value). The purpose of this method is to + * "tap into" a method chain sequence in order to modify intermediate results. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns `value`. + * @example + * + * _([1, 2, 3]) + * .tap(function(array) { + * // Mutate input array. + * array.pop(); + * }) + * .reverse() + * .value(); + * // => [2, 1] + */ + function tap(value, interceptor) { + interceptor(value); + return value; + } + + /** + * This method is like `_.tap` except that it returns the result of `interceptor`. + * The purpose of this method is to "pass thru" values replacing intermediate + * results in a method chain sequence. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Seq + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @returns {*} Returns the result of `interceptor`. + * @example + * + * _(' abc ') + * .chain() + * .trim() + * .thru(function(value) { + * return [value]; + * }) + * .value(); + * // => ['abc'] + */ + function thru(value, interceptor) { + return interceptor(value); + } + + /** + * This method is the wrapper version of `_.at`. + * + * @name at + * @memberOf _ + * @since 1.0.0 + * @category Seq + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _(object).at(['a[0].b.c', 'a[1]']).value(); + * // => [3, 4] + */ + var wrapperAt = flatRest(function(paths) { + var length = paths.length, + start = length ? paths[0] : 0, + value = this.__wrapped__, + interceptor = function(object) { return baseAt(object, paths); }; + + if (length > 1 || this.__actions__.length || + !(value instanceof LazyWrapper) || !isIndex(start)) { + return this.thru(interceptor); + } + value = value.slice(start, +start + (length ? 1 : 0)); + value.__actions__.push({ + 'func': thru, + 'args': [interceptor], + 'thisArg': undefined + }); + return new LodashWrapper(value, this.__chain__).thru(function(array) { + if (length && !array.length) { + array.push(undefined); + } + return array; + }); + }); + + /** + * Creates a `lodash` wrapper instance with explicit method chain sequences enabled. + * + * @name chain + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * // A sequence without explicit chaining. + * _(users).head(); + * // => { 'user': 'barney', 'age': 36 } + * + * // A sequence with explicit chaining. + * _(users) + * .chain() + * .head() + * .pick('user') + * .value(); + * // => { 'user': 'barney' } + */ + function wrapperChain() { + return chain(this); + } + + /** + * Executes the chain sequence and returns the wrapped result. + * + * @name commit + * @memberOf _ + * @since 3.2.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2]; + * var wrapped = _(array).push(3); + * + * console.log(array); + * // => [1, 2] + * + * wrapped = wrapped.commit(); + * console.log(array); + * // => [1, 2, 3] + * + * wrapped.last(); + * // => 3 + * + * console.log(array); + * // => [1, 2, 3] + */ + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + + /** + * Gets the next value on a wrapped object following the + * [iterator protocol](https://mdn.io/iteration_protocols#iterator). + * + * @name next + * @memberOf _ + * @since 4.0.0 + * @category Seq + * @returns {Object} Returns the next iterator value. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped.next(); + * // => { 'done': false, 'value': 1 } + * + * wrapped.next(); + * // => { 'done': false, 'value': 2 } + * + * wrapped.next(); + * // => { 'done': true, 'value': undefined } + */ + function wrapperNext() { + if (this.__values__ === undefined) { + this.__values__ = toArray(this.value()); + } + var done = this.__index__ >= this.__values__.length, + value = done ? undefined : this.__values__[this.__index__++]; + + return { 'done': done, 'value': value }; + } + + /** + * Enables the wrapper to be iterable. + * + * @name Symbol.iterator + * @memberOf _ + * @since 4.0.0 + * @category Seq + * @returns {Object} Returns the wrapper object. + * @example + * + * var wrapped = _([1, 2]); + * + * wrapped[Symbol.iterator]() === wrapped; + * // => true + * + * Array.from(wrapped); + * // => [1, 2] + */ + function wrapperToIterator() { + return this; + } + + /** + * Creates a clone of the chain sequence planting `value` as the wrapped value. + * + * @name plant + * @memberOf _ + * @since 3.2.0 + * @category Seq + * @param {*} value The value to plant. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * function square(n) { + * return n * n; + * } + * + * var wrapped = _([1, 2]).map(square); + * var other = wrapped.plant([3, 4]); + * + * other.value(); + * // => [9, 16] + * + * wrapped.value(); + * // => [1, 4] + */ + function wrapperPlant(value) { + var result, + parent = this; + + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + clone.__index__ = 0; + clone.__values__ = undefined; + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + + /** + * This method is the wrapper version of `_.reverse`. + * + * **Note:** This method mutates the wrapped array. + * + * @name reverse + * @memberOf _ + * @since 0.1.0 + * @category Seq + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2, 3]; + * + * _(array).reverse().value() + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function wrapperReverse() { + var value = this.__wrapped__; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + 'func': thru, + 'args': [reverse], + 'thisArg': undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(reverse); + } + + /** + * Executes the chain sequence to resolve the unwrapped value. + * + * @name value + * @memberOf _ + * @since 0.1.0 + * @alias toJSON, valueOf + * @category Seq + * @returns {*} Returns the resolved unwrapped value. + * @example + * + * _([1, 2, 3]).value(); + * // => [1, 2, 3] + */ + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the number of times the key was returned by `iteratee`. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.countBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': 1, '6': 2 } + * + * // The `_.property` iteratee shorthand. + * _.countBy(['one', 'two', 'three'], 'length'); + * // => { '3': 2, '5': 1 } + */ + var countBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + ++result[key]; + } else { + baseAssignValue(result, key, 1); + } + }); + + /** + * Checks if `predicate` returns truthy for **all** elements of `collection`. + * Iteration is stopped once `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * **Note:** This method returns `true` for + * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because + * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of + * elements of empty collections. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.every(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.every(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.every(users, 'active'); + * // => false + */ + function every(collection, predicate, guard) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Iterates over elements of `collection`, returning an array of all elements + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * **Note:** Unlike `_.remove`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.reject + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * _.filter(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.filter(users, { 'age': 36, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.filter(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.filter(users, 'active'); + * // => objects for ['barney'] + * + * // Combining several predicates using `_.overEvery` or `_.overSome`. + * _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]])); + * // => objects for ['fred', 'barney'] + */ + function filter(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Iterates over elements of `collection`, returning the first element + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false }, + * { 'user': 'pebbles', 'age': 1, 'active': true } + * ]; + * + * _.find(users, function(o) { return o.age < 40; }); + * // => object for 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.find(users, { 'age': 1, 'active': true }); + * // => object for 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.find(users, ['active', false]); + * // => object for 'fred' + * + * // The `_.property` iteratee shorthand. + * _.find(users, 'active'); + * // => object for 'barney' + */ + var find = createFind(findIndex); + + /** + * This method is like `_.find` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=collection.length-1] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * _.findLast([1, 2, 3, 4], function(n) { + * return n % 2 == 1; + * }); + * // => 3 + */ + var findLast = createFind(findLastIndex); + + /** + * Creates a flattened array of values by running each element in `collection` + * thru `iteratee` and flattening the mapped results. The iteratee is invoked + * with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [n, n]; + * } + * + * _.flatMap([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ + function flatMap(collection, iteratee) { + return baseFlatten(map(collection, iteratee), 1); + } + + /** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDeep([1, 2], duplicate); + * // => [1, 1, 2, 2] + */ + function flatMapDeep(collection, iteratee) { + return baseFlatten(map(collection, iteratee), INFINITY); + } + + /** + * This method is like `_.flatMap` except that it recursively flattens the + * mapped results up to `depth` times. + * + * @static + * @memberOf _ + * @since 4.7.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {number} [depth=1] The maximum recursion depth. + * @returns {Array} Returns the new flattened array. + * @example + * + * function duplicate(n) { + * return [[[n, n]]]; + * } + * + * _.flatMapDepth([1, 2], duplicate, 2); + * // => [[1, 1], [2, 2]] + */ + function flatMapDepth(collection, iteratee, depth) { + depth = depth === undefined ? 1 : toInteger(depth); + return baseFlatten(map(collection, iteratee), depth); + } + + /** + * Iterates over elements of `collection` and invokes `iteratee` for each element. + * The iteratee is invoked with three arguments: (value, index|key, collection). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * **Note:** As with other "Collections" methods, objects with a "length" + * property are iterated like arrays. To avoid this behavior use `_.forIn` + * or `_.forOwn` for object iteration. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @alias each + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEachRight + * @example + * + * _.forEach([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `1` then `2`. + * + * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forEach(collection, iteratee) { + var func = isArray(collection) ? arrayEach : baseEach; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.forEach` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @alias eachRight + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + * @see _.forEach + * @example + * + * _.forEachRight([1, 2], function(value) { + * console.log(value); + * }); + * // => Logs `2` then `1`. + */ + function forEachRight(collection, iteratee) { + var func = isArray(collection) ? arrayEachRight : baseEachRight; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The order of grouped values + * is determined by the order they occur in `collection`. The corresponding + * value of each key is an array of elements responsible for generating the + * key. The iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.groupBy([6.1, 4.2, 6.3], Math.floor); + * // => { '4': [4.2], '6': [6.1, 6.3] } + * + * // The `_.property` iteratee shorthand. + * _.groupBy(['one', 'two', 'three'], 'length'); + * // => { '3': ['one', 'two'], '5': ['three'] } + */ + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + baseAssignValue(result, key, [value]); + } + }); + + /** + * Checks if `value` is in `collection`. If `collection` is a string, it's + * checked for a substring of `value`, otherwise + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * is used for equality comparisons. If `fromIndex` is negative, it's used as + * the offset from the end of `collection`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @param {*} value The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. + * @returns {boolean} Returns `true` if `value` is found, else `false`. + * @example + * + * _.includes([1, 2, 3], 1); + * // => true + * + * _.includes([1, 2, 3], 1, 2); + * // => false + * + * _.includes({ 'a': 1, 'b': 2 }, 1); + * // => true + * + * _.includes('abcd', 'bc'); + * // => true + */ + function includes(collection, value, fromIndex, guard) { + collection = isArrayLike(collection) ? collection : values(collection); + fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0; + + var length = collection.length; + if (fromIndex < 0) { + fromIndex = nativeMax(length + fromIndex, 0); + } + return isString(collection) + ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1) + : (!!length && baseIndexOf(collection, value, fromIndex) > -1); + } + + /** + * Invokes the method at `path` of each element in `collection`, returning + * an array of the results of each invoked method. Any additional arguments + * are provided to each invoked method. If `path` is a function, it's invoked + * for, and `this` bound to, each element in `collection`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Array|Function|string} path The path of the method to invoke or + * the function invoked per iteration. + * @param {...*} [args] The arguments to invoke each method with. + * @returns {Array} Returns the array of results. + * @example + * + * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort'); + * // => [[1, 5, 7], [1, 2, 3]] + * + * _.invokeMap([123, 456], String.prototype.split, ''); + * // => [['1', '2', '3'], ['4', '5', '6']] + */ + var invokeMap = baseRest(function(collection, path, args) { + var index = -1, + isFunc = typeof path == 'function', + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value) { + result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args); + }); + return result; + }); + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` thru `iteratee`. The corresponding value of + * each key is the last element responsible for generating the key. The + * iteratee is invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The iteratee to transform keys. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * var array = [ + * { 'dir': 'left', 'code': 97 }, + * { 'dir': 'right', 'code': 100 } + * ]; + * + * _.keyBy(array, function(o) { + * return String.fromCharCode(o.code); + * }); + * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } + * + * _.keyBy(array, 'dir'); + * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } + */ + var keyBy = createAggregator(function(result, value, key) { + baseAssignValue(result, key, value); + }); + + /** + * Creates an array of values by running each element in `collection` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. + * + * The guarded methods are: + * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, + * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, + * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, + * `template`, `trim`, `trimEnd`, `trimStart`, and `words` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + * @example + * + * function square(n) { + * return n * n; + * } + * + * _.map([4, 8], square); + * // => [16, 64] + * + * _.map({ 'a': 4, 'b': 8 }, square); + * // => [16, 64] (iteration order is not guaranteed) + * + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * // The `_.property` iteratee shorthand. + * _.map(users, 'user'); + * // => ['barney', 'fred'] + */ + function map(collection, iteratee) { + var func = isArray(collection) ? arrayMap : baseMap; + return func(collection, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.sortBy` except that it allows specifying the sort + * orders of the iteratees to sort by. If `orders` is unspecified, all values + * are sorted in ascending order. Otherwise, specify an order of "desc" for + * descending or "asc" for ascending sort order of corresponding values. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]] + * The iteratees to sort by. + * @param {string[]} [orders] The sort orders of `iteratees`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 34 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'barney', 'age': 36 } + * ]; + * + * // Sort by `user` in ascending order and by `age` in descending order. + * _.orderBy(users, ['user', 'age'], ['asc', 'desc']); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] + */ + function orderBy(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [iteratees]; + } + orders = guard ? undefined : orders; + if (!isArray(orders)) { + orders = orders == null ? [] : [orders]; + } + return baseOrderBy(collection, iteratees, orders); + } + + /** + * Creates an array of elements split into two groups, the first of which + * contains elements `predicate` returns truthy for, the second of which + * contains elements `predicate` returns falsey for. The predicate is + * invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the array of grouped elements. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true }, + * { 'user': 'pebbles', 'age': 1, 'active': false } + * ]; + * + * _.partition(users, function(o) { return o.active; }); + * // => objects for [['fred'], ['barney', 'pebbles']] + * + * // The `_.matches` iteratee shorthand. + * _.partition(users, { 'age': 1, 'active': false }); + * // => objects for [['pebbles'], ['barney', 'fred']] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.partition(users, ['active', false]); + * // => objects for [['barney', 'pebbles'], ['fred']] + * + * // The `_.property` iteratee shorthand. + * _.partition(users, 'active'); + * // => objects for [['fred'], ['barney', 'pebbles']] + */ + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { return [[], []]; }); + + /** + * Reduces `collection` to a value which is the accumulated result of running + * each element in `collection` thru `iteratee`, where each successive + * invocation is supplied the return value of the previous. If `accumulator` + * is not given, the first element of `collection` is used as the initial + * value. The iteratee is invoked with four arguments: + * (accumulator, value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.reduce`, `_.reduceRight`, and `_.transform`. + * + * The guarded methods are: + * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, + * and `sortBy` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduceRight + * @example + * + * _.reduce([1, 2], function(sum, n) { + * return sum + n; + * }, 0); + * // => 3 + * + * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * return result; + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) + */ + function reduce(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduce : baseReduce, + initAccum = arguments.length < 3; + + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach); + } + + /** + * This method is like `_.reduce` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @returns {*} Returns the accumulated value. + * @see _.reduce + * @example + * + * var array = [[0, 1], [2, 3], [4, 5]]; + * + * _.reduceRight(array, function(flattened, other) { + * return flattened.concat(other); + * }, []); + * // => [4, 5, 2, 3, 0, 1] + */ + function reduceRight(collection, iteratee, accumulator) { + var func = isArray(collection) ? arrayReduceRight : baseReduce, + initAccum = arguments.length < 3; + + return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight); + } + + /** + * The opposite of `_.filter`; this method returns the elements of `collection` + * that `predicate` does **not** return truthy for. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + * @see _.filter + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true } + * ]; + * + * _.reject(users, function(o) { return !o.active; }); + * // => objects for ['fred'] + * + * // The `_.matches` iteratee shorthand. + * _.reject(users, { 'age': 40, 'active': true }); + * // => objects for ['barney'] + * + * // The `_.matchesProperty` iteratee shorthand. + * _.reject(users, ['active', false]); + * // => objects for ['fred'] + * + * // The `_.property` iteratee shorthand. + * _.reject(users, 'active'); + * // => objects for ['barney'] + */ + function reject(collection, predicate) { + var func = isArray(collection) ? arrayFilter : baseFilter; + return func(collection, negate(getIteratee(predicate, 3))); + } + + /** + * Gets a random element from `collection`. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @returns {*} Returns the random element. + * @example + * + * _.sample([1, 2, 3, 4]); + * // => 2 + */ + function sample(collection) { + var func = isArray(collection) ? arraySample : baseSample; + return func(collection); + } + + /** + * Gets `n` random elements at unique keys from `collection` up to the + * size of `collection`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Collection + * @param {Array|Object} collection The collection to sample. + * @param {number} [n=1] The number of elements to sample. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Array} Returns the random elements. + * @example + * + * _.sampleSize([1, 2, 3], 2); + * // => [3, 1] + * + * _.sampleSize([1, 2, 3], 4); + * // => [2, 3, 1] + */ + function sampleSize(collection, n, guard) { + if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); + } + var func = isArray(collection) ? arraySampleSize : baseSampleSize; + return func(collection, n); + } + + /** + * Creates an array of shuffled values, using a version of the + * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + * @example + * + * _.shuffle([1, 2, 3, 4]); + * // => [4, 1, 3, 2] + */ + function shuffle(collection) { + var func = isArray(collection) ? arrayShuffle : baseShuffle; + return func(collection); + } + + /** + * Gets the size of `collection` by returning its length for array-like + * values or the number of own enumerable string keyed properties for objects. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @returns {number} Returns the collection size. + * @example + * + * _.size([1, 2, 3]); + * // => 3 + * + * _.size({ 'a': 1, 'b': 2 }); + * // => 2 + * + * _.size('pebbles'); + * // => 7 + */ + function size(collection) { + if (collection == null) { + return 0; + } + if (isArrayLike(collection)) { + return isString(collection) ? stringSize(collection) : collection.length; + } + var tag = getTag(collection); + if (tag == mapTag || tag == setTag) { + return collection.size; + } + return baseKeys(collection).length; + } + + /** + * Checks if `predicate` returns truthy for **any** element of `collection`. + * Iteration is stopped once `predicate` returns truthy. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + * @example + * + * _.some([null, 0, 'yes', false], Boolean); + * // => true + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.some(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.some(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.some(users, 'active'); + * // => true + */ + function some(collection, predicate, guard) { + var func = isArray(collection) ? arraySome : baseSome; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, getIteratee(predicate, 3)); + } + + /** + * Creates an array of elements, sorted in ascending order by the results of + * running each element in a collection thru each iteratee. This method + * performs a stable sort, that is, it preserves the original sort order of + * equal elements. The iteratees are invoked with one argument: (value). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {...(Function|Function[])} [iteratees=[_.identity]] + * The iteratees to sort by. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'fred', 'age': 48 }, + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 30 }, + * { 'user': 'barney', 'age': 34 } + * ]; + * + * _.sortBy(users, [function(o) { return o.user; }]); + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]] + * + * _.sortBy(users, ['user', 'age']); + * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]] + */ + var sortBy = baseRest(function(collection, iteratees) { + if (collection == null) { + return []; + } + var length = iteratees.length; + if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) { + iteratees = []; + } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) { + iteratees = [iteratees[0]]; + } + return baseOrderBy(collection, baseFlatten(iteratees, 1), []); + }); + + /*------------------------------------------------------------------------*/ + + /** + * Gets the timestamp of the number of milliseconds that have elapsed since + * the Unix epoch (1 January 1970 00:00:00 UTC). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Date + * @returns {number} Returns the timestamp. + * @example + * + * _.defer(function(stamp) { + * console.log(_.now() - stamp); + * }, _.now()); + * // => Logs the number of milliseconds it took for the deferred invocation. + */ + var now = ctxNow || function() { + return root.Date.now(); + }; + + /*------------------------------------------------------------------------*/ + + /** + * The opposite of `_.before`; this method creates a function that invokes + * `func` once it's called `n` or more times. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {number} n The number of calls before `func` is invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var saves = ['profile', 'settings']; + * + * var done = _.after(saves.length, function() { + * console.log('done saving!'); + * }); + * + * _.forEach(saves, function(type) { + * asyncSave({ 'type': type, 'complete': done }); + * }); + * // => Logs 'done saving!' after the two async saves have completed. + */ + function after(n, func) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + + /** + * Creates a function that invokes `func`, with up to `n` arguments, + * ignoring any additional arguments. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to cap arguments for. + * @param {number} [n=func.length] The arity cap. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new capped function. + * @example + * + * _.map(['6', '8', '10'], _.ary(parseInt, 1)); + * // => [6, 8, 10] + */ + function ary(func, n, guard) { + n = guard ? undefined : n; + n = (func && n == null) ? func.length : n; + return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + + /** + * Creates a function that invokes `func`, with the `this` binding and arguments + * of the created function, while it's called less than `n` times. Subsequent + * calls to the created function return the result of the last `func` invocation. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {number} n The number of calls at which `func` is no longer invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * jQuery(element).on('click', _.before(5, addContactToList)); + * // => Allows adding up to 4 contacts to the list. + */ + function before(n, func) { + var result; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + + /** + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and `partials` prepended to the arguments it receives. + * + * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for partially applied arguments. + * + * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" + * property of bound functions. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * function greet(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * + * var object = { 'user': 'fred' }; + * + * var bound = _.bind(greet, object, 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * // Bound with placeholders. + * var bound = _.bind(greet, object, _, '!'); + * bound('hi'); + * // => 'hi fred!' + */ + var bind = baseRest(function(func, thisArg, partials) { + var bitmask = WRAP_BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bind)); + bitmask |= WRAP_PARTIAL_FLAG; + } + return createWrap(func, bitmask, thisArg, partials, holders); + }); + + /** + * Creates a function that invokes the method at `object[key]` with `partials` + * prepended to the arguments it receives. + * + * This method differs from `_.bind` by allowing bound functions to reference + * methods that may be redefined or don't yet exist. See + * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern) + * for more details. + * + * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Function + * @param {Object} object The object to invoke the method on. + * @param {string} key The key of the method. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var object = { + * 'user': 'fred', + * 'greet': function(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * }; + * + * var bound = _.bindKey(object, 'greet', 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * object.greet = function(greeting, punctuation) { + * return greeting + 'ya ' + this.user + punctuation; + * }; + * + * bound('!'); + * // => 'hiya fred!' + * + * // Bound with placeholders. + * var bound = _.bindKey(object, 'greet', _, '!'); + * bound('hi'); + * // => 'hiya fred!' + */ + var bindKey = baseRest(function(object, key, partials) { + var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, getHolder(bindKey)); + bitmask |= WRAP_PARTIAL_FLAG; + } + return createWrap(key, bitmask, object, partials, holders); + }); + + /** + * Creates a function that accepts arguments of `func` and either invokes + * `func` returning its result, if at least `arity` number of arguments have + * been provided, or returns a function that accepts the remaining `func` + * arguments, and so on. The arity of `func` may be specified if `func.length` + * is not sufficient. + * + * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curry(abc); + * + * curried(1)(2)(3); + * // => [1, 2, 3] + * + * curried(1, 2)(3); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(1)(_, 3)(2); + * // => [1, 2, 3] + */ + function curry(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curry.placeholder; + return result; + } + + /** + * This method is like `_.curry` except that arguments are applied to `func` + * in the manner of `_.partialRight` instead of `_.partial`. + * + * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for provided arguments. + * + * **Note:** This method doesn't set the "length" property of curried functions. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the new curried function. + * @example + * + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curryRight(abc); + * + * curried(3)(2)(1); + * // => [1, 2, 3] + * + * curried(2, 3)(1); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // Curried with placeholders. + * curried(3)(1, _)(2); + * // => [1, 2, 3] + */ + function curryRight(func, arity, guard) { + arity = guard ? undefined : arity; + var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryRight.placeholder; + return result; + } + + /** + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked. The debounced function comes with a `cancel` method to cancel + * delayed `func` invocations and a `flush` method to immediately invoke them. + * Provide `options` to indicate whether `func` should be invoked on the + * leading and/or trailing edge of the `wait` timeout. The `func` is invoked + * with the last arguments provided to the debounced function. Subsequent + * calls to the debounced function return the result of the last `func` + * invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the debounced function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.debounce` and `_.throttle`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to debounce. + * @param {number} [wait=0] The number of milliseconds to delay. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=false] + * Specify invoking on the leading edge of the timeout. + * @param {number} [options.maxWait] + * The maximum time `func` is allowed to be delayed before it's invoked. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * // Avoid costly calculations while the window size is in flux. + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); + * + * // Invoke `sendMail` when clicked, debouncing subsequent calls. + * jQuery(element).on('click', _.debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * })); + * + * // Ensure `batchLog` is invoked once after 1 second of debounced calls. + * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); + * var source = new EventSource('/stream'); + * jQuery(source).on('message', debounced); + * + * // Cancel the trailing debounced invocation. + * jQuery(window).on('popstate', debounced.cancel); + */ + function debounce(func, wait, options) { + var lastArgs, + lastThis, + maxWait, + result, + timerId, + lastCallTime, + lastInvokeTime = 0, + leading = false, + maxing = false, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = toNumber(wait) || 0; + if (isObject(options)) { + leading = !!options.leading; + maxing = 'maxWait' in options; + maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + + function invokeFunc(time) { + var args = lastArgs, + thisArg = lastThis; + + lastArgs = lastThis = undefined; + lastInvokeTime = time; + result = func.apply(thisArg, args); + return result; + } + + function leadingEdge(time) { + // Reset any `maxWait` timer. + lastInvokeTime = time; + // Start the timer for the trailing edge. + timerId = setTimeout(timerExpired, wait); + // Invoke the leading edge. + return leading ? invokeFunc(time) : result; + } + + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime, + timeWaiting = wait - timeSinceLastCall; + + return maxing + ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) + : timeWaiting; + } + + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime; + + // Either this is the first call, activity has stopped and we're at the + // trailing edge, the system time has gone backwards and we're treating + // it as the trailing edge, or we've hit the `maxWait` limit. + return (lastCallTime === undefined || (timeSinceLastCall >= wait) || + (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); + } + + function timerExpired() { + var time = now(); + if (shouldInvoke(time)) { + return trailingEdge(time); + } + // Restart the timer. + timerId = setTimeout(timerExpired, remainingWait(time)); + } + + function trailingEdge(time) { + timerId = undefined; + + // Only invoke if we have `lastArgs` which means `func` has been + // debounced at least once. + if (trailing && lastArgs) { + return invokeFunc(time); + } + lastArgs = lastThis = undefined; + return result; + } + + function cancel() { + if (timerId !== undefined) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = undefined; + } + + function flush() { + return timerId === undefined ? result : trailingEdge(now()); + } + + function debounced() { + var time = now(), + isInvoking = shouldInvoke(time); + + lastArgs = arguments; + lastThis = this; + lastCallTime = time; + + if (isInvoking) { + if (timerId === undefined) { + return leadingEdge(lastCallTime); + } + if (maxing) { + // Handle invocations in a tight loop. + clearTimeout(timerId); + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); + } + } + if (timerId === undefined) { + timerId = setTimeout(timerExpired, wait); + } + return result; + } + debounced.cancel = cancel; + debounced.flush = flush; + return debounced; + } + + /** + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to defer. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.defer(function(text) { + * console.log(text); + * }, 'deferred'); + * // => Logs 'deferred' after one millisecond. + */ + var defer = baseRest(function(func, args) { + return baseDelay(func, 1, args); + }); + + /** + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it's invoked. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {...*} [args] The arguments to invoke `func` with. + * @returns {number} Returns the timer id. + * @example + * + * _.delay(function(text) { + * console.log(text); + * }, 1000, 'later'); + * // => Logs 'later' after one second. + */ + var delay = baseRest(function(func, wait, args) { + return baseDelay(func, toNumber(wait) || 0, args); + }); + + /** + * Creates a function that invokes `func` with arguments reversed. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to flip arguments for. + * @returns {Function} Returns the new flipped function. + * @example + * + * var flipped = _.flip(function() { + * return _.toArray(arguments); + * }); + * + * flipped('a', 'b', 'c', 'd'); + * // => ['d', 'c', 'b', 'a'] + */ + function flip(func) { + return createWrap(func, WRAP_FLIP_FLAG); + } + + /** + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided, it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the map cache key. The `func` + * is invoked with the `this` binding of the memoized function. + * + * **Note:** The cache is exposed as the `cache` property on the memoized + * function. Its creation may be customized by replacing the `_.memoize.Cache` + * constructor with one whose instances implement the + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) + * method interface of `clear`, `delete`, `get`, `has`, and `set`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] The function to resolve the cache key. + * @returns {Function} Returns the new memoized function. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * var other = { 'c': 3, 'd': 4 }; + * + * var values = _.memoize(_.values); + * values(object); + * // => [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] + * + * // Modify the result cache. + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] + * + * // Replace `_.memoize.Cache`. + * _.memoize.Cache = WeakMap; + */ + function memoize(func, resolver) { + if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, + key = resolver ? resolver.apply(this, args) : args[0], + cache = memoized.cache; + + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result) || cache; + return result; + }; + memoized.cache = new (memoize.Cache || MapCache); + return memoized; + } + + // Expose `MapCache`. + memoize.Cache = MapCache; + + /** + * Creates a function that negates the result of the predicate `func`. The + * `func` predicate is invoked with the `this` binding and arguments of the + * created function. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} predicate The predicate to negate. + * @returns {Function} Returns the new negated function. + * @example + * + * function isEven(n) { + * return n % 2 == 0; + * } + * + * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); + * // => [1, 3, 5] + */ + function negate(predicate) { + if (typeof predicate != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var args = arguments; + switch (args.length) { + case 0: return !predicate.call(this); + case 1: return !predicate.call(this, args[0]); + case 2: return !predicate.call(this, args[0], args[1]); + case 3: return !predicate.call(this, args[0], args[1], args[2]); + } + return !predicate.apply(this, args); + }; + } + + /** + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first invocation. The `func` is + * invoked with the `this` binding and arguments of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // => `createApplication` is invoked once + */ + function once(func) { + return before(2, func); + } + + /** + * Creates a function that invokes `func` with its arguments transformed. + * + * @static + * @since 4.0.0 + * @memberOf _ + * @category Function + * @param {Function} func The function to wrap. + * @param {...(Function|Function[])} [transforms=[_.identity]] + * The argument transforms. + * @returns {Function} Returns the new function. + * @example + * + * function doubled(n) { + * return n * 2; + * } + * + * function square(n) { + * return n * n; + * } + * + * var func = _.overArgs(function(x, y) { + * return [x, y]; + * }, [square, doubled]); + * + * func(9, 3); + * // => [81, 6] + * + * func(10, 5); + * // => [100, 10] + */ + var overArgs = castRest(function(func, transforms) { + transforms = (transforms.length == 1 && isArray(transforms[0])) + ? arrayMap(transforms[0], baseUnary(getIteratee())) + : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee())); + + var funcsLength = transforms.length; + return baseRest(function(args) { + var index = -1, + length = nativeMin(args.length, funcsLength); + + while (++index < length) { + args[index] = transforms[index].call(this, args[index]); + } + return apply(func, this, args); + }); + }); + + /** + * Creates a function that invokes `func` with `partials` prepended to the + * arguments it receives. This method is like `_.bind` except it does **not** + * alter the `this` binding. + * + * The `_.partial.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * **Note:** This method doesn't set the "length" property of partially + * applied functions. + * + * @static + * @memberOf _ + * @since 0.2.0 + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * function greet(greeting, name) { + * return greeting + ' ' + name; + * } + * + * var sayHelloTo = _.partial(greet, 'hello'); + * sayHelloTo('fred'); + * // => 'hello fred' + * + * // Partially applied with placeholders. + * var greetFred = _.partial(greet, _, 'fred'); + * greetFred('hi'); + * // => 'hi fred' + */ + var partial = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partial)); + return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders); + }); + + /** + * This method is like `_.partial` except that partially applied arguments + * are appended to the arguments it receives. + * + * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * **Note:** This method doesn't set the "length" property of partially + * applied functions. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * function greet(greeting, name) { + * return greeting + ' ' + name; + * } + * + * var greetFred = _.partialRight(greet, 'fred'); + * greetFred('hi'); + * // => 'hi fred' + * + * // Partially applied with placeholders. + * var sayHelloTo = _.partialRight(greet, 'hello', _); + * sayHelloTo('fred'); + * // => 'hello fred' + */ + var partialRight = baseRest(function(func, partials) { + var holders = replaceHolders(partials, getHolder(partialRight)); + return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders); + }); + + /** + * Creates a function that invokes `func` with arguments arranged according + * to the specified `indexes` where the argument value at the first index is + * provided as the first argument, the argument value at the second index is + * provided as the second argument, and so on. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {Function} func The function to rearrange arguments for. + * @param {...(number|number[])} indexes The arranged argument indexes. + * @returns {Function} Returns the new function. + * @example + * + * var rearged = _.rearg(function(a, b, c) { + * return [a, b, c]; + * }, [2, 0, 1]); + * + * rearged('b', 'c', 'a') + * // => ['a', 'b', 'c'] + */ + var rearg = flatRest(function(func, indexes) { + return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes); + }); + + /** + * Creates a function that invokes `func` with the `this` binding of the + * created function and arguments from `start` and beyond provided as + * an array. + * + * **Note:** This method is based on the + * [rest parameter](https://mdn.io/rest_parameters). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.rest(function(what, names) { + * return what + ' ' + _.initial(names).join(', ') + + * (_.size(names) > 1 ? ', & ' : '') + _.last(names); + * }); + * + * say('hello', 'fred', 'barney', 'pebbles'); + * // => 'hello fred, barney, & pebbles' + */ + function rest(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start === undefined ? start : toInteger(start); + return baseRest(func, start); + } + + /** + * Creates a function that invokes `func` with the `this` binding of the + * create function and an array of arguments much like + * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply). + * + * **Note:** This method is based on the + * [spread operator](https://mdn.io/spread_operator). + * + * @static + * @memberOf _ + * @since 3.2.0 + * @category Function + * @param {Function} func The function to spread arguments over. + * @param {number} [start=0] The start position of the spread. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.spread(function(who, what) { + * return who + ' says ' + what; + * }); + * + * say(['fred', 'hello']); + * // => 'fred says hello' + * + * var numbers = Promise.all([ + * Promise.resolve(40), + * Promise.resolve(36) + * ]); + * + * numbers.then(_.spread(function(x, y) { + * return x + y; + * })); + * // => a Promise of 76 + */ + function spread(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = start == null ? 0 : nativeMax(toInteger(start), 0); + return baseRest(function(args) { + var array = args[start], + otherArgs = castSlice(args, 0, start); + + if (array) { + arrayPush(otherArgs, array); + } + return apply(func, this, otherArgs); + }); + } + + /** + * Creates a throttled function that only invokes `func` at most once per + * every `wait` milliseconds. The throttled function comes with a `cancel` + * method to cancel delayed `func` invocations and a `flush` method to + * immediately invoke them. Provide `options` to indicate whether `func` + * should be invoked on the leading and/or trailing edge of the `wait` + * timeout. The `func` is invoked with the last arguments provided to the + * throttled function. Subsequent calls to the throttled function return the + * result of the last `func` invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the throttled function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.throttle` and `_.debounce`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to throttle. + * @param {number} [wait=0] The number of milliseconds to throttle invocations to. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=true] + * Specify invoking on the leading edge of the timeout. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new throttled function. + * @example + * + * // Avoid excessively updating the position while scrolling. + * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); + * + * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. + * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); + * jQuery(element).on('click', throttled); + * + * // Cancel the trailing throttled invocation. + * jQuery(window).on('popstate', throttled.cancel); + */ + function throttle(func, wait, options) { + var leading = true, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (isObject(options)) { + leading = 'leading' in options ? !!options.leading : leading; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + 'leading': leading, + 'maxWait': wait, + 'trailing': trailing + }); + } + + /** + * Creates a function that accepts up to one argument, ignoring any + * additional arguments. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Function + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + * @example + * + * _.map(['6', '8', '10'], _.unary(parseInt)); + * // => [6, 8, 10] + */ + function unary(func) { + return ary(func, 1); + } + + /** + * Creates a function that provides `value` to `wrapper` as its first + * argument. Any additional arguments provided to the function are appended + * to those provided to the `wrapper`. The wrapper is invoked with the `this` + * binding of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {*} value The value to wrap. + * @param {Function} [wrapper=identity] The wrapper function. + * @returns {Function} Returns the new function. + * @example + * + * var p = _.wrap(_.escape, function(func, text) { + * return '

    ' + func(text) + '

    '; + * }); + * + * p('fred, barney, & pebbles'); + * // => '

    fred, barney, & pebbles

    ' + */ + function wrap(value, wrapper) { + return partial(castFunction(wrapper), value); + } + + /*------------------------------------------------------------------------*/ + + /** + * Casts `value` as an array if it's not one. + * + * @static + * @memberOf _ + * @since 4.4.0 + * @category Lang + * @param {*} value The value to inspect. + * @returns {Array} Returns the cast array. + * @example + * + * _.castArray(1); + * // => [1] + * + * _.castArray({ 'a': 1 }); + * // => [{ 'a': 1 }] + * + * _.castArray('abc'); + * // => ['abc'] + * + * _.castArray(null); + * // => [null] + * + * _.castArray(undefined); + * // => [undefined] + * + * _.castArray(); + * // => [] + * + * var array = [1, 2, 3]; + * console.log(_.castArray(array) === array); + * // => true + */ + function castArray() { + if (!arguments.length) { + return []; + } + var value = arguments[0]; + return isArray(value) ? value : [value]; + } + + /** + * Creates a shallow clone of `value`. + * + * **Note:** This method is loosely based on the + * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) + * and supports cloning arrays, array buffers, booleans, date objects, maps, + * numbers, `Object` objects, regexes, sets, strings, symbols, and typed + * arrays. The own enumerable properties of `arguments` objects are cloned + * as plain objects. An empty object is returned for uncloneable values such + * as error objects, functions, DOM nodes, and WeakMaps. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to clone. + * @returns {*} Returns the cloned value. + * @see _.cloneDeep + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var shallow = _.clone(objects); + * console.log(shallow[0] === objects[0]); + * // => true + */ + function clone(value) { + return baseClone(value, CLONE_SYMBOLS_FLAG); + } + + /** + * This method is like `_.clone` except that it accepts `customizer` which + * is invoked to produce the cloned value. If `customizer` returns `undefined`, + * cloning is handled by the method instead. The `customizer` is invoked with + * up to four arguments; (value [, index|key, object, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the cloned value. + * @see _.cloneDeepWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(false); + * } + * } + * + * var el = _.cloneWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 0 + */ + function cloneWith(value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseClone(value, CLONE_SYMBOLS_FLAG, customizer); + } + + /** + * This method is like `_.clone` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @returns {*} Returns the deep cloned value. + * @see _.clone + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var deep = _.cloneDeep(objects); + * console.log(deep[0] === objects[0]); + * // => false + */ + function cloneDeep(value) { + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG); + } + + /** + * This method is like `_.cloneWith` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @param {Function} [customizer] The function to customize cloning. + * @returns {*} Returns the deep cloned value. + * @see _.cloneWith + * @example + * + * function customizer(value) { + * if (_.isElement(value)) { + * return value.cloneNode(true); + * } + * } + * + * var el = _.cloneDeepWith(document.body, customizer); + * + * console.log(el === document.body); + * // => false + * console.log(el.nodeName); + * // => 'BODY' + * console.log(el.childNodes.length); + * // => 20 + */ + function cloneDeepWith(value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer); + } + + /** + * Checks if `object` conforms to `source` by invoking the predicate + * properties of `source` with the corresponding property values of `object`. + * + * **Note:** This method is equivalent to `_.conforms` when `source` is + * partially applied. + * + * @static + * @memberOf _ + * @since 4.14.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property predicates to conform to. + * @returns {boolean} Returns `true` if `object` conforms, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.conformsTo(object, { 'b': function(n) { return n > 1; } }); + * // => true + * + * _.conformsTo(object, { 'b': function(n) { return n > 2; } }); + * // => false + */ + function conformsTo(object, source) { + return source == null || baseConformsTo(object, source, keys(source)); + } + + /** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ + function eq(value, other) { + return value === other || (value !== value && other !== other); + } + + /** + * Checks if `value` is greater than `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than `other`, + * else `false`. + * @see _.lt + * @example + * + * _.gt(3, 1); + * // => true + * + * _.gt(3, 3); + * // => false + * + * _.gt(1, 3); + * // => false + */ + var gt = createRelationalOperation(baseGt); + + /** + * Checks if `value` is greater than or equal to `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is greater than or equal to + * `other`, else `false`. + * @see _.lte + * @example + * + * _.gte(3, 1); + * // => true + * + * _.gte(3, 3); + * // => true + * + * _.gte(1, 3); + * // => false + */ + var gte = createRelationalOperation(function(value, other) { + return value >= other; + }); + + /** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); + }; + + /** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ + var isArray = Array.isArray; + + /** + * Checks if `value` is classified as an `ArrayBuffer` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. + * @example + * + * _.isArrayBuffer(new ArrayBuffer(2)); + * // => true + * + * _.isArrayBuffer(new Array(2)); + * // => false + */ + var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer; + + /** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ + function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); + } + + /** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ + function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); + } + + /** + * Checks if `value` is classified as a boolean primitive or object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a boolean, else `false`. + * @example + * + * _.isBoolean(false); + * // => true + * + * _.isBoolean(null); + * // => false + */ + function isBoolean(value) { + return value === true || value === false || + (isObjectLike(value) && baseGetTag(value) == boolTag); + } + + /** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ + var isBuffer = nativeIsBuffer || stubFalse; + + /** + * Checks if `value` is classified as a `Date` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a date object, else `false`. + * @example + * + * _.isDate(new Date); + * // => true + * + * _.isDate('Mon April 23 2012'); + * // => false + */ + var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate; + + /** + * Checks if `value` is likely a DOM element. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. + * @example + * + * _.isElement(document.body); + * // => true + * + * _.isElement(''); + * // => false + */ + function isElement(value) { + return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value); + } + + /** + * Checks if `value` is an empty object, collection, map, or set. + * + * Objects are considered empty if they have no own enumerable string keyed + * properties. + * + * Array-like values such as `arguments` objects, arrays, buffers, strings, or + * jQuery-like collections are considered empty if they have a `length` of `0`. + * Similarly, maps and sets are considered empty if they have a `size` of `0`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. + * @example + * + * _.isEmpty(null); + * // => true + * + * _.isEmpty(true); + * // => true + * + * _.isEmpty(1); + * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false + */ + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && + (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || + isBuffer(value) || isTypedArray(value) || isArguments(value))) { + return !value.length; + } + var tag = getTag(value); + if (tag == mapTag || tag == setTag) { + return !value.size; + } + if (isPrototype(value)) { + return !baseKeys(value).length; + } + for (var key in value) { + if (hasOwnProperty.call(value, key)) { + return false; + } + } + return true; + } + + /** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are compared by strict equality, i.e. `===`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ + function isEqual(value, other) { + return baseIsEqual(value, other); + } + + /** + * This method is like `_.isEqual` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with up to + * six arguments: (objValue, othValue [, index|key, object, other, stack]). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, othValue) { + * if (isGreeting(objValue) && isGreeting(othValue)) { + * return true; + * } + * } + * + * var array = ['hello', 'goodbye']; + * var other = ['hi', 'goodbye']; + * + * _.isEqualWith(array, other, customizer); + * // => true + */ + function isEqualWith(value, other, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result; + } + + /** + * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, + * `SyntaxError`, `TypeError`, or `URIError` object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an error object, else `false`. + * @example + * + * _.isError(new Error); + * // => true + * + * _.isError(Error); + * // => false + */ + function isError(value) { + if (!isObjectLike(value)) { + return false; + } + var tag = baseGetTag(value); + return tag == errorTag || tag == domExcTag || + (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value)); + } + + /** + * Checks if `value` is a finite primitive number. + * + * **Note:** This method is based on + * [`Number.isFinite`](https://mdn.io/Number/isFinite). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. + * @example + * + * _.isFinite(3); + * // => true + * + * _.isFinite(Number.MIN_VALUE); + * // => true + * + * _.isFinite(Infinity); + * // => false + * + * _.isFinite('3'); + * // => false + */ + function isFinite(value) { + return typeof value == 'number' && nativeIsFinite(value); + } + + /** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ + function isFunction(value) { + if (!isObject(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; + } + + /** + * Checks if `value` is an integer. + * + * **Note:** This method is based on + * [`Number.isInteger`](https://mdn.io/Number/isInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an integer, else `false`. + * @example + * + * _.isInteger(3); + * // => true + * + * _.isInteger(Number.MIN_VALUE); + * // => false + * + * _.isInteger(Infinity); + * // => false + * + * _.isInteger('3'); + * // => false + */ + function isInteger(value) { + return typeof value == 'number' && value == toInteger(value); + } + + /** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ + function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ + function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); + } + + /** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ + function isObjectLike(value) { + return value != null && typeof value == 'object'; + } + + /** + * Checks if `value` is classified as a `Map` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + * @example + * + * _.isMap(new Map); + * // => true + * + * _.isMap(new WeakMap); + * // => false + */ + var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; + + /** + * Performs a partial deep comparison between `object` and `source` to + * determine if `object` contains equivalent property values. + * + * **Note:** This method is equivalent to `_.matches` when `source` is + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * + * _.isMatch(object, { 'b': 2 }); + * // => true + * + * _.isMatch(object, { 'b': 1 }); + * // => false + */ + function isMatch(object, source) { + return object === source || baseIsMatch(object, source, getMatchData(source)); + } + + /** + * This method is like `_.isMatch` except that it accepts `customizer` which + * is invoked to compare values. If `customizer` returns `undefined`, comparisons + * are handled by the method instead. The `customizer` is invoked with five + * arguments: (objValue, srcValue, index|key, object, source). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + * @example + * + * function isGreeting(value) { + * return /^h(?:i|ello)$/.test(value); + * } + * + * function customizer(objValue, srcValue) { + * if (isGreeting(objValue) && isGreeting(srcValue)) { + * return true; + * } + * } + * + * var object = { 'greeting': 'hello' }; + * var source = { 'greeting': 'hi' }; + * + * _.isMatchWith(object, source, customizer); + * // => true + */ + function isMatchWith(object, source, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return baseIsMatch(object, source, getMatchData(source), customizer); + } + + /** + * Checks if `value` is `NaN`. + * + * **Note:** This method is based on + * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as + * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for + * `undefined` and other non-number values. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ + function isNaN(value) { + // An `NaN` primitive is the only value that is not equal to itself. + // Perform the `toStringTag` check first to avoid errors with some + // ActiveX objects in IE. + return isNumber(value) && value != +value; + } + + /** + * Checks if `value` is a pristine native function. + * + * **Note:** This method can't reliably detect native functions in the presence + * of the core-js package because core-js circumvents this kind of detection. + * Despite multiple requests, the core-js maintainer has made it clear: any + * attempt to fix the detection will be obstructed. As a result, we're left + * with little choice but to throw an error. Unfortunately, this also affects + * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill), + * which rely on core-js. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + * @example + * + * _.isNative(Array.prototype.push); + * // => true + * + * _.isNative(_); + * // => false + */ + function isNative(value) { + if (isMaskable(value)) { + throw new Error(CORE_ERROR_TEXT); + } + return baseIsNative(value); + } + + /** + * Checks if `value` is `null`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `null`, else `false`. + * @example + * + * _.isNull(null); + * // => true + * + * _.isNull(void 0); + * // => false + */ + function isNull(value) { + return value === null; + } + + /** + * Checks if `value` is `null` or `undefined`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is nullish, else `false`. + * @example + * + * _.isNil(null); + * // => true + * + * _.isNil(void 0); + * // => true + * + * _.isNil(NaN); + * // => false + */ + function isNil(value) { + return value == null; + } + + /** + * Checks if `value` is classified as a `Number` primitive or object. + * + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are + * classified as numbers, use the `_.isFinite` method. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a number, else `false`. + * @example + * + * _.isNumber(3); + * // => true + * + * _.isNumber(Number.MIN_VALUE); + * // => true + * + * _.isNumber(Infinity); + * // => true + * + * _.isNumber('3'); + * // => false + */ + function isNumber(value) { + return typeof value == 'number' || + (isObjectLike(value) && baseGetTag(value) == numberTag); + } + + /** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * @static + * @memberOf _ + * @since 0.8.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ + function isPlainObject(value) { + if (!isObjectLike(value) || baseGetTag(value) != objectTag) { + return false; + } + var proto = getPrototype(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; + return typeof Ctor == 'function' && Ctor instanceof Ctor && + funcToString.call(Ctor) == objectCtorString; + } + + /** + * Checks if `value` is classified as a `RegExp` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. + * @example + * + * _.isRegExp(/abc/); + * // => true + * + * _.isRegExp('/abc/'); + * // => false + */ + var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp; + + /** + * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754 + * double precision number which isn't the result of a rounded unsafe integer. + * + * **Note:** This method is based on + * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`. + * @example + * + * _.isSafeInteger(3); + * // => true + * + * _.isSafeInteger(Number.MIN_VALUE); + * // => false + * + * _.isSafeInteger(Infinity); + * // => false + * + * _.isSafeInteger('3'); + * // => false + */ + function isSafeInteger(value) { + return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is classified as a `Set` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + * @example + * + * _.isSet(new Set); + * // => true + * + * _.isSet(new WeakSet); + * // => false + */ + var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; + + /** + * Checks if `value` is classified as a `String` primitive or object. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a string, else `false`. + * @example + * + * _.isString('abc'); + * // => true + * + * _.isString(1); + * // => false + */ + function isString(value) { + return typeof value == 'string' || + (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); + } + + /** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ + function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && baseGetTag(value) == symbolTag); + } + + /** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ + var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + + /** + * Checks if `value` is `undefined`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + * + * _.isUndefined(null); + * // => false + */ + function isUndefined(value) { + return value === undefined; + } + + /** + * Checks if `value` is classified as a `WeakMap` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak map, else `false`. + * @example + * + * _.isWeakMap(new WeakMap); + * // => true + * + * _.isWeakMap(new Map); + * // => false + */ + function isWeakMap(value) { + return isObjectLike(value) && getTag(value) == weakMapTag; + } + + /** + * Checks if `value` is classified as a `WeakSet` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a weak set, else `false`. + * @example + * + * _.isWeakSet(new WeakSet); + * // => true + * + * _.isWeakSet(new Set); + * // => false + */ + function isWeakSet(value) { + return isObjectLike(value) && baseGetTag(value) == weakSetTag; + } + + /** + * Checks if `value` is less than `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than `other`, + * else `false`. + * @see _.gt + * @example + * + * _.lt(1, 3); + * // => true + * + * _.lt(3, 3); + * // => false + * + * _.lt(3, 1); + * // => false + */ + var lt = createRelationalOperation(baseLt); + + /** + * Checks if `value` is less than or equal to `other`. + * + * @static + * @memberOf _ + * @since 3.9.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if `value` is less than or equal to + * `other`, else `false`. + * @see _.gte + * @example + * + * _.lte(1, 3); + * // => true + * + * _.lte(3, 3); + * // => true + * + * _.lte(3, 1); + * // => false + */ + var lte = createRelationalOperation(function(value, other) { + return value <= other; + }); + + /** + * Converts `value` to an array. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @returns {Array} Returns the converted array. + * @example + * + * _.toArray({ 'a': 1, 'b': 2 }); + * // => [1, 2] + * + * _.toArray('abc'); + * // => ['a', 'b', 'c'] + * + * _.toArray(1); + * // => [] + * + * _.toArray(null); + * // => [] + */ + function toArray(value) { + if (!value) { + return []; + } + if (isArrayLike(value)) { + return isString(value) ? stringToArray(value) : copyArray(value); + } + if (symIterator && value[symIterator]) { + return iteratorToArray(value[symIterator]()); + } + var tag = getTag(value), + func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values); + + return func(value); + } + + /** + * Converts `value` to a finite number. + * + * @static + * @memberOf _ + * @since 4.12.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted number. + * @example + * + * _.toFinite(3.2); + * // => 3.2 + * + * _.toFinite(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toFinite(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toFinite('3.2'); + * // => 3.2 + */ + function toFinite(value) { + if (!value) { + return value === 0 ? value : 0; + } + value = toNumber(value); + if (value === INFINITY || value === -INFINITY) { + var sign = (value < 0 ? -1 : 1); + return sign * MAX_INTEGER; + } + return value === value ? value : 0; + } + + /** + * Converts `value` to an integer. + * + * **Note:** This method is loosely based on + * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3.2); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3.2'); + * // => 3 + */ + function toInteger(value) { + var result = toFinite(value), + remainder = result % 1; + + return result === result ? (remainder ? result - remainder : result) : 0; + } + + /** + * Converts `value` to an integer suitable for use as the length of an + * array-like object. + * + * **Note:** This method is based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toLength(3.2); + * // => 3 + * + * _.toLength(Number.MIN_VALUE); + * // => 0 + * + * _.toLength(Infinity); + * // => 4294967295 + * + * _.toLength('3.2'); + * // => 3 + */ + function toLength(value) { + return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0; + } + + /** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3.2); + * // => 3.2 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3.2'); + * // => 3.2 + */ + function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + if (isObject(value)) { + var other = typeof value.valueOf == 'function' ? value.valueOf() : value; + value = isObject(other) ? (other + '') : other; + } + if (typeof value != 'string') { + return value === 0 ? value : +value; + } + value = baseTrim(value); + var isBinary = reIsBinary.test(value); + return (isBinary || reIsOctal.test(value)) + ? freeParseInt(value.slice(2), isBinary ? 2 : 8) + : (reIsBadHex.test(value) ? NAN : +value); + } + + /** + * Converts `value` to a plain object flattening inherited enumerable string + * keyed properties of `value` to own properties of the plain object. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {Object} Returns the converted plain object. + * @example + * + * function Foo() { + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.assign({ 'a': 1 }, new Foo); + * // => { 'a': 1, 'b': 2 } + * + * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); + * // => { 'a': 1, 'b': 2, 'c': 3 } + */ + function toPlainObject(value) { + return copyObject(value, keysIn(value)); + } + + /** + * Converts `value` to a safe integer. A safe integer can be compared and + * represented correctly. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toSafeInteger(3.2); + * // => 3 + * + * _.toSafeInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toSafeInteger(Infinity); + * // => 9007199254740991 + * + * _.toSafeInteger('3.2'); + * // => 3 + */ + function toSafeInteger(value) { + return value + ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) + : (value === 0 ? value : 0); + } + + /** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ + function toString(value) { + return value == null ? '' : baseToString(value); + } + + /*------------------------------------------------------------------------*/ + + /** + * Assigns own enumerable string keyed properties of source objects to the + * destination object. Source objects are applied from left to right. + * Subsequent sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object` and is loosely based on + * [`Object.assign`](https://mdn.io/Object/assign). + * + * @static + * @memberOf _ + * @since 0.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assignIn + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assign({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'c': 3 } + */ + var assign = createAssigner(function(object, source) { + if (isPrototype(source) || isArrayLike(source)) { + copyObject(source, keys(source), object); + return; + } + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + assignValue(object, key, source[key]); + } + } + }); + + /** + * This method is like `_.assign` except that it iterates over own and + * inherited source properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extend + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.assign + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * function Bar() { + * this.c = 3; + * } + * + * Foo.prototype.b = 2; + * Bar.prototype.d = 4; + * + * _.assignIn({ 'a': 0 }, new Foo, new Bar); + * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } + */ + var assignIn = createAssigner(function(object, source) { + copyObject(source, keysIn(source), object); + }); + + /** + * This method is like `_.assignIn` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias extendWith + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignInWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keysIn(source), object, customizer); + }); + + /** + * This method is like `_.assign` except that it accepts `customizer` + * which is invoked to produce the assigned values. If `customizer` returns + * `undefined`, assignment is handled by the method instead. The `customizer` + * is invoked with five arguments: (objValue, srcValue, key, object, source). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @see _.assignInWith + * @example + * + * function customizer(objValue, srcValue) { + * return _.isUndefined(objValue) ? srcValue : objValue; + * } + * + * var defaults = _.partialRight(_.assignWith, customizer); + * + * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var assignWith = createAssigner(function(object, source, srcIndex, customizer) { + copyObject(source, keys(source), object, customizer); + }); + + /** + * Creates an array of values corresponding to `paths` of `object`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Array} Returns the picked values. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; + * + * _.at(object, ['a[0].b.c', 'a[1]']); + * // => [3, 4] + */ + var at = flatRest(baseAt); + + /** + * Creates an object that inherits from the `prototype` object. If a + * `properties` object is given, its own enumerable string keyed properties + * are assigned to the created object. + * + * @static + * @memberOf _ + * @since 2.3.0 + * @category Object + * @param {Object} prototype The object to inherit from. + * @param {Object} [properties] The properties to assign to the object. + * @returns {Object} Returns the new object. + * @example + * + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * function Circle() { + * Shape.call(this); + * } + * + * Circle.prototype = _.create(Shape.prototype, { + * 'constructor': Circle + * }); + * + * var circle = new Circle; + * circle instanceof Circle; + * // => true + * + * circle instanceof Shape; + * // => true + */ + function create(prototype, properties) { + var result = baseCreate(prototype); + return properties == null ? result : baseAssign(result, properties); + } + + /** + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaultsDeep + * @example + * + * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ + var defaults = baseRest(function(object, sources) { + object = Object(object); + + var index = -1; + var length = sources.length; + var guard = length > 2 ? sources[2] : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + length = 1; + } + + while (++index < length) { + var source = sources[index]; + var props = keysIn(source); + var propsIndex = -1; + var propsLength = props.length; + + while (++propsIndex < propsLength) { + var key = props[propsIndex]; + var value = object[key]; + + if (value === undefined || + (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) { + object[key] = source[key]; + } + } + } + + return object; + }); + + /** + * This method is like `_.defaults` except that it recursively assigns + * default properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaults + * @example + * + * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } }); + * // => { 'a': { 'b': 2, 'c': 3 } } + */ + var defaultsDeep = baseRest(function(args) { + args.push(undefined, customDefaultsMerge); + return apply(mergeWith, undefined, args); + }); + + /** + * This method is like `_.find` except that it returns the key of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findKey(users, function(o) { return o.age < 40; }); + * // => 'barney' (iteration order is not guaranteed) + * + * // The `_.matches` iteratee shorthand. + * _.findKey(users, { 'age': 1, 'active': true }); + * // => 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findKey(users, 'active'); + * // => 'barney' + */ + function findKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwn); + } + + /** + * This method is like `_.findKey` except that it iterates over elements of + * a collection in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @returns {string|undefined} Returns the key of the matched element, + * else `undefined`. + * @example + * + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; + * + * _.findLastKey(users, function(o) { return o.age < 40; }); + * // => returns 'pebbles' assuming `_.findKey` returns 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.findLastKey(users, { 'age': 36, 'active': true }); + * // => 'barney' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findLastKey(users, ['active', false]); + * // => 'fred' + * + * // The `_.property` iteratee shorthand. + * _.findLastKey(users, 'active'); + * // => 'pebbles' + */ + function findLastKey(object, predicate) { + return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight); + } + + /** + * Iterates over own and inherited enumerable string keyed properties of an + * object and invokes `iteratee` for each property. The iteratee is invoked + * with three arguments: (value, key, object). Iteratee functions may exit + * iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forInRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forIn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed). + */ + function forIn(object, iteratee) { + return object == null + ? object + : baseFor(object, getIteratee(iteratee, 3), keysIn); + } + + /** + * This method is like `_.forIn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forIn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forInRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'. + */ + function forInRight(object, iteratee) { + return object == null + ? object + : baseForRight(object, getIteratee(iteratee, 3), keysIn); + } + + /** + * Iterates over own enumerable string keyed properties of an object and + * invokes `iteratee` for each property. The iteratee is invoked with three + * arguments: (value, key, object). Iteratee functions may exit iteration + * early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 0.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwnRight + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'a' then 'b' (iteration order is not guaranteed). + */ + function forOwn(object, iteratee) { + return object && baseForOwn(object, getIteratee(iteratee, 3)); + } + + /** + * This method is like `_.forOwn` except that it iterates over properties of + * `object` in the opposite order. + * + * @static + * @memberOf _ + * @since 2.0.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns `object`. + * @see _.forOwn + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forOwnRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'. + */ + function forOwnRight(object, iteratee) { + return object && baseForOwnRight(object, getIteratee(iteratee, 3)); + } + + /** + * Creates an array of function property names from own enumerable properties + * of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functionsIn + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functions(new Foo); + * // => ['a', 'b'] + */ + function functions(object) { + return object == null ? [] : baseFunctions(object, keys(object)); + } + + /** + * Creates an array of function property names from own and inherited + * enumerable properties of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the function names. + * @see _.functions + * @example + * + * function Foo() { + * this.a = _.constant('a'); + * this.b = _.constant('b'); + * } + * + * Foo.prototype.c = _.constant('c'); + * + * _.functionsIn(new Foo); + * // => ['a', 'b', 'c'] + */ + function functionsIn(object) { + return object == null ? [] : baseFunctions(object, keysIn(object)); + } + + /** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.get(object, 'a[0].b.c'); + * // => 3 + * + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */ + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, path); + return result === undefined ? defaultValue : result; + } + + /** + * Checks if `path` is a direct property of `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = { 'a': { 'b': 2 } }; + * var other = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.has(object, 'a'); + * // => true + * + * _.has(object, 'a.b'); + * // => true + * + * _.has(object, ['a', 'b']); + * // => true + * + * _.has(other, 'a'); + * // => false + */ + function has(object, path) { + return object != null && hasPath(object, path, baseHas); + } + + /** + * Checks if `path` is a direct or inherited property of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.hasIn(object, 'a'); + * // => true + * + * _.hasIn(object, 'a.b'); + * // => true + * + * _.hasIn(object, ['a', 'b']); + * // => true + * + * _.hasIn(object, 'b'); + * // => false + */ + function hasIn(object, path) { + return object != null && hasPath(object, path, baseHasIn); + } + + /** + * Creates an object composed of the inverted keys and values of `object`. + * If `object` contains duplicate values, subsequent values overwrite + * property assignments of previous values. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Object + * @param {Object} object The object to invert. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invert(object); + * // => { '1': 'c', '2': 'b' } + */ + var invert = createInverter(function(result, value, key) { + if (value != null && + typeof value.toString != 'function') { + value = nativeObjectToString.call(value); + } + + result[value] = key; + }, constant(identity)); + + /** + * This method is like `_.invert` except that the inverted object is generated + * from the results of running each element of `object` thru `iteratee`. The + * corresponding inverted value of each inverted key is an array of keys + * responsible for generating the inverted value. The iteratee is invoked + * with one argument: (value). + * + * @static + * @memberOf _ + * @since 4.1.0 + * @category Object + * @param {Object} object The object to invert. + * @param {Function} [iteratee=_.identity] The iteratee invoked per element. + * @returns {Object} Returns the new inverted object. + * @example + * + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invertBy(object); + * // => { '1': ['a', 'c'], '2': ['b'] } + * + * _.invertBy(object, function(value) { + * return 'group' + value; + * }); + * // => { 'group1': ['a', 'c'], 'group2': ['b'] } + */ + var invertBy = createInverter(function(result, value, key) { + if (value != null && + typeof value.toString != 'function') { + value = nativeObjectToString.call(value); + } + + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [key]; + } + }, getIteratee); + + /** + * Invokes the method at `path` of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the method to invoke. + * @param {...*} [args] The arguments to invoke the method with. + * @returns {*} Returns the result of the invoked method. + * @example + * + * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] }; + * + * _.invoke(object, 'a[0].b.c.slice', 1, 3); + * // => [2, 3] + */ + var invoke = baseRest(baseInvoke); + + /** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ + function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); + } + + /** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ + function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); + } + + /** + * The opposite of `_.mapValues`; this method creates an object with the + * same values as `object` and keys generated by running each own enumerable + * string keyed property of `object` thru `iteratee`. The iteratee is invoked + * with three arguments: (value, key, object). + * + * @static + * @memberOf _ + * @since 3.8.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapValues + * @example + * + * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) { + * return key + value; + * }); + * // => { 'a1': 1, 'b2': 2 } + */ + function mapKeys(object, iteratee) { + var result = {}; + iteratee = getIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, iteratee(value, key, object), value); + }); + return result; + } + + /** + * Creates an object with the same keys as `object` and values generated + * by running each own enumerable string keyed property of `object` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, key, object). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Object} Returns the new mapped object. + * @see _.mapKeys + * @example + * + * var users = { + * 'fred': { 'user': 'fred', 'age': 40 }, + * 'pebbles': { 'user': 'pebbles', 'age': 1 } + * }; + * + * _.mapValues(users, function(o) { return o.age; }); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + * + * // The `_.property` iteratee shorthand. + * _.mapValues(users, 'age'); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) + */ + function mapValues(object, iteratee) { + var result = {}; + iteratee = getIteratee(iteratee, 3); + + baseForOwn(object, function(value, key, object) { + baseAssignValue(result, key, iteratee(value, key, object)); + }); + return result; + } + + /** + * This method is like `_.assign` except that it recursively merges own and + * inherited enumerable string keyed properties of source objects into the + * destination object. Source properties that resolve to `undefined` are + * skipped if a destination value exists. Array and plain object properties + * are merged recursively. Other objects and value types are overridden by + * assignment. Source objects are applied from left to right. Subsequent + * sources overwrite property assignments of previous sources. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 0.5.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @example + * + * var object = { + * 'a': [{ 'b': 2 }, { 'd': 4 }] + * }; + * + * var other = { + * 'a': [{ 'c': 3 }, { 'e': 5 }] + * }; + * + * _.merge(object, other); + * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } + */ + var merge = createAssigner(function(object, source, srcIndex) { + baseMerge(object, source, srcIndex); + }); + + /** + * This method is like `_.merge` except that it accepts `customizer` which + * is invoked to produce the merged values of the destination and source + * properties. If `customizer` returns `undefined`, merging is handled by the + * method instead. The `customizer` is invoked with six arguments: + * (objValue, srcValue, key, object, source, stack). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} sources The source objects. + * @param {Function} customizer The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * function customizer(objValue, srcValue) { + * if (_.isArray(objValue)) { + * return objValue.concat(srcValue); + * } + * } + * + * var object = { 'a': [1], 'b': [2] }; + * var other = { 'a': [3], 'b': [4] }; + * + * _.mergeWith(object, other, customizer); + * // => { 'a': [1, 3], 'b': [2, 4] } + */ + var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { + baseMerge(object, source, srcIndex, customizer); + }); + + /** + * The opposite of `_.pick`; this method creates an object composed of the + * own and inherited enumerable property paths of `object` that are not omitted. + * + * **Note:** This method is considerably slower than `_.pick`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [paths] The property paths to omit. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omit(object, ['a', 'c']); + * // => { 'b': '2' } + */ + var omit = flatRest(function(object, paths) { + var result = {}; + if (object == null) { + return result; + } + var isDeep = false; + paths = arrayMap(paths, function(path) { + path = castPath(path, object); + isDeep || (isDeep = path.length > 1); + return path; + }); + copyObject(object, getAllKeysIn(object), result); + if (isDeep) { + result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone); + } + var length = paths.length; + while (length--) { + baseUnset(result, paths[length]); + } + return result; + }); + + /** + * The opposite of `_.pickBy`; this method creates an object composed of + * the own and inherited enumerable string keyed properties of `object` that + * `predicate` doesn't return truthy for. The predicate is invoked with two + * arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.omitBy(object, _.isNumber); + * // => { 'b': '2' } + */ + function omitBy(object, predicate) { + return pickBy(object, negate(getIteratee(predicate))); + } + + /** + * Creates an object composed of the picked `object` properties. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The source object. + * @param {...(string|string[])} [paths] The property paths to pick. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pick(object, ['a', 'c']); + * // => { 'a': 1, 'c': 3 } + */ + var pick = flatRest(function(object, paths) { + return object == null ? {} : basePick(object, paths); + }); + + /** + * Creates an object composed of the `object` properties `predicate` returns + * truthy for. The predicate is invoked with two arguments: (value, key). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The source object. + * @param {Function} [predicate=_.identity] The function invoked per property. + * @returns {Object} Returns the new object. + * @example + * + * var object = { 'a': 1, 'b': '2', 'c': 3 }; + * + * _.pickBy(object, _.isNumber); + * // => { 'a': 1, 'c': 3 } + */ + function pickBy(object, predicate) { + if (object == null) { + return {}; + } + var props = arrayMap(getAllKeysIn(object), function(prop) { + return [prop]; + }); + predicate = getIteratee(predicate); + return basePickBy(object, props, function(value, path) { + return predicate(value, path[0]); + }); + } + + /** + * This method is like `_.get` except that if the resolved value is a + * function it's invoked with the `this` binding of its parent object and + * its result is returned. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to resolve. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] }; + * + * _.result(object, 'a[0].b.c1'); + * // => 3 + * + * _.result(object, 'a[0].b.c2'); + * // => 4 + * + * _.result(object, 'a[0].b.c3', 'default'); + * // => 'default' + * + * _.result(object, 'a[0].b.c3', _.constant('default')); + * // => 'default' + */ + function result(object, path, defaultValue) { + path = castPath(path, object); + + var index = -1, + length = path.length; + + // Ensure the loop is entered when path is empty. + if (!length) { + length = 1; + object = undefined; + } + while (++index < length) { + var value = object == null ? undefined : object[toKey(path[index])]; + if (value === undefined) { + index = length; + value = defaultValue; + } + object = isFunction(value) ? value.call(object) : value; + } + return object; + } + + /** + * Sets the value at `path` of `object`. If a portion of `path` doesn't exist, + * it's created. Arrays are created for missing index properties while objects + * are created for all other missing properties. Use `_.setWith` to customize + * `path` creation. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.set(object, 'a[0].b.c', 4); + * console.log(object.a[0].b.c); + * // => 4 + * + * _.set(object, ['x', '0', 'y', 'z'], 5); + * console.log(object.x[0].y.z); + * // => 5 + */ + function set(object, path, value) { + return object == null ? object : baseSet(object, path, value); + } + + /** + * This method is like `_.set` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {*} value The value to set. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * var object = {}; + * + * _.setWith(object, '[0][1]', 'a', Object); + * // => { '0': { '1': 'a' } } + */ + function setWith(object, path, value, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseSet(object, path, value, customizer); + } + + /** + * Creates an array of own enumerable string keyed-value pairs for `object` + * which can be consumed by `_.fromPairs`. If `object` is a map or set, its + * entries are returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias entries + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairs(new Foo); + * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed) + */ + var toPairs = createToPairs(keys); + + /** + * Creates an array of own and inherited enumerable string keyed-value pairs + * for `object` which can be consumed by `_.fromPairs`. If `object` is a map + * or set, its entries are returned. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @alias entriesIn + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the key-value pairs. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.toPairsIn(new Foo); + * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed) + */ + var toPairsIn = createToPairs(keysIn); + + /** + * An alternative to `_.reduce`; this method transforms `object` to a new + * `accumulator` object which is the result of running each of its own + * enumerable string keyed properties thru `iteratee`, with each invocation + * potentially mutating the `accumulator` object. If `accumulator` is not + * provided, a new object with the same `[[Prototype]]` will be used. The + * iteratee is invoked with four arguments: (accumulator, value, key, object). + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @since 1.3.0 + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The custom accumulator value. + * @returns {*} Returns the accumulated value. + * @example + * + * _.transform([2, 3, 4], function(result, n) { + * result.push(n *= n); + * return n % 2 == 0; + * }, []); + * // => [4, 9] + * + * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { + * (result[value] || (result[value] = [])).push(key); + * }, {}); + * // => { '1': ['a', 'c'], '2': ['b'] } + */ + function transform(object, iteratee, accumulator) { + var isArr = isArray(object), + isArrLike = isArr || isBuffer(object) || isTypedArray(object); + + iteratee = getIteratee(iteratee, 4); + if (accumulator == null) { + var Ctor = object && object.constructor; + if (isArrLike) { + accumulator = isArr ? new Ctor : []; + } + else if (isObject(object)) { + accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {}; + } + else { + accumulator = {}; + } + } + (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + + /** + * Removes the property at `path` of `object`. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to unset. + * @returns {boolean} Returns `true` if the property is deleted, else `false`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 7 } }] }; + * _.unset(object, 'a[0].b.c'); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + * + * _.unset(object, ['a', '0', 'b', 'c']); + * // => true + * + * console.log(object); + * // => { 'a': [{ 'b': {} }] }; + */ + function unset(object, path) { + return object == null ? true : baseUnset(object, path); + } + + /** + * This method is like `_.set` except that accepts `updater` to produce the + * value to set. Use `_.updateWith` to customize `path` creation. The `updater` + * is invoked with one argument: (value). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @returns {Object} Returns `object`. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.update(object, 'a[0].b.c', function(n) { return n * n; }); + * console.log(object.a[0].b.c); + * // => 9 + * + * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; }); + * console.log(object.x[0].y.z); + * // => 0 + */ + function update(object, path, updater) { + return object == null ? object : baseUpdate(object, path, castFunction(updater)); + } + + /** + * This method is like `_.update` except that it accepts `customizer` which is + * invoked to produce the objects of `path`. If `customizer` returns `undefined` + * path creation is handled by the method instead. The `customizer` is invoked + * with three arguments: (nsValue, key, nsObject). + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 4.6.0 + * @category Object + * @param {Object} object The object to modify. + * @param {Array|string} path The path of the property to set. + * @param {Function} updater The function to produce the updated value. + * @param {Function} [customizer] The function to customize assigned values. + * @returns {Object} Returns `object`. + * @example + * + * var object = {}; + * + * _.updateWith(object, '[0][1]', _.constant('a'), Object); + * // => { '0': { '1': 'a' } } + */ + function updateWith(object, path, updater, customizer) { + customizer = typeof customizer == 'function' ? customizer : undefined; + return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer); + } + + /** + * Creates an array of the own enumerable string keyed property values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.values(new Foo); + * // => [1, 2] (iteration order is not guaranteed) + * + * _.values('hi'); + * // => ['h', 'i'] + */ + function values(object) { + return object == null ? [] : baseValues(object, keys(object)); + } + + /** + * Creates an array of the own and inherited enumerable string keyed property + * values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.valuesIn(new Foo); + * // => [1, 2, 3] (iteration order is not guaranteed) + */ + function valuesIn(object) { + return object == null ? [] : baseValues(object, keysIn(object)); + } + + /*------------------------------------------------------------------------*/ + + /** + * Clamps `number` within the inclusive `lower` and `upper` bounds. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Number + * @param {number} number The number to clamp. + * @param {number} [lower] The lower bound. + * @param {number} upper The upper bound. + * @returns {number} Returns the clamped number. + * @example + * + * _.clamp(-10, -5, 5); + * // => -5 + * + * _.clamp(10, -5, 5); + * // => 5 + */ + function clamp(number, lower, upper) { + if (upper === undefined) { + upper = lower; + lower = undefined; + } + if (upper !== undefined) { + upper = toNumber(upper); + upper = upper === upper ? upper : 0; + } + if (lower !== undefined) { + lower = toNumber(lower); + lower = lower === lower ? lower : 0; + } + return baseClamp(toNumber(number), lower, upper); + } + + /** + * Checks if `n` is between `start` and up to, but not including, `end`. If + * `end` is not specified, it's set to `start` with `start` then set to `0`. + * If `start` is greater than `end` the params are swapped to support + * negative ranges. + * + * @static + * @memberOf _ + * @since 3.3.0 + * @category Number + * @param {number} number The number to check. + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @returns {boolean} Returns `true` if `number` is in the range, else `false`. + * @see _.range, _.rangeRight + * @example + * + * _.inRange(3, 2, 4); + * // => true + * + * _.inRange(4, 8); + * // => true + * + * _.inRange(4, 2); + * // => false + * + * _.inRange(2, 2); + * // => false + * + * _.inRange(1.2, 2); + * // => true + * + * _.inRange(5.2, 4); + * // => false + * + * _.inRange(-3, -2, -6); + * // => true + */ + function inRange(number, start, end) { + start = toFinite(start); + if (end === undefined) { + end = start; + start = 0; + } else { + end = toFinite(end); + } + number = toNumber(number); + return baseInRange(number, start, end); + } + + /** + * Produces a random number between the inclusive `lower` and `upper` bounds. + * If only one argument is provided a number between `0` and the given number + * is returned. If `floating` is `true`, or either `lower` or `upper` are + * floats, a floating-point number is returned instead of an integer. + * + * **Note:** JavaScript follows the IEEE-754 standard for resolving + * floating-point values which can produce unexpected results. + * + * @static + * @memberOf _ + * @since 0.7.0 + * @category Number + * @param {number} [lower=0] The lower bound. + * @param {number} [upper=1] The upper bound. + * @param {boolean} [floating] Specify returning a floating-point number. + * @returns {number} Returns the random number. + * @example + * + * _.random(0, 5); + * // => an integer between 0 and 5 + * + * _.random(5); + * // => also an integer between 0 and 5 + * + * _.random(5, true); + * // => a floating-point number between 0 and 5 + * + * _.random(1.2, 5.2); + * // => a floating-point number between 1.2 and 5.2 + */ + function random(lower, upper, floating) { + if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) { + upper = floating = undefined; + } + if (floating === undefined) { + if (typeof upper == 'boolean') { + floating = upper; + upper = undefined; + } + else if (typeof lower == 'boolean') { + floating = lower; + lower = undefined; + } + } + if (lower === undefined && upper === undefined) { + lower = 0; + upper = 1; + } + else { + lower = toFinite(lower); + if (upper === undefined) { + upper = lower; + lower = 0; + } else { + upper = toFinite(upper); + } + } + if (lower > upper) { + var temp = lower; + lower = upper; + upper = temp; + } + if (floating || lower % 1 || upper % 1) { + var rand = nativeRandom(); + return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper); + } + return baseRandom(lower, upper); + } + + /*------------------------------------------------------------------------*/ + + /** + * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the camel cased string. + * @example + * + * _.camelCase('Foo Bar'); + * // => 'fooBar' + * + * _.camelCase('--foo-bar--'); + * // => 'fooBar' + * + * _.camelCase('__FOO_BAR__'); + * // => 'fooBar' + */ + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? capitalize(word) : word); + }); + + /** + * Converts the first character of `string` to upper case and the remaining + * to lower case. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to capitalize. + * @returns {string} Returns the capitalized string. + * @example + * + * _.capitalize('FRED'); + * // => 'Fred' + */ + function capitalize(string) { + return upperFirst(toString(string).toLowerCase()); + } + + /** + * Deburrs `string` by converting + * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) + * letters to basic Latin letters and removing + * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to deburr. + * @returns {string} Returns the deburred string. + * @example + * + * _.deburr('déjà vu'); + * // => 'deja vu' + */ + function deburr(string) { + string = toString(string); + return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); + } + + /** + * Checks if `string` ends with the given target string. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {string} [target] The string to search for. + * @param {number} [position=string.length] The position to search up to. + * @returns {boolean} Returns `true` if `string` ends with `target`, + * else `false`. + * @example + * + * _.endsWith('abc', 'c'); + * // => true + * + * _.endsWith('abc', 'b'); + * // => false + * + * _.endsWith('abc', 'b', 2); + * // => true + */ + function endsWith(string, target, position) { + string = toString(string); + target = baseToString(target); + + var length = string.length; + position = position === undefined + ? length + : baseClamp(toInteger(position), 0, length); + + var end = position; + position -= target.length; + return position >= 0 && string.slice(position, end) == target; + } + + /** + * Converts the characters "&", "<", ">", '"', and "'" in `string` to their + * corresponding HTML entities. + * + * **Note:** No other characters are escaped. To escape additional + * characters use a third-party library like [_he_](https://mths.be/he). + * + * Though the ">" character is escaped for symmetry, characters like + * ">" and "/" don't need escaping in HTML and have no special meaning + * unless they're part of a tag or unquoted attribute value. See + * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * (under "semi-related fun fact") for more details. + * + * When working with HTML you should always + * [quote attribute values](http://wonko.com/post/html-escaping) to reduce + * XSS vectors. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' + */ + function escape(string) { + string = toString(string); + return (string && reHasUnescapedHtml.test(string)) + ? string.replace(reUnescapedHtml, escapeHtmlChar) + : string; + } + + /** + * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+", + * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escapeRegExp('[lodash](https://lodash.com/)'); + * // => '\[lodash\]\(https://lodash\.com/\)' + */ + function escapeRegExp(string) { + string = toString(string); + return (string && reHasRegExpChar.test(string)) + ? string.replace(reRegExpChar, '\\$&') + : string; + } + + /** + * Converts `string` to + * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the kebab cased string. + * @example + * + * _.kebabCase('Foo Bar'); + * // => 'foo-bar' + * + * _.kebabCase('fooBar'); + * // => 'foo-bar' + * + * _.kebabCase('__FOO_BAR__'); + * // => 'foo-bar' + */ + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? '-' : '') + word.toLowerCase(); + }); + + /** + * Converts `string`, as space separated words, to lower case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the lower cased string. + * @example + * + * _.lowerCase('--Foo-Bar--'); + * // => 'foo bar' + * + * _.lowerCase('fooBar'); + * // => 'foo bar' + * + * _.lowerCase('__FOO_BAR__'); + * // => 'foo bar' + */ + var lowerCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + word.toLowerCase(); + }); + + /** + * Converts the first character of `string` to lower case. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.lowerFirst('Fred'); + * // => 'fred' + * + * _.lowerFirst('FRED'); + * // => 'fRED' + */ + var lowerFirst = createCaseFirst('toLowerCase'); + + /** + * Pads `string` on the left and right sides if it's shorter than `length`. + * Padding characters are truncated if they can't be evenly divided by `length`. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.pad('abc', 8); + * // => ' abc ' + * + * _.pad('abc', 8, '_-'); + * // => '_-abc_-_' + * + * _.pad('abc', 3); + * // => 'abc' + */ + function pad(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + if (!length || strLength >= length) { + return string; + } + var mid = (length - strLength) / 2; + return ( + createPadding(nativeFloor(mid), chars) + + string + + createPadding(nativeCeil(mid), chars) + ); + } + + /** + * Pads `string` on the right side if it's shorter than `length`. Padding + * characters are truncated if they exceed `length`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.padEnd('abc', 6); + * // => 'abc ' + * + * _.padEnd('abc', 6, '_-'); + * // => 'abc_-_' + * + * _.padEnd('abc', 3); + * // => 'abc' + */ + function padEnd(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (string + createPadding(length - strLength, chars)) + : string; + } + + /** + * Pads `string` on the left side if it's shorter than `length`. Padding + * characters are truncated if they exceed `length`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. + * @example + * + * _.padStart('abc', 6); + * // => ' abc' + * + * _.padStart('abc', 6, '_-'); + * // => '_-_abc' + * + * _.padStart('abc', 3); + * // => 'abc' + */ + function padStart(string, length, chars) { + string = toString(string); + length = toInteger(length); + + var strLength = length ? stringSize(string) : 0; + return (length && strLength < length) + ? (createPadding(length - strLength, chars) + string) + : string; + } + + /** + * Converts `string` to an integer of the specified radix. If `radix` is + * `undefined` or `0`, a `radix` of `10` is used unless `value` is a + * hexadecimal, in which case a `radix` of `16` is used. + * + * **Note:** This method aligns with the + * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category String + * @param {string} string The string to convert. + * @param {number} [radix=10] The radix to interpret `value` by. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {number} Returns the converted integer. + * @example + * + * _.parseInt('08'); + * // => 8 + * + * _.map(['6', '08', '10'], _.parseInt); + * // => [6, 8, 10] + */ + function parseInt(string, radix, guard) { + if (guard || radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0); + } + + /** + * Repeats the given string `n` times. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to repeat. + * @param {number} [n=1] The number of times to repeat the string. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {string} Returns the repeated string. + * @example + * + * _.repeat('*', 3); + * // => '***' + * + * _.repeat('abc', 2); + * // => 'abcabc' + * + * _.repeat('abc', 0); + * // => '' + */ + function repeat(string, n, guard) { + if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) { + n = 1; + } else { + n = toInteger(n); + } + return baseRepeat(toString(string), n); + } + + /** + * Replaces matches for `pattern` in `string` with `replacement`. + * + * **Note:** This method is based on + * [`String#replace`](https://mdn.io/String/replace). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to modify. + * @param {RegExp|string} pattern The pattern to replace. + * @param {Function|string} replacement The match replacement. + * @returns {string} Returns the modified string. + * @example + * + * _.replace('Hi Fred', 'Fred', 'Barney'); + * // => 'Hi Barney' + */ + function replace() { + var args = arguments, + string = toString(args[0]); + + return args.length < 3 ? string : string.replace(args[1], args[2]); + } + + /** + * Converts `string` to + * [snake case](https://en.wikipedia.org/wiki/Snake_case). + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the snake cased string. + * @example + * + * _.snakeCase('Foo Bar'); + * // => 'foo_bar' + * + * _.snakeCase('fooBar'); + * // => 'foo_bar' + * + * _.snakeCase('--FOO-BAR--'); + * // => 'foo_bar' + */ + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? '_' : '') + word.toLowerCase(); + }); + + /** + * Splits `string` by `separator`. + * + * **Note:** This method is based on + * [`String#split`](https://mdn.io/String/split). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category String + * @param {string} [string=''] The string to split. + * @param {RegExp|string} separator The separator pattern to split by. + * @param {number} [limit] The length to truncate results to. + * @returns {Array} Returns the string segments. + * @example + * + * _.split('a-b-c', '-', 2); + * // => ['a', 'b'] + */ + function split(string, separator, limit) { + if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) { + separator = limit = undefined; + } + limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0; + if (!limit) { + return []; + } + string = toString(string); + if (string && ( + typeof separator == 'string' || + (separator != null && !isRegExp(separator)) + )) { + separator = baseToString(separator); + if (!separator && hasUnicode(string)) { + return castSlice(stringToArray(string), 0, limit); + } + } + return string.split(separator, limit); + } + + /** + * Converts `string` to + * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). + * + * @static + * @memberOf _ + * @since 3.1.0 + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the start cased string. + * @example + * + * _.startCase('--foo-bar--'); + * // => 'Foo Bar' + * + * _.startCase('fooBar'); + * // => 'Foo Bar' + * + * _.startCase('__FOO_BAR__'); + * // => 'FOO BAR' + */ + var startCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + upperFirst(word); + }); + + /** + * Checks if `string` starts with the given target string. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category String + * @param {string} [string=''] The string to inspect. + * @param {string} [target] The string to search for. + * @param {number} [position=0] The position to search from. + * @returns {boolean} Returns `true` if `string` starts with `target`, + * else `false`. + * @example + * + * _.startsWith('abc', 'a'); + * // => true + * + * _.startsWith('abc', 'b'); + * // => false + * + * _.startsWith('abc', 'b', 1); + * // => true + */ + function startsWith(string, target, position) { + string = toString(string); + position = position == null + ? 0 + : baseClamp(toInteger(position), 0, string.length); + + target = baseToString(target); + return string.slice(position, position + target.length) == target; + } + + /** + * Creates a compiled template function that can interpolate data properties + * in "interpolate" delimiters, HTML-escape interpolated data properties in + * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data + * properties may be accessed as free variables in the template. If a setting + * object is given, it takes precedence over `_.templateSettings` values. + * + * **Note:** In the development build `_.template` utilizes + * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) + * for easier debugging. + * + * For more information on precompiling templates see + * [lodash's custom builds documentation](https://lodash.com/custom-builds). + * + * For more information on Chrome extension sandboxes see + * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval). + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The template string. + * @param {Object} [options={}] The options object. + * @param {RegExp} [options.escape=_.templateSettings.escape] + * The HTML "escape" delimiter. + * @param {RegExp} [options.evaluate=_.templateSettings.evaluate] + * The "evaluate" delimiter. + * @param {Object} [options.imports=_.templateSettings.imports] + * An object to import into the template as free variables. + * @param {RegExp} [options.interpolate=_.templateSettings.interpolate] + * The "interpolate" delimiter. + * @param {string} [options.sourceURL='lodash.templateSources[n]'] + * The sourceURL of the compiled template. + * @param {string} [options.variable='obj'] + * The data object variable name. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {Function} Returns the compiled template function. + * @example + * + * // Use the "interpolate" delimiter to create a compiled template. + * var compiled = _.template('hello <%= user %>!'); + * compiled({ 'user': 'fred' }); + * // => 'hello fred!' + * + * // Use the HTML "escape" delimiter to escape data property values. + * var compiled = _.template('<%- value %>'); + * compiled({ 'value': ' + + + + diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/__root__/index.js.html b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/__root__/index.js.html new file mode 100644 index 000000000..02e5768d3 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/__root__/index.js.html @@ -0,0 +1,69 @@ + + + + Code coverage report for index.js + + + + + + +
    +

    Code coverage report for index.js

    +

    + Statements: 100% (4 / 4)      + Branches: 100% (2 / 2)      + Functions: 100% (1 / 1)      + Lines: 100% (4 / 4)      + Ignored: none      +

    +
    All files » __root__/ » index.js
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9  +1 +  +1 +  +1 +6 +  + 
    'use strict'
    +var path = require('path')
    + 
    +var uniqueSlug = require('unique-slug')
    + 
    +module.exports = function (filepath, prefix, uniq) {
    +  return path.join(filepath, (prefix ? prefix + '-' : '') + uniqueSlug(uniq))
    +}
    + 
    + +
    + + + + + + diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/base.css b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/base.css new file mode 100644 index 000000000..a6a2f3284 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/base.css @@ -0,0 +1,182 @@ +body, html { + margin:0; padding: 0; +} +body { + font-family: Helvetica Neue, Helvetica,Arial; + font-size: 10pt; +} +div.header, div.footer { + background: #eee; + padding: 1em; +} +div.header { + z-index: 100; + position: fixed; + top: 0; + border-bottom: 1px solid #666; + width: 100%; +} +div.footer { + border-top: 1px solid #666; +} +div.body { + margin-top: 10em; +} +div.meta { + font-size: 90%; + text-align: center; +} +h1, h2, h3 { + font-weight: normal; +} +h1 { + font-size: 12pt; +} +h2 { + font-size: 10pt; +} +pre { + font-family: Consolas, Menlo, Monaco, monospace; + margin: 0; + padding: 0; + line-height: 1.3; + font-size: 14px; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} + +div.path { font-size: 110%; } +div.path a:link, div.path a:visited { color: #000; } +table.coverage { border-collapse: collapse; margin:0; padding: 0 } + +table.coverage td { + margin: 0; + padding: 0; + color: #111; + vertical-align: top; +} +table.coverage td.line-count { + width: 50px; + text-align: right; + padding-right: 5px; +} +table.coverage td.line-coverage { + color: #777 !important; + text-align: right; + border-left: 1px solid #666; + border-right: 1px solid #666; +} + +table.coverage td.text { +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 40px; +} +table.coverage td span.cline-neutral { + background: #eee; +} +table.coverage td span.cline-yes { + background: #b5d592; + color: #999; +} +table.coverage td span.cline-no { + background: #fc8c84; +} + +.cstat-yes { color: #111; } +.cstat-no { background: #fc8c84; color: #111; } +.fstat-no { background: #ffc520; color: #111 !important; } +.cbranch-no { background: yellow !important; color: #111; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +.missing-if-branch { + display: inline-block; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: black; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} + +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} + +.entity, .metric { font-weight: bold; } +.metric { display: inline-block; border: 1px solid #333; padding: 0.3em; background: white; } +.metric small { font-size: 80%; font-weight: normal; color: #666; } + +div.coverage-summary table { border-collapse: collapse; margin: 3em; font-size: 110%; } +div.coverage-summary td, div.coverage-summary table th { margin: 0; padding: 0.25em 1em; border-top: 1px solid #666; border-bottom: 1px solid #666; } +div.coverage-summary th { text-align: left; border: 1px solid #666; background: #eee; font-weight: normal; } +div.coverage-summary th.file { border-right: none !important; } +div.coverage-summary th.pic { border-left: none !important; text-align: right; } +div.coverage-summary th.pct { border-right: none !important; } +div.coverage-summary th.abs { border-left: none !important; text-align: right; } +div.coverage-summary td.pct { text-align: right; border-left: 1px solid #666; } +div.coverage-summary td.abs { text-align: right; font-size: 90%; color: #444; border-right: 1px solid #666; } +div.coverage-summary td.file { border-left: 1px solid #666; white-space: nowrap; } +div.coverage-summary td.pic { min-width: 120px !important; } +div.coverage-summary a:link { text-decoration: none; color: #000; } +div.coverage-summary a:visited { text-decoration: none; color: #777; } +div.coverage-summary a:hover { text-decoration: underline; } +div.coverage-summary tfoot td { border-top: 1px solid #666; } + +div.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +div.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +div.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} + +.high { background: #b5d592 !important; } +.medium { background: #ffe87c !important; } +.low { background: #fc8c84 !important; } + +span.cover-fill, span.cover-empty { + display:inline-block; + border:1px solid #444; + background: white; + height: 12px; +} +span.cover-fill { + background: #ccc; + border-right: 1px solid #444; +} +span.cover-empty { + background: white; + border-left: none; +} +span.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/index.html b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/index.html new file mode 100644 index 000000000..b10d186cc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/index.html @@ -0,0 +1,73 @@ + + + + Code coverage report for All files + + + + + + +
    +

    Code coverage report for All files

    +

    + Statements: 100% (4 / 4)      + Branches: 100% (2 / 2)      + Functions: 100% (1 / 1)      + Lines: 100% (4 / 4)      + Ignored: none      +

    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FileStatementsBranchesFunctionsLines
    __root__/100%(4 / 4)100%(2 / 2)100%(1 / 1)100%(4 / 4)
    +
    +
    + + + + + + diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/prettify.css b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/prettify.css new file mode 100644 index 000000000..b317a7cda --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/prettify.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/prettify.js new file mode 100644 index 000000000..ef51e0386 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/prettify.js @@ -0,0 +1 @@ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/sort-arrow-sprite.png b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/coverage/sort-arrow-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..03f704a609c6fd0dbfdac63466a7d7c958b5cbf3 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bd!3HEZxJ@+%Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>Jii$m5978H@?Fn+^JD|Y9yzj{W`447Gxa{7*dM7nnnD-Lb z6^}Hx2)'; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function (a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function (a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc ? ' sorted-desc' : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function () { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i =0 ; i < cols.length; i += 1) { + if (cols[i].sortable) { + el = getNthColumn(i).querySelector('.sorter'); + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function () { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(cols); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/index.js new file mode 100644 index 000000000..02bf1e273 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/index.js @@ -0,0 +1,8 @@ +'use strict' +var path = require('path') + +var uniqueSlug = require('unique-slug') + +module.exports = function (filepath, prefix, uniq) { + return path.join(filepath, (prefix ? prefix + '-' : '') + uniqueSlug(uniq)) +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/package.json new file mode 100644 index 000000000..bc429aa44 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/package.json @@ -0,0 +1,27 @@ +{ + "name": "unique-filename", + "version": "1.1.1", + "description": "Generate a unique filename for use in temporary directories or caches.", + "main": "index.js", + "scripts": { + "test": "standard && tap test" + }, + "repository": { + "type": "git", + "url": "https://github.com/iarna/unique-filename.git" + }, + "keywords": [], + "author": "Rebecca Turner (http://re-becca.org/)", + "license": "ISC", + "bugs": { + "url": "https://github.com/iarna/unique-filename/issues" + }, + "homepage": "https://github.com/iarna/unique-filename", + "devDependencies": { + "standard": "^5.4.1", + "tap": "^2.3.1" + }, + "dependencies": { + "unique-slug": "^2.0.0" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/test/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/test/index.js new file mode 100644 index 000000000..105b4e52e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-filename/test/index.js @@ -0,0 +1,23 @@ +'sue strict' +var t = require('tap') +var uniqueFilename = require('../index.js') + +t.plan(6) + +var randomTmpfile = uniqueFilename('tmp') +t.like(randomTmpfile, /^tmp.[a-f0-9]{8}$/, 'random tmp file') + +var randomAgain = uniqueFilename('tmp') +t.notEqual(randomAgain, randomTmpfile, 'random tmp files are not the same') + +var randomPrefixedTmpfile = uniqueFilename('tmp', 'my-test') +t.like(randomPrefixedTmpfile, /^tmp.my-test-[a-f0-9]{8}$/, 'random prefixed tmp file') + +var randomPrefixedAgain = uniqueFilename('tmp', 'my-test') +t.notEqual(randomPrefixedAgain, randomPrefixedTmpfile, 'random prefixed tmp files are not the same') + +var uniqueTmpfile = uniqueFilename('tmp', 'testing', '/my/thing/to/uniq/on') +t.like(uniqueTmpfile, /^tmp.testing-7ddd44c0$/, 'unique filename') + +var uniqueAgain = uniqueFilename('tmp', 'testing', '/my/thing/to/uniq/on') +t.is(uniqueTmpfile, uniqueAgain, 'same unique string component produces same filename') diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/.travis.yml b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/.travis.yml new file mode 100644 index 000000000..5651fce24 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/.travis.yml @@ -0,0 +1,10 @@ +language: node_js +sudo: false +before_install: + - "npm -g install npm" +node_js: + - "6" + - "8" + - "10" + - "lts/*" + - "node" diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/LICENSE new file mode 100644 index 000000000..7953647e7 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright npm, Inc + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/README.md new file mode 100644 index 000000000..87f92f1d1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/README.md @@ -0,0 +1,19 @@ +unique-slug +=========== + +Generate a unique character string suitible for use in files and URLs. + +``` +var uniqueSlug = require('unique-slug') + +var randomSlug = uniqueSlug() +var fileSlug = uniqueSlug('/etc/passwd') +``` + +### uniqueSlug(*str*) → String (8 chars) + +If *str* is passed in then the return value will be its murmur hash in +hex. + +If *str* is not passed in, it will be 4 randomly generated bytes +converted into 8 hexadecimal characters. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/index.js new file mode 100644 index 000000000..fa4761ad2 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/index.js @@ -0,0 +1,11 @@ +'use strict' +var MurmurHash3 = require('imurmurhash') + +module.exports = function (uniq) { + if (uniq) { + var hash = new MurmurHash3(uniq) + return ('00000000' + hash.result().toString(16)).substr(-8) + } else { + return (Math.random().toString(16) + '0000000').substr(2, 8) + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/package.json new file mode 100644 index 000000000..2142e6856 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/package.json @@ -0,0 +1,23 @@ +{ + "name": "unique-slug", + "version": "2.0.2", + "description": "Generate a unique character string suitible for use in files and URLs.", + "main": "index.js", + "scripts": { + "test": "standard && tap --coverage test" + }, + "keywords": [], + "author": "Rebecca Turner (http://re-becca.org)", + "license": "ISC", + "devDependencies": { + "standard": "^12.0.1", + "tap": "^12.7.0" + }, + "repository": { + "type": "git", + "url": "git://github.com/iarna/unique-slug.git" + }, + "dependencies": { + "imurmurhash": "^0.1.4" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/test/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/test/index.js new file mode 100644 index 000000000..0f4ccad04 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unique-slug/test/index.js @@ -0,0 +1,13 @@ +'use strict' +var t = require('tap') +var uniqueSlug = require('../index.js') + +t.plan(5) +var slugA = uniqueSlug() +t.is(slugA.length, 8, 'random slugs are 8 chars') +t.notEqual(slugA, uniqueSlug(), "two slugs aren't the same") +var base = '/path/to/thingy' +var slugB = uniqueSlug(base) +t.is(slugB.length, 8, 'string based slugs are 8 chars') +t.is(slugB, uniqueSlug(base), 'two string based slugs, from the same string are the same') +t.notEqual(slugB, uniqueSlug(slugA), 'two string based slongs, from diff strings are different') diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/HISTORY.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/HISTORY.md new file mode 100644 index 000000000..85e0f8d74 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/HISTORY.md @@ -0,0 +1,4 @@ +1.0.0 / 2015-06-14 +================== + + * Initial release diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/LICENSE new file mode 100644 index 000000000..aed013827 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2015 Douglas Christopher Wilson + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/README.md new file mode 100644 index 000000000..e536ad2c0 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/README.md @@ -0,0 +1,43 @@ +# unpipe + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-image]][node-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Unpipe a stream from all destinations. + +## Installation + +```sh +$ npm install unpipe +``` + +## API + +```js +var unpipe = require('unpipe') +``` + +### unpipe(stream) + +Unpipes all destinations from a given stream. With stream 2+, this is +equivalent to `stream.unpipe()`. When used with streams 1 style streams +(typically Node.js 0.8 and below), this module attempts to undo the +actions done in `stream.pipe(dest)`. + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/unpipe.svg +[npm-url]: https://npmjs.org/package/unpipe +[node-image]: https://img.shields.io/node/v/unpipe.svg +[node-url]: http://nodejs.org/download/ +[travis-image]: https://img.shields.io/travis/stream-utils/unpipe.svg +[travis-url]: https://travis-ci.org/stream-utils/unpipe +[coveralls-image]: https://img.shields.io/coveralls/stream-utils/unpipe.svg +[coveralls-url]: https://coveralls.io/r/stream-utils/unpipe?branch=master +[downloads-image]: https://img.shields.io/npm/dm/unpipe.svg +[downloads-url]: https://npmjs.org/package/unpipe diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/index.js new file mode 100644 index 000000000..15c3d97a1 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/index.js @@ -0,0 +1,69 @@ +/*! + * unpipe + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = unpipe + +/** + * Determine if there are Node.js pipe-like data listeners. + * @private + */ + +function hasPipeDataListeners(stream) { + var listeners = stream.listeners('data') + + for (var i = 0; i < listeners.length; i++) { + if (listeners[i].name === 'ondata') { + return true + } + } + + return false +} + +/** + * Unpipe a stream from all destinations. + * + * @param {object} stream + * @public + */ + +function unpipe(stream) { + if (!stream) { + throw new TypeError('argument stream is required') + } + + if (typeof stream.unpipe === 'function') { + // new-style + stream.unpipe() + return + } + + // Node.js 0.8 hack + if (!hasPipeDataListeners(stream)) { + return + } + + var listener + var listeners = stream.listeners('close') + + for (var i = 0; i < listeners.length; i++) { + listener = listeners[i] + + if (listener.name !== 'cleanup' && listener.name !== 'onclose') { + continue + } + + // invoke the listener + listener.call(stream) + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/package.json new file mode 100644 index 000000000..a2b73583b --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/unpipe/package.json @@ -0,0 +1,27 @@ +{ + "name": "unpipe", + "description": "Unpipe a stream from all destinations", + "version": "1.0.0", + "author": "Douglas Christopher Wilson ", + "license": "MIT", + "repository": "stream-utils/unpipe", + "devDependencies": { + "istanbul": "0.3.15", + "mocha": "2.2.5", + "readable-stream": "1.1.13" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "README.md", + "index.js" + ], + "engines": { + "node": ">= 0.8" + }, + "scripts": { + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/History.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/History.md new file mode 100644 index 000000000..acc867537 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/History.md @@ -0,0 +1,16 @@ + +1.0.2 / 2015-10-07 +================== + + * use try/catch when checking `localStorage` (#3, @kumavis) + +1.0.1 / 2014-11-25 +================== + + * browser: use `console.warn()` for deprecation calls + * browser: more jsdocs + +1.0.0 / 2014-04-30 +================== + + * initial commit diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/LICENSE new file mode 100644 index 000000000..6a60e8c22 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2014 Nathan Rajlich + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/README.md new file mode 100644 index 000000000..75622fa7c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/README.md @@ -0,0 +1,53 @@ +util-deprecate +============== +### The Node.js `util.deprecate()` function with browser support + +In Node.js, this module simply re-exports the `util.deprecate()` function. + +In the web browser (i.e. via browserify), a browser-specific implementation +of the `util.deprecate()` function is used. + + +## API + +A `deprecate()` function is the only thing exposed by this module. + +``` javascript +// setup: +exports.foo = deprecate(foo, 'foo() is deprecated, use bar() instead'); + + +// users see: +foo(); +// foo() is deprecated, use bar() instead +foo(); +foo(); +``` + + +## License + +(The MIT License) + +Copyright (c) 2014 Nathan Rajlich + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/browser.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/browser.js new file mode 100644 index 000000000..549ae2f06 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/browser.js @@ -0,0 +1,67 @@ + +/** + * Module exports. + */ + +module.exports = deprecate; + +/** + * Mark that a method should not be used. + * Returns a modified function which warns once by default. + * + * If `localStorage.noDeprecation = true` is set, then it is a no-op. + * + * If `localStorage.throwDeprecation = true` is set, then deprecated functions + * will throw an Error when invoked. + * + * If `localStorage.traceDeprecation = true` is set, then deprecated functions + * will invoke `console.trace()` instead of `console.error()`. + * + * @param {Function} fn - the function to deprecate + * @param {String} msg - the string to print to the console when `fn` is invoked + * @returns {Function} a new "deprecated" version of `fn` + * @api public + */ + +function deprecate (fn, msg) { + if (config('noDeprecation')) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (config('throwDeprecation')) { + throw new Error(msg); + } else if (config('traceDeprecation')) { + console.trace(msg); + } else { + console.warn(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +} + +/** + * Checks `localStorage` for boolean values for the given `name`. + * + * @param {String} name + * @returns {Boolean} + * @api private + */ + +function config (name) { + // accessing global.localStorage can trigger a DOMException in sandboxed iframes + try { + if (!global.localStorage) return false; + } catch (_) { + return false; + } + var val = global.localStorage[name]; + if (null == val) return false; + return String(val).toLowerCase() === 'true'; +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/node.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/node.js new file mode 100644 index 000000000..5e6fcff5d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/node.js @@ -0,0 +1,6 @@ + +/** + * For Node.js, simply re-export the core `util.deprecate` function. + */ + +module.exports = require('util').deprecate; diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/package.json new file mode 100644 index 000000000..2e79f89a9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/util-deprecate/package.json @@ -0,0 +1,27 @@ +{ + "name": "util-deprecate", + "version": "1.0.2", + "description": "The Node.js `util.deprecate()` function with browser support", + "main": "node.js", + "browser": "browser.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git://github.com/TooTallNate/util-deprecate.git" + }, + "keywords": [ + "util", + "deprecate", + "browserify", + "browser", + "node" + ], + "author": "Nathan Rajlich (http://n8.io/)", + "license": "MIT", + "bugs": { + "url": "https://github.com/TooTallNate/util-deprecate/issues" + }, + "homepage": "https://github.com/TooTallNate/util-deprecate" +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/HISTORY.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/HISTORY.md new file mode 100644 index 000000000..f6cbcf7f9 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/HISTORY.md @@ -0,0 +1,39 @@ +1.1.2 / 2017-09-23 +================== + + * perf: improve header token parsing speed + +1.1.1 / 2017-03-20 +================== + + * perf: hoist regular expression + +1.1.0 / 2015-09-29 +================== + + * Only accept valid field names in the `field` argument + - Ensures the resulting string is a valid HTTP header value + +1.0.1 / 2015-07-08 +================== + + * Fix setting empty header from empty `field` + * perf: enable strict mode + * perf: remove argument reassignments + +1.0.0 / 2014-08-10 +================== + + * Accept valid `Vary` header string as `field` + * Add `vary.append` for low-level string manipulation + * Move to `jshttp` orgainzation + +0.1.0 / 2014-06-05 +================== + + * Support array of fields to set + +0.0.0 / 2014-06-04 +================== + + * Initial release diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/LICENSE new file mode 100644 index 000000000..84441fbb5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2014-2017 Douglas Christopher Wilson + +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/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/README.md new file mode 100644 index 000000000..cc000b346 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/README.md @@ -0,0 +1,101 @@ +# vary + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Manipulate the HTTP Vary header + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install vary +``` + +## API + + + +```js +var vary = require('vary') +``` + +### vary(res, field) + +Adds the given header `field` to the `Vary` response header of `res`. +This can be a string of a single field, a string of a valid `Vary` +header, or an array of multiple fields. + +This will append the header if not already listed, otherwise leaves +it listed in the current location. + + + +```js +// Append "Origin" to the Vary header of the response +vary(res, 'Origin') +``` + +### vary.append(header, field) + +Adds the given header `field` to the `Vary` response header string `header`. +This can be a string of a single field, a string of a valid `Vary` header, +or an array of multiple fields. + +This will append the header if not already listed, otherwise leaves +it listed in the current location. The new header string is returned. + + + +```js +// Get header string appending "Origin" to "Accept, User-Agent" +vary.append('Accept, User-Agent', 'Origin') +``` + +## Examples + +### Updating the Vary header when content is based on it + +```js +var http = require('http') +var vary = require('vary') + +http.createServer(function onRequest (req, res) { + // about to user-agent sniff + vary(res, 'User-Agent') + + var ua = req.headers['user-agent'] || '' + var isMobile = /mobi|android|touch|mini/i.test(ua) + + // serve site, depending on isMobile + res.setHeader('Content-Type', 'text/html') + res.end('You are (probably) ' + (isMobile ? '' : 'not ') + 'a mobile user') +}) +``` + +## Testing + +```sh +$ npm test +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/vary.svg +[npm-url]: https://npmjs.org/package/vary +[node-version-image]: https://img.shields.io/node/v/vary.svg +[node-version-url]: https://nodejs.org/en/download +[travis-image]: https://img.shields.io/travis/jshttp/vary/master.svg +[travis-url]: https://travis-ci.org/jshttp/vary +[coveralls-image]: https://img.shields.io/coveralls/jshttp/vary/master.svg +[coveralls-url]: https://coveralls.io/r/jshttp/vary +[downloads-image]: https://img.shields.io/npm/dm/vary.svg +[downloads-url]: https://npmjs.org/package/vary diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/index.js new file mode 100644 index 000000000..5b5e74127 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/index.js @@ -0,0 +1,149 @@ +/*! + * vary + * Copyright(c) 2014-2017 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + */ + +module.exports = vary +module.exports.append = append + +/** + * RegExp to match field-name in RFC 7230 sec 3.2 + * + * field-name = token + * token = 1*tchar + * tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" + * / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" + * / DIGIT / ALPHA + * ; any VCHAR, except delimiters + */ + +var FIELD_NAME_REGEXP = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/ + +/** + * Append a field to a vary header. + * + * @param {String} header + * @param {String|Array} field + * @return {String} + * @public + */ + +function append (header, field) { + if (typeof header !== 'string') { + throw new TypeError('header argument is required') + } + + if (!field) { + throw new TypeError('field argument is required') + } + + // get fields array + var fields = !Array.isArray(field) + ? parse(String(field)) + : field + + // assert on invalid field names + for (var j = 0; j < fields.length; j++) { + if (!FIELD_NAME_REGEXP.test(fields[j])) { + throw new TypeError('field argument contains an invalid header name') + } + } + + // existing, unspecified vary + if (header === '*') { + return header + } + + // enumerate current values + var val = header + var vals = parse(header.toLowerCase()) + + // unspecified vary + if (fields.indexOf('*') !== -1 || vals.indexOf('*') !== -1) { + return '*' + } + + for (var i = 0; i < fields.length; i++) { + var fld = fields[i].toLowerCase() + + // append value (case-preserving) + if (vals.indexOf(fld) === -1) { + vals.push(fld) + val = val + ? val + ', ' + fields[i] + : fields[i] + } + } + + return val +} + +/** + * Parse a vary header into an array. + * + * @param {String} header + * @return {Array} + * @private + */ + +function parse (header) { + var end = 0 + var list = [] + var start = 0 + + // gather tokens + for (var i = 0, len = header.length; i < len; i++) { + switch (header.charCodeAt(i)) { + case 0x20: /* */ + if (start === end) { + start = end = i + 1 + } + break + case 0x2c: /* , */ + list.push(header.substring(start, end)) + start = end = i + 1 + break + default: + end = i + 1 + break + } + } + + // final token + list.push(header.substring(start, end)) + + return list +} + +/** + * Mark that a request is varied on a header field. + * + * @param {Object} res + * @param {String|Array} field + * @public + */ + +function vary (res, field) { + if (!res || !res.getHeader || !res.setHeader) { + // quack quack + throw new TypeError('res argument is required') + } + + // get existing header + var val = res.getHeader('Vary') || '' + var header = Array.isArray(val) + ? val.join(', ') + : String(val) + + // set new header + if ((val = append(header, field))) { + res.setHeader('Vary', val) + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/package.json new file mode 100644 index 000000000..028f72a93 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/vary/package.json @@ -0,0 +1,43 @@ +{ + "name": "vary", + "description": "Manipulate the HTTP Vary header", + "version": "1.1.2", + "author": "Douglas Christopher Wilson ", + "license": "MIT", + "keywords": [ + "http", + "res", + "vary" + ], + "repository": "jshttp/vary", + "devDependencies": { + "beautify-benchmark": "0.2.4", + "benchmark": "2.1.4", + "eslint": "3.19.0", + "eslint-config-standard": "10.2.1", + "eslint-plugin-import": "2.7.0", + "eslint-plugin-markdown": "1.0.0-beta.6", + "eslint-plugin-node": "5.1.1", + "eslint-plugin-promise": "3.5.0", + "eslint-plugin-standard": "3.0.1", + "istanbul": "0.4.5", + "mocha": "2.5.3", + "supertest": "1.1.0" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "README.md", + "index.js" + ], + "engines": { + "node": ">= 0.8" + }, + "scripts": { + "bench": "node benchmark/index.js", + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/CHANGELOG.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/CHANGELOG.md new file mode 100644 index 000000000..7fb1f2033 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/CHANGELOG.md @@ -0,0 +1,166 @@ +# Changes + + +## 2.0.2 + +* Rename bin to `node-which` + +## 2.0.1 + +* generate changelog and publish on version bump +* enforce 100% test coverage +* Promise interface + +## 2.0.0 + +* Parallel tests, modern JavaScript, and drop support for node < 8 + +## 1.3.1 + +* update deps +* update travis + +## v1.3.0 + +* Add nothrow option to which.sync +* update tap + +## v1.2.14 + +* appveyor: drop node 5 and 0.x +* travis-ci: add node 6, drop 0.x + +## v1.2.13 + +* test: Pass missing option to pass on windows +* update tap +* update isexe to 2.0.0 +* neveragain.tech pledge request + +## v1.2.12 + +* Removed unused require + +## v1.2.11 + +* Prevent changelog script from being included in package + +## v1.2.10 + +* Use env.PATH only, not env.Path + +## v1.2.9 + +* fix for paths starting with ../ +* Remove unused `is-absolute` module + +## v1.2.8 + +* bullet items in changelog that contain (but don't start with) # + +## v1.2.7 + +* strip 'update changelog' changelog entries out of changelog + +## v1.2.6 + +* make the changelog bulleted + +## v1.2.5 + +* make a changelog, and keep it up to date +* don't include tests in package +* Properly handle relative-path executables +* appveyor +* Attach error code to Not Found error +* Make tests pass on Windows + +## v1.2.4 + +* Fix typo + +## v1.2.3 + +* update isexe, fix regression in pathExt handling + +## v1.2.2 + +* update deps, use isexe module, test windows + +## v1.2.1 + +* Sometimes windows PATH entries are quoted +* Fixed a bug in the check for group and user mode bits. This bug was introduced during refactoring for supporting strict mode. +* doc cli + +## v1.2.0 + +* Add support for opt.all and -as cli flags +* test the bin +* update travis +* Allow checking for multiple programs in bin/which +* tap 2 + +## v1.1.2 + +* travis +* Refactored and fixed undefined error on Windows +* Support strict mode + +## v1.1.1 + +* test +g exes against secondary groups, if available +* Use windows exe semantics on cygwin & msys +* cwd should be first in path on win32, not last +* Handle lower-case 'env.Path' on Windows +* Update docs +* use single-quotes + +## v1.1.0 + +* Add tests, depend on is-absolute + +## v1.0.9 + +* which.js: root is allowed to execute files owned by anyone + +## v1.0.8 + +* don't use graceful-fs + +## v1.0.7 + +* add license to package.json + +## v1.0.6 + +* isc license + +## 1.0.5 + +* Awful typo + +## 1.0.4 + +* Test for path absoluteness properly +* win: Allow '' as a pathext if cmd has a . in it + +## 1.0.3 + +* Remove references to execPath +* Make `which.sync()` work on Windows by honoring the PATHEXT variable. +* Make `isExe()` always return true on Windows. +* MIT + +## 1.0.2 + +* Only files can be exes + +## 1.0.1 + +* Respect the PATHEXT env for win32 support +* should 0755 the bin +* binary +* guts +* package +* 1st diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/LICENSE new file mode 100644 index 000000000..19129e315 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/README.md new file mode 100644 index 000000000..cd833509f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/README.md @@ -0,0 +1,54 @@ +# which + +Like the unix `which` utility. + +Finds the first instance of a specified executable in the PATH +environment variable. Does not cache the results, so `hash -r` is not +needed when the PATH changes. + +## USAGE + +```javascript +var which = require('which') + +// async usage +which('node', function (er, resolvedPath) { + // er is returned if no "node" is found on the PATH + // if it is found, then the absolute path to the exec is returned +}) + +// or promise +which('node').then(resolvedPath => { ... }).catch(er => { ... not found ... }) + +// sync usage +// throws if not found +var resolved = which.sync('node') + +// if nothrow option is used, returns null if not found +resolved = which.sync('node', {nothrow: true}) + +// Pass options to override the PATH and PATHEXT environment vars. +which('node', { path: someOtherPath }, function (er, resolved) { + if (er) + throw er + console.log('found at %j', resolved) +}) +``` + +## CLI USAGE + +Same as the BSD `which(1)` binary. + +``` +usage: which [-as] program ... +``` + +## OPTIONS + +You may pass an options object as the second argument. + +- `path`: Use instead of the `PATH` environment variable. +- `pathExt`: Use instead of the `PATHEXT` environment variable. +- `all`: Return all matches, instead of just the first one. Note that + this means the function returns an array of strings instead of a + single string. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/bin/node-which b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/bin/node-which new file mode 100644 index 000000000..7cee3729e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/bin/node-which @@ -0,0 +1,52 @@ +#!/usr/bin/env node +var which = require("../") +if (process.argv.length < 3) + usage() + +function usage () { + console.error('usage: which [-as] program ...') + process.exit(1) +} + +var all = false +var silent = false +var dashdash = false +var args = process.argv.slice(2).filter(function (arg) { + if (dashdash || !/^-/.test(arg)) + return true + + if (arg === '--') { + dashdash = true + return false + } + + var flags = arg.substr(1).split('') + for (var f = 0; f < flags.length; f++) { + var flag = flags[f] + switch (flag) { + case 's': + silent = true + break + case 'a': + all = true + break + default: + console.error('which: illegal option -- ' + flag) + usage() + } + } + return false +}) + +process.exit(args.reduce(function (pv, current) { + try { + var f = which.sync(current, { all: all }) + if (all) + f = f.join('\n') + if (!silent) + console.log(f) + return pv; + } catch (e) { + return 1; + } +}, 0)) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/package.json new file mode 100644 index 000000000..97ad7fbab --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/package.json @@ -0,0 +1,43 @@ +{ + "author": "Isaac Z. Schlueter (http://blog.izs.me)", + "name": "which", + "description": "Like which(1) unix command. Find the first instance of an executable in the PATH.", + "version": "2.0.2", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-which.git" + }, + "main": "which.js", + "bin": { + "node-which": "./bin/node-which" + }, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "devDependencies": { + "mkdirp": "^0.5.0", + "rimraf": "^2.6.2", + "tap": "^14.6.9" + }, + "scripts": { + "test": "tap", + "preversion": "npm test", + "postversion": "npm publish", + "prepublish": "npm run changelog", + "prechangelog": "bash gen-changelog.sh", + "changelog": "git add CHANGELOG.md", + "postchangelog": "git commit -m 'update changelog - '${npm_package_version}", + "postpublish": "git push origin --follow-tags" + }, + "files": [ + "which.js", + "bin/node-which" + ], + "tap": { + "check-coverage": true + }, + "engines": { + "node": ">= 8" + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/which.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/which.js new file mode 100644 index 000000000..82afffd21 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/which/which.js @@ -0,0 +1,125 @@ +const isWindows = process.platform === 'win32' || + process.env.OSTYPE === 'cygwin' || + process.env.OSTYPE === 'msys' + +const path = require('path') +const COLON = isWindows ? ';' : ':' +const isexe = require('isexe') + +const getNotFoundError = (cmd) => + Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' }) + +const getPathInfo = (cmd, opt) => { + const colon = opt.colon || COLON + + // If it has a slash, then we don't bother searching the pathenv. + // just check the file itself, and that's it. + const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [''] + : ( + [ + // windows always checks the cwd first + ...(isWindows ? [process.cwd()] : []), + ...(opt.path || process.env.PATH || + /* istanbul ignore next: very unusual */ '').split(colon), + ] + ) + const pathExtExe = isWindows + ? opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM' + : '' + const pathExt = isWindows ? pathExtExe.split(colon) : [''] + + if (isWindows) { + if (cmd.indexOf('.') !== -1 && pathExt[0] !== '') + pathExt.unshift('') + } + + return { + pathEnv, + pathExt, + pathExtExe, + } +} + +const which = (cmd, opt, cb) => { + if (typeof opt === 'function') { + cb = opt + opt = {} + } + if (!opt) + opt = {} + + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] + + const step = i => new Promise((resolve, reject) => { + if (i === pathEnv.length) + return opt.all && found.length ? resolve(found) + : reject(getNotFoundError(cmd)) + + const ppRaw = pathEnv[i] + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw + + const pCmd = path.join(pathPart, cmd) + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd + : pCmd + + resolve(subStep(p, i, 0)) + }) + + const subStep = (p, i, ii) => new Promise((resolve, reject) => { + if (ii === pathExt.length) + return resolve(step(i + 1)) + const ext = pathExt[ii] + isexe(p + ext, { pathExt: pathExtExe }, (er, is) => { + if (!er && is) { + if (opt.all) + found.push(p + ext) + else + return resolve(p + ext) + } + return resolve(subStep(p, i, ii + 1)) + }) + }) + + return cb ? step(0).then(res => cb(null, res), cb) : step(0) +} + +const whichSync = (cmd, opt) => { + opt = opt || {} + + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] + + for (let i = 0; i < pathEnv.length; i ++) { + const ppRaw = pathEnv[i] + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw + + const pCmd = path.join(pathPart, cmd) + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd + : pCmd + + for (let j = 0; j < pathExt.length; j ++) { + const cur = p + pathExt[j] + try { + const is = isexe.sync(cur, { pathExt: pathExtExe }) + if (is) { + if (opt.all) + found.push(cur) + else + return cur + } + } catch (ex) {} + } + } + + if (opt.all && found.length) + return found + + if (opt.nothrow) + return null + + throw getNotFoundError(cmd) +} + +module.exports = which +which.sync = whichSync diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/LICENSE new file mode 100644 index 000000000..f4be44d88 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/LICENSE @@ -0,0 +1,14 @@ +Copyright (c) 2015, Rebecca Turner + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/README.md new file mode 100644 index 000000000..32f1be04f --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/README.md @@ -0,0 +1,47 @@ +wide-align +---------- + +A wide-character aware text alignment function for use in terminals / on the +console. + +### Usage + +``` +var align = require('wide-align') + +// Note that if you view this on a unicode console, all of the slashes are +// aligned. This is because on a console, all narrow characters are +// an en wide and all wide characters are an em. In browsers, this isn't +// held to and wide characters like "古" can be less than two narrow +// characters even with a fixed width font. + +console.log(align.center('abc', 10)) // ' abc ' +console.log(align.center('古古古', 10)) // ' 古古古 ' +console.log(align.left('abc', 10)) // 'abc ' +console.log(align.left('古古古', 10)) // '古古古 ' +console.log(align.right('abc', 10)) // ' abc' +console.log(align.right('古古古', 10)) // ' 古古古' +``` + +### Functions + +#### `align.center(str, length)` → `str` + +Returns *str* with spaces added to both sides such that that it is *length* +chars long and centered in the spaces. + +#### `align.left(str, length)` → `str` + +Returns *str* with spaces to the right such that it is *length* chars long. + +### `align.right(str, length)` → `str` + +Returns *str* with spaces to the left such that it is *length* chars long. + +### Origins + +These functions were originally taken from +[cliui](https://npmjs.com/package/cliui). Changes include switching to the +MUCH faster pad generation function from +[lodash](https://npmjs.com/package/lodash), making center alignment pad +both sides and adding left alignment. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/align.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/align.js new file mode 100644 index 000000000..4f94ca4cd --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/align.js @@ -0,0 +1,65 @@ +'use strict' +var stringWidth = require('string-width') + +exports.center = alignCenter +exports.left = alignLeft +exports.right = alignRight + +// lodash's way of generating pad characters. + +function createPadding (width) { + var result = '' + var string = ' ' + var n = width + do { + if (n % 2) { + result += string; + } + n = Math.floor(n / 2); + string += string; + } while (n); + + return result; +} + +function alignLeft (str, width) { + var trimmed = str.trimRight() + if (trimmed.length === 0 && str.length >= width) return str + var padding = '' + var strWidth = stringWidth(trimmed) + + if (strWidth < width) { + padding = createPadding(width - strWidth) + } + + return trimmed + padding +} + +function alignRight (str, width) { + var trimmed = str.trimLeft() + if (trimmed.length === 0 && str.length >= width) return str + var padding = '' + var strWidth = stringWidth(trimmed) + + if (strWidth < width) { + padding = createPadding(width - strWidth) + } + + return padding + trimmed +} + +function alignCenter (str, width) { + var trimmed = str.trim() + if (trimmed.length === 0 && str.length >= width) return str + var padLeft = '' + var padRight = '' + var strWidth = stringWidth(trimmed) + + if (strWidth < width) { + var padLeftBy = parseInt((width - strWidth) / 2, 10) + padLeft = createPadding(padLeftBy) + padRight = createPadding(width - (strWidth + padLeftBy)) + } + + return padLeft + trimmed + padRight +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/package.json new file mode 100644 index 000000000..2dd27074c --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wide-align/package.json @@ -0,0 +1,33 @@ +{ + "name": "wide-align", + "version": "1.1.5", + "description": "A wide-character aware text alignment function for use on the console or with fixed width fonts.", + "main": "align.js", + "scripts": { + "test": "tap --coverage test/*.js" + }, + "keywords": [ + "wide", + "double", + "unicode", + "cjkv", + "pad", + "align" + ], + "author": "Rebecca Turner (http://re-becca.org/)", + "license": "ISC", + "repository": { + "type": "git", + "url": "https://github.com/iarna/wide-align" + }, + "//": "But not version 5 of string-width, as that's ESM only", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + }, + "devDependencies": { + "tap": "*" + }, + "files": [ + "align.js" + ] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/LICENSE new file mode 100644 index 000000000..19129e315 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/README.md new file mode 100644 index 000000000..98eab2522 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/README.md @@ -0,0 +1,36 @@ +# wrappy + +Callback wrapping utility + +## USAGE + +```javascript +var wrappy = require("wrappy") + +// var wrapper = wrappy(wrapperFunction) + +// make sure a cb is called only once +// See also: http://npm.im/once for this specific use case +var once = wrappy(function (cb) { + var called = false + return function () { + if (called) return + called = true + return cb.apply(this, arguments) + } +}) + +function printBoo () { + console.log('boo') +} +// has some rando property +printBoo.iAmBooPrinter = true + +var onlyPrintOnce = once(printBoo) + +onlyPrintOnce() // prints 'boo' +onlyPrintOnce() // does nothing + +// random property is retained! +assert.equal(onlyPrintOnce.iAmBooPrinter, true) +``` diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/package.json new file mode 100644 index 000000000..130752046 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/package.json @@ -0,0 +1,29 @@ +{ + "name": "wrappy", + "version": "1.0.2", + "description": "Callback wrapping utility", + "main": "wrappy.js", + "files": [ + "wrappy.js" + ], + "directories": { + "test": "test" + }, + "dependencies": {}, + "devDependencies": { + "tap": "^2.3.1" + }, + "scripts": { + "test": "tap --coverage test/*.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/npm/wrappy" + }, + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "license": "ISC", + "bugs": { + "url": "https://github.com/npm/wrappy/issues" + }, + "homepage": "https://github.com/npm/wrappy" +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/wrappy.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/wrappy.js new file mode 100644 index 000000000..bb7e7d6fc --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/wrappy/wrappy.js @@ -0,0 +1,33 @@ +// Returns a wrapper function that returns a wrapped callback +// The wrapper function should do some stuff, and return a +// presumably different callback function. +// This makes sure that own properties are retained, so that +// decorations and such are not lost along the way. +module.exports = wrappy +function wrappy (fn, cb) { + if (fn && cb) return wrappy(fn)(cb) + + if (typeof fn !== 'function') + throw new TypeError('need wrapper function') + + Object.keys(fn).forEach(function (k) { + wrapper[k] = fn[k] + }) + + return wrapper + + function wrapper() { + var args = new Array(arguments.length) + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i] + } + var ret = fn.apply(this, args) + var cb = args[args.length-1] + if (typeof ret === 'function' && ret !== cb) { + Object.keys(cb).forEach(function (k) { + ret[k] = cb[k] + }) + } + return ret + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/LICENSE b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/LICENSE new file mode 100644 index 000000000..19129e315 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/README.md b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/README.md new file mode 100644 index 000000000..f58610186 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/README.md @@ -0,0 +1,204 @@ +# yallist + +Yet Another Linked List + +There are many doubly-linked list implementations like it, but this +one is mine. + +For when an array would be too big, and a Map can't be iterated in +reverse order. + + +[![Build Status](https://travis-ci.org/isaacs/yallist.svg?branch=master)](https://travis-ci.org/isaacs/yallist) [![Coverage Status](https://coveralls.io/repos/isaacs/yallist/badge.svg?service=github)](https://coveralls.io/github/isaacs/yallist) + +## basic usage + +```javascript +var yallist = require('yallist') +var myList = yallist.create([1, 2, 3]) +myList.push('foo') +myList.unshift('bar') +// of course pop() and shift() are there, too +console.log(myList.toArray()) // ['bar', 1, 2, 3, 'foo'] +myList.forEach(function (k) { + // walk the list head to tail +}) +myList.forEachReverse(function (k, index, list) { + // walk the list tail to head +}) +var myDoubledList = myList.map(function (k) { + return k + k +}) +// now myDoubledList contains ['barbar', 2, 4, 6, 'foofoo'] +// mapReverse is also a thing +var myDoubledListReverse = myList.mapReverse(function (k) { + return k + k +}) // ['foofoo', 6, 4, 2, 'barbar'] + +var reduced = myList.reduce(function (set, entry) { + set += entry + return set +}, 'start') +console.log(reduced) // 'startfoo123bar' +``` + +## api + +The whole API is considered "public". + +Functions with the same name as an Array method work more or less the +same way. + +There's reverse versions of most things because that's the point. + +### Yallist + +Default export, the class that holds and manages a list. + +Call it with either a forEach-able (like an array) or a set of +arguments, to initialize the list. + +The Array-ish methods all act like you'd expect. No magic length, +though, so if you change that it won't automatically prune or add +empty spots. + +### Yallist.create(..) + +Alias for Yallist function. Some people like factories. + +#### yallist.head + +The first node in the list + +#### yallist.tail + +The last node in the list + +#### yallist.length + +The number of nodes in the list. (Change this at your peril. It is +not magic like Array length.) + +#### yallist.toArray() + +Convert the list to an array. + +#### yallist.forEach(fn, [thisp]) + +Call a function on each item in the list. + +#### yallist.forEachReverse(fn, [thisp]) + +Call a function on each item in the list, in reverse order. + +#### yallist.get(n) + +Get the data at position `n` in the list. If you use this a lot, +probably better off just using an Array. + +#### yallist.getReverse(n) + +Get the data at position `n`, counting from the tail. + +#### yallist.map(fn, thisp) + +Create a new Yallist with the result of calling the function on each +item. + +#### yallist.mapReverse(fn, thisp) + +Same as `map`, but in reverse. + +#### yallist.pop() + +Get the data from the list tail, and remove the tail from the list. + +#### yallist.push(item, ...) + +Insert one or more items to the tail of the list. + +#### yallist.reduce(fn, initialValue) + +Like Array.reduce. + +#### yallist.reduceReverse + +Like Array.reduce, but in reverse. + +#### yallist.reverse + +Reverse the list in place. + +#### yallist.shift() + +Get the data from the list head, and remove the head from the list. + +#### yallist.slice([from], [to]) + +Just like Array.slice, but returns a new Yallist. + +#### yallist.sliceReverse([from], [to]) + +Just like yallist.slice, but the result is returned in reverse. + +#### yallist.toArray() + +Create an array representation of the list. + +#### yallist.toArrayReverse() + +Create a reversed array representation of the list. + +#### yallist.unshift(item, ...) + +Insert one or more items to the head of the list. + +#### yallist.unshiftNode(node) + +Move a Node object to the front of the list. (That is, pull it out of +wherever it lives, and make it the new head.) + +If the node belongs to a different list, then that list will remove it +first. + +#### yallist.pushNode(node) + +Move a Node object to the end of the list. (That is, pull it out of +wherever it lives, and make it the new tail.) + +If the node belongs to a list already, then that list will remove it +first. + +#### yallist.removeNode(node) + +Remove a node from the list, preserving referential integrity of head +and tail and other nodes. + +Will throw an error if you try to have a list remove a node that +doesn't belong to it. + +### Yallist.Node + +The class that holds the data and is actually the list. + +Call with `var n = new Node(value, previousNode, nextNode)` + +Note that if you do direct operations on Nodes themselves, it's very +easy to get into weird states where the list is broken. Be careful :) + +#### node.next + +The next node in the list. + +#### node.prev + +The previous node in the list. + +#### node.value + +The data the node contains. + +#### node.list + +The list to which this node belongs. (Null if it does not belong to +any list.) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/iterator.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/iterator.js new file mode 100644 index 000000000..d41c97a19 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/iterator.js @@ -0,0 +1,8 @@ +'use strict' +module.exports = function (Yallist) { + Yallist.prototype[Symbol.iterator] = function* () { + for (let walker = this.head; walker; walker = walker.next) { + yield walker.value + } + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/package.json new file mode 100644 index 000000000..8a083867d --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/package.json @@ -0,0 +1,29 @@ +{ + "name": "yallist", + "version": "4.0.0", + "description": "Yet Another Linked List", + "main": "yallist.js", + "directories": { + "test": "test" + }, + "files": [ + "yallist.js", + "iterator.js" + ], + "dependencies": {}, + "devDependencies": { + "tap": "^12.1.0" + }, + "scripts": { + "test": "tap test/*.js --100", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --all; git push origin --tags" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/isaacs/yallist.git" + }, + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "license": "ISC" +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/yallist.js b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/yallist.js new file mode 100644 index 000000000..4e83ab1c5 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/node_modules/yallist/yallist.js @@ -0,0 +1,426 @@ +'use strict' +module.exports = Yallist + +Yallist.Node = Node +Yallist.create = Yallist + +function Yallist (list) { + var self = this + if (!(self instanceof Yallist)) { + self = new Yallist() + } + + self.tail = null + self.head = null + self.length = 0 + + if (list && typeof list.forEach === 'function') { + list.forEach(function (item) { + self.push(item) + }) + } else if (arguments.length > 0) { + for (var i = 0, l = arguments.length; i < l; i++) { + self.push(arguments[i]) + } + } + + return self +} + +Yallist.prototype.removeNode = function (node) { + if (node.list !== this) { + throw new Error('removing node which does not belong to this list') + } + + var next = node.next + var prev = node.prev + + if (next) { + next.prev = prev + } + + if (prev) { + prev.next = next + } + + if (node === this.head) { + this.head = next + } + if (node === this.tail) { + this.tail = prev + } + + node.list.length-- + node.next = null + node.prev = null + node.list = null + + return next +} + +Yallist.prototype.unshiftNode = function (node) { + if (node === this.head) { + return + } + + if (node.list) { + node.list.removeNode(node) + } + + var head = this.head + node.list = this + node.next = head + if (head) { + head.prev = node + } + + this.head = node + if (!this.tail) { + this.tail = node + } + this.length++ +} + +Yallist.prototype.pushNode = function (node) { + if (node === this.tail) { + return + } + + if (node.list) { + node.list.removeNode(node) + } + + var tail = this.tail + node.list = this + node.prev = tail + if (tail) { + tail.next = node + } + + this.tail = node + if (!this.head) { + this.head = node + } + this.length++ +} + +Yallist.prototype.push = function () { + for (var i = 0, l = arguments.length; i < l; i++) { + push(this, arguments[i]) + } + return this.length +} + +Yallist.prototype.unshift = function () { + for (var i = 0, l = arguments.length; i < l; i++) { + unshift(this, arguments[i]) + } + return this.length +} + +Yallist.prototype.pop = function () { + if (!this.tail) { + return undefined + } + + var res = this.tail.value + this.tail = this.tail.prev + if (this.tail) { + this.tail.next = null + } else { + this.head = null + } + this.length-- + return res +} + +Yallist.prototype.shift = function () { + if (!this.head) { + return undefined + } + + var res = this.head.value + this.head = this.head.next + if (this.head) { + this.head.prev = null + } else { + this.tail = null + } + this.length-- + return res +} + +Yallist.prototype.forEach = function (fn, thisp) { + thisp = thisp || this + for (var walker = this.head, i = 0; walker !== null; i++) { + fn.call(thisp, walker.value, i, this) + walker = walker.next + } +} + +Yallist.prototype.forEachReverse = function (fn, thisp) { + thisp = thisp || this + for (var walker = this.tail, i = this.length - 1; walker !== null; i--) { + fn.call(thisp, walker.value, i, this) + walker = walker.prev + } +} + +Yallist.prototype.get = function (n) { + for (var i = 0, walker = this.head; walker !== null && i < n; i++) { + // abort out of the list early if we hit a cycle + walker = walker.next + } + if (i === n && walker !== null) { + return walker.value + } +} + +Yallist.prototype.getReverse = function (n) { + for (var i = 0, walker = this.tail; walker !== null && i < n; i++) { + // abort out of the list early if we hit a cycle + walker = walker.prev + } + if (i === n && walker !== null) { + return walker.value + } +} + +Yallist.prototype.map = function (fn, thisp) { + thisp = thisp || this + var res = new Yallist() + for (var walker = this.head; walker !== null;) { + res.push(fn.call(thisp, walker.value, this)) + walker = walker.next + } + return res +} + +Yallist.prototype.mapReverse = function (fn, thisp) { + thisp = thisp || this + var res = new Yallist() + for (var walker = this.tail; walker !== null;) { + res.push(fn.call(thisp, walker.value, this)) + walker = walker.prev + } + return res +} + +Yallist.prototype.reduce = function (fn, initial) { + var acc + var walker = this.head + if (arguments.length > 1) { + acc = initial + } else if (this.head) { + walker = this.head.next + acc = this.head.value + } else { + throw new TypeError('Reduce of empty list with no initial value') + } + + for (var i = 0; walker !== null; i++) { + acc = fn(acc, walker.value, i) + walker = walker.next + } + + return acc +} + +Yallist.prototype.reduceReverse = function (fn, initial) { + var acc + var walker = this.tail + if (arguments.length > 1) { + acc = initial + } else if (this.tail) { + walker = this.tail.prev + acc = this.tail.value + } else { + throw new TypeError('Reduce of empty list with no initial value') + } + + for (var i = this.length - 1; walker !== null; i--) { + acc = fn(acc, walker.value, i) + walker = walker.prev + } + + return acc +} + +Yallist.prototype.toArray = function () { + var arr = new Array(this.length) + for (var i = 0, walker = this.head; walker !== null; i++) { + arr[i] = walker.value + walker = walker.next + } + return arr +} + +Yallist.prototype.toArrayReverse = function () { + var arr = new Array(this.length) + for (var i = 0, walker = this.tail; walker !== null; i++) { + arr[i] = walker.value + walker = walker.prev + } + return arr +} + +Yallist.prototype.slice = function (from, to) { + to = to || this.length + if (to < 0) { + to += this.length + } + from = from || 0 + if (from < 0) { + from += this.length + } + var ret = new Yallist() + if (to < from || to < 0) { + return ret + } + if (from < 0) { + from = 0 + } + if (to > this.length) { + to = this.length + } + for (var i = 0, walker = this.head; walker !== null && i < from; i++) { + walker = walker.next + } + for (; walker !== null && i < to; i++, walker = walker.next) { + ret.push(walker.value) + } + return ret +} + +Yallist.prototype.sliceReverse = function (from, to) { + to = to || this.length + if (to < 0) { + to += this.length + } + from = from || 0 + if (from < 0) { + from += this.length + } + var ret = new Yallist() + if (to < from || to < 0) { + return ret + } + if (from < 0) { + from = 0 + } + if (to > this.length) { + to = this.length + } + for (var i = this.length, walker = this.tail; walker !== null && i > to; i--) { + walker = walker.prev + } + for (; walker !== null && i > from; i--, walker = walker.prev) { + ret.push(walker.value) + } + return ret +} + +Yallist.prototype.splice = function (start, deleteCount, ...nodes) { + if (start > this.length) { + start = this.length - 1 + } + if (start < 0) { + start = this.length + start; + } + + for (var i = 0, walker = this.head; walker !== null && i < start; i++) { + walker = walker.next + } + + var ret = [] + for (var i = 0; walker && i < deleteCount; i++) { + ret.push(walker.value) + walker = this.removeNode(walker) + } + if (walker === null) { + walker = this.tail + } + + if (walker !== this.head && walker !== this.tail) { + walker = walker.prev + } + + for (var i = 0; i < nodes.length; i++) { + walker = insert(this, walker, nodes[i]) + } + return ret; +} + +Yallist.prototype.reverse = function () { + var head = this.head + var tail = this.tail + for (var walker = head; walker !== null; walker = walker.prev) { + var p = walker.prev + walker.prev = walker.next + walker.next = p + } + this.head = tail + this.tail = head + return this +} + +function insert (self, node, value) { + var inserted = node === self.head ? + new Node(value, null, node, self) : + new Node(value, node, node.next, self) + + if (inserted.next === null) { + self.tail = inserted + } + if (inserted.prev === null) { + self.head = inserted + } + + self.length++ + + return inserted +} + +function push (self, item) { + self.tail = new Node(item, self.tail, null, self) + if (!self.head) { + self.head = self.tail + } + self.length++ +} + +function unshift (self, item) { + self.head = new Node(item, null, self.head, self) + if (!self.tail) { + self.tail = self.head + } + self.length++ +} + +function Node (value, prev, next, list) { + if (!(this instanceof Node)) { + return new Node(value, prev, next, list) + } + + this.list = list + this.value = value + + if (prev) { + prev.next = this + this.prev = prev + } else { + this.prev = null + } + + if (next) { + next.prev = this + this.next = next + } else { + this.next = null + } +} + +try { + // add if support for Symbol.iterator is present + require('./iterator.js')(Yallist) +} catch (er) {} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/notes.txt b/courses/foundation/intro-to-backend/introToBackendAssignment/notes.txt new file mode 100644 index 000000000..0693e8a8e --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/notes.txt @@ -0,0 +1,19 @@ +import express from "express"; + +const app = express(); +const port = 3000; + +app.get("/", (req, res) => { + res.send("Hello from exercise 1!"); +}); + +app.get("/currentYear", (req, res) => { + // TODO: Implement this function to return a JSON object containing the current year + const d = new Date(); + let year = d.getFullYear(); + res.send("The current year is "+year); +}); + +app.listen(port, () => { + console.log(`Listening on port ${port}`); +}); \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/package-lock.json b/courses/foundation/intro-to-backend/introToBackendAssignment/package-lock.json new file mode 100644 index 000000000..b52525e38 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/package-lock.json @@ -0,0 +1,2442 @@ +{ + "name": "mypackage", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mypackage", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "express": "^5.2.1", + "knex": "^3.1.0", + "sqlite3": "^5.1.7" + }, + "devDependencies": {} + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT", + "optional": true + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC", + "optional": true + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "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==", + "license": "MIT", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/aproba": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", + "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", + "license": "ISC", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT", + "optional": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz", + "integrity": "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "license": "MIT" + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT", + "optional": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC", + "optional": true + }, + "node_modules/content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT", + "optional": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/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==", + "license": "MIT", + "optional": true + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT", + "optional": true + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, + "node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC", + "optional": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/getopts": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz", + "integrity": "sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==", + "license": "MIT" + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC", + "optional": true + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC", + "optional": true + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz", + "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8.19" + } + }, + "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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC", + "optional": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "optional": 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==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ip-address": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "license": "MIT", + "optional": true + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC", + "optional": true + }, + "node_modules/knex": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/knex/-/knex-3.1.0.tgz", + "integrity": "sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw==", + "license": "MIT", + "dependencies": { + "colorette": "2.0.19", + "commander": "^10.0.0", + "debug": "4.3.4", + "escalade": "^3.1.1", + "esm": "^3.2.25", + "get-package-type": "^0.1.0", + "getopts": "2.3.0", + "interpret": "^2.2.0", + "lodash": "^4.17.21", + "pg-connection-string": "2.6.2", + "rechoir": "^0.8.0", + "resolve-from": "^5.0.0", + "tarn": "^3.0.2", + "tildify": "2.0.0" + }, + "bin": { + "knex": "bin/cli.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependenciesMeta": { + "better-sqlite3": { + "optional": true + }, + "mysql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/knex/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/knex/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "license": "ISC", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abi": { + "version": "3.85.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz", + "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==", + "license": "MIT" + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "license": "ISC", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "license": "MIT", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC", + "optional": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC", + "optional": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sqlite3": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", + "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "optional": 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==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tarn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tarn/-/tarn-3.0.2.tgz", + "integrity": "sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tildify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", + "integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "optional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + } + } +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/package.json b/courses/foundation/intro-to-backend/introToBackendAssignment/package.json new file mode 100644 index 000000000..a8f8a50f4 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/package.json @@ -0,0 +1,19 @@ +{ + "name": "mypackage", + "version": "1.0.0", + "description": "", + "license": "ISC", + "author": "", + "type": "module", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": " node index.js" + }, + "dependencies": { + "express": "^5.2.1", + "knex": "^3.1.0", + "sqlite3": "^5.1.7" + }, + "keywords": [] +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/users.sqlite3 b/courses/foundation/intro-to-backend/introToBackendAssignment/users.sqlite3 new file mode 100644 index 000000000..e69de29bb From 663a4d395dbaca269b62b4a921c5a2a0cbe3a5cc Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 7 Jan 2026 10:20:41 +0100 Subject: [PATCH 52/62] add intro to front end assignment --- .../intro-to-frontend/HYFBay/index.html | 4 +- .../HogwartsHouseGenerator/index.html | 19 ++++++ .../HogwartsHouseGenerator/script.js | 50 ++++++++++++++++ .../HogwartsHouseGenerator/styles.css | 59 +++++++++++++++++++ 4 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 courses/foundation/intro-to-frontend/HogwartsHouseGenerator/index.html create mode 100644 courses/foundation/intro-to-frontend/HogwartsHouseGenerator/script.js create mode 100644 courses/foundation/intro-to-frontend/HogwartsHouseGenerator/styles.css diff --git a/courses/foundation/intro-to-frontend/HYFBay/index.html b/courses/foundation/intro-to-frontend/HYFBay/index.html index 07f60fe48..ebe12d431 100644 --- a/courses/foundation/intro-to-frontend/HYFBay/index.html +++ b/courses/foundation/intro-to-frontend/HYFBay/index.html @@ -8,7 +8,9 @@ /> -
    +
    + +
    diff --git a/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/index.html b/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/index.html new file mode 100644 index 000000000..0f267367f --- /dev/null +++ b/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/index.html @@ -0,0 +1,19 @@ + + + + + Hogwarts House Generator + + + +
    +

    Hogwarts House Generator

    + + + +
    +
    + + + + diff --git a/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/script.js b/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/script.js new file mode 100644 index 000000000..b4caa419a --- /dev/null +++ b/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/script.js @@ -0,0 +1,50 @@ +const houses = [ + { + name: "Gryffindor", + color: "#740001", + description: "Brave, daring, and chivalrous.", + image: "https://i.pinimg.com/1200x/99/09/3c/99093c0e1cf4ba5b207e03b4babdf3f7.jpg" + }, + { + name: "Hufflepuff", + color: "#ffdb00", + description: "Loyal, patient, and fair.", + image: "https://i.pinimg.com/1200x/3d/af/c1/3dafc187a67cd577508762150985f65c.jpg" + }, + { + name: "Ravenclaw", + color: "#222f5b", + description: "Intelligent, wise, and witty.", + image: "https://i.pinimg.com/1200x/74/50/89/7450897d3dd45fbebaceadce3df15e43.jpg" + }, + { + name: "Slytherin", + color: "#1a472a", + description: "Ambitious, cunning, and resourceful.", + image: "https://i.pinimg.com/1200x/4f/e3/a4/4fe3a4aed32901f848d9dd12c5d1f5de.jpg" + } +]; + +const input = document.getElementById("name"); +const button = document.getElementById("generateBtn"); +const result = document.getElementById("result"); + +button.addEventListener("click", () => { + const name = input.value.trim(); + + if (!name) { + alert("Please enter your name!"); + return; + } + + const randomIndex = Math.floor(Math.random() * houses.length); + const house = houses[randomIndex]; + + result.innerHTML = ` +

    ${name} belongs in ${house.name}!

    +

    ${house.description}

    + ${house.name} crest + `; + + result.classList.add("show"); +}); diff --git a/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/styles.css b/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/styles.css new file mode 100644 index 000000000..06cb98976 --- /dev/null +++ b/courses/foundation/intro-to-frontend/HogwartsHouseGenerator/styles.css @@ -0,0 +1,59 @@ +body { + font-family: 'Segoe UI', sans-serif; + background: linear-gradient(to right, #926306, #251a0c); + color: #fff; + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; + margin: 0; +} + +.container { + text-align: center; + background: rgba(0,0,0,0.5); + padding: 30px 50px; + border-radius: 15px; + box-shadow: 0 0 20px rgba(0,0,0,0.7); +} + +input { + padding: 10px; + width: 200px; + border-radius: 8px; + border: none; + margin-right: 10px; +} + +button { + padding: 10px 20px; + border-radius: 8px; + border: none; + cursor: pointer; + background-color: #f5c518; + color: #000; + font-weight: bold; + transition: 0.3s; +} + +button:hover { + background-color: #ffc107; +} + +.result-card { + margin-top: 20px; + padding: 20px; + border-radius: 15px; + opacity: 0; + transition: opacity 0.6s ease-in-out; +} + +.result-card.show { + opacity: 1; +} + +.result-card img { + width: 100px; + margin-top: 15px; +} + From a29205e1c059c7ba3a9b42a9a466579d01e97042 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 7 Jan 2026 15:29:48 +0100 Subject: [PATCH 53/62] Add some modifications on HYFBay exercise --- .../intro-to-frontend/HYFBay/index.html | 3 ++- .../intro-to-frontend/HYFBay/main.css | 13 ++++++++++++ .../intro-to-frontend/HYFBay/main.js | 21 ++++++++++++++++++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/courses/foundation/intro-to-frontend/HYFBay/index.html b/courses/foundation/intro-to-frontend/HYFBay/index.html index ebe12d431..bcee9ab43 100644 --- a/courses/foundation/intro-to-frontend/HYFBay/index.html +++ b/courses/foundation/intro-to-frontend/HYFBay/index.html @@ -9,7 +9,8 @@
    - +

    hyfBay

    +
      diff --git a/courses/foundation/intro-to-frontend/HYFBay/main.css b/courses/foundation/intro-to-frontend/HYFBay/main.css index 9f6b12f10..bb8b50b2b 100644 --- a/courses/foundation/intro-to-frontend/HYFBay/main.css +++ b/courses/foundation/intro-to-frontend/HYFBay/main.css @@ -18,3 +18,16 @@ ul { margin: 0; padding: 0; } +.rating-low { + border-left: 4px solid red; +} + +.rating-high { + border-left: 4px solid green; +} + +.product-card { + background: white; + padding: 10px; + margin: 10px 0; +} diff --git a/courses/foundation/intro-to-frontend/HYFBay/main.js b/courses/foundation/intro-to-frontend/HYFBay/main.js index 00111ae11..b026e56d5 100644 --- a/courses/foundation/intro-to-frontend/HYFBay/main.js +++ b/courses/foundation/intro-to-frontend/HYFBay/main.js @@ -6,6 +6,25 @@ console.log(products); // This should create the ul and the li's with the individual products details function renderProducts(products) { // your code goes here -} + const productList = document.getElementById("productList"); + for (let i = 0; i < products.length; i++) { + const listItem = document.createElement("li"); + + const ratingClass = + products[i].rating < 5 ? "rating-low" : "rating-high"; + + listItem.className = "product-list-item"; + listItem.innerHTML = ` +
      +

      ${products[i].name}

      +

      Rating: ${products[i].rating}

      +

      Price: ${products[i].price}

      +
      + `; + + productList.appendChild(listItem); + } + +} renderProducts(products); From 0213d46dd663800877a9f175f30fc4dbf0f18342 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 14 Jan 2026 12:31:51 +0100 Subject: [PATCH 54/62] Add the trello board link into a text file --- courses/foundation/Intro to Agile/IntroToAgileAssignment.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 courses/foundation/Intro to Agile/IntroToAgileAssignment.txt diff --git a/courses/foundation/Intro to Agile/IntroToAgileAssignment.txt b/courses/foundation/Intro to Agile/IntroToAgileAssignment.txt new file mode 100644 index 000000000..ded8f3473 --- /dev/null +++ b/courses/foundation/Intro to Agile/IntroToAgileAssignment.txt @@ -0,0 +1,2 @@ +Trello Board: +https://trello.com/b/QFnjyAlk/hyf-assignment \ No newline at end of file From aecfe92251caa4f041136f814a55768225f28d28 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Tue, 3 Feb 2026 13:20:35 +0100 Subject: [PATCH 55/62] Remove node_modules folder and add it to .gitignore file --- .../intro-to-backend/exercises/.gitignore | 1 + .../intro-to-backend/exercises/README.md | 0 .../exercises/database.sqlite3 | Bin 0 -> 8192 bytes .../intro-to-backend/exercises/exercise1.js | 16 + .../intro-to-backend/exercises/exercise2.js | 30 + .../exercises/package-lock.json | 2507 +++++++++++++++++ .../intro-to-backend/exercises/package.json | 23 + 7 files changed, 2577 insertions(+) create mode 100644 courses/foundation/intro-to-backend/exercises/.gitignore create mode 100644 courses/foundation/intro-to-backend/exercises/README.md create mode 100644 courses/foundation/intro-to-backend/exercises/database.sqlite3 create mode 100644 courses/foundation/intro-to-backend/exercises/exercise1.js create mode 100644 courses/foundation/intro-to-backend/exercises/exercise2.js create mode 100644 courses/foundation/intro-to-backend/exercises/package-lock.json create mode 100644 courses/foundation/intro-to-backend/exercises/package.json diff --git a/courses/foundation/intro-to-backend/exercises/.gitignore b/courses/foundation/intro-to-backend/exercises/.gitignore new file mode 100644 index 000000000..c2658d7d1 --- /dev/null +++ b/courses/foundation/intro-to-backend/exercises/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/courses/foundation/intro-to-backend/exercises/README.md b/courses/foundation/intro-to-backend/exercises/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/courses/foundation/intro-to-backend/exercises/database.sqlite3 b/courses/foundation/intro-to-backend/exercises/database.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..da1d2676d626eaacab905c6fb83affa15a54d279 GIT binary patch literal 8192 zcmeI1&2G~`5XYTRD2|~A?>l1u<=LIHm-oA#iSo;3aP8o1By1uHg;?8R*pke zZgAuoxbi5x058HTFk>f;Kti06cD1qpJMoO?|Jz(vIeFU-5=JgW9MOc>$|EJ0QyPRQ zijtpx;FgXYTo#55g9Ok03LRVYY|X;*ucbLuyTG#dM<)G6x5U@}fbG!)Pb$Fk2C zv6)I`J1c8yhDlOeP`1THJYpWb4e^d2JxLdHFWV0=T~#r?ie60cVmnpr>UAJE-HF8w z9C|_Z`Y0P>l7vEB;k)P|idut8wq}Bh8ZoO*?QVZCv~dUL73K8Ihd;=NAoLqlb4$)Ww6wZhPiq;bh8tVY zTG;hz90sh-*dSAl>sTa$&$hOmPaUmpLawD5o4B>`qkvY@O@h!?>d1mM%pK7`5I!FZ p-WUDeWhUpY>N)I0Rj1X!7`QSV3$vSHFkmN9koXjpK1Mk=@eB431C9Uy literal 0 HcmV?d00001 diff --git a/courses/foundation/intro-to-backend/exercises/exercise1.js b/courses/foundation/intro-to-backend/exercises/exercise1.js new file mode 100644 index 000000000..1b980d03b --- /dev/null +++ b/courses/foundation/intro-to-backend/exercises/exercise1.js @@ -0,0 +1,16 @@ +import express from "express"; + +const app = express(); +const port = 3000; + +app.get("/", (req, res) => { + res.send("Hello from exercise 1!"); +}); + +app.get("/currentYear", (req, res) => { + // TODO: Implement this function to return a JSON object containing the current year +}); + +app.listen(port, () => { + console.log(`Listening on port ${port}`); +}); \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/exercises/exercise2.js b/courses/foundation/intro-to-backend/exercises/exercise2.js new file mode 100644 index 000000000..371f7329d --- /dev/null +++ b/courses/foundation/intro-to-backend/exercises/exercise2.js @@ -0,0 +1,30 @@ +import express from "express"; +import knex from "knex"; + +const app = express(); +const port = 3000; + +// This connects to the database stored in the file mentioned below +const knexInstance = knex({ + client: "sqlite3", + connection: { + filename: "./database.sqlite3", + }, + useNullAsDefault: true, // Omit warning in console +}); + +app.get("/", (req, res) => { + res.send("Hello from exercise 2!"); +}); + +// Here is an example of the first route, /all-users, which returns all users sorted by their ID +app.get("/all-users", async (req, res) => { + const rows = await knexInstance.raw("SELECT * FROM users ORDER BY id ASC;"); + res.json(rows); +}); + +// TODO implement more routes here + +app.listen(port, () => { + console.log(`Listening on port ${port}`); +}); \ No newline at end of file diff --git a/courses/foundation/intro-to-backend/exercises/package-lock.json b/courses/foundation/intro-to-backend/exercises/package-lock.json new file mode 100644 index 000000000..0fb6c5828 --- /dev/null +++ b/courses/foundation/intro-to-backend/exercises/package-lock.json @@ -0,0 +1,2507 @@ +{ + "name": "intro-to-backend", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "intro-to-backend", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "express": "^5.1.0", + "knex": "^3.1.0", + "sqlite3": "^5.1.7" + }, + "devDependencies": { + "nodemon": "^3.1.10" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "optional": true + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "optional": true + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "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==", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "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==", + "devOptional": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "devOptional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "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==", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==" + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "engines": { + "node": ">=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "devOptional": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "optional": true + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "optional": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "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==", + "optional": true + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "optional": true + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "optional": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/getopts": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz", + "integrity": "sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==" + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "optional": true + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "optional": true + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "optional": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "optional": true, + "engines": { + "node": ">=0.8.19" + } + }, + "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==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "optional": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "optional": 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==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "optional": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "optional": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "optional": true + }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "optional": true + }, + "node_modules/knex": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/knex/-/knex-3.1.0.tgz", + "integrity": "sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw==", + "dependencies": { + "colorette": "2.0.19", + "commander": "^10.0.0", + "debug": "4.3.4", + "escalade": "^3.1.1", + "esm": "^3.2.25", + "get-package-type": "^0.1.0", + "getopts": "2.3.0", + "interpret": "^2.2.0", + "lodash": "^4.17.21", + "pg-connection-string": "2.6.2", + "rechoir": "^0.8.0", + "resolve-from": "^5.0.0", + "tarn": "^3.0.2", + "tildify": "2.0.0" + }, + "bin": { + "knex": "bin/cli.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependenciesMeta": { + "better-sqlite3": { + "optional": true + }, + "mysql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/knex/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/knex/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==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "devOptional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "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==" + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abi": { + "version": "3.75.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz", + "integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==" + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/nodemon": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz", + "integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "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==", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "optional": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "optional": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "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/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz", + "integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==", + "optional": true, + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "optional": true + }, + "node_modules/sqlite3": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", + "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "optional": 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==", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-fs": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", + "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tarn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tarn/-/tarn-3.0.2.tgz", + "integrity": "sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tildify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", + "integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "optional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/courses/foundation/intro-to-backend/exercises/package.json b/courses/foundation/intro-to-backend/exercises/package.json new file mode 100644 index 000000000..117ecafd1 --- /dev/null +++ b/courses/foundation/intro-to-backend/exercises/package.json @@ -0,0 +1,23 @@ +{ + "name": "intro-to-backend", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "exercise1": "nodemon exercise1.js", + "exercise2": "nodemon exercise2.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "type": "module", + "dependencies": { + "express": "^5.1.0", + "knex": "^3.1.0", + "sqlite3": "^5.1.7" + }, + "devDependencies": { + "nodemon": "^3.1.10" + } +} From 29f064b2ad96b30373b3ea75adab04acfecbbb8d Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Tue, 3 Feb 2026 13:55:25 +0100 Subject: [PATCH 56/62] Add /search, /recent-users, POST /users/:id/confirm; move home HTML to template and style UI --- .../introToBackendAssignment/db/users.js | 75 +++++++ .../introToBackendAssignment/index.js | 202 +++++++++++------- .../templates/home.html | 101 +++++++++ 3 files changed, 303 insertions(+), 75 deletions(-) create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/db/users.js create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/templates/home.html diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/db/users.js b/courses/foundation/intro-to-backend/introToBackendAssignment/db/users.js new file mode 100644 index 000000000..e75347846 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/db/users.js @@ -0,0 +1,75 @@ +export async function getAllUsers(knex) { + return knex('users').select('*').orderBy('id', 'asc'); +} + +export async function getUserById(knex, id) { + return knex('users').where({ id }).first(); +} + +export async function createUser(knex, user) { + const [id] = await knex('users').insert(user); + return getUserById(knex, id); +} + +export async function updateUser(knex, id, changes) { + await knex('users').where({ id }).update(changes); + return getUserById(knex, id); +} + +export async function deleteUser(knex, id) { + return knex('users').where({ id }).del(); +} + +export async function countUsers(knex) { + const rows = await knex('users').count({ total_users: '*' }); + // knex (sqlite) returns [{ total_users: 42 }] + return rows[0]; +} + +export async function getUnconfirmedUsers(knex) { + return knex('users').whereNull('confirmed_at').select('*'); +} + +export async function getGmailUsers(knex) { + return knex('users').where('email', 'like', '%@gmail.com').select('*'); +} + +export async function getUsersByYear(knex, year) { + const from = `${year}-01-01`; + const to = `${year + 1}-01-01`; + return knex('users').where('created_at', '>=', from).andWhere('created_at', '<', to).select('*'); +} + +export async function getFirstUser(knex) { + return knex('users').orderBy('id', 'asc').first(); +} + +export async function lastNameCount(knex) { + return knex('users').select('last_name').count('* as last_name_count').groupBy('last_name').orderBy('last_name', 'asc'); +} + +export async function searchUsers(knex, q) { + if (!q) return []; + const like = `%${q}%`; + return knex('users') + .where(function () { + this.where('first_name', 'like', like) + .orWhere('last_name', 'like', like) + .orWhere('email', 'like', like); + }) + .select('*') + .orderBy('id', 'asc'); +} + +export async function recentUsers(knex, limit = 5) { + return knex('users') + .select('*') + .orderBy('created_at', 'desc') + .limit(limit); +} + +export async function confirmUser(knex, id) { + const now = new Date().toISOString(); + await knex('users').where({ id }).update({ confirmed_at: now }); + return getUserById(knex, id); +} diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/index.js index 58f8d36b4..96b2d1bfe 100644 --- a/courses/foundation/intro-to-backend/introToBackendAssignment/index.js +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/index.js @@ -1,5 +1,9 @@ import express from "express"; import knexLibrary from "knex"; +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; +import * as userModel from "./db/users.js"; const app = express(); const port = 3000; @@ -8,45 +12,25 @@ app.use(express.json()); /** * Knex connection to SQLite database - * Make sure users.sqlite3 exists in this folder */ const knexInstance = knexLibrary({ client: "sqlite3", connection: { - filename: "C:\Users\oumai\Documents\web developement\HackYourFuture\week-10", + filename: "./users.sqlite3", }, useNullAsDefault: true, }); +// Load home HTML from a separate file to keep route concise +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const HOME_HTML = fs.readFileSync(path.join(__dirname, "templates", "home.html"), "utf8"); + /** - * HOME ROUTE — HTML PAGE + * HOME ROUTE — concise */ app.get("/", (req, res) => { - res.send(` - - - - User API - - -

      Welcome to the User API

      -

      Use the endpoints to retrieve user data.

      -

      - Current user count: - Loading... -

      - - - - - `); + res.type("html").send(HOME_HTML); }); /** @@ -54,23 +38,20 @@ app.get("/", (req, res) => { */ app.get("/user-count", async (req, res) => { try { - const result = await knexInstance.raw( - "SELECT COUNT(*) AS total_users FROM users" - ); - res.json(result); + const row = await userModel.countUsers(knexInstance); + // row is { total_users: n } + res.json(row); } catch (error) { res.status(500).json({ error: error.message }); } }); /** - * ALL USERS (sorted by id) + * CRUD: list users */ -app.get("/all-users", async (req, res) => { +app.get("/users", async (req, res) => { try { - const rows = await knexInstance.raw( - "SELECT * FROM users ORDER BY id ASC" - ); + const rows = await userModel.getAllUsers(knexInstance); res.json(rows); } catch (error) { res.status(500).json({ error: error.message }); @@ -78,80 +59,151 @@ app.get("/all-users", async (req, res) => { }); /** - * UNCONFIRMED USERS + * CRUD: get user by id */ -app.get("/unconfirmed-users", async (req, res) => { +app.get("/users/:id", async (req, res) => { try { - const rows = await knexInstance.raw( - "SELECT * FROM users WHERE confirmed_at IS NULL" - ); - res.json(rows); + const id = Number(req.params.id); + const user = await userModel.getUserById(knexInstance, id); + if (!user) return res.status(404).json({ error: "User not found" }); + res.json(user); } catch (error) { res.status(500).json({ error: error.message }); } }); /** - * GMAIL USERS + * CRUD: create user */ -app.get("/gmail-users", async (req, res) => { +app.post("/users", async (req, res) => { try { - const rows = await knexInstance.raw( - "SELECT * FROM users WHERE email LIKE '%@gmail.com'" - ); - res.json(rows); + const { first_name, last_name, email, confirmed_at, created_at } = req.body; + if (!first_name || !email) { + return res.status(400).json({ error: "first_name and email are required" }); + } + const newUser = { + first_name, + last_name: last_name || null, + email, + confirmed_at: confirmed_at || null, + created_at: created_at || new Date().toISOString(), + }; + const inserted = await userModel.createUser(knexInstance, newUser); + res.status(201).json(inserted); } catch (error) { res.status(500).json({ error: error.message }); } }); /** - * USERS CREATED IN 2022 + * CRUD: update user */ -app.get("/2022-users", async (req, res) => { +app.put("/users/:id", async (req, res) => { try { - const rows = await knexInstance.raw(` - SELECT * FROM users - WHERE created_at >= '2022-01-01' - AND created_at < '2023-01-01' - `); - res.json(rows); + const id = Number(req.params.id); + const changes = req.body; + const existing = await userModel.getUserById(knexInstance, id); + if (!existing) return res.status(404).json({ error: "User not found" }); + const updated = await userModel.updateUser(knexInstance, id, changes); + res.json(updated); } catch (error) { res.status(500).json({ error: error.message }); } }); /** - * FIRST USER + * CRUD: delete user */ -app.get("/first-user", async (req, res) => { +app.delete("/users/:id", async (req, res) => { try { - const result = await knexInstance.raw( - "SELECT * FROM users ORDER BY id ASC LIMIT 1" - ); + const id = Number(req.params.id); + const existing = await userModel.getUserById(knexInstance, id); + if (!existing) return res.status(404).json({ error: "User not found" }); + await userModel.deleteUser(knexInstance, id); + res.status(204).send(); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); - if (result.length === 0) { - return res.status(404).send("No users found"); - } +/** + * Other helpful routes delegated to model functions + */ +app.get("/unconfirmed-users", async (req, res) => { + try { + res.json(await userModel.getUnconfirmedUsers(knexInstance)); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +app.get("/gmail-users", async (req, res) => { + try { + res.json(await userModel.getGmailUsers(knexInstance)); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +app.get("/2022-users", async (req, res) => { + try { + res.json(await userModel.getUsersByYear(knexInstance, 2022)); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); - res.json(result); +app.get("/first-user", async (req, res) => { + try { + const user = await userModel.getFirstUser(knexInstance); + if (!user) return res.status(404).json({ error: "No users found" }); + res.json(user); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +app.get("/last-name-count", async (req, res) => { + try { + res.json(await userModel.lastNameCount(knexInstance)); } catch (error) { res.status(500).json({ error: error.message }); } }); /** - * LAST NAME COUNT + * NEW ROUTES */ -app.get("/last-name-count", async (req, res) => { +// Search users by name or email: /search?q=alex +app.get('/search', async (req, res) => { + try { + const q = (req.query.q || '').trim(); + const rows = await userModel.searchUsers(knexInstance, q); + res.json(rows); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +// Recent users: /recent-users?limit=5 +app.get('/recent-users', async (req, res) => { + try { + const limit = Number(req.query.limit) || 5; + const rows = await userModel.recentUsers(knexInstance, limit); + res.json(rows); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +// Confirm a user (set confirmed_at): POST /users/:id/confirm +app.post('/users/:id/confirm', async (req, res) => { try { - const result = await knexInstance.raw(` - SELECT last_name, COUNT(*) AS last_name_count - FROM users - GROUP BY last_name - ORDER BY last_name ASC - `); - res.json(result); + const id = Number(req.params.id); + const existing = await userModel.getUserById(knexInstance, id); + if (!existing) return res.status(404).json({ error: 'User not found' }); + const updated = await userModel.confirmUser(knexInstance, id); + res.json(updated); } catch (error) { res.status(500).json({ error: error.message }); } diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/templates/home.html b/courses/foundation/intro-to-backend/introToBackendAssignment/templates/home.html new file mode 100644 index 000000000..7e730f863 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/templates/home.html @@ -0,0 +1,101 @@ + + + + + User API + + + +
      +
      +

      User API

      +
      A small UI to inspect the users database
      + +
      +
      Loading...
      +
      Total users in the database
      +
      + +
      + + + +
      + +
        +
        +
        + + + + From 92d08b76880bd3a8c5cebe123b9403d8b429e2c7 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Tue, 3 Feb 2026 14:01:10 +0100 Subject: [PATCH 57/62] Handle missing users table in /user-count and make home page tolerant of errors --- .../intro-to-backend/introToBackendAssignment/index.js | 5 +++++ .../introToBackendAssignment/templates/home.html | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/index.js b/courses/foundation/intro-to-backend/introToBackendAssignment/index.js index 96b2d1bfe..8b3ab5fa4 100644 --- a/courses/foundation/intro-to-backend/introToBackendAssignment/index.js +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/index.js @@ -42,6 +42,11 @@ app.get("/user-count", async (req, res) => { // row is { total_users: n } res.json(row); } catch (error) { + // If the users table doesn't exist, return zero instead of an error + const msg = (error && error.message) || ''; + if (msg.includes('no such table')) { + return res.json({ total_users: 0 }); + } res.status(500).json({ error: error.message }); } }); diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/templates/home.html b/courses/foundation/intro-to-backend/introToBackendAssignment/templates/home.html index 7e730f863..3cd4db45c 100644 --- a/courses/foundation/intro-to-backend/introToBackendAssignment/templates/home.html +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/templates/home.html @@ -47,6 +47,11 @@

        User API

        try{ const r = await fetch('/user-count'); const d = await r.json(); + if (d && d.error) { + document.getElementById('user-count').textContent = '0'; + console.warn('user-count returned error:', d.error); + return; + } document.getElementById('user-count').textContent = d.total_users ?? '0'; }catch(e){ document.getElementById('user-count').textContent = 'Error'; From 057de640d4d38933f5ccae2e48258fa7be3b5e33 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Tue, 3 Feb 2026 14:06:07 +0100 Subject: [PATCH 58/62] Add seed script to create users table and insert sample data --- .../introToBackendAssignment/scripts/seed.js | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 courses/foundation/intro-to-backend/introToBackendAssignment/scripts/seed.js diff --git a/courses/foundation/intro-to-backend/introToBackendAssignment/scripts/seed.js b/courses/foundation/intro-to-backend/introToBackendAssignment/scripts/seed.js new file mode 100644 index 000000000..be6fc0310 --- /dev/null +++ b/courses/foundation/intro-to-backend/introToBackendAssignment/scripts/seed.js @@ -0,0 +1,47 @@ +import knexLib from 'knex'; + +const knex = knexLib({ + client: 'sqlite3', + connection: { filename: './users.sqlite3' }, + useNullAsDefault: true, +}); + +async function run() { + // Create table if it doesn't exist + const exists = await knex.schema.hasTable('users'); + if (!exists) { + await knex.schema.createTable('users', (table) => { + table.increments('id').primary(); + table.string('first_name'); + table.string('last_name'); + table.string('email').unique(); + table.timestamp('confirmed_at').nullable(); + table.timestamp('created_at').nullable(); + }); + console.log('Created users table'); + } else { + console.log('users table already exists'); + } + + // Clear existing rows and insert seed data + await knex('users').del(); + + const now = new Date(); + const users = [ + { first_name: 'Alice', last_name: 'Anderson', email: 'alice@example.com', confirmed_at: now.toISOString(), created_at: new Date(now.getTime() - 1000 * 60 * 60 * 24 * 30).toISOString() }, + { first_name: 'Bob', last_name: 'Brown', email: 'bob@gmail.com', confirmed_at: null, created_at: new Date(now.getTime() - 1000 * 60 * 60 * 24 * 20).toISOString() }, + { first_name: 'Carol', last_name: 'Clark', email: 'carol@gmail.com', confirmed_at: now.toISOString(), created_at: new Date(now.getTime() - 1000 * 60 * 60 * 24 * 10).toISOString() }, + { first_name: 'Dave', last_name: 'Davids', email: 'dave@example.com', confirmed_at: null, created_at: new Date(now.getTime() - 1000 * 60 * 60 * 24 * 5).toISOString() }, + { first_name: 'Eve', last_name: 'Evans', email: 'eve@example.com', confirmed_at: now.toISOString(), created_at: now.toISOString() }, + ]; + + await knex('users').insert(users); + console.log(`Inserted ${users.length} sample users`); + + await knex.destroy(); +} + +run().catch((err) => { + console.error(err); + process.exit(1); +}); From 062a05fa699fc0b080c8376f076cd4f4db6753d8 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Wed, 11 Mar 2026 18:10:05 +0100 Subject: [PATCH 59/62] Add week-1 assignment in advanced js --- .../week-1/Doubling of numbers/index.html | 24 ++ .../week-1/Doubling of numbers/script.js | 16 ++ .../week-1/Doubling of numbers/style.css | 26 +++ .../week-1/Working with movies/index.html | 30 +++ .../week-1/Working with movies/movies.js | 1 + .../week-1/Working with movies/script.js | 212 ++++++++++++++++++ .../week-1/Working with movies/style.css | 49 ++++ 7 files changed, 358 insertions(+) create mode 100644 courses/frontend/advanced-javascript/week-1/Doubling of numbers/index.html create mode 100644 courses/frontend/advanced-javascript/week-1/Doubling of numbers/script.js create mode 100644 courses/frontend/advanced-javascript/week-1/Doubling of numbers/style.css create mode 100644 courses/frontend/advanced-javascript/week-1/Working with movies/index.html create mode 100644 courses/frontend/advanced-javascript/week-1/Working with movies/movies.js create mode 100644 courses/frontend/advanced-javascript/week-1/Working with movies/script.js create mode 100644 courses/frontend/advanced-javascript/week-1/Working with movies/style.css diff --git a/courses/frontend/advanced-javascript/week-1/Doubling of numbers/index.html b/courses/frontend/advanced-javascript/week-1/Doubling of numbers/index.html new file mode 100644 index 000000000..1cb01641f --- /dev/null +++ b/courses/frontend/advanced-javascript/week-1/Doubling of numbers/index.html @@ -0,0 +1,24 @@ + + + + + + Double Odd Numbers + + + + +

        Double Odd Numbers

        + + + + +

        Original Numbers:

        +
        + +

        Doubled Odd Numbers:

        +
        + + + + \ No newline at end of file diff --git a/courses/frontend/advanced-javascript/week-1/Doubling of numbers/script.js b/courses/frontend/advanced-javascript/week-1/Doubling of numbers/script.js new file mode 100644 index 000000000..017e70b15 --- /dev/null +++ b/courses/frontend/advanced-javascript/week-1/Doubling of numbers/script.js @@ -0,0 +1,16 @@ + +let numbers = []; + +document.getElementById('processBtn').addEventListener('click', () => { + const input = document.getElementById('numInput').value; + numbers = input.split(',').map(n => parseInt(n.trim())).filter(n => !isNaN(n)); + + // Show original numbers + document.getElementById('original').textContent = numbers.join(', '); + + // Filter odd numbers and double them + const newNumbers = numbers.filter(n => n % 2 !== 0).map(n => n * 2); + + // Show doubled numbers + document.getElementById('doubled').textContent = newNumbers.join(', '); +}); \ No newline at end of file diff --git a/courses/frontend/advanced-javascript/week-1/Doubling of numbers/style.css b/courses/frontend/advanced-javascript/week-1/Doubling of numbers/style.css new file mode 100644 index 000000000..27f229017 --- /dev/null +++ b/courses/frontend/advanced-javascript/week-1/Doubling of numbers/style.css @@ -0,0 +1,26 @@ +body { + font-family: Arial, sans-serif; + padding: 20px; + background-color: rgb(228, 224, 225); +} + +h1, h2 { + color:rgb(206, 142, 153); +} + + button { + padding: 5px; + margin: 5px 0; + border-radius: 2rem; + background-color: rgb(206, 142, 153); + border: 1px solid white; + color: rgb(211, 208, 208); + margin-left: 3rem; +} + +input,.original, .doubled { + margin-top: 10px; + padding: 5px; + border: 1px solid #000000; + min-height: 20px; +} \ No newline at end of file diff --git a/courses/frontend/advanced-javascript/week-1/Working with movies/index.html b/courses/frontend/advanced-javascript/week-1/Working with movies/index.html new file mode 100644 index 000000000..71c7d9730 --- /dev/null +++ b/courses/frontend/advanced-javascript/week-1/Working with movies/index.html @@ -0,0 +1,30 @@ + + + + +Movie Dashboard + + + + +

        Movie Dashboard

        + +
        + + + + + + + + + +
        + +
        + + + + + + \ No newline at end of file diff --git a/courses/frontend/advanced-javascript/week-1/Working with movies/movies.js b/courses/frontend/advanced-javascript/week-1/Working with movies/movies.js new file mode 100644 index 000000000..a114dbe4b --- /dev/null +++ b/courses/frontend/advanced-javascript/week-1/Working with movies/movies.js @@ -0,0 +1 @@ +const movies = [{"title": "'71","year": 2014,"rating": 7.2,"votes": 41702,"running_times": 5940},{"title": "'A' gai wak","year": 1983,"rating": 7.4,"votes": 11942,"running_times": 6300},{"title": "'Breaker' Morant","year": 1980,"rating": 7.9,"votes": 10702,"running_times": 6420},{"title": "'Crocodile' Dundee II","year": 1988,"rating": 5.5,"votes": 47180,"running_times": 6480},{"title": "(500) Days of Summer","year": 2009,"rating": 7.7,"votes": 412368,"running_times": 5700},{"title": "*batteries not included","year": 1987,"rating": 6.6,"votes": 25636,"running_times": 6360},{"title": "...E tu vivrai nel terrore! L'aldilà","year": 1981,"rating": 6.9,"votes": 16484,"running_times": 5220},{"title": "...and justice for all.","year": 1979,"rating": 7.4,"votes": 25408,"running_times": 7140},{"title": "10","year": 1979,"rating": 6,"votes": 13152,"running_times": 7320},{"title": "10 Cloverfield Lane","year": 2016,"rating": 7.2,"votes": 216151,"running_times": 6240},{"title": "10 Items or Less","year": 2006,"rating": 6.7,"votes": 13342,"running_times": 4920},{"title": "10 Things I Hate About You","year": 1999,"rating": 7.2,"votes": 247070,"running_times": 5820},{"title": "10 Years","year": 2011,"rating": 6.1,"votes": 20790,"running_times": 6000},{"title": "10,000 BC","year": 2008,"rating": 5.1,"votes": 114750,"running_times": 6540},{"title": "100 Feet","year": 2008,"rating": 5.5,"votes": 10979,"running_times": 6240},{"title": "100 Girls","year": 2000,"rating": 5.9,"votes": 19232,"running_times": 5640},{"title": "101 Dalmatians","year": 1996,"rating": 5.7,"votes": 83245,"running_times": 6180},{"title": "102 Dalmatians","year": 2000,"rating": 4.9,"votes": 28927,"running_times": 6000},{"title": "11-11-11","year": 2011,"rating": 4,"votes": 11425,"running_times": 5400},{"title": "11:14","year": 2003,"rating": 7.2,"votes": 40149,"running_times": 5700},{"title": "12 Angry Men","year": 1957,"rating": 8.9,"votes": 518449,"running_times": 5760},{"title": "12 Rounds","year": 2009,"rating": 5.6,"votes": 24457,"running_times": 6480},{"title": "12 Years a Slave","year": 2013,"rating": 8.1,"votes": 513047,"running_times": 8040},{"title": "127 Hours","year": 2010,"rating": 7.6,"votes": 302809,"running_times": 5640},{"title": "13","year": 2010,"rating": 6.1,"votes": 36623,"running_times": 5460},{"title": "13 Going on 30","year": 2004,"rating": 6.1,"votes": 134434,"running_times": 5880},{"title": "13 Hours","year": 2016,"rating": 7.3,"votes": 85771,"running_times": 8640},{"title": "13 Sins","year": 2014,"rating": 6.3,"votes": 26738,"running_times": 5580},{"title": "13th","year": 2016,"rating": 8.2,"votes": 15188,"running_times": 6000},{"title": "1408","year": 2007,"rating": 6.8,"votes": 228738,"running_times": 6840},{"title": "1492: Conquest of Paradise","year": 1992,"rating": 6.5,"votes": 24439,"running_times": 9240},{"title": "15 Minutes","year": 2001,"rating": 6.1,"votes": 44647,"running_times": 7200},{"title": "16 Blocks","year": 2006,"rating": 6.6,"votes": 117443,"running_times": 6600},{"title": "17 Again","year": 2009,"rating": 6.4,"votes": 156663,"running_times": 6120},{"title": "1922","year": 2017,"rating": 6.4,"votes": 15416,"running_times": 6120},{"title": "1941","year": 1979,"rating": 5.9,"votes": 27172,"running_times": 8760},{"title": "2 Days in New York","year": 2012,"rating": 6,"votes": 12766,"running_times": 5760},{"title": "2 Days in Paris","year": 2007,"rating": 6.8,"votes": 28106,"running_times": 5760},{"title": "2 Days in the Valley","year": 1996,"rating": 6.5,"votes": 16528,"running_times": 6240},{"title": "2 Fast 2 Furious","year": 2003,"rating": 5.9,"votes": 213674,"running_times": 6420},{"title": "2 Guns","year": 2013,"rating": 6.7,"votes": 170412,"running_times": 6540},{"title": "20,000 Leagues Under the Sea","year": 1954,"rating": 7.2,"votes": 24094,"running_times": 7620},{"title": "200 Cigarettes","year": 1999,"rating": 5.9,"votes": 13532,"running_times": 6060},{"title": "2001 Maniacs","year": 2005,"rating": 5.4,"votes": 10889,"running_times": 5220},{"title": "2001: A Space Odyssey","year": 1968,"rating": 8.3,"votes": 481800,"running_times": 9660},{"title": "2001: A Space Travesty","year": 2000,"rating": 3.4,"votes": 10094,"running_times": 5940},{"title": "2010","year": 1984,"rating": 6.8,"votes": 44155,"running_times": 6960},{"title": "2012","year": 2009,"rating": 5.8,"votes": 306797,"running_times": 9480},{"title": "20th Century Women","year": 2016,"rating": 7.4,"votes": 22965,"running_times": 7140},{"title": "21 & Over","year": 2013,"rating": 5.9,"votes": 65298,"running_times": 5580},{"title": "21","year": 2008,"rating": 6.8,"votes": 203251,"running_times": 7380},{"title": "21 Grams","year": 2003,"rating": 7.7,"votes": 202129,"running_times": 7440},{"title": "21 Jump Street","year": 2012,"rating": 7.2,"votes": 446476,"running_times": 6540},{"title": "22 Jump Street","year": 2014,"rating": 7.1,"votes": 292991,"running_times": 6720},{"title": "24 Hour Party People","year": 2002,"rating": 7.4,"votes": 28750,"running_times": 7020},{"title": "25th Hour","year": 2002,"rating": 7.7,"votes": 157063,"running_times": 8100},{"title": "27 Dresses","year": 2008,"rating": 6.1,"votes": 134861,"running_times": 6660},{"title": "28 Days","year": 2000,"rating": 6,"votes": 37395,"running_times": 6180},{"title": "28 Days Later...","year": 2002,"rating": 7.6,"votes": 323591,"running_times": 6780},{"title": "28 Weeks Later","year": 2007,"rating": 7,"votes": 228033,"running_times": 6000},{"title": "2:22","year": 2017,"rating": 5.7,"votes": 10266,"running_times": 5880},{"title": "3 Days to Kill","year": 2014,"rating": 6.2,"votes": 75906,"running_times": 7380},{"title": "3 Idiots","year": 2009,"rating": 8.4,"votes": 256619,"running_times": 10200},{"title": "3 Men and a Baby","year": 1987,"rating": 5.9,"votes": 39924,"running_times": 6120},{"title": "3 Men and a Little Lady","year": 1990,"rating": 5.3,"votes": 19005,"running_times": 6240},{"title": "3 Ninjas","year": 1992,"rating": 5.2,"votes": 17582,"running_times": 5880},{"title": "3 Women","year": 1977,"rating": 7.9,"votes": 10852,"running_times": 7440},{"title": "30 Days of Night","year": 2007,"rating": 6.6,"votes": 148004,"running_times": 6780},{"title": "30 Minutes or Less","year": 2011,"rating": 6.1,"votes": 83073,"running_times": 4980},{"title": "300","year": 2006,"rating": 7.7,"votes": 654380,"running_times": 7020},{"title": "3000 Miles to Graceland","year": 2001,"rating": 5.9,"votes": 39646,"running_times": 7500},{"title": "300: Rise of an Empire","year": 2014,"rating": 6.2,"votes": 245690,"running_times": 6120},{"title": "31","year": 2016,"rating": 5,"votes": 12536,"running_times": 6120},{"title": "360","year": 2011,"rating": 6.2,"votes": 14275,"running_times": 6600},{"title": "3:10 to Yuma","year": 1957,"rating": 7.6,"votes": 15498,"running_times": 5520},{"title": "3:10 to Yuma","year": 2007,"rating": 7.7,"votes": 254591,"running_times": 7320},{"title": "40 Days and 40 Nights","year": 2002,"rating": 5.6,"votes": 64777,"running_times": 5760},{"title": "42","year": 2013,"rating": 7.5,"votes": 71968,"running_times": 7680},{"title": "45 Years","year": 2015,"rating": 7.1,"votes": 24269,"running_times": 5460},{"title": "47 Meters Down","year": 2017,"rating": 5.7,"votes": 23125,"running_times": 5340},{"title": "47 Ronin","year": 2013,"rating": 6.3,"votes": 127026,"running_times": 7680},{"title": "48 Hrs.","year": 1982,"rating": 6.9,"votes": 58092,"running_times": 5760},{"title": "4: Rise of the Silver Surfer","year": 2007,"rating": 5.6,"votes": 225698,"running_times": 5520},{"title": "5 Days of War","year": 2011,"rating": 5.6,"votes": 12658,"running_times": 6780},{"title": "5 to 7","year": 2014,"rating": 7.1,"votes": 13647,"running_times": 6000},{"title": "50 First Dates","year": 2004,"rating": 6.8,"votes": 286325,"running_times": 5940},{"title": "50/50","year": 2011,"rating": 7.7,"votes": 287608,"running_times": 6000},{"title": "54","year": 1998,"rating": 5.8,"votes": 28964,"running_times": 7260},{"title": "6 Bullets","year": 2012,"rating": 6.1,"votes": 12351,"running_times": 6900},{"title": "6 Souls","year": 2010,"rating": 6.1,"votes": 27608,"running_times": 6720},{"title": "8 Mile","year": 2002,"rating": 7.1,"votes": 208201,"running_times": 6600},{"title": "8 femmes","year": 2002,"rating": 7.1,"votes": 25351,"running_times": 6660},{"title": "88 Minutes","year": 2007,"rating": 5.9,"votes": 69067,"running_times": 6480},{"title": "8MM","year": 1999,"rating": 6.5,"votes": 110165,"running_times": 7380},{"title": "8½","year": 1963,"rating": 8.1,"votes": 88077,"running_times": 8280},{"title": "9","year": 2009,"rating": 7.1,"votes": 118743,"running_times": 4740},{"title": "9 Songs","year": 2004,"rating": 4.9,"votes": 19175,"running_times": 4260},{"title": "99 Homes","year": 2014,"rating": 7.1,"votes": 23100,"running_times": 6720},{"title": "A Beautiful Mind","year": 2001,"rating": 8.2,"votes": 692444,"running_times": 8100},{"title": "A Better Life","year": 2011,"rating": 7.2,"votes": 13931,"running_times": 5880},{"title": "A Bigger Splash","year": 2015,"rating": 6.4,"votes": 17641,"running_times": 7500},{"title": "A Boy and His Dog","year": 1975,"rating": 6.6,"votes": 14010,"running_times": 5460},{"title": "A Bridge Too Far","year": 1977,"rating": 7.4,"votes": 43717,"running_times": 10500},{"title": "A Bronx Tale","year": 1993,"rating": 7.8,"votes": 107443,"running_times": 7260},{"title": "A Bug's Life","year": 1998,"rating": 7.2,"votes": 229465,"running_times": 5700},{"title": "A Christmas Carol","year": 2009,"rating": 6.8,"votes": 82681,"running_times": 5760},{"title": "A Christmas Story","year": 1983,"rating": 8,"votes": 113032,"running_times": 5640},{"title": "A Cinderella Story","year": 2004,"rating": 5.9,"votes": 69295,"running_times": 5700},{"title": "A Civil Action","year": 1998,"rating": 6.5,"votes": 24558,"running_times": 6900},{"title": "A Clockwork Orange","year": 1971,"rating": 8.3,"votes": 623645,"running_times": 8160},{"title": "A Close Shave","year": 1995,"rating": 8.2,"votes": 33053,"running_times": 1800},{"title": "A Cock and Bull Story","year": 2005,"rating": 6.8,"votes": 11624,"running_times": 5640},{"title": "A Cure for Wellness","year": 2016,"rating": 6.4,"votes": 50746,"running_times": 8760},{"title": "A Dangerous Method","year": 2011,"rating": 6.5,"votes": 87773,"running_times": 5940},{"title": "A Day at the Races","year": 1937,"rating": 7.7,"votes": 11369,"running_times": 6660},{"title": "A Dirty Shame","year": 2004,"rating": 5.1,"votes": 11191,"running_times": 5340},{"title": "A Dog's Purpose","year": 2017,"rating": 6.9,"votes": 38675,"running_times": 6000},{"title": "A Face in the Crowd","year": 1957,"rating": 8.2,"votes": 10910,"running_times": 7560},{"title": "A Fantastic Fear of Everything","year": 2012,"rating": 5.9,"votes": 12446,"running_times": 6000},{"title": "A Few Best Men","year": 2011,"rating": 5.7,"votes": 11321,"running_times": 5820},{"title": "A Few Good Men","year": 1992,"rating": 7.7,"votes": 198227,"running_times": 8280},{"title": "A Fish Called Wanda","year": 1988,"rating": 7.6,"votes": 115086,"running_times": 6480},{"title": "A Ghost Story","year": 2017,"rating": 6.9,"votes": 21003,"running_times": 5520},{"title": "A Good Day to Die Hard","year": 2013,"rating": 5.3,"votes": 177298,"running_times": 6060},{"title": "A Good Old Fashioned Orgy","year": 2011,"rating": 6.2,"votes": 18997,"running_times": 5700},{"title": "A Good Woman","year": 2004,"rating": 6.5,"votes": 10271,"running_times": 5580},{"title": "A Good Year","year": 2006,"rating": 6.9,"votes": 77087,"running_times": 7020},{"title": "A Goofy Movie","year": 1995,"rating": 6.8,"votes": 37406,"running_times": 4680},{"title": "A Grand Day Out","year": 1989,"rating": 7.8,"votes": 25751,"running_times": 1380},{"title": "A Guide to Recognizing Your Saints","year": 2006,"rating": 7,"votes": 23140,"running_times": 6000},{"title": "A Guy Thing","year": 2003,"rating": 5.6,"votes": 15052,"running_times": 6060},{"title": "A Hard Day's Night","year": 1964,"rating": 7.7,"votes": 34132,"running_times": 5220},{"title": "A Haunted House","year": 2013,"rating": 5.1,"votes": 37624,"running_times": 5160},{"title": "A Haunted House 2","year": 2014,"rating": 4.7,"votes": 16458,"running_times": 5160},{"title": "A History of Violence","year": 2005,"rating": 7.5,"votes": 200459,"running_times": 5760},{"title": "A Hologram for the King","year": 2016,"rating": 6.1,"votes": 30336,"running_times": 5880},{"title": "A Home at the End of the World","year": 2004,"rating": 6.8,"votes": 12481,"running_times": 5820},{"title": "A Knight's Tale","year": 2001,"rating": 6.9,"votes": 147493,"running_times": 8640},{"title": "A Late Quartet","year": 2012,"rating": 7.1,"votes": 12157,"running_times": 6300},{"title": "A League of Their Own","year": 1992,"rating": 7.2,"votes": 77777,"running_times": 7680},{"title": "A Life Less Ordinary","year": 1997,"rating": 6.4,"votes": 31642,"running_times": 6180},{"title": "A Little Bit of Heaven","year": 2011,"rating": 6.3,"votes": 25008,"running_times": 6360},{"title": "A Little Chaos","year": 2014,"rating": 6.5,"votes": 15692,"running_times": 6720},{"title": "A Little Princess","year": 1995,"rating": 7.7,"votes": 27204,"running_times": 5820},{"title": "A Lonely Place to Die","year": 2011,"rating": 6.3,"votes": 23882,"running_times": 5940},{"title": "A Long Way Down","year": 2014,"rating": 6.4,"votes": 27396,"running_times": 5760},{"title": "A Lot Like Love","year": 2005,"rating": 6.6,"votes": 61471,"running_times": 6420},{"title": "A Love Song for Bobby Long","year": 2004,"rating": 7.2,"votes": 23145,"running_times": 7140},{"title": "A Man Apart","year": 2003,"rating": 6.1,"votes": 40595,"running_times": 6540},{"title": "A Man for All Seasons","year": 1966,"rating": 7.9,"votes": 25716,"running_times": 7200},{"title": "A Matter of Life and Death","year": 1946,"rating": 8.1,"votes": 15190,"running_times": 6240},{"title": "A Matter of Loaf and Death","year": 2008,"rating": 7.6,"votes": 11464,"running_times": 1800},{"title": "A Midsummer Night's Dream","year": 1999,"rating": 6.5,"votes": 22260,"running_times": 6960},{"title": "A Midsummer Night's Sex Comedy","year": 1982,"rating": 6.7,"votes": 16072,"running_times": 5280},{"title": "A Mighty Heart","year": 2007,"rating": 6.7,"votes": 25029,"running_times": 6480},{"title": "A Mighty Wind","year": 2003,"rating": 7.3,"votes": 23379,"running_times": 5460},{"title": "A Million Ways to Die in the West","year": 2014,"rating": 6.1,"votes": 149454,"running_times": 8160},{"title": "A Monster Calls","year": 2016,"rating": 7.5,"votes": 54692,"running_times": 6480},{"title": "A Most Violent Year","year": 2014,"rating": 7,"votes": 53486,"running_times": 7500},{"title": "A Most Wanted Man","year": 2014,"rating": 6.8,"votes": 63277,"running_times": 7320},{"title": "A Night at the Opera","year": 1935,"rating": 8,"votes": 26694,"running_times": 5760},{"title": "A Night at the Roxbury","year": 1998,"rating": 6.2,"votes": 51079,"running_times": 4920},{"title": "A Night to Remember","year": 1958,"rating": 7.9,"votes": 11342,"running_times": 7380},{"title": "A Nightmare on Elm Street","year": 1984,"rating": 7.5,"votes": 168011,"running_times": 6060},{"title": "A Nightmare on Elm Street","year": 2010,"rating": 5.2,"votes": 80750,"running_times": 5700},{"title": "A Nightmare on Elm Street 3: Dream Warriors","year": 1987,"rating": 6.6,"votes": 56620,"running_times": 5760},{"title": "A Nightmare on Elm Street 4: The Dream Master","year": 1988,"rating": 5.7,"votes": 40437,"running_times": 5940},{"title": "A Nightmare on Elm Street Part 2: Freddy's Revenge","year": 1985,"rating": 5.4,"votes": 49036,"running_times": 5220},{"title": "A Nightmare on Elm Street: The Dream Child","year": 1989,"rating": 5.1,"votes": 33151,"running_times": 5340},{"title": "A Passage to India","year": 1984,"rating": 7.4,"votes": 14283,"running_times": 9840},{"title": "A Perfect Day","year": 2015,"rating": 6.8,"votes": 14727,"running_times": 6360},{"title": "A Perfect Getaway","year": 2009,"rating": 6.5,"votes": 60120,"running_times": 6480},{"title": "A Perfect Murder","year": 1998,"rating": 6.5,"votes": 68812,"running_times": 6420},{"title": "A Perfect World","year": 1993,"rating": 7.5,"votes": 62447,"running_times": 8280},{"title": "A Place in the Sun","year": 1951,"rating": 7.8,"votes": 16542,"running_times": 7320},{"title": "A Prairie Home Companion","year": 2006,"rating": 6.8,"votes": 20330,"running_times": 6300},{"title": "A River Runs Through It","year": 1992,"rating": 7.3,"votes": 45327,"running_times": 7380},{"title": "A Room with a View","year": 1985,"rating": 7.4,"votes": 32554,"running_times": 7020},{"title": "A Scanner Darkly","year": 2006,"rating": 7.1,"votes": 95310,"running_times": 6000},{"title": "A Series of Unfortunate Events","year": 2004,"rating": 6.8,"votes": 173998,"running_times": 6480},{"title": "A Serious Man","year": 2009,"rating": 7,"votes": 111295,"running_times": 6360},{"title": "A Shot in the Dark","year": 1964,"rating": 7.6,"votes": 21546,"running_times": 6120},{"title": "A Simple Plan","year": 1998,"rating": 7.5,"votes": 54525,"running_times": 7260},{"title": "A Single Man","year": 2009,"rating": 7.6,"votes": 93627,"running_times": 5940},{"title": "A Sound of Thunder","year": 2005,"rating": 4.2,"votes": 17277,"running_times": 6600},{"title": "A Star Is Born","year": 1954,"rating": 7.8,"votes": 11576,"running_times": 10860},{"title": "A Street Cat Named Bob","year": 2016,"rating": 7.4,"votes": 18086,"running_times": 6180},{"title": "A Streetcar Named Desire","year": 1951,"rating": 8,"votes": 84993,"running_times": 7500},{"title": "A Thousand Words","year": 2012,"rating": 5.9,"votes": 33739,"running_times": 5460},{"title": "A Time to Kill","year": 1996,"rating": 7.4,"votes": 110362,"running_times": 8940},{"title": "A Very Harold & Kumar 3D Christmas","year": 2011,"rating": 6.3,"votes": 58988,"running_times": 5760},{"title": "A View to a Kill","year": 1985,"rating": 6.3,"votes": 74476,"running_times": 7860},{"title": "A Walk Among the Tombstones","year": 2014,"rating": 6.5,"votes": 96762,"running_times": 6840},{"title": "A Walk in the Clouds","year": 1995,"rating": 6.7,"votes": 26854,"running_times": 6120},{"title": "A Walk in the Woods","year": 2015,"rating": 6.3,"votes": 19128,"running_times": 6240},{"title": "A Walk to Remember","year": 2002,"rating": 7.4,"votes": 176490,"running_times": 6060},{"title": "A Wednesday","year": 2008,"rating": 8.3,"votes": 56214,"running_times": 6240},{"title": "A Woman Under the Influence","year": 1974,"rating": 8.2,"votes": 16018,"running_times": 9300},{"title": "A.C.O.D.","year": 2013,"rating": 5.7,"votes": 11540,"running_times": 5280},{"title": "ARQ","year": 2016,"rating": 6.4,"votes": 22206,"running_times": 5280},{"title": "ATM","year": 2012,"rating": 4.7,"votes": 20365,"running_times": 5400},{"title": "AVP: Alien vs. Predator","year": 2004,"rating": 5.6,"votes": 159110,"running_times": 6540},{"title": "AVPR: Aliens vs Predator - Requiem","year": 2007,"rating": 4.7,"votes": 101047,"running_times": 6120},{"title": "Abduction","year": 2011,"rating": 5.1,"votes": 68802,"running_times": 6360},{"title": "About Last Night","year": 2014,"rating": 6.1,"votes": 18754,"running_times": 6000},{"title": "About Last Night...","year": 1986,"rating": 6.2,"votes": 12416,"running_times": 6780},{"title": "About Schmidt","year": 2002,"rating": 7.2,"votes": 112727,"running_times": 7500},{"title": "About Time","year": 2013,"rating": 7.8,"votes": 232322,"running_times": 7380},{"title": "About a Boy","year": 2002,"rating": 7.1,"votes": 152115,"running_times": 6060},{"title": "Above the Law","year": 1988,"rating": 6,"votes": 24301,"running_times": 5940},{"title": "Above the Rim","year": 1994,"rating": 6.6,"votes": 11650,"running_times": 5760},{"title": "Abraham Lincoln: Vampire Hunter","year": 2012,"rating": 5.9,"votes": 136196,"running_times": 6300},{"title": "Absentia","year": 2011,"rating": 5.8,"votes": 14480,"running_times": 5220},{"title": "Absolute Power","year": 1997,"rating": 6.7,"votes": 42869,"running_times": 7260},{"title": "Absolutely Anything","year": 2015,"rating": 6,"votes": 29541,"running_times": 5100},{"title": "Accepted","year": 2006,"rating": 6.5,"votes": 111434,"running_times": 5580},{"title": "Ace Ventura: Pet Detective","year": 1994,"rating": 6.9,"votes": 236240,"running_times": 5160},{"title": "Ace Ventura: When Nature Calls","year": 1995,"rating": 6.3,"votes": 174677,"running_times": 5400},{"title": "Ace in the Hole","year": 1951,"rating": 8.2,"votes": 21834,"running_times": 6660},{"title": "Across the Universe","year": 2007,"rating": 7.4,"votes": 97183,"running_times": 7980},{"title": "Act of Valor","year": 2012,"rating": 6.5,"votes": 61069,"running_times": 6600},{"title": "Adam","year": 2009,"rating": 7.2,"votes": 31090,"running_times": 5940},{"title": "Adam's Rib","year": 1949,"rating": 7.6,"votes": 16857,"running_times": 6060},{"title": "Adaptation.","year": 2002,"rating": 7.7,"votes": 155220,"running_times": 6840},{"title": "Addams Family Values","year": 1993,"rating": 6.6,"votes": 63626,"running_times": 5640},{"title": "Addicted to Love","year": 1997,"rating": 6.1,"votes": 20962,"running_times": 6000},{"title": "Admission","year": 2013,"rating": 5.7,"votes": 30216,"running_times": 6420},{"title": "Adoration","year": 2013,"rating": 6.2,"votes": 26611,"running_times": 6720},{"title": "Adult World","year": 2013,"rating": 6.2,"votes": 14875,"running_times": 5820},{"title": "Adulthood","year": 2008,"rating": 6.7,"votes": 10672,"running_times": 5940},{"title": "Adventureland","year": 2009,"rating": 6.8,"votes": 139933,"running_times": 6420},{"title": "Adventures in Babysitting","year": 1987,"rating": 6.9,"votes": 31300,"running_times": 6120},{"title": "Afflicted","year": 2013,"rating": 6.3,"votes": 18513,"running_times": 5100},{"title": "Affliction","year": 1997,"rating": 7,"votes": 12755,"running_times": 6840},{"title": "After Earth","year": 2013,"rating": 4.9,"votes": 170966,"running_times": 6000},{"title": "After Hours","year": 1985,"rating": 7.7,"votes": 44784,"running_times": 5820},{"title": "After the Dark","year": 2013,"rating": 5.7,"votes": 18607,"running_times": 6420},{"title": "After the Sunset","year": 2004,"rating": 6.3,"votes": 40364,"running_times": 5820},{"title": "After.Life","year": 2009,"rating": 5.9,"votes": 32865,"running_times": 6240},{"title": "Aftermath","year": 2017,"rating": 5.7,"votes": 12202,"running_times": 5640},{"title": "Agent Cody Banks","year": 2003,"rating": 5.1,"votes": 28946,"running_times": 6120},{"title": "Agent Cody Banks 2: Destination London","year": 2004,"rating": 4.5,"votes": 12154,"running_times": 6000},{"title": "Agneepath","year": 2012,"rating": 7,"votes": 19127,"running_times": 10440},{"title": "Agora","year": 2009,"rating": 7.2,"votes": 57484,"running_times": 8460},{"title": "Aguirre, der Zorn Gottes","year": 1972,"rating": 8,"votes": 42543,"running_times": 5700},{"title": "Ah fei zing zyun","year": 1990,"rating": 7.6,"votes": 13683,"running_times": 5640},{"title": "Ain't Them Bodies Saints","year": 2013,"rating": 6.4,"votes": 18005,"running_times": 5760},{"title": "Air","year": 2015,"rating": 5.1,"votes": 10524,"running_times": 5700},{"title": "Air America","year": 1990,"rating": 5.7,"votes": 23513,"running_times": 6780},{"title": "Air Bud","year": 1997,"rating": 5.1,"votes": 14077,"running_times": 5880},{"title": "Air Force One","year": 1997,"rating": 6.5,"votes": 157206,"running_times": 7440},{"title": "Airheads","year": 1994,"rating": 6.1,"votes": 40608,"running_times": 5520},{"title": "Airplane II: The Sequel","year": 1982,"rating": 6.1,"votes": 41313,"running_times": 5100},{"title": "Airplane!","year": 1980,"rating": 7.8,"votes": 176142,"running_times": 5280},{"title": "Airport","year": 1970,"rating": 6.6,"votes": 14456,"running_times": 8220},{"title": "Ajeossi","year": 2010,"rating": 7.8,"votes": 49601,"running_times": 7140},{"title": "Akeelah and the Bee","year": 2006,"rating": 7.5,"votes": 16346,"running_times": 6720},{"title": "Aladdin","year": 1992,"rating": 8,"votes": 291038,"running_times": 5400},{"title": "Alan Partridge: Alpha Papa","year": 2013,"rating": 7,"votes": 26193,"running_times": 5400},{"title": "Albert Nobbs","year": 2011,"rating": 6.7,"votes": 21042,"running_times": 6780},{"title": "Alex & Emma","year": 2003,"rating": 5.6,"votes": 12051,"running_times": 5760},{"title": "Alex Cross","year": 2012,"rating": 5.1,"votes": 29794,"running_times": 6060},{"title": "Alexander","year": 2004,"rating": 5.6,"votes": 147126,"running_times": 12840},{"title": "Alexander and the Terrible, Horrible, No Good, Very Bad Day","year": 2014,"rating": 6.2,"votes": 33699,"running_times": 4860},{"title": "Alexis Zorbas","year": 1964,"rating": 7.8,"votes": 16943,"running_times": 8520},{"title": "Alferd Packer: The Musical","year": 1993,"rating": 7.2,"votes": 10661,"running_times": 5820},{"title": "Alfie","year": 1966,"rating": 7.1,"votes": 11435,"running_times": 6840},{"title": "Alfie","year": 2004,"rating": 6.2,"votes": 46025,"running_times": 6180},{"title": "Ali","year": 2001,"rating": 6.8,"votes": 83884,"running_times": 9900},{"title": "Ali Baba ve 7 Cüceler","year": 2015,"rating": 6.1,"votes": 12986,"running_times": 6840},{"title": "Ali G Indahouse","year": 2002,"rating": 6.2,"votes": 73785,"running_times": 5100},{"title": "Alice","year": 1990,"rating": 6.6,"votes": 11437,"running_times": 6360},{"title": "Alice Doesn't Live Here Anymore","year": 1974,"rating": 7.4,"votes": 17090,"running_times": 6720},{"title": "Alice Through the Looking Glass","year": 2016,"rating": 6.2,"votes": 65458,"running_times": 6780},{"title": "Alice in Wonderland","year": 1951,"rating": 7.4,"votes": 106178,"running_times": 4500},{"title": "Alice in Wonderland","year": 2010,"rating": 6.5,"votes": 334849,"running_times": 6480},{"title": "Alien","year": 1979,"rating": 8.5,"votes": 643183,"running_times": 7020},{"title": "Alien Nation","year": 1988,"rating": 6.3,"votes": 12239,"running_times": 5460},{"title": "Alien: Covenant","year": 2017,"rating": 6.5,"votes": 176022,"running_times": 7320},{"title": "Alien: Resurrection","year": 1997,"rating": 6.2,"votes": 193440,"running_times": 6960},{"title": "Aliens","year": 1986,"rating": 8.4,"votes": 547487,"running_times": 9240},{"title": "Aliens in the Attic","year": 2009,"rating": 5.4,"votes": 18127,"running_times": 5160},{"title": "Alien³","year": 1992,"rating": 6.4,"votes": 234564,"running_times": 8700},{"title": "Alive","year": 1993,"rating": 7.1,"votes": 42628,"running_times": 7200},{"title": "All About Eve","year": 1950,"rating": 8.3,"votes": 93769,"running_times": 8280},{"title": "All About Steve","year": 2009,"rating": 4.8,"votes": 35167,"running_times": 5940},{"title": "All About the Benjamins","year": 2002,"rating": 5.8,"votes": 10378,"running_times": 5700},{"title": "All Dogs Go to Heaven","year": 1989,"rating": 6.7,"votes": 29536,"running_times": 5040},{"title": "All Eyez on Me","year": 2017,"rating": 5.8,"votes": 12426,"running_times": 8340},{"title": "All Good Things","year": 2010,"rating": 6.3,"votes": 45790,"running_times": 6060},{"title": "All Is Lost","year": 2013,"rating": 6.9,"votes": 65230,"running_times": 6360},{"title": "All Quiet on the Western Front","year": 1930,"rating": 8.1,"votes": 50226,"running_times": 8820},{"title": "All That Heaven Allows","year": 1955,"rating": 7.7,"votes": 10431,"running_times": 5340},{"title": "All That Jazz","year": 1979,"rating": 7.8,"votes": 21615,"running_times": 7380},{"title": "All of Me","year": 1984,"rating": 6.7,"votes": 14228,"running_times": 5580},{"title": "All the Boys Love Mandy Lane","year": 2006,"rating": 5.6,"votes": 27574,"running_times": 5400},{"title": "All the King's Men","year": 1949,"rating": 7.6,"votes": 10818,"running_times": 6600},{"title": "All the King's Men","year": 2006,"rating": 6.2,"votes": 21751,"running_times": 7680},{"title": "All the President's Men","year": 1976,"rating": 8,"votes": 82613,"running_times": 8280},{"title": "All the Pretty Horses","year": 2000,"rating": 5.8,"votes": 11937,"running_times": 13200},{"title": "All the Right Moves","year": 1983,"rating": 5.9,"votes": 13281,"running_times": 5460},{"title": "Allegiant","year": 2016,"rating": 5.7,"votes": 79153,"running_times": 7200},{"title": "Allied","year": 2016,"rating": 7.1,"votes": 101406,"running_times": 7440},{"title": "Almost Famous","year": 2000,"rating": 7.9,"votes": 222016,"running_times": 9720},{"title": "Almost Heroes","year": 1998,"rating": 5.8,"votes": 13847,"running_times": 5400},{"title": "Aloha","year": 2015,"rating": 5.4,"votes": 47563,"running_times": 6300},{"title": "Alone in the Dark","year": 2005,"rating": 2.3,"votes": 39084,"running_times": 5940},{"title": "Along Came Polly","year": 2004,"rating": 5.9,"votes": 112528,"running_times": 5400},{"title": "Along Came a Spider","year": 2001,"rating": 6.3,"votes": 63476,"running_times": 6240},{"title": "Alpha Dog","year": 2006,"rating": 6.9,"votes": 91925,"running_times": 7320},{"title": "Alpha and Omega","year": 2010,"rating": 5.3,"votes": 11716,"running_times": 5400},{"title": "Altered States","year": 1980,"rating": 6.9,"votes": 26407,"running_times": 6120},{"title": "Alvin and the Chipmunks","year": 2007,"rating": 5.2,"votes": 62965,"running_times": 5520},{"title": "Alvin and the Chipmunks: Chipwrecked","year": 2011,"rating": 4.4,"votes": 25279,"running_times": 5220},{"title": "Alvin and the Chipmunks: The Road Chip","year": 2015,"rating": 5.1,"votes": 12390,"running_times": 5520},{"title": "Alvin and the Chipmunks: The Squeakquel","year": 2009,"rating": 4.5,"votes": 35242,"running_times": 5340},{"title": "Always","year": 1989,"rating": 6.4,"votes": 24085,"running_times": 7320},{"title": "Amadeus","year": 1984,"rating": 8.3,"votes": 303203,"running_times": 10800},{"title": "Amanda Knox","year": 2016,"rating": 7,"votes": 12227,"running_times": 5520},{"title": "Amazing Grace","year": 2006,"rating": 7.5,"votes": 22038,"running_times": 7080},{"title": "Amelia","year": 2009,"rating": 5.8,"votes": 10698,"running_times": 6660},{"title": "Amen.","year": 2002,"rating": 7.3,"votes": 11925,"running_times": 7920},{"title": "America's Sweethearts","year": 2001,"rating": 5.7,"votes": 49926,"running_times": 6120},{"title": "American Assassin","year": 2017,"rating": 6.2,"votes": 28116,"running_times": 6720},{"title": "American Beauty","year": 1999,"rating": 8.4,"votes": 911446,"running_times": 7320},{"title": "American Dreamz","year": 2006,"rating": 5.5,"votes": 23250,"running_times": 6420},{"title": "American Gangster","year": 2007,"rating": 7.8,"votes": 345631,"running_times": 10560},{"title": "American Gigolo","year": 1980,"rating": 6.2,"votes": 17629,"running_times": 7020},{"title": "American Graffiti","year": 1973,"rating": 7.5,"votes": 68973,"running_times": 12600},{"title": "American Heist","year": 2014,"rating": 5.2,"votes": 14405,"running_times": 5640},{"title": "American History X","year": 1998,"rating": 8.5,"votes": 868976,"running_times": 7140},{"title": "American Honey","year": 2016,"rating": 7,"votes": 24638,"running_times": 9780},{"title": "American Hustle","year": 2013,"rating": 7.3,"votes": 390260,"running_times": 8280},{"title": "American Made","year": 2017,"rating": 7.2,"votes": 54330,"running_times": 6900},{"title": "American Mary","year": 2012,"rating": 6.3,"votes": 18886,"running_times": 6180},{"title": "American Movie","year": 1999,"rating": 7.9,"votes": 14634,"running_times": 6420},{"title": "American Ninja","year": 1985,"rating": 5.4,"votes": 11392,"running_times": 5700},{"title": "American Outlaws","year": 2001,"rating": 6,"votes": 12644,"running_times": 5640},{"title": "American Pie","year": 1999,"rating": 7,"votes": 334732,"running_times": 5700},{"title": "American Pie 2","year": 2001,"rating": 6.4,"votes": 213276,"running_times": 6480},{"title": "American Psycho","year": 2000,"rating": 7.6,"votes": 396021,"running_times": 6120},{"title": "American Reunion","year": 2012,"rating": 6.7,"votes": 182331,"running_times": 6780},{"title": "American Sniper","year": 2014,"rating": 7.3,"votes": 368132,"running_times": 7980},{"title": "American Splendor","year": 2003,"rating": 7.5,"votes": 43842,"running_times": 6060},{"title": "American Ultra","year": 2015,"rating": 6.1,"votes": 68944,"running_times": 5760},{"title": "American Wedding","year": 2003,"rating": 6.3,"votes": 172946,"running_times": 6180},{"title": "Amistad","year": 1997,"rating": 7.3,"votes": 61388,"running_times": 9300},{"title": "Amour","year": 2012,"rating": 7.9,"votes": 78257,"running_times": 7620},{"title": "Amy","year": 2015,"rating": 7.8,"votes": 38716,"running_times": 7680},{"title": "An Affair to Remember","year": 1957,"rating": 7.6,"votes": 23942,"running_times": 6900},{"title": "An American Crime","year": 2007,"rating": 7.4,"votes": 27534,"running_times": 5880},{"title": "An American Haunting","year": 2005,"rating": 5,"votes": 23087,"running_times": 5460},{"title": "An American Tail","year": 1986,"rating": 6.9,"votes": 41433,"running_times": 4800},{"title": "An American Tail: Fievel Goes West","year": 1991,"rating": 6.5,"votes": 19175,"running_times": 4500},{"title": "An American Werewolf in London","year": 1981,"rating": 7.6,"votes": 74437,"running_times": 5820},{"title": "An American Werewolf in Paris","year": 1997,"rating": 5.1,"votes": 20423,"running_times": 6300},{"title": "An American in Paris","year": 1951,"rating": 7.2,"votes": 24711,"running_times": 6840},{"title": "An Education","year": 2009,"rating": 7.3,"votes": 117913,"running_times": 6000},{"title": "An Ideal Husband","year": 1999,"rating": 6.9,"votes": 13647,"running_times": 5820},{"title": "An Inconvenient Truth","year": 2006,"rating": 7.5,"votes": 73591,"running_times": 5760},{"title": "An Officer and a Gentleman","year": 1982,"rating": 7,"votes": 41135,"running_times": 7440},{"title": "An Unfinished Life","year": 2005,"rating": 7,"votes": 25784,"running_times": 6480},{"title": "Anaconda","year": 1997,"rating": 4.7,"votes": 80526,"running_times": 5340},{"title": "Anacondas: The Hunt for the Blood Orchid","year": 2004,"rating": 4.6,"votes": 24190,"running_times": 5820},{"title": "Analyze That","year": 2002,"rating": 5.9,"votes": 74001,"running_times": 5760},{"title": "Analyze This","year": 1999,"rating": 6.7,"votes": 131399,"running_times": 6540},{"title": "Anastasia","year": 1997,"rating": 7.1,"votes": 95743,"running_times": 5640},{"title": "Anatomy of a Murder","year": 1959,"rating": 8.1,"votes": 50250,"running_times": 9600},{"title": "Anchorman 2: The Legend Continues","year": 2013,"rating": 6.3,"votes": 143995,"running_times": 8580},{"title": "Anchorman: The Legend of Ron Burgundy","year": 2004,"rating": 7.2,"votes": 288977,"running_times": 6240},{"title": "And Now for Something Completely Different","year": 1971,"rating": 7.6,"votes": 25816,"running_times": 5280},{"title": "And So It Goes","year": 2014,"rating": 5.8,"votes": 10471,"running_times": 5640},{"title": "And Soon the Darkness","year": 2010,"rating": 5.2,"votes": 14637,"running_times": 5460},{"title": "And Then There Were None","year": 1945,"rating": 7.6,"votes": 10271,"running_times": 5820},{"title": "Angel Eyes","year": 2001,"rating": 5.6,"votes": 20391,"running_times": 6120},{"title": "Angel Heart","year": 1987,"rating": 7.3,"votes": 68210,"running_times": 6780},{"title": "Angela's Ashes","year": 1999,"rating": 7.3,"votes": 18063,"running_times": 8700},{"title": "Angels & Demons","year": 2009,"rating": 6.7,"votes": 235481,"running_times": 8760},{"title": "Angels in the Outfield","year": 1994,"rating": 6.1,"votes": 24230,"running_times": 6120},{"title": "Angels with Dirty Faces","year": 1938,"rating": 8,"votes": 17119,"running_times": 5820},{"title": "Anger Management","year": 2003,"rating": 6.2,"votes": 181738,"running_times": 6360},{"title": "Angry Birds","year": 2016,"rating": 6.3,"votes": 61016,"running_times": 5820},{"title": "Angus, Thongs and Perfect Snogging","year": 2008,"rating": 6.4,"votes": 22067,"running_times": 6000},{"title": "Animal Crackers","year": 1930,"rating": 7.7,"votes": 11502,"running_times": 5880},{"title": "Animal Factory","year": 2000,"rating": 6.6,"votes": 11266,"running_times": 5640},{"title": "Animal Farm","year": 1954,"rating": 7.2,"votes": 11658,"running_times": 4320},{"title": "Animal House","year": 1978,"rating": 7.6,"votes": 97022,"running_times": 6540},{"title": "Animal Kingdom","year": 2010,"rating": 7.3,"votes": 48897,"running_times": 6780},{"title": "Anna","year": 2013,"rating": 6.5,"votes": 17073,"running_times": 5940},{"title": "Anna Karenina","year": 2012,"rating": 6.6,"votes": 78137,"running_times": 7740},{"title": "Anna and the King","year": 1999,"rating": 6.7,"votes": 32703,"running_times": 8880},{"title": "Annabelle","year": 2014,"rating": 5.4,"votes": 103295,"running_times": 5940},{"title": "Annabelle: Creation","year": 2017,"rating": 6.6,"votes": 58319,"running_times": 6540},{"title": "Annapolis","year": 2006,"rating": 5.8,"votes": 18758,"running_times": 6480},{"title": "Annie","year": 1982,"rating": 6.5,"votes": 33623,"running_times": 7620},{"title": "Annie","year": 2014,"rating": 5.3,"votes": 28526,"running_times": 7080},{"title": "Annie Hall","year": 1977,"rating": 8.1,"votes": 217245,"running_times": 5580},{"title": "Anomalisa","year": 2015,"rating": 7.2,"votes": 49074,"running_times": 5400},{"title": "Anonymous","year": 2011,"rating": 6.9,"votes": 36351,"running_times": 7800},{"title": "Another 48 Hrs.","year": 1990,"rating": 5.8,"votes": 32415,"running_times": 5580},{"title": "Another Earth","year": 2011,"rating": 7,"votes": 80028,"running_times": 5520},{"title": "Another Stakeout","year": 1993,"rating": 5.5,"votes": 11646,"running_times": 6480},{"title": "Another Woman","year": 1988,"rating": 7.4,"votes": 10953,"running_times": 4860},{"title": "Another Year","year": 2010,"rating": 7.3,"votes": 25033,"running_times": 7740},{"title": "Ant-Man","year": 2015,"rating": 7.3,"votes": 399388,"running_times": 7020},{"title": "Anthropoid","year": 2016,"rating": 7.2,"votes": 30614,"running_times": 7200},{"title": "Antichrist","year": 2009,"rating": 6.6,"votes": 97620,"running_times": 6480},{"title": "Antitrust","year": 2001,"rating": 6.1,"votes": 26509,"running_times": 6300},{"title": "Antiviral","year": 2012,"rating": 5.7,"votes": 10297,"running_times": 6480},{"title": "Antwone Fisher","year": 2002,"rating": 7.3,"votes": 28617,"running_times": 7200},{"title": "Antz","year": 1998,"rating": 6.6,"votes": 132303,"running_times": 4980},{"title": "Anvil: The Story of Anvil","year": 2008,"rating": 8,"votes": 14104,"running_times": 4800},{"title": "Any Given Sunday","year": 1999,"rating": 6.8,"votes": 102436,"running_times": 9720},{"title": "Any Which Way You Can","year": 1980,"rating": 6,"votes": 14435,"running_times": 6960},{"title": "Anything Else","year": 2003,"rating": 6.4,"votes": 26831,"running_times": 6480},{"title": "Anywhere But Here","year": 1999,"rating": 6.2,"votes": 15513,"running_times": 6840},{"title": "Apocalypse Now","year": 1979,"rating": 8.5,"votes": 497723,"running_times": 19800},{"title": "Apollo 13","year": 1995,"rating": 7.6,"votes": 227008,"running_times": 8400},{"title": "Apollo 18","year": 2011,"rating": 5.2,"votes": 49390,"running_times": 5160},{"title": "Appaloosa","year": 2008,"rating": 6.8,"votes": 53205,"running_times": 6900},{"title": "April Fool's Day","year": 1986,"rating": 6.2,"votes": 11611,"running_times": 5340},{"title": "Apt Pupil","year": 1998,"rating": 6.7,"votes": 31118,"running_times": 6720},{"title": "Aqua Teen Hunger Force Colon Movie Film for Theaters","year": 2007,"rating": 6.9,"votes": 12541,"running_times": 5160},{"title": "Aquamarine","year": 2006,"rating": 5.3,"votes": 33298,"running_times": 6240},{"title": "Arachnophobia","year": 1990,"rating": 6.4,"votes": 54159,"running_times": 6180},{"title": "Ararat","year": 2002,"rating": 6.6,"votes": 10789,"running_times": 6900},{"title": "Arbitrage","year": 2012,"rating": 6.6,"votes": 44620,"running_times": 6420},{"title": "Are We Done Yet?","year": 2007,"rating": 4.1,"votes": 16925,"running_times": 5520},{"title": "Are We There Yet?","year": 2005,"rating": 4.6,"votes": 24773,"running_times": 5700},{"title": "Are You Here","year": 2013,"rating": 5.3,"votes": 12834,"running_times": 6840},{"title": "Area 51","year": 2015,"rating": 4.2,"votes": 10299,"running_times": 5460},{"title": "Argo","year": 2012,"rating": 7.7,"votes": 497169,"running_times": 7800},{"title": "Arizona Dream","year": 1993,"rating": 7.4,"votes": 36586,"running_times": 8520},{"title": "Arlington Road","year": 1999,"rating": 7.2,"votes": 73649,"running_times": 7020},{"title": "Armageddon","year": 1998,"rating": 6.6,"votes": 347486,"running_times": 9180},{"title": "Armored","year": 2009,"rating": 5.7,"votes": 27421,"running_times": 5280},{"title": "Army of Darkness","year": 1992,"rating": 7.6,"votes": 140929,"running_times": 5760},{"title": "Arn: Tempelriddaren","year": 2007,"rating": 6.6,"votes": 19100,"running_times": 16200},{"title": "Around the World in 80 Days","year": 1956,"rating": 6.8,"votes": 20004,"running_times": 10980},{"title": "Around the World in 80 Days","year": 2004,"rating": 5.8,"votes": 74283,"running_times": 7200},{"title": "Arrival","year": 2016,"rating": 8,"votes": 414134,"running_times": 6960},{"title": "Arsenic and Old Lace","year": 1944,"rating": 8,"votes": 58127,"running_times": 7080},{"title": "Art School Confidential","year": 2006,"rating": 6.3,"votes": 15550,"running_times": 6120},{"title": "Arthur","year": 1981,"rating": 6.9,"votes": 22746,"running_times": 5820},{"title": "Arthur","year": 2011,"rating": 5.7,"votes": 47295,"running_times": 6600},{"title": "Arthur Christmas","year": 2011,"rating": 7.1,"votes": 40559,"running_times": 5820},{"title": "Arthur et les Minimoys","year": 2006,"rating": 6,"votes": 28009,"running_times": 6240},{"title": "Artificial Intelligence: AI","year": 2001,"rating": 7.1,"votes": 258640,"running_times": 8760},{"title": "As Above, So Below","year": 2014,"rating": 6.2,"votes": 58359,"running_times": 5580},{"title": "As Good as It Gets","year": 1997,"rating": 7.7,"votes": 240006,"running_times": 8340},{"title": "Ashby","year": 2015,"rating": 6.4,"votes": 12069,"running_times": 6000},{"title": "Assassin's Creed","year": 2016,"rating": 5.8,"votes": 142293,"running_times": 6900},{"title": "Assassination Games","year": 2011,"rating": 6.2,"votes": 14739,"running_times": 6060},{"title": "Assassination of a High School President","year": 2008,"rating": 6.3,"votes": 14585,"running_times": 5580},{"title": "Assassins","year": 1995,"rating": 6.3,"votes": 68009,"running_times": 7920},{"title": "Assault on Precinct 13","year": 1976,"rating": 7.4,"votes": 35219,"running_times": 5460},{"title": "Assault on Precinct 13","year": 2005,"rating": 6.3,"votes": 68464,"running_times": 6540},{"title": "Astro Boy","year": 2009,"rating": 6.3,"votes": 28054,"running_times": 5640},{"title": "At Close Range","year": 1986,"rating": 7,"votes": 11734,"running_times": 6660},{"title": "At First Sight","year": 1999,"rating": 5.9,"votes": 11898,"running_times": 7680},{"title": "Atlantic City, USA","year": 1980,"rating": 7.4,"votes": 12335,"running_times": 6240},{"title": "Atlantis: The Lost Empire","year": 2001,"rating": 6.8,"votes": 82313,"running_times": 5700},{"title": "Atlas Shrugged: Part I","year": 2011,"rating": 5.7,"votes": 11880,"running_times": 5820},{"title": "Atomic Blonde","year": 2017,"rating": 6.8,"votes": 84987,"running_times": 6900},{"title": "Atonement","year": 2007,"rating": 7.8,"votes": 210033,"running_times": 7380},{"title": "Attack of the Killer Tomatoes!","year": 1978,"rating": 4.6,"votes": 10524,"running_times": 5400},{"title": "Attack the Block","year": 2011,"rating": 6.6,"votes": 88476,"running_times": 5280},{"title": "Au revoir les enfants","year": 1987,"rating": 8,"votes": 26271,"running_times": 6240},{"title": "Auf der anderen Seite","year": 2007,"rating": 7.9,"votes": 27515,"running_times": 7320},{"title": "August Rush","year": 2007,"rating": 7.5,"votes": 93885,"running_times": 6840},{"title": "August: Osage County","year": 2013,"rating": 7.2,"votes": 74140,"running_times": 7260},{"title": "Austenland","year": 2013,"rating": 6.3,"votes": 16601,"running_times": 5820},{"title": "Austin Powers in Goldmember","year": 2002,"rating": 6.2,"votes": 173560,"running_times": 5640},{"title": "Austin Powers: International Man of Mystery","year": 1997,"rating": 7,"votes": 195127,"running_times": 5640},{"title": "Austin Powers: The Spy Who Shagged Me","year": 1999,"rating": 6.6,"votes": 192813,"running_times": 5700},{"title": "Australia","year": 2008,"rating": 6.6,"votes": 108464,"running_times": 9900},{"title": "Auto Focus","year": 2002,"rating": 6.6,"votes": 11840,"running_times": 6300},{"title": "Autoreiji","year": 2010,"rating": 6.8,"votes": 10080,"running_times": 6540},{"title": "Autumn in New York","year": 2000,"rating": 5.5,"votes": 21753,"running_times": 6180},{"title": "Autómata","year": 2014,"rating": 6.1,"votes": 47310,"running_times": 6540},{"title": "Avatar","year": 2009,"rating": 7.8,"votes": 965391,"running_times": 10680},{"title": "Avengers: Age of Ultron","year": 2015,"rating": 7.4,"votes": 549839,"running_times": 8460},{"title": "Awake","year": 2007,"rating": 6.5,"votes": 66756,"running_times": 5040},{"title": "Awakenings","year": 1990,"rating": 7.8,"votes": 102781,"running_times": 7260},{"title": "Away We Go","year": 2009,"rating": 7.1,"votes": 47856,"running_times": 5880},{"title": "Away from Her","year": 2006,"rating": 7.6,"votes": 19754,"running_times": 6600},{"title": "Ayla: The Daughter of War","year": 2017,"rating": 9.1,"votes": 15688,"running_times": 7500},{"title": "BASEketball","year": 1998,"rating": 6.6,"votes": 51153,"running_times": 6180},{"title": "Babe","year": 1995,"rating": 6.8,"votes": 101472,"running_times": 5460},{"title": "Babe: Pig in the City","year": 1998,"rating": 5.8,"votes": 27221,"running_times": 5820},{"title": "Babel","year": 2006,"rating": 7.5,"votes": 259583,"running_times": 8580},{"title": "Baby Boom","year": 1987,"rating": 6.2,"votes": 11562,"running_times": 6600},{"title": "Baby Boy","year": 2001,"rating": 6.4,"votes": 10653,"running_times": 7800},{"title": "Baby Driver","year": 2017,"rating": 7.8,"votes": 228946,"running_times": 6720},{"title": "Baby Geniuses","year": 1999,"rating": 2.6,"votes": 21448,"running_times": 5820},{"title": "Baby Mama","year": 2008,"rating": 6,"votes": 36224,"running_times": 5940},{"title": "Baby's Day Out","year": 1994,"rating": 6,"votes": 37128,"running_times": 5940},{"title": "Babylon A.D.","year": 2008,"rating": 5.6,"votes": 86189,"running_times": 6060},{"title": "Bachelor Party","year": 1984,"rating": 6.3,"votes": 30852,"running_times": 6300},{"title": "Bachelorette","year": 2012,"rating": 5.3,"votes": 40392,"running_times": 5220},{"title": "Back to School","year": 1986,"rating": 6.6,"votes": 23321,"running_times": 5760},{"title": "Back to the Future","year": 1985,"rating": 8.5,"votes": 829676,"running_times": 6960},{"title": "Back to the Future Part II","year": 1989,"rating": 7.8,"votes": 382721,"running_times": 6480},{"title": "Back to the Future Part III","year": 1990,"rating": 7.4,"votes": 321449,"running_times": 7080},{"title": "Backcountry","year": 2014,"rating": 6,"votes": 13092,"running_times": 5520},{"title": "Backdraft","year": 1991,"rating": 6.7,"votes": 62230,"running_times": 8220},{"title": "Bad Ass","year": 2012,"rating": 5.5,"votes": 16900,"running_times": 5400},{"title": "Bad Boy Bubby","year": 1993,"rating": 7.4,"votes": 10399,"running_times": 6840},{"title": "Bad Boys","year": 1983,"rating": 7.2,"votes": 11737,"running_times": 7380},{"title": "Bad Boys","year": 1995,"rating": 6.8,"votes": 189209,"running_times": 7140},{"title": "Bad Boys II","year": 2003,"rating": 6.6,"votes": 192281,"running_times": 8820},{"title": "Bad Company","year": 2002,"rating": 5.6,"votes": 41533,"running_times": 7500},{"title": "Bad Day at Black Rock","year": 1955,"rating": 7.8,"votes": 15934,"running_times": 4860},{"title": "Bad Girls","year": 1994,"rating": 5.1,"votes": 10276,"running_times": 5940},{"title": "Bad Grandpa","year": 2013,"rating": 6.5,"votes": 82213,"running_times": 6120},{"title": "Bad Lieutenant","year": 1992,"rating": 7.1,"votes": 32064,"running_times": 5760},{"title": "Bad Moms","year": 2016,"rating": 6.2,"votes": 82020,"running_times": 6000},{"title": "Bad News Bears","year": 2005,"rating": 5.8,"votes": 18370,"running_times": 6780},{"title": "Bad Santa","year": 2003,"rating": 7.1,"votes": 119914,"running_times": 5940},{"title": "Bad Santa 2","year": 2016,"rating": 5.6,"votes": 14963,"running_times": 5520},{"title": "Bad Taste","year": 1987,"rating": 6.7,"votes": 38949,"running_times": 5880},{"title": "Bad Teacher","year": 2011,"rating": 5.7,"votes": 171167,"running_times": 5820},{"title": "Bad Words","year": 2013,"rating": 6.7,"votes": 41335,"running_times": 5340},{"title": "Badlands","year": 1973,"rating": 7.9,"votes": 53019,"running_times": 5640},{"title": "Bailout: The Age of Greed","year": 2013,"rating": 6.1,"votes": 18091,"running_times": 5940},{"title": "Baiohazâdo: Dijenerêshon","year": 2008,"rating": 6.6,"votes": 26286,"running_times": 5880},{"title": "Bait","year": 2012,"rating": 5.2,"votes": 13089,"running_times": 5580},{"title": "Bakjwi","year": 2009,"rating": 7.2,"votes": 34458,"running_times": 8880},{"title": "Ballerina","year": 2016,"rating": 6.8,"votes": 10767,"running_times": 5340},{"title": "Ballistic: Ecks vs. Sever","year": 2002,"rating": 3.6,"votes": 17379,"running_times": 5460},{"title": "Balls of Fury","year": 2007,"rating": 5.3,"votes": 37437,"running_times": 5400},{"title": "Balto","year": 1995,"rating": 7.1,"votes": 33431,"running_times": 4680},{"title": "Bambi","year": 1942,"rating": 7.3,"votes": 105971,"running_times": 4200},{"title": "Bana Masal Anlatma","year": 2015,"rating": 7.8,"votes": 11133,"running_times": 6180},{"title": "Bananas","year": 1971,"rating": 7.1,"votes": 29990,"running_times": 4920},{"title": "Band Baaja Baaraat","year": 2010,"rating": 7.3,"votes": 11333,"running_times": 8340},{"title": "Bande à part","year": 1964,"rating": 7.8,"votes": 18308,"running_times": 5700},{"title": "Bandidas","year": 2006,"rating": 5.7,"votes": 30735,"running_times": 5580},{"title": "Bandits","year": 2001,"rating": 6.5,"votes": 59840,"running_times": 7380},{"title": "Bandslam","year": 2009,"rating": 6.4,"votes": 12646,"running_times": 6660},{"title": "Bang Bang You're Dead","year": 2002,"rating": 7.9,"votes": 11636,"running_times": 5580},{"title": "Bangkok Dangerous","year": 2008,"rating": 5.4,"votes": 50670,"running_times": 5940},{"title": "Banlieue 13: Ultimatum","year": 2009,"rating": 6.5,"votes": 39420,"running_times": 6060},{"title": "Barb Wire","year": 1996,"rating": 3.2,"votes": 21839,"running_times": 6000},{"title": "Barbarella","year": 1968,"rating": 5.9,"votes": 26937,"running_times": 5880},{"title": "Barbershop","year": 2002,"rating": 6.3,"votes": 24682,"running_times": 6120},{"title": "Barbershop 2: Back in Business","year": 2004,"rating": 5.7,"votes": 11461,"running_times": 6360},{"title": "Barbershop: The Next Cut","year": 2016,"rating": 5.9,"votes": 11117,"running_times": 6660},{"title": "Barefoot","year": 2014,"rating": 6.6,"votes": 19458,"running_times": 5400},{"title": "Barefoot in the Park","year": 1967,"rating": 7,"votes": 13053,"running_times": 6360},{"title": "Barely Lethal","year": 2015,"rating": 5.4,"votes": 14428,"running_times": 5760},{"title": "Barfly","year": 1987,"rating": 7.3,"votes": 15840,"running_times": 6000},{"title": "Barney's Version","year": 2010,"rating": 7.3,"votes": 22142,"running_times": 8040},{"title": "Barnyard","year": 2006,"rating": 5.6,"votes": 22961,"running_times": 5400},{"title": "Barry Lyndon","year": 1975,"rating": 8.1,"votes": 114697,"running_times": 11100},{"title": "Barton Fink","year": 1991,"rating": 7.7,"votes": 97076,"running_times": 6960},{"title": "Basic","year": 2003,"rating": 6.5,"votes": 53220,"running_times": 5880},{"title": "Basic Instinct","year": 1992,"rating": 6.9,"votes": 145427,"running_times": 7680},{"title": "Basic Instinct 2","year": 2006,"rating": 4.3,"votes": 33147,"running_times": 6960},{"title": "Basket Case","year": 1982,"rating": 6.1,"votes": 12730,"running_times": 5460},{"title": "Basquiat","year": 1996,"rating": 6.9,"votes": 17003,"running_times": 6480},{"title": "Bastille Day","year": 2016,"rating": 6.3,"votes": 24569,"running_times": 5520},{"title": "Batman & Robin","year": 1997,"rating": 3.7,"votes": 204277,"running_times": 7500},{"title": "Batman","year": 1989,"rating": 7.6,"votes": 292105,"running_times": 7560},{"title": "Batman Begins","year": 2005,"rating": 8.3,"votes": 1089733,"running_times": 8400},{"title": "Batman Forever","year": 1995,"rating": 5.4,"votes": 206110,"running_times": 7260},{"title": "Batman Returns","year": 1992,"rating": 7,"votes": 234839,"running_times": 7560},{"title": "Batman v Superman: Dawn of Justice","year": 2016,"rating": 6.6,"votes": 512936,"running_times": 10980},{"title": "Batman: Mask of the Phantasm","year": 1993,"rating": 7.9,"votes": 34069,"running_times": 4560},{"title": "Batman: The Killing Joke","year": 2016,"rating": 6.5,"votes": 37257,"running_times": 5160},{"title": "Batman: The Movie","year": 1966,"rating": 6.5,"votes": 25655,"running_times": 6300},{"title": "Battle Los Angeles","year": 2011,"rating": 5.8,"votes": 161428,"running_times": 6960},{"title": "Battle for the Planet of the Apes","year": 1973,"rating": 5.5,"votes": 25097,"running_times": 5760},{"title": "Battle in Seattle","year": 2007,"rating": 6.7,"votes": 13340,"running_times": 5940},{"title": "Battle of Britain","year": 1969,"rating": 7,"votes": 17536,"running_times": 7920},{"title": "Battle of the Bulge","year": 1965,"rating": 6.8,"votes": 12257,"running_times": 10020},{"title": "Battlefield Earth","year": 2000,"rating": 2.4,"votes": 68599,"running_times": 7140},{"title": "Battleship","year": 2012,"rating": 5.8,"votes": 214998,"running_times": 7860},{"title": "Baywatch","year": 2017,"rating": 5.6,"votes": 82335,"running_times": 7260},{"title": "Be Cool","year": 2005,"rating": 5.7,"votes": 62138,"running_times": 7080},{"title": "Be Kind Rewind","year": 2008,"rating": 6.4,"votes": 83213,"running_times": 6120},{"title": "Beaches","year": 1988,"rating": 6.8,"votes": 19848,"running_times": 7380},{"title": "Bean","year": 1997,"rating": 6.4,"votes": 82345,"running_times": 5340},{"title": "Beastly","year": 2011,"rating": 5.6,"votes": 68792,"running_times": 5160},{"title": "Beasts of No Nation","year": 2015,"rating": 7.8,"votes": 54204,"running_times": 8220},{"title": "Beasts of the Southern Wild","year": 2012,"rating": 7.3,"votes": 74360,"running_times": 5580},{"title": "Beautiful Creatures","year": 2013,"rating": 6.2,"votes": 74302,"running_times": 7440},{"title": "Beautiful Girls","year": 1996,"rating": 7.2,"votes": 28097,"running_times": 6720},{"title": "Beautiful Thing","year": 1996,"rating": 7.7,"votes": 19989,"running_times": 5400},{"title": "Beauty Shop","year": 2005,"rating": 5.5,"votes": 14381,"running_times": 6300},{"title": "Beauty and the Beast","year": 1991,"rating": 8,"votes": 350813,"running_times": 5460},{"title": "Beauty and the Beast","year": 2017,"rating": 7.3,"votes": 184598,"running_times": 7740},{"title": "Beavis and Butt-Head Do America","year": 1996,"rating": 6.8,"votes": 45803,"running_times": 4860},{"title": "Because I Said So","year": 2007,"rating": 5.6,"votes": 34147,"running_times": 6120},{"title": "Becket","year": 1964,"rating": 8,"votes": 11879,"running_times": 9000},{"title": "Becoming Jane","year": 2007,"rating": 7.1,"votes": 50882,"running_times": 7200},{"title": "Bedazzled","year": 2000,"rating": 6,"votes": 86774,"running_times": 5580},{"title": "Bedknobs and Broomsticks","year": 1971,"rating": 7,"votes": 28432,"running_times": 8340},{"title": "Bedtime Stories","year": 2008,"rating": 6.1,"votes": 77344,"running_times": 5940},{"title": "Bee Movie","year": 2007,"rating": 6.1,"votes": 116761,"running_times": 5460},{"title": "Beerfest","year": 2006,"rating": 6.3,"votes": 57341,"running_times": 6600},{"title": "Beethoven","year": 1992,"rating": 5.6,"votes": 54880,"running_times": 5220},{"title": "Beethoven's 2nd","year": 1993,"rating": 4.8,"votes": 21277,"running_times": 5340},{"title": "Beetlejuice","year": 1988,"rating": 7.5,"votes": 210761,"running_times": 5520},{"title": "Before I Fall","year": 2017,"rating": 6.4,"votes": 25814,"running_times": 5880},{"title": "Before I Go to Sleep","year": 2014,"rating": 6.3,"votes": 57345,"running_times": 5520},{"title": "Before I Wake","year": 2016,"rating": 6.1,"votes": 21958,"running_times": 5820},{"title": "Before Midnight","year": 2013,"rating": 7.9,"votes": 110256,"running_times": 6540},{"title": "Before Night Falls","year": 2000,"rating": 7.3,"votes": 21900,"running_times": 7980},{"title": "Before Sunrise","year": 1995,"rating": 8.1,"votes": 210714,"running_times": 6060},{"title": "Before Sunset","year": 2004,"rating": 8,"votes": 185303,"running_times": 4800},{"title": "Before We Go","year": 2014,"rating": 6.9,"votes": 35613,"running_times": 5700},{"title": "Before the Devil Knows You're Dead","year": 2007,"rating": 7.3,"votes": 86289,"running_times": 7020},{"title": "Before the Flood","year": 2016,"rating": 8.3,"votes": 18725,"running_times": 5760},{"title": "Before the Rain","year": 1994,"rating": 8.1,"votes": 12111,"running_times": 6780},{"title": "Begin Again","year": 2013,"rating": 7.4,"votes": 118069,"running_times": 6240},{"title": "Beginners","year": 2010,"rating": 7.2,"votes": 79601,"running_times": 6300},{"title": "Behind Enemy Lines","year": 2001,"rating": 6.4,"votes": 91282,"running_times": 6360},{"title": "Behind the Mask: The Rise of Leslie Vernon","year": 2006,"rating": 6.8,"votes": 18319,"running_times": 5520},{"title": "Being Flynn","year": 2012,"rating": 6.4,"votes": 14976,"running_times": 6120},{"title": "Being John Malkovich","year": 1999,"rating": 7.8,"votes": 272442,"running_times": 6720},{"title": "Being Julia","year": 2004,"rating": 7,"votes": 11098,"running_times": 6240},{"title": "Being There","year": 1979,"rating": 8,"votes": 56236,"running_times": 7800},{"title": "Bel Ami","year": 2012,"rating": 5.4,"votes": 16345,"running_times": 6120},{"title": "Belle","year": 2013,"rating": 7.4,"votes": 23459,"running_times": 6000},{"title": "Below","year": 2002,"rating": 6.2,"votes": 18954,"running_times": 6300},{"title": "Ben-Hur","year": 1959,"rating": 8.1,"votes": 180774,"running_times": 13440},{"title": "Ben-Hur","year": 2016,"rating": 5.7,"votes": 33045,"running_times": 7380},{"title": "Bend It Like Beckham","year": 2002,"rating": 6.7,"votes": 95098,"running_times": 6900},{"title": "Beneath the Planet of the Apes","year": 1970,"rating": 6.1,"votes": 36158,"running_times": 5700},{"title": "Benny & Joon","year": 1993,"rating": 7.2,"votes": 49002,"running_times": 5880},{"title": "Benny's Video","year": 1992,"rating": 7.2,"votes": 10776,"running_times": 6300},{"title": "Beowulf & Grendel","year": 2005,"rating": 5.9,"votes": 16350,"running_times": 6180},{"title": "Beowulf","year": 1999,"rating": 4,"votes": 10148,"running_times": 5940},{"title": "Beowulf","year": 2007,"rating": 6.2,"votes": 149083,"running_times": 6900},{"title": "Berberian Sound Studio","year": 2012,"rating": 6.2,"votes": 11697,"running_times": 5520},{"title": "Berlin Syndrome","year": 2017,"rating": 6.3,"votes": 11929,"running_times": 6960},{"title": "Bernie","year": 2011,"rating": 6.8,"votes": 50518,"running_times": 6240},{"title": "Best in Show","year": 2000,"rating": 7.5,"votes": 48767,"running_times": 5400},{"title": "Best of the Best","year": 1989,"rating": 6.4,"votes": 10324,"running_times": 5820},{"title": "Better Living Through Chemistry","year": 2014,"rating": 6.3,"votes": 12403,"running_times": 5460},{"title": "Better Off Dead...","year": 1985,"rating": 7.2,"votes": 36214,"running_times": 5820},{"title": "Beverly Hills Chihuahua","year": 2008,"rating": 3.7,"votes": 18917,"running_times": 5460},{"title": "Beverly Hills Cop","year": 1984,"rating": 7.3,"votes": 138092,"running_times": 6300},{"title": "Beverly Hills Cop II","year": 1987,"rating": 6.5,"votes": 91948,"running_times": 6000},{"title": "Beverly Hills Cop III","year": 1994,"rating": 5.5,"votes": 65593,"running_times": 6240},{"title": "Beverly Hills Ninja","year": 1997,"rating": 5.5,"votes": 33242,"running_times": 5280},{"title": "Bewitched","year": 2005,"rating": 4.8,"votes": 61926,"running_times": 6120},{"title": "Beyond Borders","year": 2003,"rating": 6.5,"votes": 23974,"running_times": 7620},{"title": "Beyond a Reasonable Doubt","year": 2009,"rating": 5.9,"votes": 11253,"running_times": 6360},{"title": "Beyond the Lights","year": 2014,"rating": 6.9,"votes": 12882,"running_times": 6960},{"title": "Beyond the Sea","year": 2004,"rating": 6.7,"votes": 13535,"running_times": 7080},{"title": "Bicentennial Man","year": 1999,"rating": 6.8,"votes": 95874,"running_times": 7920},{"title": "Big","year": 1988,"rating": 7.3,"votes": 165755,"running_times": 7800},{"title": "Big Daddy","year": 1999,"rating": 6.4,"votes": 173724,"running_times": 5580},{"title": "Big Eyes","year": 2014,"rating": 7,"votes": 68354,"running_times": 6360},{"title": "Big Fat Liar","year": 2002,"rating": 5.4,"votes": 30820,"running_times": 5280},{"title": "Big Fish","year": 2003,"rating": 8,"votes": 372206,"running_times": 7500},{"title": "Big Game","year": 2014,"rating": 5.4,"votes": 25066,"running_times": 6600},{"title": "Big Hero 6","year": 2014,"rating": 7.8,"votes": 325944,"running_times": 6120},{"title": "Big Miracle","year": 2012,"rating": 6.5,"votes": 16311,"running_times": 6420},{"title": "Big Momma's House","year": 2000,"rating": 5.1,"votes": 71764,"running_times": 5940},{"title": "Big Momma's House 2","year": 2006,"rating": 4.6,"votes": 34990,"running_times": 5940},{"title": "Big Mommas: Like Father, Like Son","year": 2011,"rating": 4.4,"votes": 21699,"running_times": 6780},{"title": "Big Night","year": 1996,"rating": 7.3,"votes": 14157,"running_times": 6540},{"title": "Big Nothing","year": 2006,"rating": 6.8,"votes": 27146,"running_times": 5160},{"title": "Big Stan","year": 2007,"rating": 6.2,"votes": 36691,"running_times": 6300},{"title": "Big Trouble","year": 2002,"rating": 6.5,"votes": 18242,"running_times": 5100},{"title": "Big Trouble in Little China","year": 1986,"rating": 7.3,"votes": 103133,"running_times": 5940},{"title": "Bigger Stronger Faster*","year": 2008,"rating": 7.6,"votes": 12389,"running_times": 6300},{"title": "Biker Boyz","year": 2003,"rating": 4.6,"votes": 11604,"running_times": 6600},{"title": "Bikur Ha-Tizmoret","year": 2007,"rating": 7.6,"votes": 11513,"running_times": 5220},{"title": "Bill & Ted's Bogus Journey","year": 1991,"rating": 6.2,"votes": 53320,"running_times": 5580},{"title": "Bill & Ted's Excellent Adventure","year": 1989,"rating": 6.9,"votes": 91698,"running_times": 5400},{"title": "Bill","year": 2007,"rating": 6.3,"votes": 18340,"running_times": 5580},{"title": "Billy Bathgate","year": 1991,"rating": 5.9,"votes": 10143,"running_times": 6360},{"title": "Billy Elliot","year": 2000,"rating": 7.7,"votes": 105511,"running_times": 6600},{"title": "Billy Lynn's Long Halftime Walk","year": 2016,"rating": 6.3,"votes": 15639,"running_times": 6780},{"title": "Billy Madison","year": 1995,"rating": 6.4,"votes": 113436,"running_times": 5340},{"title": "Biloxi Blues","year": 1988,"rating": 6.6,"votes": 12664,"running_times": 6360},{"title": "Bio-Dome","year": 1996,"rating": 4.4,"votes": 22920,"running_times": 5700},{"title": "Bird on a Wire","year": 1990,"rating": 5.9,"votes": 33891,"running_times": 6600},{"title": "Birdemic: Shock and Terror","year": 2010,"rating": 1.8,"votes": 16894,"running_times": 6300},{"title": "Birdman of Alcatraz","year": 1962,"rating": 7.8,"votes": 13386,"running_times": 8820},{"title": "Birdman or (The Unexpected Virtue of Ignorance)","year": 2014,"rating": 7.8,"votes": 463395,"running_times": 7140},{"title": "Birdy","year": 1984,"rating": 7.3,"votes": 18621,"running_times": 7200},{"title": "Birth","year": 2004,"rating": 6.1,"votes": 31442,"running_times": 6000},{"title": "Birthday Girl","year": 2001,"rating": 6.1,"votes": 22488,"running_times": 5580},{"title": "Bitch Slap","year": 2009,"rating": 4.5,"votes": 12541,"running_times": 6540},{"title": "Bitter Moon","year": 1992,"rating": 7.2,"votes": 28437,"running_times": 8340},{"title": "Black","year": 2005,"rating": 8.2,"votes": 28133,"running_times": 7320},{"title": "Black Christmas","year": 1974,"rating": 7.2,"votes": 24393,"running_times": 5880},{"title": "Black Christmas","year": 2006,"rating": 4.6,"votes": 21469,"running_times": 5640},{"title": "Black Death","year": 2010,"rating": 6.4,"votes": 38775,"running_times": 6120},{"title": "Black Dynamite","year": 2009,"rating": 7.4,"votes": 38921,"running_times": 5040},{"title": "Black Hawk Down","year": 2001,"rating": 7.7,"votes": 317178,"running_times": 9120},{"title": "Black Knight","year": 2001,"rating": 4.8,"votes": 33164,"running_times": 5700},{"title": "Black Mass","year": 2015,"rating": 6.9,"votes": 142953,"running_times": 7380},{"title": "Black Narcissus","year": 1947,"rating": 8,"votes": 17316,"running_times": 6060},{"title": "Black Rain","year": 1989,"rating": 6.6,"votes": 42471,"running_times": 7500},{"title": "Black Sea","year": 2014,"rating": 6.4,"votes": 28893,"running_times": 6840},{"title": "Black Sheep","year": 1996,"rating": 6.2,"votes": 31823,"running_times": 5220},{"title": "Black Sheep","year": 2006,"rating": 5.8,"votes": 36324,"running_times": 5220},{"title": "Black Snake Moan","year": 2006,"rating": 7,"votes": 55960,"running_times": 6960},{"title": "Black Swan","year": 2010,"rating": 8,"votes": 601083,"running_times": 6480},{"title": "Black Water","year": 2007,"rating": 6,"votes": 10724,"running_times": 5400},{"title": "Blackadder Back & Forth","year": 1999,"rating": 7.7,"votes": 11766,"running_times": 1980},{"title": "Blackfish","year": 2013,"rating": 8.1,"votes": 51958,"running_times": 4980},{"title": "Blackhat","year": 2015,"rating": 5.4,"votes": 44981,"running_times": 7980},{"title": "Blade","year": 1998,"rating": 7.1,"votes": 209150,"running_times": 7200},{"title": "Blade II","year": 2002,"rating": 6.7,"votes": 173270,"running_times": 7020},{"title": "Blade Runner","year": 1982,"rating": 8.2,"votes": 549243,"running_times": 7020},{"title": "Blade Runner 2049","year": 2017,"rating": 8.4,"votes": 159689,"running_times": 9840},{"title": "Blade: Trinity","year": 2004,"rating": 5.9,"votes": 145063,"running_times": 7320},{"title": "Blades of Glory","year": 2007,"rating": 6.3,"votes": 138656,"running_times": 5580},{"title": "Blair Witch","year": 2016,"rating": 5,"votes": 31208,"running_times": 5340},{"title": "Blank Check","year": 1994,"rating": 5.2,"votes": 15623,"running_times": 5580},{"title": "Blast from the Past","year": 1999,"rating": 6.6,"votes": 52616,"running_times": 6720},{"title": "Blazing Saddles","year": 1974,"rating": 7.8,"votes": 106624,"running_times": 5580},{"title": "Bleed for This","year": 2016,"rating": 6.8,"votes": 16729,"running_times": 7020},{"title": "Blended","year": 2014,"rating": 6.5,"votes": 97403,"running_times": 7020},{"title": "Bless the Child","year": 2000,"rating": 5.1,"votes": 12753,"running_times": 6420},{"title": "Blind Date","year": 1987,"rating": 5.9,"votes": 18050,"running_times": 5700},{"title": "Blind Dating","year": 2006,"rating": 6.1,"votes": 10481,"running_times": 5700},{"title": "Blind Fury","year": 1989,"rating": 6.3,"votes": 11747,"running_times": 5160},{"title": "Blindness","year": 2008,"rating": 6.6,"votes": 62790,"running_times": 7260},{"title": "Blitz","year": 2011,"rating": 6.2,"votes": 73267,"running_times": 5820},{"title": "Blood Diamond","year": 2006,"rating": 8,"votes": 434531,"running_times": 8580},{"title": "Blood Father","year": 2016,"rating": 6.4,"votes": 45527,"running_times": 5280},{"title": "Blood Simple.","year": 1984,"rating": 7.7,"votes": 73424,"running_times": 5940},{"title": "Blood Ties","year": 2013,"rating": 6.5,"votes": 16346,"running_times": 8640},{"title": "Blood Work","year": 2002,"rating": 6.4,"votes": 36930,"running_times": 6600},{"title": "Blood and Bone","year": 2009,"rating": 6.7,"votes": 27624,"running_times": 5580},{"title": "Blood and Chocolate","year": 2007,"rating": 5.5,"votes": 16063,"running_times": 5880},{"title": "Blood: The Last Vampire","year": 2000,"rating": 6.7,"votes": 10762,"running_times": 2880},{"title": "Blood: The Last Vampire","year": 2009,"rating": 5.3,"votes": 13610,"running_times": 5460},{"title": "BloodRayne","year": 2005,"rating": 2.9,"votes": 31603,"running_times": 5700},{"title": "Bloodsport","year": 1988,"rating": 6.8,"votes": 64098,"running_times": 5520},{"title": "Bloody Sunday","year": 2002,"rating": 7.7,"votes": 21001,"running_times": 6420},{"title": "Blow","year": 2001,"rating": 7.6,"votes": 212868,"running_times": 7440},{"title": "Blow Out","year": 1981,"rating": 7.4,"votes": 32263,"running_times": 6420},{"title": "Blown Away","year": 1994,"rating": 6.2,"votes": 24653,"running_times": 7260},{"title": "Blowup","year": 1966,"rating": 7.6,"votes": 46137,"running_times": 6660},{"title": "Blue Chips","year": 1994,"rating": 6.1,"votes": 10259,"running_times": 6480},{"title": "Blue Crush","year": 2002,"rating": 5.6,"votes": 27345,"running_times": 6240},{"title": "Blue Jasmine","year": 2013,"rating": 7.3,"votes": 166439,"running_times": 5880},{"title": "Blue Mountain State: The Rise of Thadland","year": 2016,"rating": 5.9,"votes": 11882,"running_times": 5400},{"title": "Blue Ruin","year": 2013,"rating": 7.1,"votes": 52383,"running_times": 5400},{"title": "Blue Steel","year": 1989,"rating": 5.6,"votes": 10090,"running_times": 6120},{"title": "Blue Streak","year": 1999,"rating": 6.3,"votes": 64619,"running_times": 5580},{"title": "Blue Thunder","year": 1983,"rating": 6.4,"votes": 13524,"running_times": 6540},{"title": "Blue Valentine","year": 2010,"rating": 7.4,"votes": 156851,"running_times": 6720},{"title": "Blue Velvet","year": 1986,"rating": 7.8,"votes": 148871,"running_times": 10320},{"title": "Blues Brothers 2000","year": 1998,"rating": 4.8,"votes": 27755,"running_times": 7380},{"title": "Boat Trip","year": 2002,"rating": 4.9,"votes": 28039,"running_times": 5820},{"title": "Bob Roberts","year": 1992,"rating": 7,"votes": 12125,"running_times": 6120},{"title": "Bobby","year": 2006,"rating": 7,"votes": 39233,"running_times": 7020},{"title": "Body Double","year": 1984,"rating": 6.8,"votes": 22822,"running_times": 6840},{"title": "Body Heat","year": 1981,"rating": 7.4,"votes": 25400,"running_times": 6780},{"title": "Body Snatchers","year": 1993,"rating": 5.9,"votes": 14485,"running_times": 5220},{"title": "Body of Evidence","year": 1993,"rating": 4.4,"votes": 12109,"running_times": 6120},{"title": "Body of Lies","year": 2008,"rating": 7.1,"votes": 187229,"running_times": 7680},{"title": "Bodyguard","year": 2011,"rating": 4.6,"votes": 18446,"running_times": 7800},{"title": "Boiler Room","year": 2000,"rating": 7,"votes": 44177,"running_times": 7200},{"title": "Bolt","year": 2008,"rating": 6.9,"votes": 160434,"running_times": 5760},{"title": "Bon Cop, Bad Cop","year": 2006,"rating": 6.9,"votes": 10218,"running_times": 7200},{"title": "Bone Tomahawk","year": 2015,"rating": 7.1,"votes": 53235,"running_times": 7920},{"title": "Bonnie and Clyde","year": 1967,"rating": 7.9,"votes": 87339,"running_times": 6660},{"title": "Boogeyman","year": 2005,"rating": 4.1,"votes": 27541,"running_times": 5340},{"title": "Boogie Nights","year": 1997,"rating": 7.9,"votes": 204133,"running_times": 9300},{"title": "Book of Shadows: Blair Witch 2","year": 2000,"rating": 4,"votes": 31854,"running_times": 5400},{"title": "Boomerang","year": 1992,"rating": 5.4,"votes": 21930,"running_times": 7020},{"title": "Borat: Cultural Learnings of America for Make Benefit Glorious Nation of Kazakhstan","year": 2006,"rating": 7.3,"votes": 315298,"running_times": 5040},{"title": "Bordello of Blood","year": 1996,"rating": 5.3,"votes": 11395,"running_times": 5220},{"title": "Borgman","year": 2013,"rating": 6.8,"votes": 13256,"running_times": 6780},{"title": "Born Into Brothels: Calcutta's Red Light Kids","year": 2004,"rating": 7.4,"votes": 13355,"running_times": 5100},{"title": "Born on the Fourth of July","year": 1989,"rating": 7.2,"votes": 83568,"running_times": 8700},{"title": "Bottle Rocket","year": 1996,"rating": 7.1,"votes": 59209,"running_times": 5700},{"title": "Bottle Shock","year": 2008,"rating": 6.8,"votes": 13142,"running_times": 6600},{"title": "Bounce","year": 2000,"rating": 5.7,"votes": 18442,"running_times": 6360},{"title": "Bound","year": 1996,"rating": 7.4,"votes": 44030,"running_times": 6540},{"title": "Bound by Honor","year": 1993,"rating": 8,"votes": 24940,"running_times": 19800},{"title": "Boundin'","year": 2003,"rating": 7,"votes": 10569,"running_times": 300},{"title": "Bowfinger","year": 1999,"rating": 6.4,"votes": 59927,"running_times": 5820},{"title": "Bowling for Columbine","year": 2002,"rating": 8,"votes": 129424,"running_times": 7200},{"title": "Boxing Helena","year": 1993,"rating": 4.6,"votes": 10175,"running_times": 6420},{"title": "Boy","year": 2010,"rating": 7.5,"votes": 12607,"running_times": 5220},{"title": "Boy A","year": 2007,"rating": 7.7,"votes": 34618,"running_times": 6120},{"title": "Boyhood","year": 2014,"rating": 7.9,"votes": 296371,"running_times": 9900},{"title": "Boys Don't Cry","year": 1999,"rating": 7.6,"votes": 82611,"running_times": 7080},{"title": "Boys and Girls","year": 2000,"rating": 5.4,"votes": 14502,"running_times": 5640},{"title": "Boys on the Side","year": 1995,"rating": 6.4,"votes": 10282,"running_times": 6900},{"title": "Boyz n the Hood","year": 1991,"rating": 7.8,"votes": 103550,"running_times": 6720},{"title": "Braindead","year": 1992,"rating": 7.5,"votes": 82550,"running_times": 6240},{"title": "Brake","year": 2012,"rating": 6.1,"votes": 10558,"running_times": 5520},{"title": "Brassed Off","year": 1996,"rating": 7.1,"votes": 16742,"running_times": 6180},{"title": "Brat","year": 1997,"rating": 8,"votes": 12125,"running_times": 5940},{"title": "Bratz","year": 2007,"rating": 2.9,"votes": 15681,"running_times": 6600},{"title": "Brave","year": 2012,"rating": 7.2,"votes": 306335,"running_times": 5580},{"title": "Braveheart","year": 1995,"rating": 8.4,"votes": 817912,"running_times": 13500},{"title": "Brawl in Cell Block 99","year": 2017,"rating": 7.2,"votes": 11487,"running_times": 7920},{"title": "Brazil","year": 1985,"rating": 8,"votes": 164563,"running_times": 8520},{"title": "Breach","year": 2007,"rating": 7,"votes": 53971,"running_times": 6600},{"title": "Breakdown","year": 1997,"rating": 6.9,"votes": 41285,"running_times": 5580},{"title": "Breakfast at Tiffany's","year": 1961,"rating": 7.7,"votes": 137679,"running_times": 6900},{"title": "Breakfast on Pluto","year": 2005,"rating": 7.3,"votes": 18572,"running_times": 7680},{"title": "Breaking Away","year": 1979,"rating": 7.7,"votes": 18743,"running_times": 6060},{"title": "Breaking and Entering","year": 2006,"rating": 6.5,"votes": 20696,"running_times": 7200},{"title": "Breaking the Waves","year": 1996,"rating": 7.9,"votes": 52970,"running_times": 9540},{"title": "Breathe In","year": 2013,"rating": 6.4,"votes": 12109,"running_times": 5880},{"title": "Brewster's Millions","year": 1985,"rating": 6.5,"votes": 30512,"running_times": 6120},{"title": "Brick","year": 2005,"rating": 7.4,"votes": 90277,"running_times": 6600},{"title": "Brick Mansions","year": 2014,"rating": 5.7,"votes": 35186,"running_times": 6000},{"title": "Bride & Prejudice","year": 2004,"rating": 6.2,"votes": 18303,"running_times": 7320},{"title": "Bride Wars","year": 2009,"rating": 5.5,"votes": 87239,"running_times": 5340},{"title": "Bride of Chucky","year": 1998,"rating": 5.4,"votes": 43904,"running_times": 5340},{"title": "Bride of Frankenstein","year": 1935,"rating": 7.9,"votes": 35950,"running_times": 4500},{"title": "Bride of Re-Animator","year": 1989,"rating": 6.3,"votes": 10648,"running_times": 5760},{"title": "Brideshead Revisited","year": 2008,"rating": 6.7,"votes": 10686,"running_times": 7980},{"title": "Bridesmaids","year": 2011,"rating": 6.8,"votes": 234286,"running_times": 7800},{"title": "Bridge of Spies","year": 2015,"rating": 7.6,"votes": 232893,"running_times": 8520},{"title": "Bridge to Terabithia","year": 2007,"rating": 7.2,"votes": 121347,"running_times": 5760},{"title": "Bridget Jones's Baby","year": 2016,"rating": 6.6,"votes": 50177,"running_times": 7080},{"title": "Bridget Jones's Diary","year": 2001,"rating": 6.7,"votes": 191145,"running_times": 5820},{"title": "Bridget Jones: The Edge of Reason","year": 2004,"rating": 5.9,"votes": 87286,"running_times": 6480},{"title": "Brief Encounter","year": 1945,"rating": 8.1,"votes": 28907,"running_times": 5160},{"title": "Bright Star","year": 2009,"rating": 7,"votes": 22780,"running_times": 7140},{"title": "Brimstone","year": 2016,"rating": 7.1,"votes": 20832,"running_times": 8880},{"title": "Bring It On","year": 2000,"rating": 6,"votes": 75286,"running_times": 5880},{"title": "Bring Me the Head of Alfredo Garcia","year": 1974,"rating": 7.5,"votes": 15116,"running_times": 6720},{"title": "Bringing Down the House","year": 2003,"rating": 5.6,"votes": 31573,"running_times": 6300},{"title": "Bringing Out the Dead","year": 1999,"rating": 6.8,"votes": 56164,"running_times": 7260},{"title": "Bringing Up Baby","year": 1938,"rating": 8,"votes": 47943,"running_times": 6120},{"title": "Broadcast News","year": 1987,"rating": 7.2,"votes": 23019,"running_times": 7980},{"title": "Broadway Danny Rose","year": 1984,"rating": 7.5,"votes": 20316,"running_times": 5040},{"title": "Brokeback Mountain","year": 2005,"rating": 7.7,"votes": 279350,"running_times": 8040},{"title": "Brokedown Palace","year": 1999,"rating": 6.4,"votes": 19642,"running_times": 6000},{"title": "Broken","year": 2012,"rating": 7.3,"votes": 11713,"running_times": 5460},{"title": "Broken Arrow","year": 1996,"rating": 6,"votes": 81632,"running_times": 6480},{"title": "Broken City","year": 2013,"rating": 6.2,"votes": 68201,"running_times": 6540},{"title": "Broken Flowers","year": 2005,"rating": 7.2,"votes": 87301,"running_times": 6360},{"title": "Bronson","year": 2008,"rating": 7.1,"votes": 99451,"running_times": 5520},{"title": "Brooklyn","year": 2015,"rating": 7.5,"votes": 101435,"running_times": 7020},{"title": "Brooklyn's Finest","year": 2009,"rating": 6.7,"votes": 55474,"running_times": 7920},{"title": "Brother","year": 2000,"rating": 7.2,"votes": 19732,"running_times": 6840},{"title": "Brother Bear","year": 2003,"rating": 6.8,"votes": 78629,"running_times": 5100},{"title": "Brothers","year": 2009,"rating": 7.1,"votes": 95987,"running_times": 6300},{"title": "Brubaker","year": 1980,"rating": 7.1,"votes": 13091,"running_times": 7860},{"title": "Bruce Almighty","year": 2003,"rating": 6.7,"votes": 322967,"running_times": 6060},{"title": "Brüno","year": 2009,"rating": 5.8,"votes": 126745,"running_times": 4860},{"title": "Bubba Ho-Tep","year": 2002,"rating": 7.2,"votes": 40966,"running_times": 5520},{"title": "Bubble Boy","year": 2001,"rating": 5.6,"votes": 27195,"running_times": 5040},{"title": "Bucky Larson: Born to Be a Star","year": 2011,"rating": 3.3,"votes": 10028,"running_times": 5820},{"title": "Bud Abbott Lou Costello Meet Frankenstein","year": 1948,"rating": 7.6,"votes": 12025,"running_times": 5400},{"title": "Buena Vista Social Club","year": 1999,"rating": 7.6,"votes": 14396,"running_times": 6300},{"title": "Buffalo '66","year": 1998,"rating": 7.5,"votes": 39780,"running_times": 6600},{"title": "Buffalo Soldiers","year": 2001,"rating": 6.9,"votes": 21482,"running_times": 5880},{"title": "Buffy the Vampire Slayer","year": 1992,"rating": 5.6,"votes": 34513,"running_times": 5160},{"title": "Bug","year": 2006,"rating": 6.1,"votes": 29613,"running_times": 6120},{"title": "Bugsy","year": 1991,"rating": 6.8,"votes": 22391,"running_times": 8940},{"title": "Bugsy Malone","year": 1976,"rating": 6.8,"votes": 13397,"running_times": 5580},{"title": "Bull Durham","year": 1988,"rating": 7.1,"votes": 39732,"running_times": 6480},{"title": "Bullet to the Head","year": 2012,"rating": 5.7,"votes": 42174,"running_times": 5520},{"title": "Bulletproof","year": 1996,"rating": 5.8,"votes": 31443,"running_times": 5040},{"title": "Bulletproof Monk","year": 2003,"rating": 5.5,"votes": 44196,"running_times": 6240},{"title": "Bullets Over Broadway","year": 1994,"rating": 7.5,"votes": 31528,"running_times": 5880},{"title": "Bullitt","year": 1968,"rating": 7.5,"votes": 50729,"running_times": 6840},{"title": "Bully","year": 2001,"rating": 7,"votes": 30991,"running_times": 6780},{"title": "Bulworth","year": 1998,"rating": 6.8,"votes": 22996,"running_times": 6480},{"title": "Bunraku","year": 2010,"rating": 6.2,"votes": 17571,"running_times": 7440},{"title": "Buried","year": 2010,"rating": 7,"votes": 129590,"running_times": 5700},{"title": "Burke and Hare","year": 2010,"rating": 6.2,"votes": 17376,"running_times": 5460},{"title": "Burlesque","year": 2010,"rating": 6.4,"votes": 66239,"running_times": 7140},{"title": "Burn After Reading","year": 2008,"rating": 7,"votes": 267214,"running_times": 5760},{"title": "Burnt","year": 2015,"rating": 6.6,"votes": 82978,"running_times": 6060},{"title": "But I'm a Cheerleader","year": 1999,"rating": 6.6,"votes": 21535,"running_times": 5100},{"title": "Butch Cassidy and the Sundance Kid","year": 1969,"rating": 8.1,"votes": 168819,"running_times": 6600},{"title": "Butter","year": 2011,"rating": 6.2,"votes": 18455,"running_times": 5400},{"title": "Butterfly on a Wheel","year": 2007,"rating": 6.7,"votes": 27161,"running_times": 5880},{"title": "By the Sea","year": 2015,"rating": 5.2,"votes": 13448,"running_times": 7320},{"title": "Byzantium","year": 2012,"rating": 6.5,"votes": 35211,"running_times": 7080},{"title": "Byôsoku 5 senchimêtoru","year": 2007,"rating": 7.7,"votes": 35965,"running_times": 3780},{"title": "Bølgen","year": 2015,"rating": 6.7,"votes": 21289,"running_times": 6300},{"title": "C.R.A.Z.Y.","year": 2005,"rating": 8,"votes": 28956,"running_times": 7620},{"title": "CHIPS","year": 2017,"rating": 6,"votes": 24799,"running_times": 6060},{"title": "Cabaret","year": 1972,"rating": 7.8,"votes": 39966,"running_times": 7440},{"title": "Cabin Fever","year": 2002,"rating": 5.6,"votes": 66293,"running_times": 5880},{"title": "Cabin Fever 2: Spring Fever","year": 2009,"rating": 4.3,"votes": 11073,"running_times": 5160},{"title": "Caddyshack","year": 1980,"rating": 7.3,"votes": 88789,"running_times": 5880},{"title": "Caddyshack II","year": 1988,"rating": 3.7,"votes": 13034,"running_times": 5880},{"title": "Cadillac Man","year": 1990,"rating": 5.6,"votes": 11472,"running_times": 5820},{"title": "Cadillac Records","year": 2008,"rating": 7,"votes": 16892,"running_times": 6540},{"title": "Café Society","year": 2016,"rating": 6.6,"votes": 52800,"running_times": 5760},{"title": "Cake","year": 2014,"rating": 6.4,"votes": 30781,"running_times": 6120},{"title": "Calendar Girls","year": 2003,"rating": 6.9,"votes": 20684,"running_times": 6480},{"title": "Caligola","year": 1979,"rating": 5.3,"votes": 29361,"running_times": 9360},{"title": "Calvary","year": 2014,"rating": 7.4,"votes": 47886,"running_times": 6120},{"title": "Camp X-Ray","year": 2014,"rating": 7,"votes": 33991,"running_times": 7020},{"title": "Can't Buy Me Love","year": 1987,"rating": 6.7,"votes": 26695,"running_times": 5640},{"title": "Can't Hardly Wait","year": 1998,"rating": 6.5,"votes": 39898,"running_times": 6060},{"title": "Canadian Bacon","year": 1995,"rating": 5.9,"votes": 14379,"running_times": 5460},{"title": "Candy","year": 2006,"rating": 7.3,"votes": 38489,"running_times": 6960},{"title": "Candyman","year": 1992,"rating": 6.6,"votes": 54767,"running_times": 5940},{"title": "Cannibal Holocaust","year": 1980,"rating": 6,"votes": 42774,"running_times": 5700},{"title": "Cannonball Run II","year": 1984,"rating": 4.9,"votes": 12651,"running_times": 6480},{"title": "Cape Fear","year": 1962,"rating": 7.8,"votes": 22104,"running_times": 6360},{"title": "Cape Fear","year": 1991,"rating": 7.3,"votes": 140015,"running_times": 7680},{"title": "Capitalism: A Love Story","year": 2009,"rating": 7.4,"votes": 37838,"running_times": 7620},{"title": "Capote","year": 2005,"rating": 7.4,"votes": 109265,"running_times": 6840},{"title": "Capricorn One","year": 1977,"rating": 6.8,"votes": 17173,"running_times": 7800},{"title": "Captain America: Civil War","year": 2016,"rating": 7.9,"votes": 457587,"running_times": 8820},{"title": "Captain America: The First Avenger","year": 2011,"rating": 6.9,"votes": 572492,"running_times": 7440},{"title": "Captain America: The Winter Soldier","year": 2014,"rating": 7.8,"votes": 570329,"running_times": 8160},{"title": "Captain Blood","year": 1935,"rating": 7.8,"votes": 10708,"running_times": 7140},{"title": "Captain Corelli's Mandolin","year": 2001,"rating": 5.9,"votes": 29674,"running_times": 7860},{"title": "Captain Fantastic","year": 2016,"rating": 7.9,"votes": 127916,"running_times": 7080},{"title": "Captain Phillips","year": 2013,"rating": 7.8,"votes": 358882,"running_times": 8040},{"title": "Captain Ron","year": 1992,"rating": 5.7,"votes": 18068,"running_times": 5760},{"title": "Captain Underpants: The First Epic Movie","year": 2017,"rating": 6.2,"votes": 13648,"running_times": 5340},{"title": "Captivity","year": 2007,"rating": 4.7,"votes": 21294,"running_times": 5760},{"title": "Capturing the Friedmans","year": 2003,"rating": 7.8,"votes": 20887,"running_times": 6420},{"title": "Carlito's Way","year": 1993,"rating": 7.9,"votes": 174852,"running_times": 8640},{"title": "Carnage","year": 2011,"rating": 7.2,"votes": 104582,"running_times": 4800},{"title": "Carnival of Souls","year": 1962,"rating": 7.2,"votes": 15495,"running_times": 5460},{"title": "Carol","year": 2015,"rating": 7.2,"votes": 84444,"running_times": 7080},{"title": "Carrie","year": 1976,"rating": 7.4,"votes": 138986,"running_times": 5880},{"title": "Carrie","year": 2013,"rating": 5.9,"votes": 117179,"running_times": 6000},{"title": "Carriers","year": 2009,"rating": 6,"votes": 37502,"running_times": 5040},{"title": "Cars","year": 2006,"rating": 7.1,"votes": 295881,"running_times": 7020},{"title": "Cars 2","year": 2011,"rating": 6.2,"votes": 119432,"running_times": 6360},{"title": "Cars 3","year": 2017,"rating": 6.9,"votes": 32897,"running_times": 6120},{"title": "Cartel Land","year": 2015,"rating": 7.4,"votes": 14922,"running_times": 6000},{"title": "Casa de mi Padre","year": 2012,"rating": 5.5,"votes": 18263,"running_times": 5040},{"title": "Casablanca","year": 1942,"rating": 8.5,"votes": 430019,"running_times": 6120},{"title": "Casanova","year": 2005,"rating": 6.5,"votes": 47010,"running_times": 6720},{"title": "Case 39","year": 2009,"rating": 6.2,"votes": 66072,"running_times": 6540},{"title": "Cashback","year": 2006,"rating": 7.2,"votes": 76620,"running_times": 6120},{"title": "Casino","year": 1995,"rating": 8.2,"votes": 372920,"running_times": 10680},{"title": "Casino Jack","year": 2010,"rating": 6.2,"votes": 15537,"running_times": 6480},{"title": "Casino Royale","year": 1967,"rating": 5.2,"votes": 23463,"running_times": 7860},{"title": "Casino Royale","year": 2006,"rating": 8,"votes": 508304,"running_times": 8640},{"title": "Casper","year": 1995,"rating": 6.1,"votes": 96437,"running_times": 6000},{"title": "Cassandra's Dream","year": 2007,"rating": 6.7,"votes": 46383,"running_times": 6480},{"title": "Casse-tête chinois","year": 2013,"rating": 7,"votes": 11298,"running_times": 7020},{"title": "Cast Away","year": 2000,"rating": 7.8,"votes": 435433,"running_times": 8580},{"title": "Casualties of War","year": 1989,"rating": 7.1,"votes": 35750,"running_times": 7140},{"title": "Cat Ballou","year": 1965,"rating": 6.9,"votes": 11292,"running_times": 5820},{"title": "Cat People","year": 1942,"rating": 7.4,"votes": 15253,"running_times": 4380},{"title": "Cat People","year": 1982,"rating": 6.1,"votes": 15650,"running_times": 7080},{"title": "Cat on a Hot Tin Roof","year": 1958,"rating": 8.1,"votes": 37011,"running_times": 6480},{"title": "Cat's Eye","year": 1985,"rating": 6.3,"votes": 18823,"running_times": 5640},{"title": "Catch .44","year": 2011,"rating": 4.6,"votes": 15331,"running_times": 5640},{"title": "Catch Me If You Can","year": 2002,"rating": 8.1,"votes": 624495,"running_times": 8460},{"title": "Catch and Release","year": 2006,"rating": 6,"votes": 20037,"running_times": 7440},{"title": "Catch-22","year": 1970,"rating": 7.2,"votes": 18485,"running_times": 7320},{"title": "Catfish","year": 2010,"rating": 7.1,"votes": 37245,"running_times": 5220},{"title": "Cats & Dogs","year": 2001,"rating": 5.1,"votes": 49443,"running_times": 5220},{"title": "Cats & Dogs: The Revenge of Kitty Galore","year": 2010,"rating": 4.3,"votes": 11291,"running_times": 4920},{"title": "Catwoman","year": 2004,"rating": 3.3,"votes": 94234,"running_times": 6240},{"title": "Cave of Forgotten Dreams","year": 2010,"rating": 7.4,"votes": 12911,"running_times": 5700},{"title": "Cecil B. DeMented","year": 2000,"rating": 6.2,"votes": 12003,"running_times": 5220},{"title": "Cedar Rapids","year": 2011,"rating": 6.3,"votes": 33876,"running_times": 5220},{"title": "Celda 211","year": 2009,"rating": 7.7,"votes": 54977,"running_times": 6780},{"title": "Celebrity","year": 1998,"rating": 6.3,"votes": 21809,"running_times": 6780},{"title": "Celeste & Jesse Forever","year": 2012,"rating": 6.6,"votes": 26184,"running_times": 5520},{"title": "Cell","year": 2016,"rating": 4.3,"votes": 18673,"running_times": 5880},{"title": "Cellular","year": 2004,"rating": 6.5,"votes": 83353,"running_times": 5640},{"title": "Cemetery Junction","year": 2010,"rating": 6.9,"votes": 18430,"running_times": 5700},{"title": "Center Stage","year": 2000,"rating": 6.7,"votes": 16679,"running_times": 6900},{"title": "Central Intelligence","year": 2016,"rating": 6.3,"votes": 109993,"running_times": 6960},{"title": "Centurion","year": 2010,"rating": 6.4,"votes": 69872,"running_times": 5820},{"title": "Chain Reaction","year": 1996,"rating": 5.6,"votes": 42923,"running_times": 6420},{"title": "Chained","year": 2012,"rating": 6.4,"votes": 13885,"running_times": 5640},{"title": "Chakushin ari","year": 2003,"rating": 6.2,"votes": 15089,"running_times": 6720},{"title": "Chalet Girl","year": 2011,"rating": 6.3,"votes": 20636,"running_times": 5820},{"title": "Changeling","year": 2008,"rating": 7.8,"votes": 211563,"running_times": 8460},{"title": "Changing Lanes","year": 2002,"rating": 6.5,"votes": 60854,"running_times": 5880},{"title": "Chaos","year": 2005,"rating": 6.5,"votes": 46470,"running_times": 6360},{"title": "Chaos Theory","year": 2008,"rating": 6.7,"votes": 29293,"running_times": 5220},{"title": "Chaplin","year": 1992,"rating": 7.6,"votes": 46419,"running_times": 8580},{"title": "Chappie","year": 2015,"rating": 6.8,"votes": 197879,"running_times": 7200},{"title": "Charade","year": 1963,"rating": 8,"votes": 54637,"running_times": 6780},{"title": "Chariots of Fire","year": 1981,"rating": 7.2,"votes": 44814,"running_times": 7500},{"title": "Charlie Bartlett","year": 2007,"rating": 7,"votes": 58841,"running_times": 5820},{"title": "Charlie St. Cloud","year": 2010,"rating": 6.5,"votes": 51299,"running_times": 5940},{"title": "Charlie Wilson's War","year": 2007,"rating": 7.1,"votes": 94821,"running_times": 6120},{"title": "Charlie and the Chocolate Factory","year": 2005,"rating": 6.7,"votes": 355757,"running_times": 6900},{"title": "Charlie's Angels","year": 2000,"rating": 5.5,"votes": 154142,"running_times": 5880},{"title": "Charlie's Angels: Full Throttle","year": 2003,"rating": 4.8,"votes": 106759,"running_times": 6420},{"title": "Charlotte's Web","year": 1973,"rating": 6.9,"votes": 14527,"running_times": 5640},{"title": "Charlotte's Web","year": 2006,"rating": 6.3,"votes": 30791,"running_times": 5820},{"title": "Chasing Amy","year": 1997,"rating": 7.3,"votes": 120382,"running_times": 6780},{"title": "Chasing Liberty","year": 2004,"rating": 6.1,"votes": 32180,"running_times": 6660},{"title": "Chasing Mavericks","year": 2012,"rating": 7.2,"votes": 27345,"running_times": 6960},{"title": "Che: Part One","year": 2008,"rating": 7.2,"votes": 40419,"running_times": 8040},{"title": "Che: Part Two","year": 2008,"rating": 6.9,"votes": 29183,"running_times": 8100},{"title": "Cheap Thrills","year": 2013,"rating": 6.8,"votes": 14997,"running_times": 5280},{"title": "Cheaper by the Dozen","year": 2003,"rating": 5.8,"votes": 81367,"running_times": 5880},{"title": "Cheaper by the Dozen 2","year": 2005,"rating": 5.5,"votes": 46696,"running_times": 5640},{"title": "Chef","year": 2014,"rating": 7.3,"votes": 158787,"running_times": 6840},{"title": "Chennai Express","year": 2013,"rating": 6,"votes": 40979,"running_times": 8460},{"title": "Chernobyl Diaries","year": 2012,"rating": 5,"votes": 56089,"running_times": 5160},{"title": "Cherry Falls","year": 2000,"rating": 5.1,"votes": 10550,"running_times": 5520},{"title": "Chicago","year": 2002,"rating": 7.2,"votes": 186928,"running_times": 6780},{"title": "Chicken Little","year": 2005,"rating": 5.8,"votes": 71208,"running_times": 4860},{"title": "Chicken Run","year": 2000,"rating": 7,"votes": 152354,"running_times": 5040},{"title": "Child 44","year": 2015,"rating": 6.5,"votes": 51699,"running_times": 8220},{"title": "Child's Play","year": 1988,"rating": 6.6,"votes": 69387,"running_times": 5220},{"title": "Child's Play 2","year": 1990,"rating": 5.8,"votes": 35756,"running_times": 5400},{"title": "Child's Play 3","year": 1991,"rating": 5,"votes": 28492,"running_times": 5400},{"title": "Children of Men","year": 2006,"rating": 7.9,"votes": 396186,"running_times": 6540},{"title": "Children of a Lesser God","year": 1986,"rating": 7.2,"votes": 12664,"running_times": 7140},{"title": "Children of the Corn","year": 1984,"rating": 5.6,"votes": 39139,"running_times": 5520},{"title": "Chinatown","year": 1974,"rating": 8.2,"votes": 240563,"running_times": 7800},{"title": "Chinjeolhan geumjassi","year": 2005,"rating": 7.6,"votes": 59464,"running_times": 6900},{"title": "Chitty Chitty Bang Bang","year": 1968,"rating": 6.9,"votes": 33986,"running_times": 8640},{"title": "Chloe","year": 2009,"rating": 6.3,"votes": 61084,"running_times": 5760},{"title": "Chocolat","year": 2000,"rating": 7.3,"votes": 160087,"running_times": 7260},{"title": "Chocolate","year": 2008,"rating": 7,"votes": 15889,"running_times": 6600},{"title": "Choke","year": 2008,"rating": 6.5,"votes": 29570,"running_times": 5520},{"title": "Chopper","year": 2000,"rating": 7.2,"votes": 33112,"running_times": 5640},{"title": "Christine","year": 1983,"rating": 6.7,"votes": 56332,"running_times": 6600},{"title": "Christmas with the Kranks","year": 2004,"rating": 5.2,"votes": 32280,"running_times": 5940},{"title": "Chronicle","year": 2012,"rating": 7.1,"votes": 218220,"running_times": 5340},{"title": "Chung Hing sam lam","year": 1994,"rating": 8.1,"votes": 46274,"running_times": 6120},{"title": "Cinderella","year": 1950,"rating": 7.3,"votes": 118829,"running_times": 4440},{"title": "Cinderella","year": 2015,"rating": 7,"votes": 123774,"running_times": 6840},{"title": "Cinderella Man","year": 2005,"rating": 8,"votes": 158231,"running_times": 8640},{"title": "Circle","year": 2015,"rating": 6,"votes": 22091,"running_times": 5220},{"title": "Cirque du Freak: The Vampire's Assistant","year": 2009,"rating": 5.9,"votes": 38122,"running_times": 6540},{"title": "Citizen Kane","year": 1941,"rating": 8.4,"votes": 329256,"running_times": 7140},{"title": "Citizenfour","year": 2014,"rating": 8.1,"votes": 44407,"running_times": 6840},{"title": "City Hall","year": 1996,"rating": 6.2,"votes": 17638,"running_times": 6660},{"title": "City Island","year": 2009,"rating": 7.4,"votes": 28457,"running_times": 6240},{"title": "City Lights","year": 1931,"rating": 8.6,"votes": 125731,"running_times": 5220},{"title": "City Slickers","year": 1991,"rating": 6.7,"votes": 41722,"running_times": 6780},{"title": "City Slickers II: The Legend of Curly's Gold","year": 1994,"rating": 5.5,"votes": 16077,"running_times": 6960},{"title": "City by the Sea","year": 2002,"rating": 6.1,"votes": 22301,"running_times": 6480},{"title": "City of Angels","year": 1998,"rating": 6.7,"votes": 100989,"running_times": 6840},{"title": "City of Ember","year": 2008,"rating": 6.5,"votes": 56656,"running_times": 5400},{"title": "Clash of the Titans","year": 1981,"rating": 6.9,"votes": 35380,"running_times": 7080},{"title": "Clash of the Titans","year": 2010,"rating": 5.8,"votes": 243626,"running_times": 6360},{"title": "Cleaner","year": 2007,"rating": 6.1,"votes": 34279,"running_times": 5580},{"title": "Cleanskin","year": 2012,"rating": 6.3,"votes": 18425,"running_times": 6480},{"title": "Clear and Present Danger","year": 1994,"rating": 6.9,"votes": 75175,"running_times": 8460},{"title": "Cleopatra","year": 1963,"rating": 7,"votes": 24093,"running_times": 19200},{"title": "Clerks","year": 1994,"rating": 7.8,"votes": 191979,"running_times": 6120},{"title": "Clerks II","year": 2006,"rating": 7.4,"votes": 120022,"running_times": 5820},{"title": "Click","year": 2006,"rating": 6.4,"votes": 266298,"running_times": 6420},{"title": "Cliffhanger","year": 1993,"rating": 6.4,"votes": 103922,"running_times": 7440},{"title": "Clockers","year": 1995,"rating": 6.9,"votes": 17806,"running_times": 7740},{"title": "Clockstoppers","year": 2002,"rating": 5.2,"votes": 12024,"running_times": 5640},{"title": "Close Encounters of the Third Kind","year": 1977,"rating": 7.7,"votes": 154463,"running_times": 8280},{"title": "Closed Circuit","year": 2013,"rating": 6.2,"votes": 19118,"running_times": 5760},{"title": "Closer","year": 2004,"rating": 7.3,"votes": 179295,"running_times": 6240},{"title": "Cloud Atlas","year": 2012,"rating": 7.5,"votes": 307896,"running_times": 10320},{"title": "Clouds of Sils Maria","year": 2014,"rating": 6.7,"votes": 22177,"running_times": 7440},{"title": "Cloudy with a Chance of Meatballs","year": 2009,"rating": 7,"votes": 169393,"running_times": 5400},{"title": "Cloudy with a Chance of Meatballs 2","year": 2013,"rating": 6.4,"votes": 72622,"running_times": 5700},{"title": "Cloverfield","year": 2008,"rating": 7,"votes": 322764,"running_times": 5100},{"title": "Clown","year": 2014,"rating": 5.7,"votes": 16910,"running_times": 6000},{"title": "Club Dread","year": 2004,"rating": 5.7,"votes": 25170,"running_times": 7140},{"title": "Clue","year": 1985,"rating": 7.3,"votes": 63435,"running_times": 5820},{"title": "Clueless","year": 1995,"rating": 6.8,"votes": 139268,"running_times": 5820},{"title": "Coach Carter","year": 2005,"rating": 7.3,"votes": 101888,"running_times": 8160},{"title": "Coal Miner's Daughter","year": 1980,"rating": 7.5,"votes": 14038,"running_times": 7440},{"title": "Cobain: Montage of Heck","year": 2015,"rating": 7.6,"votes": 23885,"running_times": 8700},{"title": "Cobra","year": 1986,"rating": 5.7,"votes": 55581,"running_times": 5220},{"title": "Cocaine Cowboys","year": 2006,"rating": 7.9,"votes": 11305,"running_times": 9120},{"title": "Cockneys vs Zombies","year": 2012,"rating": 5.9,"votes": 16293,"running_times": 5280},{"title": "Cocktail","year": 1988,"rating": 5.8,"votes": 66672,"running_times": 6240},{"title": "Coco","year": 2017,"rating": 8.8,"votes": 38493,"running_times": 6300},{"title": "Coco avant Chanel","year": 2009,"rating": 6.7,"votes": 34380,"running_times": 6660},{"title": "Cocoon","year": 1985,"rating": 6.7,"votes": 48540,"running_times": 7020},{"title": "Cocoon: The Return","year": 1988,"rating": 5.3,"votes": 13077,"running_times": 6960},{"title": "Code 46","year": 2003,"rating": 6.2,"votes": 18825,"running_times": 5580},{"title": "Code Name: The Cleaner","year": 2007,"rating": 4.5,"votes": 10369,"running_times": 5460},{"title": "Coffee and Cigarettes","year": 2003,"rating": 7.1,"votes": 51479,"running_times": 5700},{"title": "Coherence","year": 2013,"rating": 7.2,"votes": 74162,"running_times": 5340},{"title": "Cold Creek Manor","year": 2003,"rating": 4.9,"votes": 19224,"running_times": 7080},{"title": "Cold Mountain","year": 2003,"rating": 7.2,"votes": 125299,"running_times": 9240},{"title": "Cold in July","year": 2014,"rating": 6.8,"votes": 29209,"running_times": 6540},{"title": "Collateral","year": 2004,"rating": 7.6,"votes": 314995,"running_times": 6900},{"title": "Collateral Beauty","year": 2016,"rating": 6.8,"votes": 61621,"running_times": 5820},{"title": "Collateral Damage","year": 2002,"rating": 5.5,"votes": 65175,"running_times": 6480},{"title": "College","year": 2008,"rating": 4.6,"votes": 11386,"running_times": 5640},{"title": "College Road Trip","year": 2008,"rating": 4.3,"votes": 13947,"running_times": 4980},{"title": "Collide","year": 2016,"rating": 5.7,"votes": 10342,"running_times": 5940},{"title": "Colombiana","year": 2011,"rating": 6.4,"votes": 81904,"running_times": 6720},{"title": "Colonia","year": 2015,"rating": 7.1,"votes": 34529,"running_times": 6360},{"title": "Color of Night","year": 1994,"rating": 5.1,"votes": 19983,"running_times": 8400},{"title": "Colors","year": 1988,"rating": 6.7,"votes": 20690,"running_times": 7620},{"title": "Colossal","year": 2016,"rating": 6.2,"votes": 34754,"running_times": 6540},{"title": "Coma","year": 1978,"rating": 6.9,"votes": 14481,"running_times": 6780},{"title": "Comet","year": 2014,"rating": 6.8,"votes": 14582,"running_times": 5460},{"title": "Coming Home","year": 1978,"rating": 7.3,"votes": 10277,"running_times": 7620},{"title": "Coming to America","year": 1988,"rating": 7,"votes": 132385,"running_times": 6960},{"title": "Commando","year": 1985,"rating": 6.7,"votes": 123223,"running_times": 5520},{"title": "Comme un chef","year": 2012,"rating": 6.7,"votes": 13946,"running_times": 5040},{"title": "Como agua para chocolate","year": 1992,"rating": 7.2,"votes": 14661,"running_times": 6780},{"title": "Compliance","year": 2012,"rating": 6.4,"votes": 26887,"running_times": 5400},{"title": "Con Air","year": 1997,"rating": 6.8,"votes": 241529,"running_times": 7380},{"title": "Conan the Barbarian","year": 1982,"rating": 6.9,"votes": 120899,"running_times": 7740},{"title": "Conan the Barbarian","year": 2011,"rating": 5.2,"votes": 86384,"running_times": 6780},{"title": "Conan the Destroyer","year": 1984,"rating": 5.9,"votes": 66764,"running_times": 6180},{"title": "Concussion","year": 2015,"rating": 7.1,"votes": 66336,"running_times": 7380},{"title": "Coneheads","year": 1993,"rating": 5.3,"votes": 44457,"running_times": 5280},{"title": "Confessions of a Dangerous Mind","year": 2002,"rating": 7.1,"votes": 75279,"running_times": 6780},{"title": "Confessions of a Shopaholic","year": 2009,"rating": 5.9,"votes": 67162,"running_times": 6240},{"title": "Confessions of a Teenage Drama Queen","year": 2004,"rating": 4.6,"votes": 24723,"running_times": 5340},{"title": "Confidence","year": 2003,"rating": 6.7,"votes": 31438,"running_times": 5820},{"title": "Congo","year": 1995,"rating": 5.1,"votes": 37007,"running_times": 6540},{"title": "Conquest of the Planet of the Apes","year": 1972,"rating": 6.1,"votes": 25995,"running_times": 5280},{"title": "Conspiracy Theory","year": 1997,"rating": 6.7,"votes": 82265,"running_times": 8100},{"title": "Constantine","year": 2005,"rating": 6.9,"votes": 256735,"running_times": 7260},{"title": "Contact","year": 1997,"rating": 7.4,"votes": 220252,"running_times": 9000},{"title": "Contagion","year": 2011,"rating": 6.6,"votes": 191199,"running_times": 6360},{"title": "Contraband","year": 2012,"rating": 6.5,"votes": 106830,"running_times": 6540},{"title": "Contracted","year": 2013,"rating": 5.3,"votes": 12077,"running_times": 5040},{"title": "Control","year": 2007,"rating": 7.7,"votes": 54840,"running_times": 7320},{"title": "Conversations with Other Women","year": 2005,"rating": 7.1,"votes": 10768,"running_times": 5040},{"title": "Conviction","year": 2010,"rating": 7.2,"votes": 37479,"running_times": 6420},{"title": "Convoy","year": 1978,"rating": 6.3,"votes": 12446,"running_times": 6600},{"title": "Coogan's Bluff","year": 1968,"rating": 6.5,"votes": 12776,"running_times": 5580},{"title": "Cookie's Fortune","year": 1999,"rating": 6.9,"votes": 11591,"running_times": 7080},{"title": "Cool Hand Luke","year": 1967,"rating": 8.2,"votes": 132362,"running_times": 7560},{"title": "Cool Runnings","year": 1993,"rating": 6.9,"votes": 76261,"running_times": 5880},{"title": "Cool World","year": 1992,"rating": 4.8,"votes": 17941,"running_times": 8820},{"title": "Cooties","year": 2014,"rating": 5.6,"votes": 18063,"running_times": 5280},{"title": "Cop Car","year": 2015,"rating": 6.3,"votes": 24603,"running_times": 5280},{"title": "Cop Land","year": 1997,"rating": 6.9,"votes": 74641,"running_times": 7200},{"title": "Cop Out","year": 2010,"rating": 5.6,"votes": 78523,"running_times": 6420},{"title": "Copenhagen","year": 2014,"rating": 7.2,"votes": 10195,"running_times": 5880},{"title": "Copie conforme","year": 2010,"rating": 7.3,"votes": 16521,"running_times": 6360},{"title": "Copycat","year": 1995,"rating": 6.6,"votes": 45500,"running_times": 7380},{"title": "Copying Beethoven","year": 2006,"rating": 6.8,"votes": 11733,"running_times": 6240},{"title": "Coraline","year": 2009,"rating": 7.7,"votes": 164057,"running_times": 6000},{"title": "Coriolanus","year": 2011,"rating": 6.2,"votes": 28410,"running_times": 7380},{"title": "Corky Romano","year": 2001,"rating": 4.6,"votes": 11368,"running_times": 5160},{"title": "Corpse Bride","year": 2005,"rating": 7.4,"votes": 208321,"running_times": 4620},{"title": "Corrina, Corrina","year": 1994,"rating": 6.5,"votes": 10767,"running_times": 6900},{"title": "Cosmopolis","year": 2012,"rating": 5,"votes": 39968,"running_times": 6540},{"title": "Country Strong","year": 2010,"rating": 6.3,"votes": 15545,"running_times": 7020},{"title": "Couples Retreat","year": 2009,"rating": 5.5,"votes": 88557,"running_times": 6780},{"title": "Courage Under Fire","year": 1996,"rating": 6.6,"votes": 43563,"running_times": 6960},{"title": "Courageous","year": 2011,"rating": 7,"votes": 16551,"running_times": 7740},{"title": "Cowboy Bebop: Tengoku no tobira","year": 2001,"rating": 7.9,"votes": 35543,"running_times": 6900},{"title": "Cowboys & Aliens","year": 2011,"rating": 6,"votes": 184726,"running_times": 8100},{"title": "Cowspiracy: The Sustainability Secret","year": 2014,"rating": 8.4,"votes": 14590,"running_times": 5100},{"title": "Coyote Ugly","year": 2000,"rating": 5.6,"votes": 95982,"running_times": 6420},{"title": "Cracks","year": 2009,"rating": 6.7,"votes": 16901,"running_times": 6240},{"title": "Cradle 2 the Grave","year": 2003,"rating": 5.8,"votes": 37167,"running_times": 6060},{"title": "Crank","year": 2006,"rating": 7,"votes": 210220,"running_times": 5580},{"title": "Crank: High Voltage","year": 2009,"rating": 6.2,"votes": 122969,"running_times": 5760},{"title": "Crash","year": 1996,"rating": 6.4,"votes": 45105,"running_times": 6000},{"title": "Crash","year": 2004,"rating": 7.8,"votes": 382043,"running_times": 6900},{"title": "Crazy Heart","year": 2009,"rating": 7.3,"votes": 73969,"running_times": 6720},{"title": "Crazy, Stupid, Love.","year": 2011,"rating": 7.4,"votes": 409038,"running_times": 7080},{"title": "Crazy/Beautiful","year": 2001,"rating": 6.5,"votes": 22330,"running_times": 8100},{"title": "Creation","year": 2009,"rating": 6.7,"votes": 12373,"running_times": 6480},{"title": "Creature from the Black Lagoon","year": 1954,"rating": 7,"votes": 20009,"running_times": 4740},{"title": "Creed","year": 2015,"rating": 7.6,"votes": 186555,"running_times": 7980},{"title": "Creep","year": 2004,"rating": 5.6,"votes": 24964,"running_times": 5100},{"title": "Creep","year": 2014,"rating": 6.2,"votes": 20497,"running_times": 4620},{"title": "Creepshow","year": 1982,"rating": 6.9,"votes": 33804,"running_times": 7800},{"title": "Creepshow 2","year": 1987,"rating": 6,"votes": 17797,"running_times": 5520},{"title": "Crimes and Misdemeanors","year": 1989,"rating": 8,"votes": 46799,"running_times": 6240},{"title": "Criminal","year": 2016,"rating": 6.3,"votes": 43955,"running_times": 6780},{"title": "Crimson Peak","year": 2015,"rating": 6.5,"votes": 105157,"running_times": 7140},{"title": "Crimson Tide","year": 1995,"rating": 7.3,"votes": 87400,"running_times": 7380},{"title": "Critters","year": 1986,"rating": 6,"votes": 25883,"running_times": 4920},{"title": "Critters 2","year": 1988,"rating": 5.4,"votes": 11269,"running_times": 5160},{"title": "Crocodile Dundee","year": 1986,"rating": 6.5,"votes": 80228,"running_times": 5820},{"title": "Crocodile Dundee in Los Angeles","year": 2001,"rating": 4.8,"votes": 20997,"running_times": 5520},{"title": "Cronos","year": 1993,"rating": 6.7,"votes": 22058,"running_times": 5640},{"title": "Cross of Iron","year": 1977,"rating": 7.5,"votes": 22038,"running_times": 7920},{"title": "Crossing Over","year": 2009,"rating": 6.8,"votes": 20695,"running_times": 8400},{"title": "Crossroads","year": 1986,"rating": 7.1,"votes": 11548,"running_times": 5940},{"title": "Crossroads","year": 2002,"rating": 3.4,"votes": 35455,"running_times": 5580},{"title": "Crouching Tiger, Hidden Dragon: Sword of Destiny","year": 2016,"rating": 6.1,"votes": 13783,"running_times": 6180},{"title": "Croupier","year": 1998,"rating": 7.2,"votes": 16685,"running_times": 5640},{"title": "Cruel Intentions","year": 1999,"rating": 6.8,"votes": 158764,"running_times": 5820},{"title": "Cruising","year": 1980,"rating": 6.4,"votes": 14634,"running_times": 6120},{"title": "Crumb","year": 1994,"rating": 8,"votes": 15416,"running_times": 7140},{"title": "Cry Freedom","year": 1987,"rating": 7.5,"votes": 10789,"running_times": 9420},{"title": "Cry Wolf","year": 2005,"rating": 5.9,"votes": 23969,"running_times": 5400},{"title": "Cry-Baby","year": 1990,"rating": 6.5,"votes": 47450,"running_times": 5460},{"title": "Crying Freeman","year": 1995,"rating": 6.5,"votes": 10059,"running_times": 6120},{"title": "Cuban Fury","year": 2014,"rating": 6.2,"votes": 16055,"running_times": 5880},{"title": "Cube","year": 1997,"rating": 7.3,"votes": 177332,"running_times": 5400},{"title": "Cube 2: Hypercube","year": 2002,"rating": 5.6,"votes": 54831,"running_times": 5640},{"title": "Cube Zero","year": 2004,"rating": 5.7,"votes": 31210,"running_times": 5820},{"title": "Cujo","year": 1983,"rating": 6,"votes": 30871,"running_times": 5580},{"title": "Cult of Chucky","year": 2017,"rating": 5.2,"votes": 11206,"running_times": 7140},{"title": "Curious George","year": 2006,"rating": 6.5,"votes": 13591,"running_times": 5220},{"title": "Curly Sue","year": 1991,"rating": 5.8,"votes": 17904,"running_times": 6060},{"title": "Curse of Chucky","year": 2013,"rating": 5.6,"votes": 27291,"running_times": 5820},{"title": "Cursed","year": 2005,"rating": 5,"votes": 27579,"running_times": 5940},{"title": "Cutthroat Island","year": 1995,"rating": 5.6,"votes": 22715,"running_times": 7440},{"title": "Cyborg","year": 1989,"rating": 5,"votes": 25164,"running_times": 5160},{"title": "Cypher","year": 2002,"rating": 6.8,"votes": 28151,"running_times": 5700},{"title": "Cyrus","year": 2010,"rating": 6.3,"votes": 31474,"running_times": 5460},{"title": "D-Tox","year": 2002,"rating": 5.3,"votes": 20961,"running_times": 5760},{"title": "D-War","year": 2007,"rating": 3.6,"votes": 22115,"running_times": 6420},{"title": "D.A.R.Y.L.","year": 1985,"rating": 6.2,"votes": 10271,"running_times": 5940},{"title": "D.E.B.S.","year": 2004,"rating": 5.3,"votes": 12982,"running_times": 5460},{"title": "D2: The Mighty Ducks","year": 1994,"rating": 6,"votes": 30535,"running_times": 6360},{"title": "D3: The Mighty Ducks","year": 1996,"rating": 5.3,"votes": 20741,"running_times": 6240},{"title": "DOA: Dead or Alive","year": 2006,"rating": 4.8,"votes": 40160,"running_times": 5220},{"title": "Dabba","year": 2013,"rating": 7.8,"votes": 37643,"running_times": 6240},{"title": "Daddy Day Camp","year": 2007,"rating": 3,"votes": 13152,"running_times": 5580},{"title": "Daddy Day Care","year": 2003,"rating": 5.5,"votes": 53857,"running_times": 5520},{"title": "Daddy's Home","year": 2015,"rating": 6.1,"votes": 77927,"running_times": 5760},{"title": "Dagon","year": 2001,"rating": 6.3,"votes": 13890,"running_times": 5880},{"title": "Dallas Buyers Club","year": 2013,"rating": 8,"votes": 367890,"running_times": 7020},{"title": "Damage","year": 1992,"rating": 6.9,"votes": 13462,"running_times": 6660},{"title": "Damien: Omen II","year": 1978,"rating": 6.3,"votes": 24472,"running_times": 6420},{"title": "Dan in Real Life","year": 2007,"rating": 6.8,"votes": 90389,"running_times": 5880},{"title": "Dance Flick","year": 2009,"rating": 3.5,"votes": 10591,"running_times": 5280},{"title": "Dance of the Dead","year": 2008,"rating": 5.8,"votes": 10563,"running_times": 5220},{"title": "Dance of the Vampires","year": 1967,"rating": 7.3,"votes": 24957,"running_times": 6480},{"title": "Dancer in the Dark","year": 2000,"rating": 8,"votes": 86306,"running_times": 8400},{"title": "Dances with Wolves","year": 1990,"rating": 8,"votes": 203335,"running_times": 14160},{"title": "Dangerous Beauty","year": 1998,"rating": 7.3,"votes": 13633,"running_times": 6660},{"title": "Dangerous Liaisons","year": 1988,"rating": 7.7,"votes": 56386,"running_times": 7140},{"title": "Dangerous Minds","year": 1995,"rating": 6.4,"votes": 41341,"running_times": 5940},{"title": "Danny Collins","year": 2015,"rating": 7,"votes": 25060,"running_times": 6360},{"title": "Dante's Peak","year": 1997,"rating": 5.9,"votes": 68066,"running_times": 6480},{"title": "Daredevil","year": 2003,"rating": 5.3,"votes": 187093,"running_times": 7980},{"title": "Dark Blue","year": 2002,"rating": 6.6,"votes": 18322,"running_times": 7080},{"title": "Dark City","year": 1998,"rating": 7.7,"votes": 168451,"running_times": 6660},{"title": "Dark Passage","year": 1947,"rating": 7.6,"votes": 14253,"running_times": 6360},{"title": "Dark Places","year": 2015,"rating": 6.2,"votes": 33917,"running_times": 6780},{"title": "Dark Shadows","year": 2012,"rating": 6.2,"votes": 215809,"running_times": 6780},{"title": "Dark Skies","year": 2013,"rating": 6.3,"votes": 62454,"running_times": 5820},{"title": "Dark Star","year": 1974,"rating": 6.5,"votes": 18630,"running_times": 4980},{"title": "Dark Water","year": 2005,"rating": 5.6,"votes": 53540,"running_times": 6300},{"title": "Darkman","year": 1990,"rating": 6.4,"votes": 51054,"running_times": 5760},{"title": "Darkness","year": 2002,"rating": 5.4,"votes": 17484,"running_times": 6180},{"title": "Darkness Falls","year": 2003,"rating": 5,"votes": 27450,"running_times": 5760},{"title": "Darr","year": 1993,"rating": 7.9,"votes": 18344,"running_times": 10680},{"title": "Das Boot","year": 1981,"rating": 8.4,"votes": 187200,"running_times": 17580},{"title": "Das Experiment","year": 2001,"rating": 7.8,"votes": 83528,"running_times": 7200},{"title": "Date Movie","year": 2006,"rating": 2.7,"votes": 52564,"running_times": 5100},{"title": "Date Night","year": 2010,"rating": 6.3,"votes": 136609,"running_times": 6060},{"title": "Dave","year": 1993,"rating": 6.8,"votes": 43104,"running_times": 6600},{"title": "Dawn of the Dead","year": 1978,"rating": 8,"votes": 97223,"running_times": 9360},{"title": "Dawn of the Dead","year": 2004,"rating": 7.3,"votes": 208261,"running_times": 6600},{"title": "Dawn of the Planet of the Apes","year": 2014,"rating": 7.6,"votes": 362251,"running_times": 7800},{"title": "Day & Night","year": 2010,"rating": 8.1,"votes": 13289,"running_times": 360},{"title": "Day of the Dead","year": 1985,"rating": 7.2,"votes": 54076,"running_times": 6060},{"title": "Day of the Woman","year": 1978,"rating": 5.7,"votes": 21922,"running_times": 6060},{"title": "Daybreakers","year": 2009,"rating": 6.5,"votes": 111322,"running_times": 5880},{"title": "Daydream Nation","year": 2010,"rating": 6.4,"votes": 11338,"running_times": 5880},{"title": "Daylight","year": 1996,"rating": 5.8,"votes": 57247,"running_times": 6840},{"title": "Days of Heaven","year": 1978,"rating": 7.9,"votes": 42093,"running_times": 5640},{"title": "Days of Thunder","year": 1990,"rating": 5.9,"votes": 65974,"running_times": 6420},{"title": "Dazed and Confused","year": 1993,"rating": 7.7,"votes": 135321,"running_times": 6120},{"title": "De battre mon coeur s'est arrêté","year": 2005,"rating": 7.3,"votes": 16729,"running_times": 6480},{"title": "De rouille et d'os","year": 2012,"rating": 7.5,"votes": 54550,"running_times": 7200},{"title": "De-Lovely","year": 2004,"rating": 6.6,"votes": 10074,"running_times": 7500},{"title": "Dead Again","year": 1991,"rating": 7,"votes": 22986,"running_times": 6420},{"title": "Dead Calm","year": 1989,"rating": 6.8,"votes": 31732,"running_times": 5760},{"title": "Dead End","year": 2003,"rating": 6.7,"votes": 21560,"running_times": 5100},{"title": "Dead Man","year": 1995,"rating": 7.7,"votes": 78292,"running_times": 7260},{"title": "Dead Man Down","year": 2013,"rating": 6.5,"votes": 58376,"running_times": 7080},{"title": "Dead Man Walking","year": 1995,"rating": 7.6,"votes": 77979,"running_times": 7320},{"title": "Dead Man on Campus","year": 1998,"rating": 6.1,"votes": 12326,"running_times": 5760},{"title": "Dead Man's Shoes","year": 2004,"rating": 7.7,"votes": 43049,"running_times": 5400},{"title": "Dead Men Don't Wear Plaid","year": 1982,"rating": 6.8,"votes": 17854,"running_times": 5280},{"title": "Dead Poets Society","year": 1989,"rating": 8,"votes": 310883,"running_times": 7680},{"title": "Dead Presidents","year": 1995,"rating": 6.9,"votes": 16576,"running_times": 7140},{"title": "Dead Ringers","year": 1988,"rating": 7.3,"votes": 32622,"running_times": 6960},{"title": "Dead Silence","year": 2007,"rating": 6.2,"votes": 74013,"running_times": 5520},{"title": "Deadfall","year": 2012,"rating": 6.3,"votes": 34661,"running_times": 5700},{"title": "Deadgirl","year": 2008,"rating": 5.7,"votes": 16648,"running_times": 6060},{"title": "Deadpool","year": 2016,"rating": 8,"votes": 686133,"running_times": 6480},{"title": "Dear Frankie","year": 2004,"rating": 7.8,"votes": 19677,"running_times": 6300},{"title": "Dear John","year": 2010,"rating": 6.3,"votes": 117324,"running_times": 6480},{"title": "Dear White People","year": 2014,"rating": 6.2,"votes": 22550,"running_times": 6480},{"title": "Dear Zachary: A Letter to a Son About His Father","year": 2008,"rating": 8.6,"votes": 25811,"running_times": 5700},{"title": "Death Becomes Her","year": 1992,"rating": 6.5,"votes": 86672,"running_times": 6240},{"title": "Death Note","year": 2017,"rating": 4.6,"votes": 51215,"running_times": 6060},{"title": "Death Proof","year": 2007,"rating": 7.1,"votes": 227440,"running_times": 7260},{"title": "Death Race","year": 2008,"rating": 6.4,"votes": 177881,"running_times": 6660},{"title": "Death Race 2000","year": 1975,"rating": 6.2,"votes": 21390,"running_times": 5040},{"title": "Death Sentence","year": 2007,"rating": 6.8,"votes": 63505,"running_times": 6660},{"title": "Death Warrant","year": 1990,"rating": 5.6,"votes": 13976,"running_times": 5340},{"title": "Death Wish","year": 1974,"rating": 7,"votes": 27842,"running_times": 5580},{"title": "Death Wish 3","year": 1985,"rating": 5.9,"votes": 11198,"running_times": 5520},{"title": "Death Wish II","year": 1982,"rating": 6,"votes": 11457,"running_times": 5700},{"title": "Death and the Maiden","year": 1994,"rating": 7.3,"votes": 19027,"running_times": 6180},{"title": "Death at a Funeral","year": 2007,"rating": 7.4,"votes": 96036,"running_times": 5220},{"title": "Death at a Funeral","year": 2010,"rating": 5.7,"votes": 38975,"running_times": 5520},{"title": "Death on the Nile","year": 1978,"rating": 7.3,"votes": 22145,"running_times": 8400},{"title": "Death to Smoochy","year": 2002,"rating": 6.4,"votes": 35983,"running_times": 6540},{"title": "Deathgasm","year": 2015,"rating": 6.3,"votes": 12177,"running_times": 5160},{"title": "December Boys","year": 2007,"rating": 6.6,"votes": 10972,"running_times": 6300},{"title": "Deception","year": 2008,"rating": 6.1,"votes": 34624,"running_times": 6420},{"title": "Deck the Halls","year": 2006,"rating": 4.9,"votes": 18286,"running_times": 5580},{"title": "Deconstructing Harry","year": 1997,"rating": 7.4,"votes": 38001,"running_times": 5760},{"title": "Deep Blue Sea","year": 1999,"rating": 5.8,"votes": 106958,"running_times": 6300},{"title": "Deep Impact","year": 1998,"rating": 6.1,"votes": 143093,"running_times": 7200},{"title": "Deep Rising","year": 1998,"rating": 6,"votes": 28323,"running_times": 6360},{"title": "Deepwater Horizon","year": 2016,"rating": 7.2,"votes": 110464,"running_times": 6420},{"title": "Defending Your Life","year": 1991,"rating": 7.3,"votes": 14660,"running_times": 6720},{"title": "Defendor","year": 2009,"rating": 6.8,"votes": 33008,"running_times": 6060},{"title": "Defiance","year": 2008,"rating": 7.2,"votes": 124297,"running_times": 9600},{"title": "Definitely, Maybe","year": 2008,"rating": 7.2,"votes": 136326,"running_times": 6720},{"title": "Deja Vu","year": 2006,"rating": 7,"votes": 260387,"running_times": 7560},{"title": "Delhi Belly","year": 2011,"rating": 7.6,"votes": 21588,"running_times": 6180},{"title": "Deliver Us from Evil","year": 2014,"rating": 6.2,"votes": 59445,"running_times": 7080},{"title": "Deliverance","year": 1972,"rating": 7.7,"votes": 84402,"running_times": 6540},{"title": "Delivery Man","year": 2013,"rating": 6.4,"votes": 65838,"running_times": 6300},{"title": "Dellamorte Dellamore","year": 1994,"rating": 7.3,"votes": 17402,"running_times": 6300},{"title": "Demain tout commence","year": 2016,"rating": 7.4,"votes": 10878,"running_times": 7080},{"title": "Demolition","year": 2015,"rating": 7,"votes": 66447,"running_times": 6060},{"title": "Demolition Man","year": 1993,"rating": 6.6,"votes": 135026,"running_times": 6900},{"title": "Demonic","year": 2015,"rating": 5.3,"votes": 10386,"running_times": 4980},{"title": "Den skaldede frisør","year": 2012,"rating": 6.6,"votes": 11148,"running_times": 6960},{"title": "Denial","year": 2016,"rating": 6.6,"votes": 11827,"running_times": 6540},{"title": "Dennis the Menace","year": 1993,"rating": 5.5,"votes": 47952,"running_times": 5640},{"title": "Der Baader Meinhof Komplex","year": 2008,"rating": 7.4,"votes": 31874,"running_times": 11040},{"title": "Der Himmel über Berlin","year": 1987,"rating": 8.1,"votes": 52212,"running_times": 7680},{"title": "Der Name der Rose","year": 1986,"rating": 7.8,"votes": 88129,"running_times": 7800},{"title": "Der amerikanische Freund","year": 1977,"rating": 7.4,"votes": 10256,"running_times": 7500},{"title": "Der blaue Engel","year": 1930,"rating": 7.8,"votes": 11350,"running_times": 6480},{"title": "Der rote Baron","year": 2008,"rating": 6.4,"votes": 10408,"running_times": 7740},{"title": "Derailed","year": 2005,"rating": 6.6,"votes": 65502,"running_times": 6720},{"title": "Desert Flower","year": 2009,"rating": 7.4,"votes": 10105,"running_times": 7200},{"title": "Desperado","year": 1995,"rating": 7.2,"votes": 149465,"running_times": 6240},{"title": "Desperate Measures","year": 1998,"rating": 6.1,"votes": 14560,"running_times": 6000},{"title": "Desperately Seeking Susan","year": 1985,"rating": 5.9,"votes": 17678,"running_times": 6240},{"title": "Despicable Me","year": 2010,"rating": 7.7,"votes": 427150,"running_times": 5700},{"title": "Despicable Me 2","year": 2013,"rating": 7.4,"votes": 317679,"running_times": 5880},{"title": "Despicable Me 3","year": 2017,"rating": 6.3,"votes": 58386,"running_times": 5400},{"title": "Detachment","year": 2011,"rating": 7.7,"votes": 63889,"running_times": 5880},{"title": "Detention","year": 2011,"rating": 5.8,"votes": 13464,"running_times": 5580},{"title": "Detour","year": 1945,"rating": 7.4,"votes": 11049,"running_times": 4080},{"title": "Detroit","year": 2017,"rating": 7.5,"votes": 16424,"running_times": 8580},{"title": "Detroit Rock City","year": 1999,"rating": 6.8,"votes": 31978,"running_times": 5700},{"title": "Deuce Bigalow: European Gigolo","year": 2005,"rating": 4.6,"votes": 43661,"running_times": 4980},{"title": "Deuce Bigalow: Male Gigolo","year": 1999,"rating": 5.7,"votes": 63262,"running_times": 5280},{"title": "Deux frères","year": 2004,"rating": 7.1,"votes": 12776,"running_times": 6540},{"title": "Deux jours, une nuit","year": 2014,"rating": 7.4,"votes": 37791,"running_times": 5700},{"title": "Dev.D","year": 2009,"rating": 8.1,"votes": 23620,"running_times": 8640},{"title": "Devil","year": 2010,"rating": 6.2,"votes": 113748,"running_times": 4800},{"title": "Devil in a Blue Dress","year": 1995,"rating": 6.7,"votes": 14584,"running_times": 6120},{"title": "Devil's Due","year": 2014,"rating": 4.1,"votes": 14846,"running_times": 5340},{"title": "Devil's Knot","year": 2013,"rating": 6.1,"votes": 16589,"running_times": 6840},{"title": "Dheepan","year": 2015,"rating": 7.2,"votes": 10267,"running_times": 6900},{"title": "Dhobi Ghat","year": 2010,"rating": 7.1,"votes": 10542,"running_times": 6000},{"title": "Dhoom:2","year": 2006,"rating": 6.4,"votes": 19515,"running_times": 9120},{"title": "Dhoom:3","year": 2013,"rating": 5.4,"votes": 37312,"running_times": 10320},{"title": "Diabolique","year": 1996,"rating": 5.3,"votes": 11767,"running_times": 6420},{"title": "Dial M for Murder","year": 1954,"rating": 8.2,"votes": 122214,"running_times": 6300},{"title": "Diamonds Are Forever","year": 1971,"rating": 6.7,"votes": 80479,"running_times": 7200},{"title": "Diana","year": 2013,"rating": 5.5,"votes": 16578,"running_times": 6780},{"title": "Diary of a Mad Black Woman","year": 2005,"rating": 5.7,"votes": 11236,"running_times": 6960},{"title": "Diary of a Wimpy Kid","year": 2010,"rating": 6.2,"votes": 35635,"running_times": 5640},{"title": "Diary of a Wimpy Kid: Dog Days","year": 2012,"rating": 6.3,"votes": 17804,"running_times": 5640},{"title": "Diary of a Wimpy Kid: Rodrick Rules","year": 2011,"rating": 6.6,"votes": 21150,"running_times": 5940},{"title": "Diary of the Dead","year": 2007,"rating": 5.7,"votes": 42623,"running_times": 5700},{"title": "Dick","year": 1999,"rating": 6.1,"votes": 16753,"running_times": 5640},{"title": "Dick Tracy","year": 1990,"rating": 6.1,"votes": 50794,"running_times": 6300},{"title": "Dickie Roberts: Former Child Star","year": 2003,"rating": 5.6,"votes": 12350,"running_times": 5880},{"title": "Did You Hear About the Morgans?","year": 2009,"rating": 4.8,"votes": 31932,"running_times": 6180},{"title": "Die Another Day","year": 2002,"rating": 6.1,"votes": 180923,"running_times": 7980},{"title": "Die Fälscher","year": 2007,"rating": 7.6,"votes": 38896,"running_times": 5880},{"title": "Die Hard","year": 1988,"rating": 8.2,"votes": 655576,"running_times": 7920},{"title": "Die Hard 2","year": 1990,"rating": 7.1,"votes": 291702,"running_times": 7440},{"title": "Die Hard with a Vengeance","year": 1995,"rating": 7.6,"votes": 320519,"running_times": 7680},{"title": "Die fetten Jahre sind vorbei","year": 2004,"rating": 7.5,"votes": 28388,"running_times": 7620},{"title": "Die unendliche Geschichte","year": 1984,"rating": 7.4,"votes": 109827,"running_times": 6120},{"title": "Dil Chahta Hai","year": 2001,"rating": 8.2,"votes": 55585,"running_times": 10980},{"title": "Dilwale Dulhania Le Jayenge","year": 1995,"rating": 8.2,"votes": 52081,"running_times": 11340},{"title": "Diner","year": 1982,"rating": 7.2,"votes": 16075,"running_times": 6600},{"title": "Dinner for Schmucks","year": 2010,"rating": 5.9,"votes": 85267,"running_times": 6840},{"title": "Dinosaur","year": 2000,"rating": 6.5,"votes": 42813,"running_times": 4920},{"title": "Dirty Dancing","year": 1987,"rating": 6.9,"votes": 158022,"running_times": 6000},{"title": "Dirty Dancing: Havana Nights","year": 2004,"rating": 6,"votes": 23751,"running_times": 5160},{"title": "Dirty Grandpa","year": 2016,"rating": 6,"votes": 85369,"running_times": 6540},{"title": "Dirty Harry","year": 1971,"rating": 7.8,"votes": 123351,"running_times": 6120},{"title": "Dirty Pretty Things","year": 2002,"rating": 7.4,"votes": 36840,"running_times": 5820},{"title": "Dirty Rotten Scoundrels","year": 1988,"rating": 7.3,"votes": 54644,"running_times": 6600},{"title": "Dirty Work","year": 1998,"rating": 6.4,"votes": 21069,"running_times": 4920},{"title": "Disaster Movie","year": 2008,"rating": 1.9,"votes": 78624,"running_times": 5280},{"title": "Disclosure","year": 1994,"rating": 6,"votes": 39560,"running_times": 7680},{"title": "Disconnect","year": 2012,"rating": 7.6,"votes": 66555,"running_times": 6900},{"title": "District 9","year": 2009,"rating": 8,"votes": 571695,"running_times": 6720},{"title": "Disturbia","year": 2007,"rating": 6.9,"votes": 197793,"running_times": 6300},{"title": "Disturbing Behavior","year": 1998,"rating": 5.5,"votes": 18430,"running_times": 5040},{"title": "Diva","year": 1981,"rating": 7.3,"votes": 10052,"running_times": 7020},{"title": "Divergent","year": 2014,"rating": 6.7,"votes": 374171,"running_times": 8340},{"title": "Divine Secrets of the Ya-Ya Sisterhood","year": 2002,"rating": 6,"votes": 16225,"running_times": 6960},{"title": "Django Unchained","year": 2012,"rating": 8.4,"votes": 1087375,"running_times": 9900},{"title": "Do the Right Thing","year": 1989,"rating": 7.9,"votes": 66608,"running_times": 7200},{"title": "Dobermann","year": 1997,"rating": 6.6,"votes": 15076,"running_times": 6180},{"title": "Doc Hollywood","year": 1991,"rating": 6.1,"votes": 27982,"running_times": 6240},{"title": "Doctor Dolittle","year": 1998,"rating": 5.3,"votes": 80924,"running_times": 5100},{"title": "Doctor Strange","year": 2016,"rating": 7.5,"votes": 369625,"running_times": 6900},{"title": "Doctor Zhivago","year": 1965,"rating": 8,"votes": 59974,"running_times": 12000},{"title": "Dodgeball: A True Underdog Story","year": 2004,"rating": 6.7,"votes": 200273,"running_times": 5520},{"title": "Dog Day Afternoon","year": 1975,"rating": 8,"votes": 201845,"running_times": 7860},{"title": "Dog Soldiers","year": 2002,"rating": 6.8,"votes": 48200,"running_times": 6300},{"title": "Doghouse","year": 2009,"rating": 6.1,"votes": 19400,"running_times": 5340},{"title": "Dogma","year": 1999,"rating": 7.3,"votes": 190705,"running_times": 7800},{"title": "Dogtown and Z-Boys","year": 2001,"rating": 7.7,"votes": 10986,"running_times": 5460},{"title": "Dogville","year": 2003,"rating": 8,"votes": 116919,"running_times": 10680},{"title": "Dolores Claiborne","year": 1995,"rating": 7.4,"votes": 31617,"running_times": 7920},{"title": "Dolphin Tale","year": 2011,"rating": 6.9,"votes": 19277,"running_times": 6780},{"title": "Dom Hemingway","year": 2013,"rating": 6.2,"votes": 23217,"running_times": 5580},{"title": "Dom za vesanje","year": 1988,"rating": 8.3,"votes": 20308,"running_times": 16200},{"title": "Domestic Disturbance","year": 2001,"rating": 5.5,"votes": 22329,"running_times": 5520},{"title": "Domino","year": 2005,"rating": 6,"votes": 60282,"running_times": 7620},{"title": "Don 2","year": 2011,"rating": 7.1,"votes": 43541,"running_times": 8880},{"title": "Don Jon","year": 2013,"rating": 6.6,"votes": 205177,"running_times": 5400},{"title": "Don Juan DeMarco","year": 1994,"rating": 6.7,"votes": 43768,"running_times": 5820},{"title": "Don't Be Afraid of the Dark","year": 2010,"rating": 5.6,"votes": 42818,"running_times": 5940},{"title": "Don't Be a Menace to South Central While Drinking Your Juice in the Hood","year": 1996,"rating": 6.6,"votes": 41316,"running_times": 5640},{"title": "Don't Breathe","year": 2016,"rating": 7.1,"votes": 147018,"running_times": 5280},{"title": "Don't Look Now","year": 1973,"rating": 7.3,"votes": 38356,"running_times": 6600},{"title": "Don't Say a Word","year": 2001,"rating": 6.3,"votes": 42979,"running_times": 6780},{"title": "Don't Tell Mom the Babysitter's Dead","year": 1991,"rating": 6.1,"votes": 23305,"running_times": 6120},{"title": "Don't Think Twice","year": 2016,"rating": 6.8,"votes": 12772,"running_times": 5520},{"title": "Donnie Brasco","year": 1997,"rating": 7.8,"votes": 241674,"running_times": 8820},{"title": "Donnie Darko","year": 2001,"rating": 8.1,"votes": 644118,"running_times": 7980},{"title": "Doodlebug","year": 1997,"rating": 7.1,"votes": 13264,"running_times": 180},{"title": "Doom","year": 2005,"rating": 5.2,"votes": 93106,"running_times": 6780},{"title": "Doomsday","year": 2008,"rating": 6,"votes": 65892,"running_times": 6780},{"title": "Dope","year": 2015,"rating": 7.2,"votes": 70696,"running_times": 6180},{"title": "Dorian Gray","year": 2009,"rating": 6.3,"votes": 55011,"running_times": 6720},{"title": "Dostana","year": 2008,"rating": 6.5,"votes": 11858,"running_times": 8700},{"title": "Dou fo sin","year": 2007,"rating": 6.8,"votes": 11247,"running_times": 5280},{"title": "Double Impact","year": 1991,"rating": 5.5,"votes": 31989,"running_times": 6600},{"title": "Double Indemnity","year": 1944,"rating": 8.3,"votes": 110821,"running_times": 6600},{"title": "Double Jeopardy","year": 1999,"rating": 6.4,"votes": 60879,"running_times": 6300},{"title": "Double Team","year": 1997,"rating": 4.7,"votes": 27220,"running_times": 5580},{"title": "Doubt","year": 2008,"rating": 7.5,"votes": 106866,"running_times": 6240},{"title": "Down Periscope","year": 1996,"rating": 6,"votes": 18230,"running_times": 5520},{"title": "Down and Out in Beverly Hills","year": 1986,"rating": 6.1,"votes": 13684,"running_times": 6180},{"title": "Down by Law","year": 1986,"rating": 7.8,"votes": 39932,"running_times": 6420},{"title": "Down in the Valley","year": 2005,"rating": 6.4,"votes": 17043,"running_times": 6840},{"title": "Down to Earth","year": 2001,"rating": 5.4,"votes": 19850,"running_times": 5220},{"title": "Down to You","year": 2000,"rating": 4.9,"votes": 12954,"running_times": 5460},{"title": "Down with Love","year": 2003,"rating": 6.3,"votes": 35365,"running_times": 6060},{"title": "Dr. Dolittle 2","year": 2001,"rating": 4.7,"votes": 36568,"running_times": 5220},{"title": "Dr. Jekyll and Mr. Hyde","year": 1931,"rating": 7.7,"votes": 10414,"running_times": 5880},{"title": "Dr. No","year": 1962,"rating": 7.3,"votes": 125450,"running_times": 6600},{"title": "Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb","year": 1964,"rating": 8.5,"votes": 379103,"running_times": 5700},{"title": "Dr. T & the Women","year": 2000,"rating": 4.6,"votes": 16257,"running_times": 7320},{"title": "Dracula","year": 1931,"rating": 7.6,"votes": 37354,"running_times": 4500},{"title": "Dracula","year": 1958,"rating": 7.4,"votes": 17052,"running_times": 4920},{"title": "Dracula","year": 1992,"rating": 7.5,"votes": 158038,"running_times": 9300},{"title": "Dracula 2000","year": 2000,"rating": 4.9,"votes": 28908,"running_times": 5940},{"title": "Dracula Untold","year": 2014,"rating": 6.3,"votes": 153899,"running_times": 5520},{"title": "Dracula: Dead and Loving It","year": 1995,"rating": 5.8,"votes": 33009,"running_times": 5280},{"title": "Draft Day","year": 2014,"rating": 6.8,"votes": 44200,"running_times": 6600},{"title": "Drag Me to Hell","year": 2009,"rating": 6.6,"votes": 168087,"running_times": 5940},{"title": "Dragnet","year": 1987,"rating": 5.9,"votes": 27668,"running_times": 6360},{"title": "Dragon: The Bruce Lee Story","year": 1993,"rating": 7,"votes": 23689,"running_times": 7200},{"title": "DragonHeart","year": 1996,"rating": 6.4,"votes": 82651,"running_times": 6180},{"title": "Dragonball Evolution","year": 2009,"rating": 2.6,"votes": 61559,"running_times": 6000},{"title": "Dragonfly","year": 2002,"rating": 6.1,"votes": 33351,"running_times": 6240},{"title": "Dragonslayer","year": 1981,"rating": 6.7,"votes": 11944,"running_times": 6540},{"title": "Dread","year": 2009,"rating": 5.7,"votes": 10792,"running_times": 6480},{"title": "Dream House","year": 2011,"rating": 6,"votes": 55422,"running_times": 5040},{"title": "Dreamcatcher","year": 2003,"rating": 5.5,"votes": 80773,"running_times": 8160},{"title": "Dreamer: Inspired by a True Story","year": 2005,"rating": 6.9,"votes": 10701,"running_times": 6360},{"title": "Dreamgirls","year": 2006,"rating": 6.5,"votes": 60700,"running_times": 8400},{"title": "Dreamscape","year": 1984,"rating": 6.3,"votes": 11483,"running_times": 5940},{"title": "Dredd","year": 2012,"rating": 7.1,"votes": 220351,"running_times": 5700},{"title": "Dressed to Kill","year": 1980,"rating": 7.1,"votes": 27122,"running_times": 6300},{"title": "Drillbit Taylor","year": 2008,"rating": 5.7,"votes": 52903,"running_times": 6600},{"title": "Drinking Buddies","year": 2013,"rating": 6.1,"votes": 50184,"running_times": 5400},{"title": "Drive","year": 2011,"rating": 7.8,"votes": 480193,"running_times": 6000},{"title": "Drive Angry","year": 2011,"rating": 5.4,"votes": 86046,"running_times": 6240},{"title": "Drive Me Crazy","year": 1999,"rating": 5.7,"votes": 15979,"running_times": 5460},{"title": "Driven","year": 2001,"rating": 4.5,"votes": 35985,"running_times": 6960},{"title": "Driving Miss Daisy","year": 1989,"rating": 7.4,"votes": 80605,"running_times": 5940},{"title": "Drop Dead Fred","year": 1991,"rating": 5.8,"votes": 23342,"running_times": 6180},{"title": "Drop Dead Gorgeous","year": 1999,"rating": 6.6,"votes": 28622,"running_times": 5820},{"title": "Drop Zone","year": 1994,"rating": 5.6,"votes": 16935,"running_times": 6060},{"title": "Drowning Mona","year": 2000,"rating": 5.6,"votes": 12216,"running_times": 5760},{"title": "Drugstore Cowboy","year": 1989,"rating": 7.4,"votes": 27237,"running_times": 6120},{"title": "Drumline","year": 2002,"rating": 5.7,"votes": 29808,"running_times": 7080},{"title": "Du rififi chez les hommes","year": 1955,"rating": 8.2,"votes": 20796,"running_times": 7080},{"title": "Duck Soup","year": 1933,"rating": 8,"votes": 49627,"running_times": 4080},{"title": "DuckTales the Movie: Treasure of the Lost Lamp","year": 1990,"rating": 6.9,"votes": 21820,"running_times": 4440},{"title": "Dude, Where's My Car?","year": 2000,"rating": 5.5,"votes": 122824,"running_times": 4980},{"title": "Due Date","year": 2010,"rating": 6.6,"votes": 288907,"running_times": 5700},{"title": "Dumb and Dumber","year": 1994,"rating": 7.3,"votes": 309873,"running_times": 6780},{"title": "Dumb and Dumber To","year": 2014,"rating": 5.6,"votes": 108504,"running_times": 6540},{"title": "Dumb and Dumberer: When Harry Met Lloyd","year": 2003,"rating": 3.4,"votes": 32270,"running_times": 5100},{"title": "Dumbo","year": 1941,"rating": 7.3,"votes": 96388,"running_times": 3840},{"title": "Dune","year": 1984,"rating": 6.6,"votes": 104438,"running_times": 11400},{"title": "Dungeons & Dragons","year": 2000,"rating": 3.7,"votes": 28833,"running_times": 6420},{"title": "Dunkirk","year": 2017,"rating": 8.2,"votes": 274342,"running_times": 6360},{"title": "Dunston Checks In","year": 1996,"rating": 5.3,"votes": 10452,"running_times": 5280},{"title": "Duplex","year": 2003,"rating": 5.9,"votes": 49293,"running_times": 5340},{"title": "Duplicity","year": 2009,"rating": 6.2,"votes": 43403,"running_times": 7500},{"title": "Dutch","year": 1991,"rating": 6.4,"votes": 10177,"running_times": 6420},{"title": "Dying Young","year": 1991,"rating": 5.9,"votes": 12716,"running_times": 6660},{"title": "Dylan Dog: Dead of Night","year": 2010,"rating": 5.1,"votes": 13629,"running_times": 6420},{"title": "Dèmoni","year": 1985,"rating": 6.7,"votes": 16120,"running_times": 5280},{"title": "Død snø 2","year": 2014,"rating": 6.9,"votes": 18637,"running_times": 6000},{"title": "E.T. the Extra-Terrestrial","year": 1982,"rating": 7.9,"votes": 309754,"running_times": 7200},{"title": "Eagle Eye","year": 2008,"rating": 6.6,"votes": 159498,"running_times": 7080},{"title": "Eagle vs Shark","year": 2007,"rating": 6.8,"votes": 18542,"running_times": 5580},{"title": "Earth","year": 2007,"rating": 8,"votes": 13297,"running_times": 5760},{"title": "Earth Girls Are Easy","year": 1988,"rating": 5.2,"votes": 17480,"running_times": 6000},{"title": "Earth to Echo","year": 2014,"rating": 5.8,"votes": 16868,"running_times": 5460},{"title": "Earthlings","year": 2005,"rating": 8.7,"votes": 14644,"running_times": 5700},{"title": "Earthquake","year": 1974,"rating": 5.8,"votes": 11463,"running_times": 9600},{"title": "East Is East","year": 1999,"rating": 6.9,"votes": 15380,"running_times": 5760},{"title": "East of Eden","year": 1955,"rating": 8,"votes": 33398,"running_times": 7080},{"title": "Eastern Promises","year": 2007,"rating": 7.7,"votes": 203215,"running_times": 6000},{"title": "Easy A","year": 2010,"rating": 7.1,"votes": 305254,"running_times": 5520},{"title": "Easy Rider","year": 1969,"rating": 7.4,"votes": 81753,"running_times": 5700},{"title": "Easy Virtue","year": 2008,"rating": 6.7,"votes": 17839,"running_times": 5820},{"title": "Eat Pray Love","year": 2010,"rating": 5.7,"votes": 70716,"running_times": 8400},{"title": "Echelon Conspiracy","year": 2009,"rating": 5.8,"votes": 17641,"running_times": 6300},{"title": "Ed Wood","year": 1994,"rating": 7.9,"votes": 150437,"running_times": 7620},{"title": "Eddie Murphy: Raw","year": 1987,"rating": 7.6,"votes": 16140,"running_times": 5580},{"title": "Eddie the Eagle","year": 2016,"rating": 7.4,"votes": 62469,"running_times": 6360},{"title": "Eden Lake","year": 2008,"rating": 6.8,"votes": 64341,"running_times": 5460},{"title": "Edge of Darkness","year": 2010,"rating": 6.6,"votes": 80466,"running_times": 7020},{"title": "Edge of Tomorrow","year": 2014,"rating": 7.9,"votes": 494688,"running_times": 6780},{"title": "Edison","year": 2005,"rating": 5.3,"votes": 13825,"running_times": 5940},{"title": "Edmond","year": 2005,"rating": 6.3,"votes": 10303,"running_times": 4920},{"title": "Edtv","year": 1999,"rating": 6.1,"votes": 37443,"running_times": 7320},{"title": "Educating Rita","year": 1983,"rating": 7.2,"votes": 10465,"running_times": 6600},{"title": "Edward Scissorhands","year": 1990,"rating": 7.9,"votes": 388885,"running_times": 6300},{"title": "Efter brylluppet","year": 2006,"rating": 7.8,"votes": 27865,"running_times": 7200},{"title": "Eight Below","year": 2006,"rating": 7.3,"votes": 52915,"running_times": 7200},{"title": "Eight Crazy Nights","year": 2002,"rating": 5.3,"votes": 19215,"running_times": 4560},{"title": "Eight Legged Freaks","year": 2002,"rating": 5.4,"votes": 46740,"running_times": 5940},{"title": "Eight Men Out","year": 1988,"rating": 7.3,"votes": 16091,"running_times": 7140},{"title": "Ek Tha Tiger","year": 2012,"rating": 5.4,"votes": 23349,"running_times": 7920},{"title": "El Cid","year": 1961,"rating": 7.3,"votes": 10715,"running_times": 10920},{"title": "El Dorado","year": 1967,"rating": 7.6,"votes": 19689,"running_times": 7560},{"title": "El abrazo de la serpiente","year": 2015,"rating": 7.9,"votes": 14165,"running_times": 7500},{"title": "Election","year": 1999,"rating": 7.3,"votes": 78350,"running_times": 6180},{"title": "Elegy","year": 2008,"rating": 6.8,"votes": 20349,"running_times": 6720},{"title": "Elektra","year": 2005,"rating": 4.8,"votes": 76634,"running_times": 6000},{"title": "Elephant","year": 2003,"rating": 7.2,"votes": 75743,"running_times": 4860},{"title": "Elf","year": 2003,"rating": 6.9,"votes": 166818,"running_times": 5820},{"title": "Eliza Graves","year": 2014,"rating": 6.8,"votes": 41308,"running_times": 6720},{"title": "Elizabeth","year": 1998,"rating": 7.5,"votes": 80820,"running_times": 7440},{"title": "Elizabeth: The Golden Age","year": 2007,"rating": 6.9,"votes": 58559,"running_times": 6840},{"title": "Elizabethtown","year": 2005,"rating": 6.4,"votes": 61503,"running_times": 7380},{"title": "Ella Enchanted","year": 2004,"rating": 6.3,"votes": 52416,"running_times": 5760},{"title": "Elle s'appelait Sarah","year": 2010,"rating": 7.5,"votes": 14100,"running_times": 6660},{"title": "Elvis & Nixon","year": 2016,"rating": 6.4,"votes": 10328,"running_times": 5160},{"title": "Elysium","year": 2013,"rating": 6.6,"votes": 370766,"running_times": 6540},{"title": "Emergo","year": 2011,"rating": 5.1,"votes": 10158,"running_times": 4800},{"title": "Emma","year": 1996,"rating": 6.7,"votes": 30394,"running_times": 7200},{"title": "Emperor","year": 2012,"rating": 6.5,"votes": 11452,"running_times": 6300},{"title": "Empire Records","year": 1995,"rating": 6.7,"votes": 41332,"running_times": 6420},{"title": "Empire State","year": 2013,"rating": 5.2,"votes": 16319,"running_times": 5640},{"title": "Empire of the Sun","year": 1987,"rating": 7.8,"votes": 97960,"running_times": 9180},{"title": "Employee of the Month","year": 2006,"rating": 5.5,"votes": 39579,"running_times": 6180},{"title": "En duva satt på en gren och funderade på tillvaron","year": 2014,"rating": 7,"votes": 12501,"running_times": 6060},{"title": "En kongelig affære","year": 2012,"rating": 7.6,"votes": 37904,"running_times": 8220},{"title": "Enchanted","year": 2007,"rating": 7.1,"votes": 154524,"running_times": 6420},{"title": "Encino Man","year": 1992,"rating": 5.7,"votes": 32299,"running_times": 5280},{"title": "Encounters at the End of the World","year": 2007,"rating": 7.8,"votes": 15121,"running_times": 5940},{"title": "End of Days","year": 1999,"rating": 5.7,"votes": 94909,"running_times": 7260},{"title": "End of Watch","year": 2012,"rating": 7.7,"votes": 198682,"running_times": 6540},{"title": "Ender's Game","year": 2013,"rating": 6.7,"votes": 199409,"running_times": 6840},{"title": "Endless Love","year": 2014,"rating": 6.3,"votes": 35053,"running_times": 6240},{"title": "Enemy","year": 2013,"rating": 6.9,"votes": 121880,"running_times": 5460},{"title": "Enemy Mine","year": 1985,"rating": 6.9,"votes": 37013,"running_times": 6480},{"title": "Enemy at the Gates","year": 2001,"rating": 7.6,"votes": 208107,"running_times": 7860},{"title": "Enemy of the State","year": 1998,"rating": 7.3,"votes": 201476,"running_times": 8400},{"title": "English Vinglish","year": 2012,"rating": 7.9,"votes": 26437,"running_times": 8040},{"title": "Enigma","year": 2001,"rating": 6.4,"votes": 18513,"running_times": 7140},{"title": "Enough","year": 2002,"rating": 5.7,"votes": 33306,"running_times": 6900},{"title": "Enough Said","year": 2013,"rating": 7.1,"votes": 52803,"running_times": 5580},{"title": "Enron: The Smartest Guys in the Room","year": 2005,"rating": 7.7,"votes": 13946,"running_times": 6600},{"title": "Enter the Dragon","year": 1973,"rating": 7.7,"votes": 83111,"running_times": 6120},{"title": "Enter the Void","year": 2009,"rating": 7.3,"votes": 52921,"running_times": 9660},{"title": "Entourage","year": 2015,"rating": 6.6,"votes": 67060,"running_times": 6240},{"title": "Entrapment","year": 1999,"rating": 6.3,"votes": 94568,"running_times": 6780},{"title": "Envy","year": 2004,"rating": 4.8,"votes": 27619,"running_times": 5940},{"title": "Epic","year": 2013,"rating": 6.7,"votes": 91102,"running_times": 6120},{"title": "Epic Movie","year": 2007,"rating": 2.3,"votes": 94044,"running_times": 5580},{"title": "Equals","year": 2015,"rating": 6,"votes": 19497,"running_times": 6060},{"title": "Equilibrium","year": 2002,"rating": 7.5,"votes": 280173,"running_times": 6420},{"title": "Eragon","year": 2006,"rating": 5.1,"votes": 112989,"running_times": 6240},{"title": "Erased","year": 2012,"rating": 6.1,"votes": 25184,"running_times": 6000},{"title": "Eraser","year": 1996,"rating": 6.1,"votes": 90788,"running_times": 6900},{"title": "Eraserhead","year": 1977,"rating": 7.4,"votes": 80638,"running_times": 5340},{"title": "Erik the Viking","year": 1989,"rating": 6.2,"votes": 11535,"running_times": 6420},{"title": "Erin Brockovich","year": 2000,"rating": 7.3,"votes": 147095,"running_times": 7860},{"title": "Escape Plan","year": 2013,"rating": 6.7,"votes": 194559,"running_times": 6900},{"title": "Escape from Alcatraz","year": 1979,"rating": 7.6,"votes": 95509,"running_times": 6720},{"title": "Escape from L.A.","year": 1996,"rating": 5.7,"votes": 59275,"running_times": 6060},{"title": "Escape from New York","year": 1981,"rating": 7.2,"votes": 101894,"running_times": 6360},{"title": "Escape from Planet Earth","year": 2013,"rating": 5.9,"votes": 22083,"running_times": 5340},{"title": "Escape from the Planet of the Apes","year": 1971,"rating": 6.3,"votes": 26898,"running_times": 5880},{"title": "Escobar: Paradise Lost","year": 2014,"rating": 6.5,"votes": 17217,"running_times": 7200},{"title": "Eternal Sunshine of the Spotless Mind","year": 2004,"rating": 8.3,"votes": 746335,"running_times": 6480},{"title": "EuroTrip","year": 2004,"rating": 6.6,"votes": 172986,"running_times": 5520},{"title": "Europa","year": 1991,"rating": 7.7,"votes": 17049,"running_times": 6720},{"title": "Europa Report","year": 2013,"rating": 6.5,"votes": 58836,"running_times": 5820},{"title": "Evan Almighty","year": 2007,"rating": 5.4,"votes": 122445,"running_times": 5760},{"title": "Evening","year": 2007,"rating": 6.6,"votes": 12168,"running_times": 7020},{"title": "Event Horizon","year": 1997,"rating": 6.7,"votes": 132242,"running_times": 7800},{"title": "EverAfter","year": 1998,"rating": 7,"votes": 61506,"running_times": 7260},{"title": "Everest","year": 2015,"rating": 7.1,"votes": 163956,"running_times": 7260},{"title": "Everly","year": 2014,"rating": 5.1,"votes": 14426,"running_times": 5520},{"title": "Every Which Way But Loose","year": 1978,"rating": 6.3,"votes": 19104,"running_times": 6840},{"title": "Everybody Wants Some!!","year": 2016,"rating": 7,"votes": 41481,"running_times": 7020},{"title": "Everybody's Fine","year": 2009,"rating": 7.1,"votes": 53263,"running_times": 5940},{"title": "Everyone Says I Love You","year": 1996,"rating": 6.8,"votes": 31978,"running_times": 6060},{"title": "Everything Is Illuminated","year": 2005,"rating": 7.5,"votes": 53082,"running_times": 6360},{"title": "Everything Must Go","year": 2010,"rating": 6.4,"votes": 43647,"running_times": 5820},{"title": "Everything You Always Wanted to Know About Sex * But Were Afraid to Ask","year": 1972,"rating": 6.8,"votes": 33803,"running_times": 5280},{"title": "Everything, Everything","year": 2017,"rating": 6.4,"votes": 14421,"running_times": 5760},{"title": "Evil Dead","year": 2013,"rating": 6.5,"votes": 137348,"running_times": 5820},{"title": "Evil Dead II","year": 1987,"rating": 7.8,"votes": 125028,"running_times": 5460},{"title": "Evil Under the Sun","year": 1982,"rating": 7,"votes": 10493,"running_times": 7020},{"title": "Evita","year": 1996,"rating": 6.3,"votes": 30668,"running_times": 8100},{"title": "Evolution","year": 2001,"rating": 6.1,"votes": 107448,"running_times": 6060},{"title": "Ex Machina","year": 2014,"rating": 7.7,"votes": 364240,"running_times": 6480},{"title": "Exam","year": 2009,"rating": 6.9,"votes": 84658,"running_times": 6060},{"title": "Excalibur","year": 1981,"rating": 7.4,"votes": 50072,"running_times": 8400},{"title": "Excess Baggage","year": 1997,"rating": 5.3,"votes": 11451,"running_times": 6060},{"title": "Excision","year": 2012,"rating": 6.1,"votes": 17447,"running_times": 4860},{"title": "Executive Decision","year": 1996,"rating": 6.4,"votes": 43820,"running_times": 7980},{"title": "Exit Through the Gift Shop","year": 2010,"rating": 8,"votes": 55428,"running_times": 5220},{"title": "Exit Wounds","year": 2001,"rating": 5.5,"votes": 28944,"running_times": 6060},{"title": "Exodus: Gods and Kings","year": 2014,"rating": 6,"votes": 141750,"running_times": 9000},{"title": "Exorcist II: The Heretic","year": 1977,"rating": 3.7,"votes": 17846,"running_times": 7080},{"title": "Exorcist: The Beginning","year": 2004,"rating": 5.1,"votes": 30144,"running_times": 7500},{"title": "Exotica","year": 1994,"rating": 7.1,"votes": 15581,"running_times": 6180},{"title": "Expelled: No Intelligence Allowed","year": 2008,"rating": 3.7,"votes": 11451,"running_times": 5820},{"title": "Experimenter","year": 2015,"rating": 6.6,"votes": 13685,"running_times": 5880},{"title": "Explorers","year": 1985,"rating": 6.6,"votes": 16258,"running_times": 6540},{"title": "Extinction","year": 2015,"rating": 5.8,"votes": 13381,"running_times": 6720},{"title": "Extract","year": 2009,"rating": 6.2,"votes": 39751,"running_times": 5520},{"title": "Extracted","year": 2012,"rating": 6.5,"votes": 10716,"running_times": 5100},{"title": "Extraordinary Measures","year": 2010,"rating": 6.5,"votes": 15069,"running_times": 6360},{"title": "Extraterrestrial","year": 2014,"rating": 5,"votes": 12754,"running_times": 6060},{"title": "Extreme Measures","year": 1996,"rating": 6.1,"votes": 14967,"running_times": 7080},{"title": "Extremely Loud & Incredibly Close","year": 2011,"rating": 6.9,"votes": 88270,"running_times": 7740},{"title": "Eye for an Eye","year": 1996,"rating": 6.1,"votes": 11091,"running_times": 6060},{"title": "Eye in the Sky","year": 2015,"rating": 7.3,"votes": 63254,"running_times": 6120},{"title": "Eye of the Beholder","year": 1999,"rating": 4.9,"votes": 13722,"running_times": 6540},{"title": "Eyes Wide Shut","year": 1999,"rating": 7.4,"votes": 249671,"running_times": 9540},{"title": "F for Fake","year": 1973,"rating": 7.8,"votes": 11788,"running_times": 5340},{"title": "F/X","year": 1986,"rating": 6.7,"votes": 14697,"running_times": 6540},{"title": "Face/Off","year": 1997,"rating": 7.3,"votes": 304712,"running_times": 8280},{"title": "Faces in the Crowd","year": 2011,"rating": 5.8,"votes": 16738,"running_times": 6180},{"title": "Facing the Giants","year": 2006,"rating": 6.7,"votes": 13404,"running_times": 6660},{"title": "Factory Girl","year": 2006,"rating": 6.4,"votes": 19330,"running_times": 5940},{"title": "Factotum","year": 2005,"rating": 6.6,"votes": 12632,"running_times": 5640},{"title": "Fading Gigolo","year": 2013,"rating": 6.2,"votes": 21136,"running_times": 5400},{"title": "Fahrenheit 451","year": 1966,"rating": 7.3,"votes": 35599,"running_times": 6720},{"title": "Fahrenheit 9/11","year": 2004,"rating": 7.5,"votes": 118010,"running_times": 7320},{"title": "Fail-Safe","year": 1964,"rating": 8,"votes": 16325,"running_times": 6720},{"title": "Failure to Launch","year": 2006,"rating": 5.6,"votes": 62881,"running_times": 5820},{"title": "Fair Game","year": 1995,"rating": 4.2,"votes": 10737,"running_times": 5460},{"title": "Fair Game","year": 2010,"rating": 6.8,"votes": 41205,"running_times": 6480},{"title": "Fallen","year": 1998,"rating": 7,"votes": 63656,"running_times": 7440},{"title": "Falling Down","year": 1993,"rating": 7.6,"votes": 145355,"running_times": 6780},{"title": "Falling in Love","year": 1984,"rating": 6.5,"votes": 10477,"running_times": 6360},{"title": "Fame","year": 1980,"rating": 6.6,"votes": 17572,"running_times": 8040},{"title": "Fame","year": 2009,"rating": 5,"votes": 14795,"running_times": 7380},{"title": "Family Business","year": 1989,"rating": 5.7,"votes": 10321,"running_times": 6600},{"title": "Family Plot","year": 1976,"rating": 6.8,"votes": 17005,"running_times": 7200},{"title": "Fanboys","year": 2009,"rating": 6.6,"votes": 52152,"running_times": 5400},{"title": "Fanny och Alexander","year": 1982,"rating": 8.1,"votes": 46972,"running_times": 18720},{"title": "Fantasia","year": 1940,"rating": 7.8,"votes": 77065,"running_times": 7500},{"title": "Fantasia 2000","year": 1999,"rating": 7.2,"votes": 29995,"running_times": 4500},{"title": "Fantastic Beasts and Where to Find Them","year": 2016,"rating": 7.4,"votes": 282792,"running_times": 7980},{"title": "Fantastic Four","year": 2005,"rating": 5.7,"votes": 282206,"running_times": 7500},{"title": "Fantastic Four","year": 2015,"rating": 4.3,"votes": 127702,"running_times": 6000},{"title": "Fantastic Mr. Fox","year": 2009,"rating": 7.8,"votes": 156778,"running_times": 5220},{"title": "Fantastic Voyage","year": 1966,"rating": 6.8,"votes": 14347,"running_times": 6000},{"title": "Far Cry","year": 2008,"rating": 3.1,"votes": 11917,"running_times": 5700},{"title": "Far and Away","year": 1992,"rating": 6.5,"votes": 51351,"running_times": 8400},{"title": "Far from Heaven","year": 2002,"rating": 7.4,"votes": 38810,"running_times": 6420},{"title": "Far from the Madding Crowd","year": 2015,"rating": 7.1,"votes": 36905,"running_times": 7140},{"title": "Fargo","year": 1996,"rating": 8.1,"votes": 507798,"running_times": 5880},{"title": "Fasandræberne","year": 2014,"rating": 7.1,"votes": 12548,"running_times": 7140},{"title": "Fast & Furious","year": 2009,"rating": 6.6,"votes": 225507,"running_times": 6420},{"title": "Fast Five","year": 2011,"rating": 7.3,"votes": 310070,"running_times": 7920},{"title": "Fast Food Nation","year": 2006,"rating": 6.3,"votes": 21840,"running_times": 6960},{"title": "Fast Times at Ridgemont High","year": 1982,"rating": 7.2,"votes": 78461,"running_times": 5400},{"title": "Fast Track","year": 2006,"rating": 5.5,"votes": 15704,"running_times": 5700},{"title": "Faster","year": 2010,"rating": 6.5,"votes": 86086,"running_times": 5880},{"title": "Faster, Pussycat! Kill! Kill!","year": 1965,"rating": 6.8,"votes": 11707,"running_times": 4980},{"title": "Fatal Attraction","year": 1987,"rating": 6.9,"votes": 61185,"running_times": 7140},{"title": "Father of the Bride","year": 1991,"rating": 6.5,"votes": 59093,"running_times": 6300},{"title": "Father of the Bride Part II","year": 1995,"rating": 5.9,"votes": 28927,"running_times": 6360},{"title": "Fathers & Daughters","year": 2015,"rating": 7.1,"votes": 17840,"running_times": 6960},{"title": "Fathers' Day","year": 1997,"rating": 5.1,"votes": 12966,"running_times": 5880},{"title": "Fear","year": 1996,"rating": 6.2,"votes": 34409,"running_times": 5820},{"title": "Fear and Loathing in Las Vegas","year": 1998,"rating": 7.7,"votes": 228574,"running_times": 7080},{"title": "Feardotcom","year": 2002,"rating": 3.3,"votes": 17929,"running_times": 6060},{"title": "Fearless","year": 1993,"rating": 7.1,"votes": 18784,"running_times": 7320},{"title": "Feast","year": 2005,"rating": 6.4,"votes": 26881,"running_times": 5700},{"title": "Feast","year": 2014,"rating": 8.3,"votes": 20154,"running_times": 360},{"title": "Feast of Love","year": 2007,"rating": 6.7,"votes": 14876,"running_times": 5820},{"title": "Fehér isten","year": 2014,"rating": 6.9,"votes": 12224,"running_times": 7260},{"title": "Felon","year": 2008,"rating": 7.5,"votes": 69677,"running_times": 6240},{"title": "Femme Fatale","year": 2002,"rating": 6.3,"votes": 30192,"running_times": 6840},{"title": "Fences","year": 2016,"rating": 7.2,"votes": 67254,"running_times": 8340},{"title": "FernGully: The Last Rainforest","year": 1992,"rating": 6.5,"votes": 22799,"running_times": 4560},{"title": "Ferris Bueller's Day Off","year": 1986,"rating": 7.8,"votes": 267726,"running_times": 6180},{"title": "Festen","year": 1998,"rating": 8.1,"votes": 69948,"running_times": 6300},{"title": "Fever Pitch","year": 2005,"rating": 6.2,"votes": 38133,"running_times": 6240},{"title": "Fiddler on the Roof","year": 1971,"rating": 8,"votes": 32288,"running_times": 10860},{"title": "Fido","year": 2006,"rating": 6.7,"votes": 26218,"running_times": 5580},{"title": "Field of Dreams","year": 1989,"rating": 7.5,"votes": 92902,"running_times": 6420},{"title": "Fierce Creatures","year": 1997,"rating": 6.4,"votes": 20671,"running_times": 5580},{"title": "Fifty Dead Men Walking","year": 2008,"rating": 6.9,"votes": 10022,"running_times": 7020},{"title": "Fifty Shades Darker","year": 2017,"rating": 4.6,"votes": 60766,"running_times": 7860},{"title": "Fifty Shades of Black","year": 2016,"rating": 3.5,"votes": 14489,"running_times": 5520},{"title": "Fifty Shades of Grey","year": 2015,"rating": 4.1,"votes": 253284,"running_times": 7740},{"title": "Fight Club","year": 1999,"rating": 8.8,"votes": 1513600,"running_times": 9060},{"title": "Fighting","year": 2009,"rating": 5.6,"votes": 29246,"running_times": 6300},{"title": "Filth","year": 2013,"rating": 7.1,"votes": 85698,"running_times": 5820},{"title": "Final Analysis","year": 1992,"rating": 5.8,"votes": 11587,"running_times": 7440},{"title": "Final Destination","year": 2000,"rating": 6.7,"votes": 196574,"running_times": 5880},{"title": "Final Destination 2","year": 2003,"rating": 6.2,"votes": 130693,"running_times": 5400},{"title": "Final Destination 3","year": 2006,"rating": 5.8,"votes": 111829,"running_times": 5580},{"title": "Final Destination 5","year": 2011,"rating": 5.9,"votes": 90949,"running_times": 5520},{"title": "Final Fantasy: The Spirits Within","year": 2001,"rating": 6.4,"votes": 75791,"running_times": 6360},{"title": "Final Girl","year": 2015,"rating": 4.7,"votes": 10302,"running_times": 5400},{"title": "Find Me Guilty","year": 2006,"rating": 7.1,"votes": 29806,"running_times": 7500},{"title": "Finding Dory","year": 2016,"rating": 7.4,"votes": 179302,"running_times": 5820},{"title": "Finding Forrester","year": 2000,"rating": 7.3,"votes": 76078,"running_times": 8160},{"title": "Finding Nemo","year": 2003,"rating": 8.1,"votes": 782783,"running_times": 6000},{"title": "Finding Neverland","year": 2004,"rating": 7.7,"votes": 183400,"running_times": 6360},{"title": "Finding Vivian Maier","year": 2013,"rating": 7.7,"votes": 10672,"running_times": 4980},{"title": "Fire Down Below","year": 1997,"rating": 5,"votes": 14680,"running_times": 6300},{"title": "Fire in the Sky","year": 1993,"rating": 6.5,"votes": 17724,"running_times": 6540},{"title": "Fire with Fire","year": 2012,"rating": 5.7,"votes": 22378,"running_times": 5820},{"title": "Fired Up!","year": 2009,"rating": 6.2,"votes": 39156,"running_times": 5460},{"title": "Fireflies in the Garden","year": 2008,"rating": 6.5,"votes": 11372,"running_times": 7200},{"title": "Firefox","year": 1982,"rating": 5.9,"votes": 21537,"running_times": 8160},{"title": "Fireproof","year": 2008,"rating": 6.6,"votes": 18427,"running_times": 7320},{"title": "Firestarter","year": 1984,"rating": 6,"votes": 24912,"running_times": 6840},{"title": "Firewall","year": 2006,"rating": 5.8,"votes": 52024,"running_times": 6300},{"title": "First Blood","year": 1982,"rating": 7.7,"votes": 187564,"running_times": 5580},{"title": "First Daughter","year": 2004,"rating": 5,"votes": 18521,"running_times": 6360},{"title": "First Knight","year": 1995,"rating": 5.9,"votes": 59640,"running_times": 8040},{"title": "Fish Tank","year": 2009,"rating": 7.3,"votes": 51982,"running_times": 7380},{"title": "Fist Fight","year": 2017,"rating": 5.6,"votes": 25330,"running_times": 5460},{"title": "Five Easy Pieces","year": 1970,"rating": 7.5,"votes": 27948,"running_times": 5880},{"title": "Five Minarets in New York","year": 2010,"rating": 5.9,"votes": 12857,"running_times": 7140},{"title": "Five Minutes of Heaven","year": 2009,"rating": 6.7,"votes": 11230,"running_times": 5340},{"title": "Flags of Our Fathers","year": 2006,"rating": 7.1,"votes": 107000,"running_times": 8100},{"title": "Flash Gordon","year": 1980,"rating": 6.5,"votes": 41587,"running_times": 6660},{"title": "Flash of Genius","year": 2008,"rating": 7,"votes": 15199,"running_times": 7140},{"title": "Flashbacks of a Fool","year": 2008,"rating": 6.8,"votes": 10970,"running_times": 6540},{"title": "Flashdance","year": 1983,"rating": 6.1,"votes": 39098,"running_times": 5700},{"title": "Flatliners","year": 1990,"rating": 6.6,"votes": 68965,"running_times": 6900},{"title": "Flawless","year": 1999,"rating": 6.4,"votes": 15528,"running_times": 6720},{"title": "Flawless","year": 2007,"rating": 6.8,"votes": 20643,"running_times": 6480},{"title": "Flesh+Blood","year": 1985,"rating": 6.7,"votes": 13910,"running_times": 7680},{"title": "Fletch","year": 1985,"rating": 6.9,"votes": 40497,"running_times": 5880},{"title": "Fletch Lives","year": 1989,"rating": 6.1,"votes": 16589,"running_times": 5700},{"title": "Flickan som lekte med elden","year": 2009,"rating": 7.2,"votes": 79566,"running_times": 10980},{"title": "Flight","year": 2012,"rating": 7.3,"votes": 283505,"running_times": 8280},{"title": "Flight 7500","year": 2014,"rating": 4.8,"votes": 12670,"running_times": 5820},{"title": "Flight of the Navigator","year": 1986,"rating": 6.9,"votes": 37089,"running_times": 5400},{"title": "Flight of the Phoenix","year": 2004,"rating": 6.1,"votes": 47745,"running_times": 6780},{"title": "Flightplan","year": 2005,"rating": 6.3,"votes": 135399,"running_times": 5880},{"title": "Flipped","year": 2010,"rating": 7.7,"votes": 68344,"running_times": 5400},{"title": "Flirting with Disaster","year": 1996,"rating": 6.8,"votes": 15896,"running_times": 5520},{"title": "Florence Foster Jenkins","year": 2016,"rating": 6.9,"votes": 37157,"running_times": 6660},{"title": "Flubber","year": 1997,"rating": 5.2,"votes": 70930,"running_times": 5580},{"title": "Flushed Away","year": 2006,"rating": 6.6,"votes": 93636,"running_times": 5100},{"title": "Fly Away Home","year": 1996,"rating": 6.8,"votes": 20944,"running_times": 6420},{"title": "Flyboys","year": 2006,"rating": 6.5,"votes": 37640,"running_times": 8400},{"title": "Flypaper","year": 2011,"rating": 6.4,"votes": 28968,"running_times": 5220},{"title": "Focus","year": 2015,"rating": 6.6,"votes": 174745,"running_times": 6300},{"title": "Following","year": 1998,"rating": 7.6,"votes": 72994,"running_times": 4140},{"title": "Food, Inc.","year": 2008,"rating": 7.8,"votes": 45811,"running_times": 5640},{"title": "Fool's Gold","year": 2008,"rating": 5.7,"votes": 64621,"running_times": 6720},{"title": "Fools Rush In","year": 1997,"rating": 6,"votes": 29168,"running_times": 6540},{"title": "Footloose","year": 1984,"rating": 6.5,"votes": 57957,"running_times": 6420},{"title": "Footloose","year": 2011,"rating": 5.9,"votes": 40438,"running_times": 6780},{"title": "For Love of the Game","year": 1999,"rating": 6.6,"votes": 27712,"running_times": 8220},{"title": "For Love or Money","year": 1993,"rating": 6.1,"votes": 10127,"running_times": 5760},{"title": "For Your Consideration","year": 2006,"rating": 6.3,"votes": 12713,"running_times": 5160},{"title": "For Your Eyes Only","year": 1981,"rating": 6.8,"votes": 77968,"running_times": 7620},{"title": "For a Good Time, Call...","year": 2012,"rating": 6,"votes": 14357,"running_times": 5280},{"title": "Forbidden Planet","year": 1956,"rating": 7.7,"votes": 37834,"running_times": 5880},{"title": "Force 10 from Navarone","year": 1978,"rating": 6.3,"votes": 14403,"running_times": 7560},{"title": "Forces of Nature","year": 1999,"rating": 5.4,"votes": 28462,"running_times": 6300},{"title": "Forces spéciales","year": 2011,"rating": 6.4,"votes": 16027,"running_times": 6540},{"title": "Foreign Correspondent","year": 1940,"rating": 7.6,"votes": 15032,"running_times": 7200},{"title": "Forever Young","year": 1992,"rating": 6.3,"votes": 39195,"running_times": 6120},{"title": "Forgetting Sarah Marshall","year": 2008,"rating": 7.2,"votes": 232023,"running_times": 7080},{"title": "Forrest Gump","year": 1994,"rating": 8.8,"votes": 1425423,"running_times": 8520},{"title": "Fort Apache","year": 1948,"rating": 7.6,"votes": 13695,"running_times": 7680},{"title": "Fortress","year": 1992,"rating": 5.9,"votes": 24762,"running_times": 5700},{"title": "Forushande","year": 2016,"rating": 7.9,"votes": 30515,"running_times": 7440},{"title": "Foul Play","year": 1978,"rating": 6.8,"votes": 11507,"running_times": 6960},{"title": "Four Brothers","year": 2005,"rating": 6.9,"votes": 118156,"running_times": 6540},{"title": "Four Christmases","year": 2008,"rating": 5.6,"votes": 53208,"running_times": 5280},{"title": "Four Lions","year": 2010,"rating": 7.3,"votes": 61920,"running_times": 5820},{"title": "Four Rooms","year": 1995,"rating": 6.7,"votes": 84665,"running_times": 6600},{"title": "Four Weddings and a Funeral","year": 1994,"rating": 7.1,"votes": 116667,"running_times": 7020},{"title": "Foxcatcher","year": 2014,"rating": 7,"votes": 118206,"running_times": 8040},{"title": "Fracture","year": 2007,"rating": 7.2,"votes": 155144,"running_times": 6780},{"title": "Frailty","year": 2001,"rating": 7.3,"votes": 66362,"running_times": 6000},{"title": "Frances Ha","year": 2012,"rating": 7.4,"votes": 51589,"running_times": 5160},{"title": "Frank","year": 2014,"rating": 7,"votes": 63921,"running_times": 5700},{"title": "Frankenstein","year": 1931,"rating": 7.9,"votes": 53795,"running_times": 4200},{"title": "Frankenweenie","year": 2012,"rating": 7,"votes": 82174,"running_times": 5220},{"title": "Frankie and Johnny","year": 1991,"rating": 6.7,"votes": 24600,"running_times": 7080},{"title": "Franklyn","year": 2008,"rating": 6.2,"votes": 15585,"running_times": 5880},{"title": "Frantic","year": 1988,"rating": 6.9,"votes": 42109,"running_times": 7200},{"title": "Freaks","year": 1932,"rating": 7.9,"votes": 35354,"running_times": 3840},{"title": "Freaky Friday","year": 2003,"rating": 6.2,"votes": 106102,"running_times": 5820},{"title": "Fred Claus","year": 2007,"rating": 5.6,"votes": 34482,"running_times": 6960},{"title": "Freddy Got Fingered","year": 2001,"rating": 4.5,"votes": 41471,"running_times": 5220},{"title": "Freddy vs. Jason","year": 2003,"rating": 5.8,"votes": 96473,"running_times": 5820},{"title": "Freddy's Dead: The Final Nightmare","year": 1991,"rating": 4.9,"votes": 34194,"running_times": 6300},{"title": "Free Birds","year": 2013,"rating": 5.9,"votes": 19574,"running_times": 5460},{"title": "Free Fire","year": 2016,"rating": 6.5,"votes": 25682,"running_times": 5460},{"title": "Free State of Jones","year": 2016,"rating": 6.9,"votes": 36148,"running_times": 8340},{"title": "Free Willy","year": 1993,"rating": 5.9,"votes": 56881,"running_times": 6720},{"title": "Free Willy 2: The Adventure Home","year": 1995,"rating": 4.9,"votes": 14085,"running_times": 5700},{"title": "Free to Play","year": 2014,"rating": 8,"votes": 12429,"running_times": 4500},{"title": "Freedom Writers","year": 2007,"rating": 7.5,"votes": 57530,"running_times": 7380},{"title": "Freedomland","year": 2006,"rating": 5.1,"votes": 14015,"running_times": 6780},{"title": "Freejack","year": 1992,"rating": 5.3,"votes": 12999,"running_times": 6600},{"title": "Freeway","year": 1996,"rating": 6.9,"votes": 23361,"running_times": 6240},{"title": "French Connection II","year": 1975,"rating": 6.8,"votes": 13988,"running_times": 7140},{"title": "French Kiss","year": 1995,"rating": 6.6,"votes": 41271,"running_times": 6660},{"title": "Frenzy","year": 1972,"rating": 7.5,"votes": 34045,"running_times": 6960},{"title": "Frequency","year": 2000,"rating": 7.4,"votes": 88661,"running_times": 7080},{"title": "Frequently Asked Questions About Time Travel","year": 2009,"rating": 7.1,"votes": 28572,"running_times": 4980},{"title": "Fresh","year": 1994,"rating": 7.6,"votes": 10428,"running_times": 6840},{"title": "Frida","year": 2002,"rating": 7.4,"votes": 67944,"running_times": 7380},{"title": "Friday","year": 1995,"rating": 7.3,"votes": 83187,"running_times": 5820},{"title": "Friday After Next","year": 2002,"rating": 5.8,"votes": 21533,"running_times": 5100},{"title": "Friday Night Lights","year": 2004,"rating": 7.3,"votes": 50876,"running_times": 7080},{"title": "Friday the 13th","year": 1980,"rating": 6.5,"votes": 94488,"running_times": 5700},{"title": "Friday the 13th","year": 2009,"rating": 5.6,"votes": 82090,"running_times": 6360},{"title": "Friday the 13th Part 2","year": 1981,"rating": 6.1,"votes": 45589,"running_times": 5220},{"title": "Friday the 13th Part III","year": 1982,"rating": 5.7,"votes": 36832,"running_times": 5700},{"title": "Friday the 13th Part VII: The New Blood","year": 1988,"rating": 5.3,"votes": 24702,"running_times": 5280},{"title": "Friday the 13th Part VIII: Jason Takes Manhattan","year": 1989,"rating": 4.6,"votes": 26121,"running_times": 6000},{"title": "Friday the 13th: A New Beginning","year": 1985,"rating": 4.8,"votes": 25750,"running_times": 5520},{"title": "Friday the 13th: The Final Chapter","year": 1984,"rating": 6,"votes": 34069,"running_times": 5820},{"title": "Fried Green Tomatoes","year": 1991,"rating": 7.7,"votes": 56574,"running_times": 8220},{"title": "Friend Request","year": 2016,"rating": 5.4,"votes": 16174,"running_times": 5520},{"title": "Friends with Benefits","year": 2011,"rating": 6.6,"votes": 295776,"running_times": 6540},{"title": "Friends with Kids","year": 2011,"rating": 6.2,"votes": 37913,"running_times": 6420},{"title": "Friends with Money","year": 2006,"rating": 5.8,"votes": 21365,"running_times": 5280},{"title": "Fright Night","year": 1985,"rating": 7.1,"votes": 48068,"running_times": 6360},{"title": "Fright Night","year": 2011,"rating": 6.4,"votes": 90148,"running_times": 6360},{"title": "From Beyond","year": 1986,"rating": 6.7,"votes": 17125,"running_times": 5160},{"title": "From Dusk Till Dawn","year": 1996,"rating": 7.3,"votes": 239943,"running_times": 6480},{"title": "From Hell","year": 2001,"rating": 6.8,"votes": 132974,"running_times": 7320},{"title": "From Here to Eternity","year": 1953,"rating": 7.7,"votes": 36695,"running_times": 7080},{"title": "From Justin to Kelly","year": 2003,"rating": 2.1,"votes": 24027,"running_times": 5400},{"title": "From Paris with Love","year": 2010,"rating": 6.5,"votes": 102829,"running_times": 5520},{"title": "From Prada to Nada","year": 2011,"rating": 5.5,"votes": 12822,"running_times": 6420},{"title": "From Russia with Love","year": 1963,"rating": 7.5,"votes": 97600,"running_times": 6900},{"title": "Frost/Nixon","year": 2008,"rating": 7.7,"votes": 92853,"running_times": 7320},{"title": "Frozen","year": 2010,"rating": 6.2,"votes": 57941,"running_times": 5580},{"title": "Frozen","year": 2013,"rating": 7.5,"votes": 470780,"running_times": 6120},{"title": "Frozen Fever","year": 2015,"rating": 7,"votes": 10101,"running_times": 480},{"title": "Frozen River","year": 2008,"rating": 7.2,"votes": 22666,"running_times": 5820},{"title": "Fruitvale Station","year": 2013,"rating": 7.5,"votes": 60680,"running_times": 5100},{"title": "Frágiles","year": 2005,"rating": 6.1,"votes": 13897,"running_times": 6060},{"title": "Full Metal Jacket","year": 1987,"rating": 8.3,"votes": 545907,"running_times": 6960},{"title": "Fun Size","year": 2012,"rating": 5.4,"votes": 12179,"running_times": 5160},{"title": "Fun with Dick and Jane","year": 2005,"rating": 6.1,"votes": 118363,"running_times": 5400},{"title": "Funny Face","year": 1957,"rating": 7.1,"votes": 21425,"running_times": 6180},{"title": "Funny Farm","year": 1988,"rating": 6.1,"votes": 16500,"running_times": 6060},{"title": "Funny Games","year": 2007,"rating": 6.5,"votes": 77100,"running_times": 6660},{"title": "Funny Girl","year": 1968,"rating": 7.6,"votes": 14783,"running_times": 9300},{"title": "Funny People","year": 2009,"rating": 6.3,"votes": 104820,"running_times": 9180},{"title": "Fur: An Imaginary Portrait of Diane Arbus","year": 2006,"rating": 6.5,"votes": 13935,"running_times": 7320},{"title": "Furious 6","year": 2013,"rating": 7.1,"votes": 327726,"running_times": 7860},{"title": "Furious Seven","year": 2015,"rating": 7.2,"votes": 313301,"running_times": 8400},{"title": "Furry Vengeance","year": 2010,"rating": 3.8,"votes": 13359,"running_times": 5520},{"title": "Fury","year": 2014,"rating": 7.6,"votes": 346870,"running_times": 8040},{"title": "G-Force","year": 2009,"rating": 5.1,"votes": 35892,"running_times": 5280},{"title": "G.I. Jane","year": 1997,"rating": 5.9,"votes": 64842,"running_times": 7500},{"title": "G.I. Joe: Retaliation","year": 2013,"rating": 5.8,"votes": 155817,"running_times": 7320},{"title": "G.I. Joe: The Rise of Cobra","year": 2009,"rating": 5.8,"votes": 183800,"running_times": 7080},{"title": "G.O.R.A.","year": 2004,"rating": 8,"votes": 41034,"running_times": 7620},{"title": "Gabriel","year": 2007,"rating": 5.7,"votes": 12850,"running_times": 6840},{"title": "Galaxy Quest","year": 1999,"rating": 7.3,"votes": 131167,"running_times": 6120},{"title": "Gallipoli","year": 1981,"rating": 7.5,"votes": 31959,"running_times": 6600},{"title": "Gambit","year": 2012,"rating": 5.7,"votes": 20482,"running_times": 6000},{"title": "Game of Death","year": 1978,"rating": 6.1,"votes": 13710,"running_times": 6180},{"title": "Gamer","year": 2009,"rating": 5.8,"votes": 119266,"running_times": 5700},{"title": "Gandhi","year": 1982,"rating": 8.1,"votes": 189632,"running_times": 11460},{"title": "Gangs of New York","year": 2002,"rating": 7.5,"votes": 344488,"running_times": 10020},{"title": "Gangster No. 1","year": 2000,"rating": 6.8,"votes": 11589,"running_times": 6180},{"title": "Gangster Squad","year": 2013,"rating": 6.7,"votes": 185855,"running_times": 6780},{"title": "Garden State","year": 2004,"rating": 7.5,"votes": 195068,"running_times": 6120},{"title": "Garfield","year": 2004,"rating": 5,"votes": 65785,"running_times": 4800},{"title": "Garfield: A Tail of Two Kitties","year": 2006,"rating": 5,"votes": 31226,"running_times": 5160},{"title": "Gaslight","year": 1944,"rating": 7.9,"votes": 18810,"running_times": 6840},{"title": "Gattaca","year": 1997,"rating": 7.8,"votes": 241382,"running_times": 6360},{"title": "Gegen die Wand","year": 2004,"rating": 8,"votes": 44019,"running_times": 7260},{"title": "Genius","year": 2016,"rating": 6.5,"votes": 12867,"running_times": 6240},{"title": "Gentleman's Agreement","year": 1947,"rating": 7.4,"votes": 12227,"running_times": 7080},{"title": "Gentlemen Prefer Blondes","year": 1953,"rating": 7.2,"votes": 25540,"running_times": 5460},{"title": "George of the Jungle","year": 1997,"rating": 5.4,"votes": 60896,"running_times": 5520},{"title": "Georgia Rule","year": 2007,"rating": 5.9,"votes": 21661,"running_times": 6780},{"title": "Geostorm","year": 2017,"rating": 5.5,"votes": 25413,"running_times": 6540},{"title": "Gerald's Game","year": 2017,"rating": 6.7,"votes": 31247,"running_times": 6180},{"title": "Gerry","year": 2002,"rating": 6.2,"votes": 16037,"running_times": 6180},{"title": "Get Carter","year": 1971,"rating": 7.5,"votes": 23892,"running_times": 6720},{"title": "Get Carter","year": 2000,"rating": 5.1,"votes": 29067,"running_times": 6120},{"title": "Get Hard","year": 2015,"rating": 6,"votes": 100323,"running_times": 6420},{"title": "Get Him to the Greek","year": 2010,"rating": 6.4,"votes": 154875,"running_times": 6840},{"title": "Get Low","year": 2009,"rating": 7.1,"votes": 20115,"running_times": 6180},{"title": "Get Out","year": 2017,"rating": 7.7,"votes": 210820,"running_times": 6240},{"title": "Get Over It","year": 2001,"rating": 5.8,"votes": 16318,"running_times": 5220},{"title": "Get Real","year": 1998,"rating": 7.6,"votes": 11209,"running_times": 6480},{"title": "Get Rich or Die Tryin'","year": 2005,"rating": 5.1,"votes": 39021,"running_times": 7020},{"title": "Get Shorty","year": 1995,"rating": 6.9,"votes": 66881,"running_times": 6300},{"title": "Get Smart","year": 2008,"rating": 6.5,"votes": 178169,"running_times": 6600},{"title": "Get a Job","year": 2016,"rating": 5.3,"votes": 17080,"running_times": 4980},{"title": "Get on Up","year": 2014,"rating": 6.9,"votes": 17525,"running_times": 8340},{"title": "Get the Gringo","year": 2012,"rating": 7,"votes": 93330,"running_times": 5760},{"title": "Getaway","year": 2013,"rating": 4.4,"votes": 20947,"running_times": 5400},{"title": "Gettysburg","year": 1993,"rating": 7.7,"votes": 23119,"running_times": 16260},{"title": "Ghost","year": 1990,"rating": 7,"votes": 166395,"running_times": 7620},{"title": "Ghost Dog: The Way of the Samurai","year": 1999,"rating": 7.5,"votes": 75463,"running_times": 6960},{"title": "Ghost Rider","year": 2007,"rating": 5.2,"votes": 196160,"running_times": 7380},{"title": "Ghost Rider: Spirit of Vengeance","year": 2011,"rating": 4.3,"votes": 95767,"running_times": 5760},{"title": "Ghost Ship","year": 2002,"rating": 5.5,"votes": 81267,"running_times": 5460},{"title": "Ghost Town","year": 2008,"rating": 6.7,"votes": 63420,"running_times": 6120},{"title": "Ghost World","year": 2001,"rating": 7.4,"votes": 102347,"running_times": 6660},{"title": "Ghost in the Shell","year": 2017,"rating": 6.4,"votes": 134199,"running_times": 6420},{"title": "Ghostbusters","year": 1984,"rating": 7.8,"votes": 299502,"running_times": 6300},{"title": "Ghostbusters","year": 2016,"rating": 5.3,"votes": 160952,"running_times": 8040},{"title": "Ghostbusters II","year": 1989,"rating": 6.5,"votes": 154653,"running_times": 6480},{"title": "Ghosts of Girlfriends Past","year": 2009,"rating": 5.8,"votes": 72653,"running_times": 6000},{"title": "Ghosts of Mars","year": 2001,"rating": 4.9,"votes": 45631,"running_times": 5880},{"title": "Giant","year": 1956,"rating": 7.7,"votes": 28660,"running_times": 12060},{"title": "Gifted","year": 2017,"rating": 7.6,"votes": 53458,"running_times": 6060},{"title": "Gigi","year": 1958,"rating": 6.8,"votes": 16227,"running_times": 6900},{"title": "Gigli","year": 2003,"rating": 2.4,"votes": 43066,"running_times": 7260},{"title": "Gilda","year": 1946,"rating": 7.8,"votes": 22667,"running_times": 6600},{"title": "Gin gwai","year": 2002,"rating": 6.7,"votes": 25927,"running_times": 6600},{"title": "Ging chaat goo si 4: Ji gaan daan yam mo","year": 1996,"rating": 6.6,"votes": 16216,"running_times": 6420},{"title": "Ging chaat goo si III: Chiu kup ging chaat","year": 1992,"rating": 6.9,"votes": 16239,"running_times": 5700},{"title": "Ginger Snaps","year": 2000,"rating": 6.8,"votes": 35786,"running_times": 6480},{"title": "Ginger Snaps 2: Unleashed","year": 2004,"rating": 6.5,"votes": 11059,"running_times": 5640},{"title": "Girl Most Likely","year": 2012,"rating": 5.8,"votes": 13274,"running_times": 6180},{"title": "Girl with a Pearl Earring","year": 2003,"rating": 7,"votes": 64538,"running_times": 6000},{"title": "Girl, Interrupted","year": 1999,"rating": 7.4,"votes": 137077,"running_times": 7620},{"title": "Girls Trip","year": 2017,"rating": 6.3,"votes": 14944,"running_times": 7320},{"title": "Gladiator","year": 2000,"rating": 8.5,"votes": 1095540,"running_times": 10260},{"title": "Glengarry Glen Ross","year": 1992,"rating": 7.8,"votes": 83225,"running_times": 6000},{"title": "Glitter","year": 2001,"rating": 2.2,"votes": 20105,"running_times": 6240},{"title": "Glory","year": 1989,"rating": 7.9,"votes": 108006,"running_times": 7320},{"title": "Glory Road","year": 2006,"rating": 7.2,"votes": 37469,"running_times": 7080},{"title": "Gnomeo & Juliet","year": 2011,"rating": 6,"votes": 45741,"running_times": 5040},{"title": "Go","year": 1999,"rating": 7.3,"votes": 61798,"running_times": 6120},{"title": "Goal II: Living the Dream","year": 2007,"rating": 5.9,"votes": 28017,"running_times": 6900},{"title": "Goal!","year": 2005,"rating": 6.7,"votes": 54338,"running_times": 7080},{"title": "God Bless America","year": 2011,"rating": 7.2,"votes": 63613,"running_times": 6300},{"title": "God's Not Dead","year": 2014,"rating": 4.8,"votes": 35130,"running_times": 6780},{"title": "Gods and Generals","year": 2003,"rating": 6.3,"votes": 13902,"running_times": 16800},{"title": "Gods and Monsters","year": 1998,"rating": 7.5,"votes": 26224,"running_times": 6300},{"title": "Gods of Egypt","year": 2016,"rating": 5.4,"votes": 80478,"running_times": 7620},{"title": "Godsend","year": 2004,"rating": 4.8,"votes": 23240,"running_times": 6120},{"title": "Godzilla","year": 1998,"rating": 5.3,"votes": 161405,"running_times": 8340},{"title": "Godzilla","year": 2014,"rating": 6.4,"votes": 326395,"running_times": 7380},{"title": "Going Clear: Scientology & the Prison of Belief","year": 2015,"rating": 8.1,"votes": 30417,"running_times": 7140},{"title": "Going Overboard","year": 1989,"rating": 1.9,"votes": 11122,"running_times": 5940},{"title": "Going in Style","year": 2017,"rating": 6.6,"votes": 46139,"running_times": 5760},{"title": "Going the Distance","year": 2010,"rating": 6.3,"votes": 52785,"running_times": 6120},{"title": "Gold","year": 2016,"rating": 6.7,"votes": 37148,"running_times": 7200},{"title": "GoldenEye","year": 1995,"rating": 7.2,"votes": 211375,"running_times": 7800},{"title": "Goldfinger","year": 1964,"rating": 7.8,"votes": 149047,"running_times": 6600},{"title": "Gone","year": 2012,"rating": 5.9,"votes": 37015,"running_times": 5640},{"title": "Gone Baby Gone","year": 2007,"rating": 7.7,"votes": 216054,"running_times": 6840},{"title": "Gone Girl","year": 2014,"rating": 8.1,"votes": 673078,"running_times": 8940},{"title": "Gone in Sixty Seconds","year": 2000,"rating": 6.5,"votes": 232755,"running_times": 7620},{"title": "Gone with the Wind","year": 1939,"rating": 8.2,"votes": 238572,"running_times": 14280},{"title": "Gongdong gyeongbi guyeok JSA","year": 2000,"rating": 7.9,"votes": 21127,"running_times": 6600},{"title": "Good Burger","year": 1997,"rating": 5.7,"votes": 22472,"running_times": 5700},{"title": "Good Bye Lenin!","year": 2003,"rating": 7.7,"votes": 122384,"running_times": 7260},{"title": "Good Kill","year": 2014,"rating": 6.4,"votes": 19133,"running_times": 6120},{"title": "Good Luck Chuck","year": 2007,"rating": 5.6,"votes": 78036,"running_times": 6060},{"title": "Good Morning, Vietnam","year": 1987,"rating": 7.3,"votes": 108279,"running_times": 7260},{"title": "Good Night, and Good Luck.","year": 2005,"rating": 7.5,"votes": 87338,"running_times": 5580},{"title": "Good People","year": 2014,"rating": 5.5,"votes": 13131,"running_times": 5400},{"title": "Good Time","year": 2017,"rating": 7.4,"votes": 17035,"running_times": 6060},{"title": "Good Will Hunting","year": 1997,"rating": 8.3,"votes": 686934,"running_times": 7560},{"title": "Goodbye Bafana","year": 2007,"rating": 7.1,"votes": 10712,"running_times": 7080},{"title": "Goodfellas","year": 1990,"rating": 8.7,"votes": 813765,"running_times": 8760},{"title": "Goon","year": 2011,"rating": 6.8,"votes": 76154,"running_times": 5520},{"title": "Goosebumps","year": 2015,"rating": 6.3,"votes": 61471,"running_times": 6180},{"title": "Gorillas in the Mist: The Story of Dian Fossey","year": 1988,"rating": 7,"votes": 20600,"running_times": 7740},{"title": "Gorky Park","year": 1983,"rating": 6.8,"votes": 10348,"running_times": 7680},{"title": "Gosford Park","year": 2001,"rating": 7.3,"votes": 69204,"running_times": 7860},{"title": "Gossip","year": 2000,"rating": 5.9,"votes": 13108,"running_times": 5400},{"title": "Gothika","year": 2003,"rating": 5.8,"votes": 95216,"running_times": 5880},{"title": "Goya's Ghosts","year": 2006,"rating": 6.9,"votes": 26554,"running_times": 6780},{"title": "Grabbers","year": 2012,"rating": 6.3,"votes": 14687,"running_times": 5640},{"title": "Grace of Monaco","year": 2014,"rating": 5.7,"votes": 14565,"running_times": 6180},{"title": "Gran Torino","year": 2008,"rating": 8.2,"votes": 617362,"running_times": 6960},{"title": "Grand Canyon","year": 1991,"rating": 6.9,"votes": 13347,"running_times": 8040},{"title": "Grand Hotel","year": 1932,"rating": 7.6,"votes": 14274,"running_times": 6720},{"title": "Grand Piano","year": 2013,"rating": 5.9,"votes": 14935,"running_times": 5400},{"title": "Grandma","year": 2015,"rating": 6.7,"votes": 12295,"running_times": 4740},{"title": "Grandma's Boy","year": 2006,"rating": 7,"votes": 71010,"running_times": 5640},{"title": "Grave Encounters","year": 2011,"rating": 6.1,"votes": 44630,"running_times": 5520},{"title": "Grave Encounters 2","year": 2012,"rating": 5.1,"votes": 19167,"running_times": 5700},{"title": "Gravity","year": 2013,"rating": 7.8,"votes": 646916,"running_times": 5460},{"title": "Grease","year": 1978,"rating": 7.2,"votes": 188022,"running_times": 6600},{"title": "Grease 2","year": 1982,"rating": 4.2,"votes": 28318,"running_times": 6900},{"title": "Great Balls of Fire!","year": 1989,"rating": 6.2,"votes": 13571,"running_times": 6480},{"title": "Great Expectations","year": 1946,"rating": 8,"votes": 18970,"running_times": 7080},{"title": "Great Expectations","year": 1998,"rating": 6.8,"votes": 45586,"running_times": 6660},{"title": "Great Expectations","year": 2012,"rating": 6.4,"votes": 10560,"running_times": 7680},{"title": "Greedy","year": 1994,"rating": 6.3,"votes": 11136,"running_times": 6780},{"title": "Green Card","year": 1990,"rating": 6.2,"votes": 19778,"running_times": 6420},{"title": "Green Lantern","year": 2011,"rating": 5.6,"votes": 237741,"running_times": 7380},{"title": "Green Room","year": 2015,"rating": 7,"votes": 72111,"running_times": 5700},{"title": "Green Zone","year": 2010,"rating": 6.8,"votes": 117010,"running_times": 6900},{"title": "Greenberg","year": 2010,"rating": 6.1,"votes": 32106,"running_times": 6420},{"title": "Gremlins","year": 1984,"rating": 7.2,"votes": 160563,"running_times": 6360},{"title": "Gremlins 2: The New Batch","year": 1990,"rating": 6.3,"votes": 76549,"running_times": 6360},{"title": "Greystoke: The Legend of Tarzan, Lord of the Apes","year": 1984,"rating": 6.4,"votes": 15791,"running_times": 8580},{"title": "Gridiron Gang","year": 2006,"rating": 6.9,"votes": 36158,"running_times": 7500},{"title": "Gridlock'd","year": 1997,"rating": 7,"votes": 12700,"running_times": 5460},{"title": "Grimsby","year": 2016,"rating": 6.2,"votes": 69187,"running_times": 4980},{"title": "Grind","year": 2003,"rating": 6,"votes": 10800,"running_times": 6300},{"title": "Grindhouse","year": 2007,"rating": 7.6,"votes": 163369,"running_times": 11460},{"title": "Grizzly Man","year": 2005,"rating": 7.8,"votes": 45276,"running_times": 6180},{"title": "Grosse Pointe Blank","year": 1997,"rating": 7.4,"votes": 78182,"running_times": 6420},{"title": "Groundhog Day","year": 1993,"rating": 8,"votes": 490746,"running_times": 6060},{"title": "Grown Ups","year": 2010,"rating": 6,"votes": 196291,"running_times": 6120},{"title": "Grown Ups 2","year": 2013,"rating": 5.4,"votes": 118711,"running_times": 6060},{"title": "Grudge Match","year": 2013,"rating": 6.4,"votes": 50640,"running_times": 6780},{"title": "Grumpier Old Men","year": 1995,"rating": 6.6,"votes": 20921,"running_times": 6060},{"title": "Grumpy Old Men","year": 1993,"rating": 7,"votes": 37362,"running_times": 6180},{"title": "Guardians of the Galaxy","year": 2014,"rating": 8.1,"votes": 804806,"running_times": 7260},{"title": "Guardians of the Galaxy Vol. 2","year": 2017,"rating": 7.8,"votes": 307773,"running_times": 8160},{"title": "Guarding Tess","year": 1994,"rating": 6.2,"votes": 13643,"running_times": 5760},{"title": "Guess Who","year": 2005,"rating": 5.9,"votes": 35779,"running_times": 6300},{"title": "Guess Who's Coming to Dinner","year": 1967,"rating": 7.8,"votes": 32153,"running_times": 6480},{"title": "Gulliver's Travels","year": 2010,"rating": 4.9,"votes": 56804,"running_times": 5100},{"title": "Gummo","year": 1997,"rating": 6.7,"votes": 26744,"running_times": 5340},{"title": "Gunfight at the O.K. Corral","year": 1957,"rating": 7.2,"votes": 11317,"running_times": 7320},{"title": "Gung Ho","year": 1986,"rating": 6.2,"votes": 10087,"running_times": 6720},{"title": "Guys and Dolls","year": 1955,"rating": 7.3,"votes": 12935,"running_times": 9120},{"title": "Guzaarish","year": 2010,"rating": 7.5,"votes": 13589,"running_times": 7560},{"title": "Gwoemul","year": 2006,"rating": 7,"votes": 77654,"running_times": 7200},{"title": "Habemus Papam","year": 2011,"rating": 6.7,"votes": 11615,"running_times": 6120},{"title": "Habitación en Roma","year": 2010,"rating": 6.2,"votes": 18445,"running_times": 6540},{"title": "Hachi: A Dog's Tale","year": 2009,"rating": 8.1,"votes": 190809,"running_times": 5580},{"title": "Hackers","year": 1995,"rating": 6.2,"votes": 58262,"running_times": 6420},{"title": "Hacksaw Ridge","year": 2016,"rating": 8.2,"votes": 282761,"running_times": 8340},{"title": "Hail, Caesar!","year": 2016,"rating": 6.3,"votes": 96939,"running_times": 6360},{"title": "Hair","year": 1979,"rating": 7.6,"votes": 29465,"running_times": 7260},{"title": "Hairspray","year": 1988,"rating": 7,"votes": 17296,"running_times": 5520},{"title": "Hairspray","year": 2007,"rating": 6.7,"votes": 105515,"running_times": 7020},{"title": "Half Baked","year": 1998,"rating": 6.7,"votes": 51176,"running_times": 4920},{"title": "Half Light","year": 2006,"rating": 6,"votes": 11903,"running_times": 6600},{"title": "Half Nelson","year": 2006,"rating": 7.2,"votes": 76232,"running_times": 6360},{"title": "Half Past Dead","year": 2002,"rating": 4.6,"votes": 12929,"running_times": 5880},{"title": "Hall Pass","year": 2011,"rating": 5.9,"votes": 108841,"running_times": 6660},{"title": "Hallam Foe","year": 2007,"rating": 7,"votes": 11427,"running_times": 5700},{"title": "Halloween","year": 1978,"rating": 7.8,"votes": 176749,"running_times": 6060},{"title": "Halloween","year": 2007,"rating": 6.1,"votes": 94747,"running_times": 7260},{"title": "Halloween 4: The Return of Michael Myers","year": 1988,"rating": 5.9,"votes": 33335,"running_times": 5280},{"title": "Halloween 5","year": 1989,"rating": 5.2,"votes": 26022,"running_times": 5760},{"title": "Halloween H20: 20 Years Later","year": 1998,"rating": 5.7,"votes": 53537,"running_times": 5160},{"title": "Halloween II","year": 1981,"rating": 6.6,"votes": 57321,"running_times": 5520},{"title": "Halloween II","year": 2009,"rating": 4.9,"votes": 39987,"running_times": 7140},{"title": "Halloween III: Season of the Witch","year": 1982,"rating": 4.7,"votes": 32487,"running_times": 5880},{"title": "Halloween: Resurrection","year": 2002,"rating": 4.1,"votes": 29692,"running_times": 5640},{"title": "Halloween: The Curse of Michael Myers","year": 1995,"rating": 5,"votes": 23489,"running_times": 5700},{"title": "Hamburger Hill","year": 1987,"rating": 6.7,"votes": 20324,"running_times": 6600},{"title": "Hamlet","year": 1948,"rating": 7.8,"votes": 12859,"running_times": 9240},{"title": "Hamlet","year": 1990,"rating": 6.8,"votes": 18948,"running_times": 8100},{"title": "Hamlet","year": 1996,"rating": 7.8,"votes": 32395,"running_times": 14520},{"title": "Hamlet 2","year": 2008,"rating": 6.4,"votes": 15690,"running_times": 5520},{"title": "Hancock","year": 2008,"rating": 6.4,"votes": 379865,"running_times": 6120},{"title": "Hands of Stone","year": 2016,"rating": 6.6,"votes": 10581,"running_times": 6660},{"title": "Hang 'Em High","year": 1968,"rating": 7,"votes": 28346,"running_times": 6840},{"title": "Hanging Up","year": 2000,"rating": 4.8,"votes": 10695,"running_times": 5640},{"title": "Hanna","year": 2011,"rating": 6.8,"votes": 167885,"running_times": 6660},{"title": "Hannah Montana: The Movie","year": 2009,"rating": 4.3,"votes": 34482,"running_times": 6120},{"title": "Hannah and Her Sisters","year": 1986,"rating": 8,"votes": 57685,"running_times": 6420},{"title": "Hannibal","year": 2001,"rating": 6.8,"votes": 223188,"running_times": 7860},{"title": "Hannibal Rising","year": 2007,"rating": 6.2,"votes": 92521,"running_times": 7860},{"title": "Hansel & Gretel: Witch Hunters","year": 2013,"rating": 6.1,"votes": 172538,"running_times": 5880},{"title": "Happiness","year": 1998,"rating": 7.8,"votes": 59093,"running_times": 8040},{"title": "Happy Death Day","year": 2017,"rating": 6.5,"votes": 26480,"running_times": 5760},{"title": "Happy Feet","year": 2006,"rating": 6.5,"votes": 145943,"running_times": 6480},{"title": "Happy Feet Two","year": 2011,"rating": 5.9,"votes": 35383,"running_times": 6000},{"title": "Happy Gilmore","year": 1996,"rating": 7,"votes": 168423,"running_times": 5520},{"title": "Happy-Go-Lucky","year": 2008,"rating": 7,"votes": 33856,"running_times": 7080},{"title": "Happythankyoumoreplease","year": 2010,"rating": 6.8,"votes": 27488,"running_times": 6000},{"title": "Hard Ball","year": 2001,"rating": 6.4,"votes": 24106,"running_times": 6540},{"title": "Hard Candy","year": 2005,"rating": 7.1,"votes": 140132,"running_times": 6240},{"title": "Hard Rain","year": 1998,"rating": 5.8,"votes": 28690,"running_times": 5820},{"title": "Hard Target","year": 1993,"rating": 6.1,"votes": 37873,"running_times": 7680},{"title": "Hard to Kill","year": 1990,"rating": 5.8,"votes": 23647,"running_times": 5760},{"title": "Hardcore Henry","year": 2015,"rating": 6.7,"votes": 66693,"running_times": 5760},{"title": "Hardware","year": 1990,"rating": 5.9,"votes": 10673,"running_times": 5640},{"title": "Harlem Nights","year": 1989,"rating": 6,"votes": 15812,"running_times": 6960},{"title": "Harley Davidson and the Marlboro Man","year": 1991,"rating": 6,"votes": 15709,"running_times": 5880},{"title": "Harold & Kumar Escape from Guantanamo Bay","year": 2008,"rating": 6.6,"votes": 119872,"running_times": 6420},{"title": "Harold & Kumar Go to White Castle","year": 2004,"rating": 7.1,"votes": 164461,"running_times": 5280},{"title": "Harold and Maude","year": 1971,"rating": 8,"votes": 61251,"running_times": 5460},{"title": "Harry Brown","year": 2009,"rating": 7.2,"votes": 77817,"running_times": 6180},{"title": "Harry Potter and the Chamber of Secrets","year": 2002,"rating": 7.4,"votes": 439161,"running_times": 10440},{"title": "Harry Potter and the Deathly Hallows: Part 1","year": 2010,"rating": 7.7,"votes": 374837,"running_times": 8760},{"title": "Harry Potter and the Deathly Hallows: Part 2","year": 2011,"rating": 8.1,"votes": 618562,"running_times": 7800},{"title": "Harry Potter and the Goblet of Fire","year": 2005,"rating": 7.7,"votes": 435781,"running_times": 9960},{"title": "Harry Potter and the Half-Blood Prince","year": 2009,"rating": 7.5,"votes": 368314,"running_times": 9180},{"title": "Harry Potter and the Order of the Phoenix","year": 2007,"rating": 7.5,"votes": 402883,"running_times": 8280},{"title": "Harry Potter and the Prisoner of Azkaban","year": 2004,"rating": 7.8,"votes": 434113,"running_times": 8520},{"title": "Harry Potter and the Sorcerer's Stone","year": 2001,"rating": 7.6,"votes": 506880,"running_times": 9540},{"title": "Harry and the Hendersons","year": 1987,"rating": 5.9,"votes": 26455,"running_times": 6600},{"title": "Harsh Times","year": 2005,"rating": 6.9,"votes": 57586,"running_times": 6960},{"title": "Hart's War","year": 2002,"rating": 6.3,"votes": 46235,"running_times": 7500},{"title": "Harvey","year": 1950,"rating": 8,"votes": 47393,"running_times": 6660},{"title": "Hasee Toh Phasee","year": 2014,"rating": 6.9,"votes": 11522,"running_times": 8460},{"title": "Hatchet","year": 2006,"rating": 5.7,"votes": 24930,"running_times": 5580},{"title": "Hatchet II","year": 2010,"rating": 5.5,"votes": 10247,"running_times": 5100},{"title": "Haunter","year": 2013,"rating": 5.9,"votes": 14290,"running_times": 5820},{"title": "Haute tension","year": 2003,"rating": 6.8,"votes": 59182,"running_times": 5460},{"title": "Havoc","year": 2005,"rating": 5.5,"votes": 16845,"running_times": 5580},{"title": "Haywire","year": 2011,"rating": 5.8,"votes": 75871,"running_times": 5580},{"title": "He Got Game","year": 1998,"rating": 6.9,"votes": 38768,"running_times": 8160},{"title": "He Never Died","year": 2015,"rating": 6.4,"votes": 12574,"running_times": 5940},{"title": "He Was a Quiet Man","year": 2007,"rating": 6.8,"votes": 20947,"running_times": 5700},{"title": "He's Just Not That Into You","year": 2009,"rating": 6.4,"votes": 141177,"running_times": 7740},{"title": "Head Over Heels","year": 2001,"rating": 5.4,"votes": 12415,"running_times": 5160},{"title": "Head in the Clouds","year": 2004,"rating": 6.6,"votes": 13236,"running_times": 7920},{"title": "Head of State","year": 2003,"rating": 5.4,"votes": 15818,"running_times": 5700},{"title": "Heart and Souls","year": 1993,"rating": 6.9,"votes": 13971,"running_times": 6240},{"title": "Heartbreak Ridge","year": 1986,"rating": 6.8,"votes": 33303,"running_times": 7800},{"title": "Heartbreakers","year": 2001,"rating": 6.2,"votes": 46577,"running_times": 7380},{"title": "Hearts in Atlantis","year": 2001,"rating": 6.9,"votes": 32398,"running_times": 6060},{"title": "Hearts of Darkness: A Filmmaker's Apocalypse","year": 1991,"rating": 8.2,"votes": 15340,"running_times": 5760},{"title": "Heat","year": 1995,"rating": 8.2,"votes": 476332,"running_times": 10200},{"title": "Heathers","year": 1988,"rating": 7.3,"votes": 68413,"running_times": 6180},{"title": "Heaven & Earth","year": 1993,"rating": 6.8,"votes": 11528,"running_times": 8400},{"title": "Heaven","year": 2002,"rating": 7.1,"votes": 21401,"running_times": 5820},{"title": "Heaven Can Wait","year": 1978,"rating": 6.9,"votes": 15486,"running_times": 6060},{"title": "Heaven Is for Real","year": 2014,"rating": 5.8,"votes": 22680,"running_times": 5940},{"title": "Heaven's Gate","year": 1980,"rating": 6.8,"votes": 11079,"running_times": 19500},{"title": "Heavenly Creatures","year": 1994,"rating": 7.4,"votes": 53288,"running_times": 6480},{"title": "Heavy Metal","year": 1981,"rating": 6.7,"votes": 25961,"running_times": 5400},{"title": "Heavy Weights","year": 1995,"rating": 6.7,"votes": 21356,"running_times": 6000},{"title": "Hector and the Search for Happiness","year": 2014,"rating": 7,"votes": 38151,"running_times": 7200},{"title": "Hedwig and the Angry Inch","year": 2001,"rating": 7.8,"votes": 27944,"running_times": 5700},{"title": "Heisei tanuki gassen ponpoko","year": 1994,"rating": 7.4,"votes": 16877,"running_times": 7140},{"title": "Heist","year": 2001,"rating": 6.6,"votes": 29396,"running_times": 6540},{"title": "Heist","year": 2015,"rating": 6.1,"votes": 21521,"running_times": 5580},{"title": "Hell Ride","year": 2008,"rating": 5.1,"votes": 14601,"running_times": 5040},{"title": "Hell or High Water","year": 2016,"rating": 7.6,"votes": 139821,"running_times": 6120},{"title": "Hellbound: Hellraiser II","year": 1988,"rating": 6.5,"votes": 33894,"running_times": 5940},{"title": "Hellboy","year": 2004,"rating": 6.8,"votes": 264309,"running_times": 7920},{"title": "Hellboy II: The Golden Army","year": 2008,"rating": 7,"votes": 223462,"running_times": 7200},{"title": "Hello, Dolly!","year": 1969,"rating": 7.2,"votes": 11068,"running_times": 8760},{"title": "Hello, My Name Is Doris","year": 2015,"rating": 6.7,"votes": 14600,"running_times": 5400},{"title": "Hellraiser","year": 1987,"rating": 7,"votes": 84790,"running_times": 5640},{"title": "Hellraiser III: Hell on Earth","year": 1992,"rating": 5.5,"votes": 22469,"running_times": 5820},{"title": "Hellraiser: Bloodline","year": 1996,"rating": 5.1,"votes": 15913,"running_times": 5100},{"title": "Help!","year": 1965,"rating": 7.3,"votes": 14710,"running_times": 5520},{"title": "Henry & June","year": 1990,"rating": 6.3,"votes": 10875,"running_times": 8160},{"title": "Henry Poole Is Here","year": 2008,"rating": 6.5,"votes": 11416,"running_times": 5940},{"title": "Henry V","year": 1989,"rating": 7.7,"votes": 25019,"running_times": 8220},{"title": "Henry's Crime","year": 2010,"rating": 6,"votes": 16652,"running_times": 6480},{"title": "Henry: Portrait of a Serial Killer","year": 1986,"rating": 7,"votes": 25794,"running_times": 4980},{"title": "Her","year": 2013,"rating": 8,"votes": 412823,"running_times": 7560},{"title": "Herbie Fully Loaded","year": 2005,"rating": 4.8,"votes": 39449,"running_times": 6060},{"title": "Hercules","year": 1997,"rating": 7.3,"votes": 162326,"running_times": 5580},{"title": "Hercules","year": 2014,"rating": 6,"votes": 126532,"running_times": 6060},{"title": "Hercules in New York","year": 1970,"rating": 3.2,"votes": 14990,"running_times": 5460},{"title": "Here Comes the Boom","year": 2012,"rating": 6.4,"votes": 78346,"running_times": 6300},{"title": "Hereafter","year": 2010,"rating": 6.5,"votes": 83811,"running_times": 7740},{"title": "Hero","year": 1992,"rating": 6.5,"votes": 18785,"running_times": 7140},{"title": "Hesher","year": 2010,"rating": 7.1,"votes": 46468,"running_times": 6360},{"title": "Hick","year": 2011,"rating": 5.7,"votes": 17000,"running_times": 5940},{"title": "Hidalgo","year": 2004,"rating": 6.7,"votes": 71055,"running_times": 8160},{"title": "Hidden","year": 2015,"rating": 6.4,"votes": 15457,"running_times": 5040},{"title": "Hidden Figures","year": 2016,"rating": 7.8,"votes": 130784,"running_times": 7620},{"title": "Hide and Seek","year": 2005,"rating": 5.9,"votes": 74510,"running_times": 6060},{"title": "High Anxiety","year": 1977,"rating": 6.7,"votes": 16701,"running_times": 5640},{"title": "High Crimes","year": 2002,"rating": 6.3,"votes": 33013,"running_times": 6900},{"title": "High Fidelity","year": 2000,"rating": 7.5,"votes": 151450,"running_times": 6780},{"title": "High Noon","year": 1952,"rating": 8,"votes": 85253,"running_times": 5100},{"title": "High Plains Drifter","year": 1973,"rating": 7.6,"votes": 40775,"running_times": 6300},{"title": "High School High","year": 1996,"rating": 5.5,"votes": 11436,"running_times": 5160},{"title": "High School Musical 3: Senior Year","year": 2008,"rating": 4.6,"votes": 48125,"running_times": 6720},{"title": "High Sierra","year": 1941,"rating": 7.6,"votes": 12432,"running_times": 6000},{"title": "High Society","year": 1956,"rating": 7,"votes": 11413,"running_times": 6660},{"title": "High-Rise","year": 2015,"rating": 5.7,"votes": 28955,"running_times": 7140},{"title": "Higher Learning","year": 1995,"rating": 6.5,"votes": 15725,"running_times": 7620},{"title": "Highlander","year": 1986,"rating": 7.2,"votes": 105854,"running_times": 6960},{"title": "Highlander II: The Quickening","year": 1991,"rating": 4.1,"votes": 38881,"running_times": 6540},{"title": "Highlander III: The Sorcerer","year": 1994,"rating": 4.4,"votes": 17489,"running_times": 5940},{"title": "Highlander: Endgame","year": 2000,"rating": 4.6,"votes": 17359,"running_times": 6060},{"title": "Highway","year": 2014,"rating": 7.6,"votes": 20548,"running_times": 7980},{"title": "Hiroshima mon amour","year": 1959,"rating": 8,"votes": 22156,"running_times": 5400},{"title": "His Girl Friday","year": 1940,"rating": 8,"votes": 44758,"running_times": 5520},{"title": "History of the World: Part I","year": 1981,"rating": 6.9,"votes": 39778,"running_times": 5820},{"title": "Hit and Run","year": 2012,"rating": 6.1,"votes": 31091,"running_times": 6000},{"title": "Hitch","year": 2005,"rating": 6.6,"votes": 262082,"running_times": 7080},{"title": "Hitchcock","year": 2012,"rating": 6.8,"votes": 64671,"running_times": 5880},{"title": "Hitman","year": 2007,"rating": 6.3,"votes": 147724,"running_times": 6000},{"title": "Hitman: Agent 47","year": 2015,"rating": 5.7,"votes": 74251,"running_times": 5760},{"title": "Hobo with a Shotgun","year": 2011,"rating": 6.1,"votes": 39715,"running_times": 5160},{"title": "Hocus Pocus","year": 1993,"rating": 6.8,"votes": 70603,"running_times": 5760},{"title": "Hodejegerne","year": 2011,"rating": 7.6,"votes": 86454,"running_times": 5760},{"title": "Hoffa","year": 1992,"rating": 6.6,"votes": 18392,"running_times": 8400},{"title": "Hokkabaz","year": 2006,"rating": 7.5,"votes": 22397,"running_times": 7320},{"title": "Holes","year": 2003,"rating": 7.1,"votes": 64114,"running_times": 7020},{"title": "Holiday","year": 1938,"rating": 7.9,"votes": 11757,"running_times": 5700},{"title": "Hollow Man","year": 2000,"rating": 5.7,"votes": 108608,"running_times": 7140},{"title": "Hollywood Ending","year": 2002,"rating": 6.6,"votes": 23284,"running_times": 6720},{"title": "Hollywood Homicide","year": 2003,"rating": 5.3,"votes": 32736,"running_times": 6960},{"title": "Hollywoodland","year": 2006,"rating": 6.5,"votes": 30461,"running_times": 7560},{"title": "Holy Man","year": 1998,"rating": 4.9,"votes": 17246,"running_times": 6840},{"title": "Holy Motors","year": 2012,"rating": 7.1,"votes": 33547,"running_times": 6900},{"title": "Holy Smoke","year": 1999,"rating": 5.9,"votes": 12767,"running_times": 6900},{"title": "Home","year": 2009,"rating": 8.6,"votes": 19620,"running_times": 7200},{"title": "Home","year": 2015,"rating": 6.7,"votes": 80214,"running_times": 5640},{"title": "Home Alone","year": 1990,"rating": 7.5,"votes": 358522,"running_times": 6180},{"title": "Home Alone 2: Lost in New York","year": 1992,"rating": 6.6,"votes": 231633,"running_times": 7200},{"title": "Home Alone 3","year": 1997,"rating": 4.3,"votes": 84915,"running_times": 6120},{"title": "Home Sweet Hell","year": 2015,"rating": 5.4,"votes": 11800,"running_times": 5880},{"title": "Home on the Range","year": 2004,"rating": 5.4,"votes": 15587,"running_times": 4560},{"title": "Homefront","year": 2013,"rating": 6.5,"votes": 91464,"running_times": 6000},{"title": "Homeward Bound II: Lost in San Francisco","year": 1996,"rating": 5.9,"votes": 11621,"running_times": 5340},{"title": "Homeward Bound: The Incredible Journey","year": 1993,"rating": 6.9,"votes": 36406,"running_times": 5040},{"title": "Honey","year": 2003,"rating": 5.3,"votes": 39141,"running_times": 5640},{"title": "Honey I Blew Up the Kid","year": 1992,"rating": 4.7,"votes": 34738,"running_times": 5340},{"title": "Honey, I Shrunk the Kids","year": 1989,"rating": 6.3,"votes": 118405,"running_times": 5580},{"title": "Honeymoon","year": 2014,"rating": 5.7,"votes": 20850,"running_times": 5220},{"title": "Honeymoon in Vegas","year": 1992,"rating": 5.8,"votes": 15156,"running_times": 5760},{"title": "Hoodwinked Too! Hood vs. Evil","year": 2011,"rating": 4.8,"votes": 10424,"running_times": 5160},{"title": "Hoodwinked!","year": 2005,"rating": 6.5,"votes": 49338,"running_times": 4800},{"title": "Hook","year": 1991,"rating": 6.7,"votes": 198650,"running_times": 8520},{"title": "Hooligans","year": 2005,"rating": 7.5,"votes": 127112,"running_times": 6540},{"title": "Hoop Dreams","year": 1994,"rating": 8.3,"votes": 20884,"running_times": 10200},{"title": "Hoosiers","year": 1986,"rating": 7.6,"votes": 36946,"running_times": 6840},{"title": "Hop","year": 2011,"rating": 5.5,"votes": 26311,"running_times": 5700},{"title": "Hope Floats","year": 1998,"rating": 5.9,"votes": 20949,"running_times": 6840},{"title": "Hope Springs","year": 2012,"rating": 6.3,"votes": 36803,"running_times": 6000},{"title": "Hope and Glory","year": 1987,"rating": 7.4,"votes": 10464,"running_times": 6780},{"title": "Horns","year": 2013,"rating": 6.5,"votes": 64239,"running_times": 7200},{"title": "Horrible Bosses","year": 2011,"rating": 6.9,"votes": 378107,"running_times": 6360},{"title": "Horrible Bosses 2","year": 2014,"rating": 6.3,"votes": 131371,"running_times": 6960},{"title": "Hors de prix","year": 2006,"rating": 7,"votes": 27628,"running_times": 6360},{"title": "Horse Feathers","year": 1932,"rating": 7.7,"votes": 10105,"running_times": 4080},{"title": "Horsemen","year": 2009,"rating": 5.6,"votes": 19785,"running_times": 5400},{"title": "Horton Hears a Who!","year": 2008,"rating": 6.8,"votes": 114271,"running_times": 5160},{"title": "Hostage","year": 2005,"rating": 6.6,"votes": 98148,"running_times": 6780},{"title": "Hostel","year": 2005,"rating": 5.9,"votes": 149732,"running_times": 5640},{"title": "Hostel: Part II","year": 2007,"rating": 5.5,"votes": 75544,"running_times": 5640},{"title": "Hot Fuzz","year": 2007,"rating": 7.9,"votes": 390102,"running_times": 7260},{"title": "Hot Girls Wanted","year": 2015,"rating": 6.1,"votes": 11368,"running_times": 5040},{"title": "Hot Pursuit","year": 2015,"rating": 5.1,"votes": 41002,"running_times": 5220},{"title": "Hot Rod","year": 2007,"rating": 6.7,"votes": 65211,"running_times": 5280},{"title": "Hot Shots!","year": 1991,"rating": 6.7,"votes": 86014,"running_times": 5040},{"title": "Hot Shots! Part Deux","year": 1993,"rating": 6.6,"votes": 72998,"running_times": 5160},{"title": "Hot Tub Time Machine","year": 2010,"rating": 6.4,"votes": 146646,"running_times": 6060},{"title": "Hot Tub Time Machine 2","year": 2015,"rating": 5.1,"votes": 32007,"running_times": 5940},{"title": "Hotel Chevalier","year": 2007,"rating": 7.3,"votes": 25983,"running_times": 780},{"title": "Hotel Rwanda","year": 2004,"rating": 8.1,"votes": 289707,"running_times": 7260},{"title": "Hotel Transylvania","year": 2012,"rating": 7.1,"votes": 183497,"running_times": 5460},{"title": "Hotel Transylvania 2","year": 2015,"rating": 6.7,"votes": 75463,"running_times": 5340},{"title": "Hotel for Dogs","year": 2009,"rating": 5.4,"votes": 18004,"running_times": 6000},{"title": "Hours","year": 2013,"rating": 6.5,"votes": 24595,"running_times": 5820},{"title": "House","year": 1985,"rating": 6.2,"votes": 18925,"running_times": 5580},{"title": "House at the End of the Street","year": 2012,"rating": 5.6,"votes": 62772,"running_times": 6060},{"title": "House of 1000 Corpses","year": 2003,"rating": 6,"votes": 65306,"running_times": 6300},{"title": "House of Games","year": 1987,"rating": 7.3,"votes": 17627,"running_times": 6120},{"title": "House of Sand and Fog","year": 2003,"rating": 7.6,"votes": 59246,"running_times": 7560},{"title": "House of Wax","year": 1953,"rating": 7.1,"votes": 13079,"running_times": 5280},{"title": "House of Wax","year": 2005,"rating": 5.3,"votes": 101370,"running_times": 6480},{"title": "House of the Dead","year": 2003,"rating": 2,"votes": 33466,"running_times": 5400},{"title": "House on Haunted Hill","year": 1959,"rating": 6.9,"votes": 18072,"running_times": 4500},{"title": "House on Haunted Hill","year": 1999,"rating": 5.6,"votes": 47824,"running_times": 5940},{"title": "HouseSitter","year": 1992,"rating": 6,"votes": 18605,"running_times": 6120},{"title": "Housebound","year": 2014,"rating": 6.8,"votes": 27690,"running_times": 6420},{"title": "How Do You Know","year": 2010,"rating": 5.4,"votes": 37932,"running_times": 7260},{"title": "How Green Was My Valley","year": 1941,"rating": 7.8,"votes": 17395,"running_times": 7080},{"title": "How High","year": 2001,"rating": 6.3,"votes": 46268,"running_times": 5700},{"title": "How I Live Now","year": 2013,"rating": 6.5,"votes": 24050,"running_times": 6060},{"title": "How the Grinch Stole Christmas","year": 2000,"rating": 6.1,"votes": 159672,"running_times": 6600},{"title": "How the West Was Won","year": 1962,"rating": 7.1,"votes": 15613,"running_times": 9840},{"title": "How to Be Single","year": 2016,"rating": 6.1,"votes": 64963,"running_times": 6600},{"title": "How to Lose Friends & Alienate People","year": 2008,"rating": 6.4,"votes": 63646,"running_times": 6600},{"title": "How to Lose a Guy in 10 Days","year": 2003,"rating": 6.4,"votes": 174435,"running_times": 6960},{"title": "How to Marry a Millionaire","year": 1953,"rating": 7,"votes": 17157,"running_times": 5700},{"title": "How to Steal a Million","year": 1966,"rating": 7.6,"votes": 19967,"running_times": 7380},{"title": "How to Train Your Dragon","year": 2010,"rating": 8.1,"votes": 546154,"running_times": 5880},{"title": "How to Train Your Dragon 2","year": 2014,"rating": 7.8,"votes": 246660,"running_times": 6120},{"title": "Howard the Duck","year": 1986,"rating": 4.6,"votes": 36526,"running_times": 6600},{"title": "Howards End","year": 1992,"rating": 7.5,"votes": 23352,"running_times": 8520},{"title": "Howl","year": 2010,"rating": 6.8,"votes": 11508,"running_times": 5040},{"title": "Hud","year": 1963,"rating": 7.9,"votes": 16445,"running_times": 6720},{"title": "Hudson Hawk","year": 1991,"rating": 5.8,"votes": 46017,"running_times": 6000},{"title": "Hugo","year": 2011,"rating": 7.5,"votes": 266903,"running_times": 7560},{"title": "Hulk","year": 2003,"rating": 5.7,"votes": 226165,"running_times": 8280},{"title": "Hum Dil De Chuke Sanam","year": 1999,"rating": 7.6,"votes": 13474,"running_times": 11280},{"title": "Hum Tum","year": 2004,"rating": 7.1,"votes": 11318,"running_times": 8520},{"title": "Human Nature","year": 2001,"rating": 6.4,"votes": 16165,"running_times": 5760},{"title": "Human Traffic","year": 1999,"rating": 7.1,"votes": 20483,"running_times": 5940},{"title": "Hummingbird","year": 2013,"rating": 6.2,"votes": 56975,"running_times": 6000},{"title": "Hundraåringen som klev ut genom fönstret och försvann","year": 2013,"rating": 7.1,"votes": 31798,"running_times": 6840},{"title": "Hung fan kui","year": 1995,"rating": 6.7,"votes": 32871,"running_times": 6240},{"title": "Hunger","year": 2008,"rating": 7.6,"votes": 56874,"running_times": 5760},{"title": "Hunt for the Wilderpeople","year": 2016,"rating": 7.9,"votes": 65738,"running_times": 6060},{"title": "Huo yuanjia","year": 2006,"rating": 7.7,"votes": 66069,"running_times": 8460},{"title": "Husbands and Wives","year": 1992,"rating": 7.6,"votes": 23348,"running_times": 6180},{"title": "Hush","year": 2016,"rating": 6.6,"votes": 56665,"running_times": 4860},{"title": "Hush...Hush, Sweet Charlotte","year": 1964,"rating": 7.7,"votes": 10077,"running_times": 7980},{"title": "Hustle & Flow","year": 2005,"rating": 7.4,"votes": 35128,"running_times": 6960},{"title": "Hyde Park on Hudson","year": 2012,"rating": 5.9,"votes": 10079,"running_times": 5640},{"title": "Hysteria","year": 2011,"rating": 6.7,"votes": 27483,"running_times": 6000},{"title": "Hævnen","year": 2010,"rating": 7.7,"votes": 34828,"running_times": 7140},{"title": "Höstsonaten","year": 1978,"rating": 8.3,"votes": 17643,"running_times": 5940},{"title": "I Am Legend","year": 2007,"rating": 7.2,"votes": 587088,"running_times": 6240},{"title": "I Am Number Four","year": 2011,"rating": 6.1,"votes": 207158,"running_times": 6540},{"title": "I Am Sam","year": 2001,"rating": 7.6,"votes": 129669,"running_times": 7920},{"title": "I Confess","year": 1953,"rating": 7.3,"votes": 15940,"running_times": 5700},{"title": "I Could Never Be Your Woman","year": 2007,"rating": 6,"votes": 15268,"running_times": 5820},{"title": "I Don't Feel at Home in This World Anymore.","year": 2017,"rating": 7,"votes": 21910,"running_times": 5580},{"title": "I Don't Know How She Does It","year": 2011,"rating": 4.9,"votes": 17591,"running_times": 5340},{"title": "I Give It a Year","year": 2013,"rating": 5.7,"votes": 32224,"running_times": 5820},{"title": "I Heart Huckabees","year": 2004,"rating": 6.7,"votes": 58804,"running_times": 6420},{"title": "I Kina spiser de hunde","year": 1999,"rating": 7.5,"votes": 17406,"running_times": 5460},{"title": "I Know What You Did Last Summer","year": 1997,"rating": 5.6,"votes": 114383,"running_times": 6060},{"title": "I Know Who Killed Me","year": 2007,"rating": 3.6,"votes": 23923,"running_times": 6300},{"title": "I Love Trouble","year": 1994,"rating": 5.2,"votes": 10211,"running_times": 7380},{"title": "I Love You Phillip Morris","year": 2009,"rating": 6.6,"votes": 83209,"running_times": 6120},{"title": "I Love You to Death","year": 1990,"rating": 6.4,"votes": 11731,"running_times": 5820},{"title": "I Love You, Beth Cooper","year": 2009,"rating": 5.3,"votes": 30092,"running_times": 6120},{"title": "I Love You, Man","year": 2009,"rating": 7,"votes": 176457,"running_times": 6300},{"title": "I Now Pronounce You Chuck & Larry","year": 2007,"rating": 6,"votes": 126959,"running_times": 6900},{"title": "I Origins","year": 2014,"rating": 7.3,"votes": 92619,"running_times": 6360},{"title": "I Spit on Your Grave","year": 2010,"rating": 6.3,"votes": 62588,"running_times": 6480},{"title": "I Spit on Your Grave 2","year": 2013,"rating": 5.7,"votes": 21431,"running_times": 6360},{"title": "I Spy","year": 2002,"rating": 5.4,"votes": 44160,"running_times": 5820},{"title": "I Still Know What You Did Last Summer","year": 1998,"rating": 4.6,"votes": 59565,"running_times": 6000},{"title": "I Think I Love My Wife","year": 2007,"rating": 5.5,"votes": 14333,"running_times": 5640},{"title": "I'm Gonna Git You Sucka","year": 1988,"rating": 6.6,"votes": 10536,"running_times": 5280},{"title": "I'm Not There.","year": 2007,"rating": 7,"votes": 50996,"running_times": 8100},{"title": "I'm Still Here","year": 2010,"rating": 6.2,"votes": 17253,"running_times": 6480},{"title": "I, Daniel Blake","year": 2016,"rating": 7.9,"votes": 33594,"running_times": 6000},{"title": "I, Frankenstein","year": 2014,"rating": 5.1,"votes": 71379,"running_times": 5520},{"title": "I, Robot","year": 2004,"rating": 7.1,"votes": 428767,"running_times": 6900},{"title": "I.Q.","year": 1994,"rating": 6.2,"votes": 21084,"running_times": 6000},{"title": "I.T.","year": 2016,"rating": 5.4,"votes": 10972,"running_times": 5700},{"title": "Ice Age","year": 2002,"rating": 7.6,"votes": 362481,"running_times": 6180},{"title": "Ice Age: Collision Course","year": 2016,"rating": 5.7,"votes": 39957,"running_times": 5640},{"title": "Ice Age: Continental Drift","year": 2012,"rating": 6.6,"votes": 160411,"running_times": 5280},{"title": "Ice Age: Dawn of the Dinosaurs","year": 2009,"rating": 7,"votes": 184847,"running_times": 7320},{"title": "Ice Age: The Meltdown","year": 2006,"rating": 6.8,"votes": 214495,"running_times": 6900},{"title": "Ice Princess","year": 2005,"rating": 6,"votes": 21459,"running_times": 5880},{"title": "Identity","year": 2003,"rating": 7.3,"votes": 194439,"running_times": 5460},{"title": "Identity Thief","year": 2013,"rating": 5.7,"votes": 106125,"running_times": 7260},{"title": "Idiocracy","year": 2006,"rating": 6.6,"votes": 119657,"running_times": 5040},{"title": "Idle Hands","year": 1999,"rating": 6.2,"votes": 35508,"running_times": 5520},{"title": "If I Stay","year": 2014,"rating": 6.8,"votes": 97119,"running_times": 6420},{"title": "If Only","year": 2004,"rating": 7.2,"votes": 28528,"running_times": 5580},{"title": "If....","year": 1968,"rating": 7.7,"votes": 18590,"running_times": 6660},{"title": "Igby Goes Down","year": 2002,"rating": 7,"votes": 30041,"running_times": 5940},{"title": "Igor","year": 2008,"rating": 6,"votes": 20624,"running_times": 5220},{"title": "Il conformista","year": 1970,"rating": 8.1,"votes": 20440,"running_times": 6780},{"title": "Il divo - La spettacolare vita di Giulio Andreotti","year": 2008,"rating": 7.3,"votes": 13070,"running_times": 6600},{"title": "Il grande silenzio","year": 1968,"rating": 7.8,"votes": 10696,"running_times": 6300},{"title": "Il racconto dei racconti - Tale of Tales","year": 2015,"rating": 6.4,"votes": 19327,"running_times": 8040},{"title": "Il y a longtemps que je t'aime","year": 2008,"rating": 7.6,"votes": 18473,"running_times": 7020},{"title": "Im Juli","year": 2000,"rating": 7.8,"votes": 18049,"running_times": 5940},{"title": "Imagine Me & You","year": 2005,"rating": 6.8,"votes": 25393,"running_times": 5400},{"title": "Imagine That","year": 2009,"rating": 5.6,"votes": 11384,"running_times": 6420},{"title": "Imitation of Life","year": 1959,"rating": 7.9,"votes": 12112,"running_times": 7500},{"title": "Immortal Beloved","year": 1994,"rating": 7.5,"votes": 20290,"running_times": 7260},{"title": "Immortals","year": 2011,"rating": 6,"votes": 146055,"running_times": 6600},{"title": "Immortel (ad vitam)","year": 2004,"rating": 6,"votes": 19010,"running_times": 6180},{"title": "Imperium","year": 2016,"rating": 6.5,"votes": 31969,"running_times": 6540},{"title": "Impostor","year": 2001,"rating": 6.2,"votes": 20888,"running_times": 6120},{"title": "In & Out","year": 1997,"rating": 6.3,"votes": 34168,"running_times": 5400},{"title": "In America","year": 2002,"rating": 7.8,"votes": 37906,"running_times": 6300},{"title": "In Bruges","year": 2008,"rating": 7.9,"votes": 332444,"running_times": 6420},{"title": "In Cold Blood","year": 1967,"rating": 8,"votes": 20567,"running_times": 8040},{"title": "In Dreams","year": 1999,"rating": 5.5,"votes": 11367,"running_times": 6000},{"title": "In Good Company","year": 2004,"rating": 6.5,"votes": 50486,"running_times": 6540},{"title": "In Hell","year": 2003,"rating": 6.3,"votes": 16438,"running_times": 5880},{"title": "In Her Shoes","year": 2005,"rating": 6.5,"votes": 54532,"running_times": 7800},{"title": "In Time","year": 2011,"rating": 6.7,"votes": 327425,"running_times": 6540},{"title": "In Your Eyes","year": 2014,"rating": 7.1,"votes": 26765,"running_times": 6360},{"title": "In a Lonely Place","year": 1950,"rating": 8,"votes": 19749,"running_times": 5640},{"title": "In a World...","year": 2013,"rating": 6.7,"votes": 28040,"running_times": 5580},{"title": "In the Army Now","year": 1994,"rating": 4.8,"votes": 10741,"running_times": 5460},{"title": "In the Bedroom","year": 2001,"rating": 7.5,"votes": 33930,"running_times": 8280},{"title": "In the Company of Men","year": 1997,"rating": 7.3,"votes": 12049,"running_times": 5820},{"title": "In the Cut","year": 2003,"rating": 5.3,"votes": 19559,"running_times": 7140},{"title": "In the Electric Mist","year": 2009,"rating": 6.1,"votes": 14439,"running_times": 7020},{"title": "In the Heart of the Sea","year": 2015,"rating": 6.9,"votes": 96896,"running_times": 7320},{"title": "In the Heat of the Night","year": 1967,"rating": 8,"votes": 55172,"running_times": 6540},{"title": "In the Land of Blood and Honey","year": 2011,"rating": 4.4,"votes": 32191,"running_times": 7620},{"title": "In the Land of Women","year": 2007,"rating": 6.5,"votes": 28999,"running_times": 5820},{"title": "In the Line of Fire","year": 1993,"rating": 7.2,"votes": 79362,"running_times": 8280},{"title": "In the Loop","year": 2009,"rating": 7.5,"votes": 47572,"running_times": 6360},{"title": "In the Mouth of Madness","year": 1994,"rating": 7.2,"votes": 48288,"running_times": 5700},{"title": "In the Name of the Father","year": 1993,"rating": 8.1,"votes": 125082,"running_times": 7980},{"title": "In the Name of the King: A Dungeon Siege Tale","year": 2007,"rating": 3.8,"votes": 40212,"running_times": 9360},{"title": "In the Valley of Elah","year": 2007,"rating": 7.2,"votes": 63206,"running_times": 7260},{"title": "Incendies","year": 2010,"rating": 8.2,"votes": 101345,"running_times": 7860},{"title": "Inception","year": 2010,"rating": 8.8,"votes": 1653028,"running_times": 8880},{"title": "Indecent Proposal","year": 1993,"rating": 5.8,"votes": 52305,"running_times": 7020},{"title": "Independence Day","year": 1996,"rating": 7,"votes": 465279,"running_times": 9240},{"title": "Independence Day: Resurgence","year": 2016,"rating": 5.3,"votes": 139960,"running_times": 7200},{"title": "Indiana Jones and the Kingdom of the Crystal Skull","year": 2008,"rating": 6.2,"votes": 362353,"running_times": 7320},{"title": "Indiana Jones and the Last Crusade","year": 1989,"rating": 8.3,"votes": 574150,"running_times": 7620},{"title": "Indiana Jones and the Temple of Doom","year": 1984,"rating": 7.6,"votes": 367264,"running_times": 7080},{"title": "Indie Game: The Movie","year": 2012,"rating": 7.7,"votes": 18687,"running_times": 6180},{"title": "Infamous","year": 2006,"rating": 7.1,"votes": 14944,"running_times": 7080},{"title": "Inferno","year": 1980,"rating": 6.7,"votes": 13844,"running_times": 7200},{"title": "Inferno","year": 2016,"rating": 6.2,"votes": 115981,"running_times": 7260},{"title": "Infini","year": 2015,"rating": 5.4,"votes": 12268,"running_times": 6600},{"title": "Infinitely Polar Bear","year": 2014,"rating": 7,"votes": 12653,"running_times": 5400},{"title": "Inglourious Basterds","year": 2009,"rating": 8.3,"votes": 1004190,"running_times": 9180},{"title": "Ingrid Goes West","year": 2017,"rating": 6.7,"votes": 10144,"running_times": 5880},{"title": "Inherent Vice","year": 2014,"rating": 6.7,"votes": 73405,"running_times": 8880},{"title": "Inherit the Wind","year": 1960,"rating": 8.2,"votes": 22703,"running_times": 7680},{"title": "Ink","year": 2009,"rating": 7,"votes": 19498,"running_times": 6420},{"title": "Inkheart","year": 2008,"rating": 6.1,"votes": 65047,"running_times": 6360},{"title": "Inland Empire","year": 2006,"rating": 7,"votes": 46150,"running_times": 11820},{"title": "Innerspace","year": 1987,"rating": 6.8,"votes": 45776,"running_times": 7200},{"title": "Innocence","year": 2004,"rating": 7.6,"votes": 31374,"running_times": 6000},{"title": "Inside I'm Dancing","year": 2004,"rating": 7.9,"votes": 12600,"running_times": 6240},{"title": "Inside Job","year": 2010,"rating": 8.3,"votes": 61590,"running_times": 6300},{"title": "Inside Llewyn Davis","year": 2013,"rating": 7.5,"votes": 110845,"running_times": 6240},{"title": "Inside Man","year": 2006,"rating": 7.6,"votes": 293330,"running_times": 7740},{"title": "Inside Out","year": 2015,"rating": 8.2,"votes": 451282,"running_times": 5700},{"title": "Insidious","year": 2010,"rating": 6.8,"votes": 229734,"running_times": 6180},{"title": "Insidious: Chapter 2","year": 2013,"rating": 6.6,"votes": 125404,"running_times": 6360},{"title": "Insidious: Chapter 3","year": 2015,"rating": 6.1,"votes": 69063,"running_times": 5820},{"title": "Insomnia","year": 2002,"rating": 7.2,"votes": 238048,"running_times": 7080},{"title": "Inspector Gadget","year": 1999,"rating": 4.1,"votes": 39282,"running_times": 6600},{"title": "Instinct","year": 1999,"rating": 6.5,"votes": 28930,"running_times": 7560},{"title": "Insurgent","year": 2015,"rating": 6.3,"votes": 181020,"running_times": 7140},{"title": "Intacto","year": 2001,"rating": 6.9,"votes": 11851,"running_times": 6480},{"title": "Interiors","year": 1978,"rating": 7.5,"votes": 15486,"running_times": 5520},{"title": "Intermission","year": 2003,"rating": 6.9,"votes": 14149,"running_times": 6300},{"title": "Internal Affairs","year": 1990,"rating": 6.5,"votes": 14372,"running_times": 6900},{"title": "Interstate 60: Episodes of the Road","year": 2002,"rating": 7.7,"votes": 25480,"running_times": 6960},{"title": "Interstella 5555: The 5tory of the 5ecret 5tar 5ystem","year": 2003,"rating": 7.9,"votes": 11987,"running_times": 4080},{"title": "Interstellar","year": 2014,"rating": 8.6,"votes": 1119789,"running_times": 10140},{"title": "Interview","year": 2007,"rating": 6.8,"votes": 12610,"running_times": 5040},{"title": "Interview with the Vampire: The Vampire Chronicles","year": 1994,"rating": 7.6,"votes": 257571,"running_times": 7380},{"title": "Into the Abyss","year": 2011,"rating": 7.3,"votes": 13936,"running_times": 6420},{"title": "Into the Blue","year": 2005,"rating": 5.8,"votes": 66989,"running_times": 6600},{"title": "Into the Forest","year": 2015,"rating": 5.9,"votes": 12306,"running_times": 6060},{"title": "Into the Storm","year": 2014,"rating": 5.8,"votes": 57871,"running_times": 5340},{"title": "Into the White","year": 2012,"rating": 7.2,"votes": 16822,"running_times": 6240},{"title": "Into the Wild","year": 2007,"rating": 8.1,"votes": 478844,"running_times": 8880},{"title": "Into the Woods","year": 2014,"rating": 6,"votes": 113738,"running_times": 7500},{"title": "Intolerable Cruelty","year": 2003,"rating": 6.3,"votes": 81396,"running_times": 6000},{"title": "Intouchables","year": 2011,"rating": 8.6,"votes": 590763,"running_times": 6720},{"title": "Intruders","year": 2011,"rating": 5.4,"votes": 18646,"running_times": 6000},{"title": "Invasion of the Body Snatchers","year": 1956,"rating": 7.8,"votes": 37639,"running_times": 4800},{"title": "Invasion of the Body Snatchers","year": 1978,"rating": 7.4,"votes": 41739,"running_times": 6900},{"title": "Inventing the Abbotts","year": 1997,"rating": 6.4,"votes": 10116,"running_times": 6600},{"title": "Invictus","year": 2009,"rating": 7.4,"votes": 133507,"running_times": 8040},{"title": "Invincible","year": 2006,"rating": 7.1,"votes": 56381,"running_times": 6300},{"title": "Io sono l'amore","year": 2009,"rating": 7,"votes": 15807,"running_times": 7200},{"title": "Iris","year": 2001,"rating": 7.1,"votes": 15548,"running_times": 5460},{"title": "Irma la Douce","year": 1963,"rating": 7.4,"votes": 13869,"running_times": 8820},{"title": "Iron Eagle","year": 1986,"rating": 5.3,"votes": 11396,"running_times": 7020},{"title": "Iron Man","year": 2008,"rating": 7.9,"votes": 765492,"running_times": 7560},{"title": "Iron Man 2","year": 2010,"rating": 7,"votes": 579338,"running_times": 7440},{"title": "Iron Man Three","year": 2013,"rating": 7.2,"votes": 613287,"running_times": 11700},{"title": "Iron Sky","year": 2012,"rating": 5.9,"votes": 83589,"running_times": 6600},{"title": "Ironclad","year": 2011,"rating": 6.2,"votes": 36401,"running_times": 7260},{"title": "Irrational Man","year": 2015,"rating": 6.6,"votes": 44129,"running_times": 5700},{"title": "Irréversible","year": 2002,"rating": 7.4,"votes": 96418,"running_times": 5940},{"title": "It","year": 2017,"rating": 7.7,"votes": 193799,"running_times": 8100},{"title": "It Comes at Night","year": 2017,"rating": 6.2,"votes": 42069,"running_times": 5460},{"title": "It Could Happen to You","year": 1994,"rating": 6.3,"votes": 29833,"running_times": 6060},{"title": "It Follows","year": 2014,"rating": 6.9,"votes": 152676,"running_times": 6000},{"title": "It Happened One Night","year": 1934,"rating": 8.2,"votes": 73493,"running_times": 6300},{"title": "It Might Get Loud","year": 2008,"rating": 7.6,"votes": 11240,"running_times": 5880},{"title": "It Takes Two","year": 1995,"rating": 5.8,"votes": 16405,"running_times": 6060},{"title": "It's All Gone Pete Tong","year": 2004,"rating": 7.4,"votes": 17682,"running_times": 5400},{"title": "It's Complicated","year": 2009,"rating": 6.6,"votes": 74931,"running_times": 7200},{"title": "It's Kind of a Funny Story","year": 2010,"rating": 7.1,"votes": 116972,"running_times": 6060},{"title": "It's a Boy Girl Thing","year": 2006,"rating": 6.3,"votes": 34972,"running_times": 5700},{"title": "It's a Mad Mad Mad Mad World","year": 1963,"rating": 7.6,"votes": 31888,"running_times": 12300},{"title": "It's a Wonderful Life","year": 1946,"rating": 8.6,"votes": 312993,"running_times": 7800},{"title": "Italiensk for begyndere","year": 2000,"rating": 7.1,"votes": 11849,"running_times": 7080},{"title": "J. Edgar","year": 2011,"rating": 6.6,"votes": 109877,"running_times": 8220},{"title": "JCVD","year": 2008,"rating": 7.2,"votes": 34799,"running_times": 5820},{"title": "JFK","year": 1991,"rating": 8,"votes": 122897,"running_times": 12360},{"title": "Jab We Met","year": 2007,"rating": 8,"votes": 37148,"running_times": 8280},{"title": "Jabberwocky","year": 1977,"rating": 6.2,"votes": 10865,"running_times": 6300},{"title": "Jack","year": 1996,"rating": 5.8,"votes": 49751,"running_times": 6780},{"title": "Jack Frost","year": 1998,"rating": 5.3,"votes": 27169,"running_times": 6060},{"title": "Jack Reacher","year": 2012,"rating": 7,"votes": 260550,"running_times": 7800},{"title": "Jack Reacher: Never Go Back","year": 2016,"rating": 6.1,"votes": 96285,"running_times": 7080},{"title": "Jack Ryan: Shadow Recruit","year": 2014,"rating": 6.2,"votes": 106376,"running_times": 6300},{"title": "Jack and Jill","year": 2011,"rating": 3.4,"votes": 65679,"running_times": 5460},{"title": "Jack the Giant Slayer","year": 2013,"rating": 6.3,"votes": 115065,"running_times": 6840},{"title": "Jackass 3D","year": 2010,"rating": 7,"votes": 50664,"running_times": 6060},{"title": "Jackass Number Two","year": 2006,"rating": 7.1,"votes": 59800,"running_times": 5520},{"title": "Jackass: The Movie","year": 2002,"rating": 6.6,"votes": 72492,"running_times": 5220},{"title": "Jackie","year": 2016,"rating": 6.7,"votes": 54108,"running_times": 6000},{"title": "Jackie Brown","year": 1997,"rating": 7.5,"votes": 260746,"running_times": 9240},{"title": "Jacob's Ladder","year": 1990,"rating": 7.5,"votes": 83001,"running_times": 6780},{"title": "Jagged Edge","year": 1985,"rating": 6.5,"votes": 11243,"running_times": 6480},{"title": "Jagten","year": 2012,"rating": 8.3,"votes": 206070,"running_times": 6900},{"title": "Jakob the Liar","year": 1999,"rating": 6.5,"votes": 13452,"running_times": 7200},{"title": "James and the Giant Peach","year": 1996,"rating": 6.7,"votes": 53040,"running_times": 4740},{"title": "Jane Austen's Mafia!","year": 1998,"rating": 5.5,"votes": 13259,"running_times": 5220},{"title": "Jane Eyre","year": 2011,"rating": 7.4,"votes": 69801,"running_times": 7200},{"title": "Jane Got a Gun","year": 2015,"rating": 5.9,"votes": 16203,"running_times": 5880},{"title": "Jarhead","year": 2005,"rating": 7,"votes": 153689,"running_times": 7500},{"title": "Jason Bourne","year": 2016,"rating": 6.6,"votes": 168047,"running_times": 7380},{"title": "Jason Goes to Hell: The Final Friday","year": 1993,"rating": 4.3,"votes": 21936,"running_times": 5460},{"title": "Jason Lives: Friday the 13th Part VI","year": 1986,"rating": 5.9,"votes": 29197,"running_times": 5160},{"title": "Jason X","year": 2001,"rating": 4.4,"votes": 42714,"running_times": 5460},{"title": "Jason and the Argonauts","year": 1963,"rating": 7.4,"votes": 19059,"running_times": 6240},{"title": "Jawbreaker","year": 1999,"rating": 5.5,"votes": 20502,"running_times": 5760},{"title": "Jaws","year": 1975,"rating": 8,"votes": 461570,"running_times": 7800},{"title": "Jaws 2","year": 1978,"rating": 5.7,"votes": 57309,"running_times": 7860},{"title": "Jaws 3-D","year": 1983,"rating": 3.6,"votes": 31520,"running_times": 5940},{"title": "Jaws: The Revenge","year": 1987,"rating": 2.9,"votes": 33783,"running_times": 5520},{"title": "Jay and Silent Bob Strike Back","year": 2001,"rating": 6.9,"votes": 135086,"running_times": 6240},{"title": "Jeepers Creepers","year": 2001,"rating": 6.1,"votes": 96505,"running_times": 5400},{"title": "Jeepers Creepers II","year": 2003,"rating": 5.6,"votes": 50446,"running_times": 6240},{"title": "Jeff, Who Lives at Home","year": 2011,"rating": 6.5,"votes": 58122,"running_times": 4980},{"title": "Jennifer Eight","year": 1992,"rating": 6.2,"votes": 13166,"running_times": 7500},{"title": "Jennifer's Body","year": 2009,"rating": 5.1,"votes": 99183,"running_times": 6420},{"title": "Jeremiah Johnson","year": 1972,"rating": 7.6,"votes": 23289,"running_times": 6960},{"title": "Jerry Maguire","year": 1996,"rating": 7.3,"votes": 206427,"running_times": 8340},{"title": "Jersey Boys","year": 2014,"rating": 6.8,"votes": 27880,"running_times": 8040},{"title": "Jersey Girl","year": 2004,"rating": 6.2,"votes": 57587,"running_times": 6120},{"title": "Jessabelle","year": 2014,"rating": 5.4,"votes": 18987,"running_times": 5400},{"title": "Jesus Camp","year": 2006,"rating": 7.5,"votes": 24239,"running_times": 5220},{"title": "Jesus Christ Superstar","year": 1973,"rating": 7.3,"votes": 21189,"running_times": 6480},{"title": "Jigsaw","year": 2017,"rating": 6.1,"votes": 16047,"running_times": 5520},{"title": "Jimmy Neutron: Boy Genius","year": 2001,"rating": 6,"votes": 26177,"running_times": 5040},{"title": "Jin ling shi san chai","year": 2011,"rating": 7.6,"votes": 42340,"running_times": 8760},{"title": "Jing wu men","year": 1972,"rating": 7.4,"votes": 20490,"running_times": 6480},{"title": "Jingle All the Way","year": 1996,"rating": 5.5,"votes": 76054,"running_times": 5640},{"title": "Joan of Arc","year": 1999,"rating": 6.4,"votes": 58830,"running_times": 9480},{"title": "Jobs","year": 2013,"rating": 5.9,"votes": 84088,"running_times": 7680},{"title": "Jodorowsky's Dune","year": 2013,"rating": 8.1,"votes": 16961,"running_times": 5400},{"title": "Joe","year": 2013,"rating": 6.9,"votes": 39777,"running_times": 7020},{"title": "Joe Dirt","year": 2001,"rating": 5.9,"votes": 44605,"running_times": 5460},{"title": "Joe Kidd","year": 1972,"rating": 6.5,"votes": 13727,"running_times": 5280},{"title": "Joe Versus the Volcano","year": 1990,"rating": 5.7,"votes": 30028,"running_times": 6120},{"title": "Joe's Apartment","year": 1996,"rating": 5.4,"votes": 11193,"running_times": 4800},{"title": "John Carter","year": 2012,"rating": 6.6,"votes": 226112,"running_times": 7920},{"title": "John Dies at the End","year": 2012,"rating": 6.4,"votes": 32588,"running_times": 5940},{"title": "John Q","year": 2002,"rating": 7.1,"votes": 107437,"running_times": 6960},{"title": "John Tucker Must Die","year": 2006,"rating": 5.8,"votes": 71843,"running_times": 5700},{"title": "John Wick","year": 2014,"rating": 7.3,"votes": 365044,"running_times": 6060},{"title": "John Wick: Chapter 2","year": 2017,"rating": 7.5,"votes": 201944,"running_times": 7320},{"title": "Johnny Dangerously","year": 1984,"rating": 6.4,"votes": 11727,"running_times": 5400},{"title": "Johnny English","year": 2003,"rating": 6.1,"votes": 122454,"running_times": 5280},{"title": "Johnny English Reborn","year": 2011,"rating": 6.3,"votes": 96666,"running_times": 6060},{"title": "Johnny Got His Gun","year": 1971,"rating": 7.9,"votes": 13068,"running_times": 6660},{"title": "Johnny Guitar","year": 1954,"rating": 7.7,"votes": 12458,"running_times": 6600},{"title": "Johnny Mnemonic","year": 1995,"rating": 5.6,"votes": 59292,"running_times": 6180},{"title": "Jonah Hex","year": 2010,"rating": 4.7,"votes": 48928,"running_times": 4860},{"title": "Jonas Brothers: The 3D Concert Experience","year": 2009,"rating": 2.1,"votes": 17138,"running_times": 5100},{"title": "Joshua","year": 2007,"rating": 5.9,"votes": 10668,"running_times": 6360},{"title": "Josie and the Pussycats","year": 2001,"rating": 5.4,"votes": 19739,"running_times": 5880},{"title": "Journey 2: The Mysterious Island","year": 2012,"rating": 5.8,"votes": 74661,"running_times": 5640},{"title": "Journey to the Center of the Earth","year": 1959,"rating": 7.1,"votes": 12773,"running_times": 7920},{"title": "Journey to the Center of the Earth","year": 2008,"rating": 5.8,"votes": 95171,"running_times": 5580},{"title": "Joy","year": 2015,"rating": 6.6,"votes": 104704,"running_times": 7440},{"title": "Joy Ride","year": 2001,"rating": 6.6,"votes": 56944,"running_times": 5820},{"title": "Joyeux Noël","year": 2005,"rating": 7.8,"votes": 23749,"running_times": 6960},{"title": "Judge Dredd","year": 1995,"rating": 5.5,"votes": 96037,"running_times": 5760},{"title": "Judgment Night","year": 1993,"rating": 6.6,"votes": 13094,"running_times": 6600},{"title": "Judgment at Nuremberg","year": 1961,"rating": 8.3,"votes": 51733,"running_times": 11160},{"title": "Jue di tao wang","year": 2016,"rating": 5.7,"votes": 14156,"running_times": 6420},{"title": "Juice","year": 1992,"rating": 7.1,"votes": 19092,"running_times": 5700},{"title": "Jules et Jim","year": 1962,"rating": 7.9,"votes": 30428,"running_times": 6300},{"title": "Julie & Julia","year": 2009,"rating": 7,"votes": 87286,"running_times": 7080},{"title": "Jumanji","year": 1995,"rating": 6.9,"votes": 236688,"running_times": 6240},{"title": "Jumper","year": 2008,"rating": 6.1,"votes": 258533,"running_times": 5280},{"title": "Jumpin' Jack Flash","year": 1986,"rating": 5.8,"votes": 15852,"running_times": 6300},{"title": "Junebug","year": 2005,"rating": 7,"votes": 19931,"running_times": 6360},{"title": "Jungle","year": 2017,"rating": 6.7,"votes": 16117,"running_times": 6900},{"title": "Jungle 2 Jungle","year": 1997,"rating": 5.1,"votes": 19645,"running_times": 6300},{"title": "Jungle Fever","year": 1991,"rating": 6.5,"votes": 14456,"running_times": 7920},{"title": "Junior","year": 1994,"rating": 4.6,"votes": 57432,"running_times": 6540},{"title": "Juno","year": 2007,"rating": 7.5,"votes": 442969,"running_times": 5760},{"title": "Jupiter Ascending","year": 2015,"rating": 5.3,"votes": 155246,"running_times": 7620},{"title": "Jurassic Park","year": 1993,"rating": 8.1,"votes": 695981,"running_times": 7620},{"title": "Jurassic Park III","year": 2001,"rating": 5.9,"votes": 242697,"running_times": 5520},{"title": "Jurassic World","year": 2015,"rating": 7,"votes": 476644,"running_times": 7440},{"title": "Just Before I Go","year": 2014,"rating": 6.4,"votes": 15316,"running_times": 5700},{"title": "Just Cause","year": 1995,"rating": 6.4,"votes": 21147,"running_times": 6120},{"title": "Just Friends","year": 2005,"rating": 6.2,"votes": 89395,"running_times": 5760},{"title": "Just Go with It","year": 2011,"rating": 6.4,"votes": 187549,"running_times": 7020},{"title": "Just Like Heaven","year": 2005,"rating": 6.7,"votes": 88168,"running_times": 5700},{"title": "Just Married","year": 2003,"rating": 5.5,"votes": 61009,"running_times": 5700},{"title": "Just My Luck","year": 2006,"rating": 5.4,"votes": 47721,"running_times": 6180},{"title": "Just One of the Guys","year": 1985,"rating": 6.5,"votes": 10976,"running_times": 6000},{"title": "Just Visiting","year": 2001,"rating": 5.8,"votes": 16255,"running_times": 5280},{"title": "Just Wright","year": 2010,"rating": 5.9,"votes": 11239,"running_times": 6000},{"title": "Justice League","year": 2017,"rating": 7.2,"votes": 141370,"running_times": 7200},{"title": "Justin Bieber: Never Say Never","year": 2011,"rating": 1.6,"votes": 74720,"running_times": 6900},{"title": "K-19: The Widowmaker","year": 2002,"rating": 6.7,"votes": 52505,"running_times": 8280},{"title": "K-9","year": 1989,"rating": 6,"votes": 27515,"running_times": 6060},{"title": "K-PAX","year": 2001,"rating": 7.4,"votes": 160033,"running_times": 7200},{"title": "Kabhi Alvida Naa Kehna","year": 2006,"rating": 6.1,"votes": 15518,"running_times": 11580},{"title": "Kabhi Haan Kabhi Naa","year": 1994,"rating": 8,"votes": 14320,"running_times": 9480},{"title": "Kabhi Khushi Kabhie Gham...","year": 2001,"rating": 7.5,"votes": 35341,"running_times": 12600},{"title": "Kaboom","year": 2010,"rating": 5.7,"votes": 11187,"running_times": 5160},{"title": "Kahaani","year": 2012,"rating": 8.2,"votes": 46148,"running_times": 7320},{"title": "Kaho Naa... Pyaar Hai","year": 2000,"rating": 6.9,"votes": 11078,"running_times": 10620},{"title": "Kalifornia","year": 1993,"rating": 6.7,"votes": 44968,"running_times": 7080},{"title": "Kaminey","year": 2009,"rating": 7.4,"votes": 14048,"running_times": 7800},{"title": "Kangaroo Jack","year": 2003,"rating": 4.4,"votes": 25282,"running_times": 5340},{"title": "Kapringen","year": 2012,"rating": 7.2,"votes": 13742,"running_times": 6180},{"title": "Kari-gurashi no Arietti","year": 2010,"rating": 7.6,"votes": 60734,"running_times": 5640},{"title": "Kate & Leopold","year": 2001,"rating": 6.4,"votes": 69690,"running_times": 7380},{"title": "Katy Perry: Part of Me","year": 2012,"rating": 5.9,"votes": 12764,"running_times": 5580},{"title": "Kazaam","year": 1996,"rating": 2.8,"votes": 20470,"running_times": 5580},{"title": "Kaze no tani no Naushika","year": 1984,"rating": 8.1,"votes": 111109,"running_times": 7020},{"title": "Keanu","year": 2016,"rating": 6.3,"votes": 35524,"running_times": 6000},{"title": "Keeping Mum","year": 2005,"rating": 6.8,"votes": 29947,"running_times": 5940},{"title": "Keeping Up with the Joneses","year": 2016,"rating": 5.9,"votes": 42363,"running_times": 6300},{"title": "Keeping the Faith","year": 2000,"rating": 6.4,"votes": 46463,"running_times": 7680},{"title": "Keith","year": 2008,"rating": 7.5,"votes": 32592,"running_times": 5580},{"title": "Kelly's Heroes","year": 1970,"rating": 7.7,"votes": 38115,"running_times": 8640},{"title": "Ken Park","year": 2002,"rating": 5.9,"votes": 26369,"running_times": 5880},{"title": "Kes","year": 1969,"rating": 7.9,"votes": 14791,"running_times": 6660},{"title": "Kevin & Perry Go Large","year": 2000,"rating": 5.4,"votes": 10780,"running_times": 4980},{"title": "Key Largo","year": 1948,"rating": 7.9,"votes": 31269,"running_times": 6000},{"title": "Kick-Ass","year": 2010,"rating": 7.7,"votes": 469966,"running_times": 7020},{"title": "Kick-Ass 2","year": 2013,"rating": 6.6,"votes": 222224,"running_times": 6180},{"title": "Kickboxer","year": 1989,"rating": 6.4,"votes": 40995,"running_times": 5820},{"title": "Kicking & Screaming","year": 2005,"rating": 5.6,"votes": 32051,"running_times": 5700},{"title": "Kidnap","year": 2017,"rating": 5.9,"votes": 19654,"running_times": 5700},{"title": "Kidnapping Mr. Heineken","year": 2015,"rating": 6.1,"votes": 15614,"running_times": 5700},{"title": "Kids","year": 1995,"rating": 7,"votes": 63667,"running_times": 5460},{"title": "Kidulthood","year": 2006,"rating": 6.8,"votes": 16066,"running_times": 5340},{"title": "Kill Bill: Vol. 1","year": 2003,"rating": 8.1,"votes": 818635,"running_times": 6720},{"title": "Kill Bill: Vol. 2","year": 2004,"rating": 8,"votes": 562155,"running_times": 8220},{"title": "Kill List","year": 2011,"rating": 6.4,"votes": 29640,"running_times": 5700},{"title": "Kill Me Three Times","year": 2014,"rating": 5.9,"votes": 16475,"running_times": 5400},{"title": "Kill Your Darlings","year": 2013,"rating": 6.5,"votes": 29764,"running_times": 6240},{"title": "Kill the Irishman","year": 2011,"rating": 7.1,"votes": 38020,"running_times": 6360},{"title": "Kill the Messenger","year": 2014,"rating": 7,"votes": 37172,"running_times": 6720},{"title": "Killer Elite","year": 2011,"rating": 6.5,"votes": 112178,"running_times": 6960},{"title": "Killer Joe","year": 2011,"rating": 6.7,"votes": 63883,"running_times": 6120},{"title": "Killer Klowns from Outer Space","year": 1988,"rating": 6.1,"votes": 25861,"running_times": 5400},{"title": "Killer's Kiss","year": 1955,"rating": 6.7,"votes": 17257,"running_times": 4020},{"title": "Killers","year": 2010,"rating": 5.4,"votes": 77516,"running_times": 6000},{"title": "Killing Me Softly","year": 2002,"rating": 5.5,"votes": 15313,"running_times": 6240},{"title": "Killing Season","year": 2013,"rating": 5.4,"votes": 31036,"running_times": 5460},{"title": "Killing Them Softly","year": 2012,"rating": 6.2,"votes": 118699,"running_times": 9000},{"title": "Killing Zoe","year": 1993,"rating": 6.5,"votes": 18088,"running_times": 5940},{"title": "Killshot","year": 2008,"rating": 6,"votes": 19189,"running_times": 5700},{"title": "Kimssi pyoryugi","year": 2009,"rating": 8.1,"votes": 12593,"running_times": 6960},{"title": "Kind Hearts and Coronets","year": 1949,"rating": 8.1,"votes": 29983,"running_times": 6360},{"title": "Kindergarten Cop","year": 1990,"rating": 6.1,"votes": 116526,"running_times": 6660},{"title": "King Arthur","year": 2004,"rating": 6.3,"votes": 145122,"running_times": 8520},{"title": "King Arthur: Legend of the Sword","year": 2017,"rating": 6.9,"votes": 126686,"running_times": 7560},{"title": "King Kong","year": 1933,"rating": 7.9,"votes": 69395,"running_times": 7500},{"title": "King Kong","year": 1976,"rating": 5.8,"votes": 25327,"running_times": 10920},{"title": "King Kong","year": 2005,"rating": 7.2,"votes": 343810,"running_times": 12000},{"title": "King Ralph","year": 1991,"rating": 5.2,"votes": 13406,"running_times": 5820},{"title": "King Solomon's Mines","year": 1985,"rating": 5.1,"votes": 10636,"running_times": 6000},{"title": "King of California","year": 2007,"rating": 6.7,"votes": 20594,"running_times": 5760},{"title": "King of New York","year": 1990,"rating": 7,"votes": 25783,"running_times": 6180},{"title": "Kingdom of Heaven","year": 2005,"rating": 7.2,"votes": 235089,"running_times": 11640},{"title": "Kingpin","year": 1996,"rating": 6.9,"votes": 67678,"running_times": 7020},{"title": "Kingsglaive: Final Fantasy XV","year": 2016,"rating": 6.9,"votes": 16107,"running_times": 6600},{"title": "Kingsman: The Golden Circle","year": 2017,"rating": 7,"votes": 110963,"running_times": 8460},{"title": "Kingsman: The Secret Service","year": 2014,"rating": 7.7,"votes": 484875,"running_times": 7740},{"title": "Kinky Boots","year": 2005,"rating": 7.1,"votes": 15459,"running_times": 6420},{"title": "Kinsey","year": 2004,"rating": 7.1,"votes": 44243,"running_times": 7080},{"title": "Kis Uykusu","year": 2014,"rating": 8.2,"votes": 30351,"running_times": 11760},{"title": "Kiss Kiss Bang Bang","year": 2005,"rating": 7.6,"votes": 190431,"running_times": 6180},{"title": "Kiss Me Deadly","year": 1955,"rating": 7.7,"votes": 15308,"running_times": 6360},{"title": "Kiss of Death","year": 1995,"rating": 5.9,"votes": 15074,"running_times": 6060},{"title": "Kiss of the Dragon","year": 2001,"rating": 6.6,"votes": 55800,"running_times": 5880},{"title": "Kiss of the Spider Woman","year": 1985,"rating": 7.4,"votes": 11944,"running_times": 7200},{"title": "Kiss the Girls","year": 1997,"rating": 6.6,"votes": 55048,"running_times": 6900},{"title": "Kissing Jessica Stein","year": 2001,"rating": 6.6,"votes": 14678,"running_times": 5820},{"title": "Kites","year": 2010,"rating": 6.1,"votes": 10633,"running_times": 7380},{"title": "Klute","year": 1971,"rating": 7.2,"votes": 17394,"running_times": 6840},{"title": "Knick Knack","year": 1989,"rating": 7.6,"votes": 10535,"running_times": 240},{"title": "Knight and Day","year": 2010,"rating": 6.3,"votes": 159127,"running_times": 7020},{"title": "Knight of Cups","year": 2015,"rating": 5.7,"votes": 19328,"running_times": 7080},{"title": "Knights of Badassdom","year": 2013,"rating": 5.7,"votes": 17324,"running_times": 5160},{"title": "Knock Knock","year": 2015,"rating": 4.9,"votes": 58848,"running_times": 5940},{"title": "Knock Off","year": 1998,"rating": 4.8,"votes": 12281,"running_times": 5460},{"title": "Knockaround Guys","year": 2001,"rating": 6.1,"votes": 20617,"running_times": 5520},{"title": "Knocked Up","year": 2007,"rating": 7,"votes": 315872,"running_times": 7980},{"title": "Knockin' on Heaven's Door","year": 1997,"rating": 8,"votes": 22709,"running_times": 5220},{"title": "Knowing","year": 2009,"rating": 6.2,"votes": 198560,"running_times": 7260},{"title": "Koi... Mil Gaya","year": 2003,"rating": 7.1,"votes": 16564,"running_times": 10260},{"title": "Kon-Tiki","year": 2012,"rating": 7.2,"votes": 38464,"running_times": 7080},{"title": "Kong: Skull Island","year": 2017,"rating": 6.7,"votes": 179436,"running_times": 7080},{"title": "Kopps","year": 2003,"rating": 6.8,"votes": 17114,"running_times": 5400},{"title": "Koroshiya 1","year": 2001,"rating": 7.1,"votes": 45555,"running_times": 7740},{"title": "Koto no ha no niwa","year": 2013,"rating": 7.6,"votes": 17489,"running_times": 2760},{"title": "Kraftidioten","year": 2014,"rating": 7.2,"votes": 15869,"running_times": 6960},{"title": "Kramer vs. Kramer","year": 1979,"rating": 7.8,"votes": 107796,"running_times": 6300},{"title": "Krampus","year": 2015,"rating": 6.2,"votes": 46500,"running_times": 5880},{"title": "Krrish","year": 2006,"rating": 6.3,"votes": 14376,"running_times": 11100},{"title": "Krull","year": 1983,"rating": 6.1,"votes": 25399,"running_times": 7260},{"title": "Kubo and the Two Strings","year": 2016,"rating": 7.8,"votes": 86088,"running_times": 6060},{"title": "Kuch Kuch Hota Hai","year": 1998,"rating": 7.7,"votes": 38584,"running_times": 10620},{"title": "Kumiko, the Treasure Hunter","year": 2014,"rating": 6.6,"votes": 10007,"running_times": 6300},{"title": "Kundun","year": 1997,"rating": 7,"votes": 23036,"running_times": 8040},{"title": "Kung Fu Panda","year": 2008,"rating": 7.6,"votes": 343919,"running_times": 5520},{"title": "Kung Fu Panda 2","year": 2011,"rating": 7.3,"votes": 205944,"running_times": 5400},{"title": "Kung Fu Panda 3","year": 2016,"rating": 7.1,"votes": 97816,"running_times": 5700},{"title": "Kung Fury","year": 2015,"rating": 8.1,"votes": 47091,"running_times": 1860},{"title": "Kung Pow: Enter the Fist","year": 2002,"rating": 6.2,"votes": 39822,"running_times": 5220},{"title": "Kurtlar Vadisi: Irak","year": 2006,"rating": 5.9,"votes": 15471,"running_times": 7320},{"title": "L'amant","year": 1992,"rating": 6.9,"votes": 16277,"running_times": 6960},{"title": "L'appartement","year": 1996,"rating": 7.5,"votes": 12177,"running_times": 6960},{"title": "L'armée des ombres","year": 1969,"rating": 8.2,"votes": 16310,"running_times": 8700},{"title": "L'arnacoeur","year": 2010,"rating": 6.8,"votes": 22667,"running_times": 6300},{"title": "L'auberge espagnole","year": 2002,"rating": 7.3,"votes": 36179,"running_times": 7320},{"title": "L'avventura","year": 1960,"rating": 7.9,"votes": 20494,"running_times": 8580},{"title": "L'eclisse","year": 1962,"rating": 7.9,"votes": 13282,"running_times": 7560},{"title": "L'ennemi public n°1","year": 2008,"rating": 7.5,"votes": 25292,"running_times": 7980},{"title": "L'illusionniste","year": 2010,"rating": 7.5,"votes": 30209,"running_times": 4800},{"title": "L'instinct de mort","year": 2008,"rating": 7.6,"votes": 28541,"running_times": 6780},{"title": "L'ours","year": 1988,"rating": 7.7,"votes": 14103,"running_times": 5760},{"title": "L'écume des jours","year": 2013,"rating": 6.5,"votes": 13056,"running_times": 7860},{"title": "L.A. Confidential","year": 1997,"rating": 8.3,"votes": 453989,"running_times": 8280},{"title": "L.A. Story","year": 1991,"rating": 6.7,"votes": 26514,"running_times": 5700},{"title": "LOL","year": 2012,"rating": 4.3,"votes": 48379,"running_times": 5820},{"title": "La Bamba","year": 1987,"rating": 6.8,"votes": 23070,"running_times": 6480},{"title": "La La Land","year": 2016,"rating": 8.1,"votes": 330222,"running_times": 7680},{"title": "La Luna","year": 2011,"rating": 8,"votes": 10173,"running_times": 420},{"title": "La battaglia di Algeri","year": 1966,"rating": 8.1,"votes": 42954,"running_times": 7260},{"title": "La belle et la bête","year": 2014,"rating": 6.4,"votes": 16164,"running_times": 6720},{"title": "La dolce vita","year": 1960,"rating": 8.1,"votes": 54029,"running_times": 10800},{"title": "La grande illusion","year": 1937,"rating": 8.1,"votes": 29036,"running_times": 6780},{"title": "La grande vadrouille","year": 1966,"rating": 8,"votes": 12617,"running_times": 7920},{"title": "La leggenda del pianista sull'oceano","year": 1998,"rating": 8.1,"votes": 45764,"running_times": 9900},{"title": "La marche de l'empereur","year": 2005,"rating": 7.6,"votes": 50416,"running_times": 4800},{"title": "La maschera del demonio","year": 1960,"rating": 7.3,"votes": 10828,"running_times": 5220},{"title": "La meglio gioventù","year": 2003,"rating": 8.5,"votes": 17794,"running_times": 21960},{"title": "La migliore offerta","year": 2013,"rating": 7.8,"votes": 83547,"running_times": 7860},{"title": "La montaña sagrada","year": 1973,"rating": 7.9,"votes": 27321,"running_times": 6840},{"title": "La môme","year": 2007,"rating": 7.6,"votes": 72235,"running_times": 8400},{"title": "La nuit américaine","year": 1973,"rating": 8.1,"votes": 16124,"running_times": 6900},{"title": "La règle du jeu","year": 1939,"rating": 8.1,"votes": 22461,"running_times": 6600},{"title": "La science des rêves","year": 2006,"rating": 7.3,"votes": 63946,"running_times": 6300},{"title": "La tigre e la neve","year": 2005,"rating": 7.2,"votes": 12250,"running_times": 6840},{"title": "La vie d'Adèle","year": 2013,"rating": 7.8,"votes": 109423,"running_times": 10800},{"title": "La vita è bella","year": 1997,"rating": 8.6,"votes": 484883,"running_times": 7320},{"title": "Labor Day","year": 2013,"rating": 6.9,"votes": 35525,"running_times": 6660},{"title": "Labyrinth","year": 1986,"rating": 7.4,"votes": 104063,"running_times": 6060},{"title": "Ladder 49","year": 2004,"rating": 6.5,"votes": 50649,"running_times": 6900},{"title": "Lady Bird","year": 2017,"rating": 8.4,"votes": 10997,"running_times": 5640},{"title": "Lady and the Tramp","year": 1955,"rating": 7.3,"votes": 96911,"running_times": 4560},{"title": "Lady in the Water","year": 2006,"rating": 5.6,"votes": 84760,"running_times": 6600},{"title": "Ladyhawke","year": 1985,"rating": 7,"votes": 36607,"running_times": 7260},{"title": "Lagaan: Once Upon a Time in India","year": 2001,"rating": 8.2,"votes": 83674,"running_times": 13440},{"title": "Laggies","year": 2014,"rating": 6.4,"votes": 35284,"running_times": 5940},{"title": "Lake Mungo","year": 2008,"rating": 6.1,"votes": 11249,"running_times": 5340},{"title": "Lake Placid","year": 1999,"rating": 5.6,"votes": 46572,"running_times": 4920},{"title": "Lakeview Terrace","year": 2008,"rating": 6.1,"votes": 43282,"running_times": 6600},{"title": "Lakposhtha parvaz mikonand","year": 2004,"rating": 8.1,"votes": 14924,"running_times": 5880},{"title": "Lakshya","year": 2004,"rating": 7.9,"votes": 15400,"running_times": 11160},{"title": "Land of the Dead","year": 2005,"rating": 6.2,"votes": 83236,"running_times": 5820},{"title": "Land of the Lost","year": 2009,"rating": 5.4,"votes": 55270,"running_times": 6120},{"title": "Lantana","year": 2001,"rating": 7.3,"votes": 17192,"running_times": 7260},{"title": "Lara Croft Tomb Raider: The Cradle of Life","year": 2003,"rating": 5.5,"votes": 111378,"running_times": 7020},{"title": "Lara Croft: Tomb Raider","year": 2001,"rating": 5.8,"votes": 169611,"running_times": 6000},{"title": "Largo Winch","year": 2008,"rating": 6.5,"votes": 12004,"running_times": 6480},{"title": "Larry Crowne","year": 2011,"rating": 6.1,"votes": 54197,"running_times": 5880},{"title": "Lars and the Real Girl","year": 2007,"rating": 7.4,"votes": 123925,"running_times": 6360},{"title": "Last Action Hero","year": 1993,"rating": 6.3,"votes": 115720,"running_times": 7800},{"title": "Last Chance Harvey","year": 2008,"rating": 6.7,"votes": 18870,"running_times": 5580},{"title": "Last Days","year": 2005,"rating": 5.8,"votes": 19794,"running_times": 5820},{"title": "Last Holiday","year": 2006,"rating": 6.4,"votes": 23312,"running_times": 6720},{"title": "Last Knights","year": 2015,"rating": 6.2,"votes": 32149,"running_times": 6900},{"title": "Last Man Standing","year": 1996,"rating": 6.4,"votes": 47431,"running_times": 6060},{"title": "Last Night","year": 2010,"rating": 6.6,"votes": 42441,"running_times": 5580},{"title": "Last Shift","year": 2014,"rating": 5.8,"votes": 12443,"running_times": 5400},{"title": "Last Vegas","year": 2013,"rating": 6.6,"votes": 115090,"running_times": 6300},{"title": "Lat sau san taam","year": 1992,"rating": 7.9,"votes": 41050,"running_times": 7860},{"title": "Latter Days","year": 2003,"rating": 7.1,"votes": 15357,"running_times": 6420},{"title": "Laura","year": 1944,"rating": 8.1,"votes": 35204,"running_times": 5280},{"title": "Laurel Canyon","year": 2002,"rating": 6.4,"votes": 13693,"running_times": 6180},{"title": "Laurence Anyways","year": 2012,"rating": 7.6,"votes": 13696,"running_times": 10080},{"title": "Lava","year": 2014,"rating": 7.2,"votes": 11034,"running_times": 420},{"title": "Law Abiding Citizen","year": 2009,"rating": 7.4,"votes": 234737,"running_times": 7080},{"title": "Lawless","year": 2012,"rating": 7.3,"votes": 201216,"running_times": 6960},{"title": "Lawrence of Arabia","year": 1962,"rating": 8.3,"votes": 215696,"running_times": 13680},{"title": "Laws of Attraction","year": 2004,"rating": 5.9,"votes": 19929,"running_times": 5400},{"title": "Layer Cake","year": 2004,"rating": 7.4,"votes": 143588,"running_times": 6300},{"title": "Le cinquième élément","year": 1997,"rating": 7.7,"votes": 374767,"running_times": 7560},{"title": "Le divorce","year": 2003,"rating": 4.9,"votes": 10178,"running_times": 7020},{"title": "Le fabuleux destin d'Amélie Poulain","year": 2001,"rating": 8.3,"votes": 594927,"running_times": 7320},{"title": "Le grand bleu","year": 1988,"rating": 7.6,"votes": 41252,"running_times": 10080},{"title": "Le locataire","year": 1976,"rating": 7.8,"votes": 30919,"running_times": 7560},{"title": "Le mépris","year": 1963,"rating": 7.7,"votes": 22380,"running_times": 6180},{"title": "Le procès","year": 1962,"rating": 7.8,"votes": 15401,"running_times": 7140},{"title": "Le salaire de la peur","year": 1953,"rating": 8.2,"votes": 40345,"running_times": 9360},{"title": "Le violon rouge","year": 1998,"rating": 7.7,"votes": 28394,"running_times": 8400},{"title": "Lean on Me","year": 1989,"rating": 7.4,"votes": 15573,"running_times": 6480},{"title": "Leap Year","year": 2010,"rating": 6.5,"votes": 78668,"running_times": 6000},{"title": "Leap of Faith","year": 1992,"rating": 6.1,"votes": 10526,"running_times": 6480},{"title": "Leatherface: Texas Chainsaw Massacre III","year": 1990,"rating": 5.2,"votes": 11025,"running_times": 5100},{"title": "Leatherheads","year": 2008,"rating": 6,"votes": 28907,"running_times": 6840},{"title": "Leaves of Grass","year": 2009,"rating": 6.5,"votes": 24966,"running_times": 6300},{"title": "Leaving Las Vegas","year": 1995,"rating": 7.6,"votes": 100091,"running_times": 6660},{"title": "Lebanon","year": 2009,"rating": 6.9,"votes": 10014,"running_times": 5580},{"title": "Left Behind","year": 2014,"rating": 3.1,"votes": 28793,"running_times": 6600},{"title": "Legally Blonde","year": 2001,"rating": 6.2,"votes": 147263,"running_times": 5760},{"title": "Legally Blonde 2: Red, White & Blonde","year": 2003,"rating": 4.7,"votes": 51197,"running_times": 5700},{"title": "Legend","year": 1985,"rating": 6.5,"votes": 50438,"running_times": 6840},{"title": "Legend","year": 2015,"rating": 7,"votes": 118845,"running_times": 7920},{"title": "Legend of the Guardians: The Owls of Ga'Hoole","year": 2010,"rating": 7,"votes": 70245,"running_times": 6060},{"title": "Legends of the Fall","year": 1994,"rating": 7.5,"votes": 122945,"running_times": 7980},{"title": "Legion","year": 2010,"rating": 5.2,"votes": 86405,"running_times": 6000},{"title": "Legionnaire","year": 1998,"rating": 5.4,"votes": 19924,"running_times": 5940},{"title": "Lenny","year": 1974,"rating": 7.6,"votes": 12098,"running_times": 6660},{"title": "Lepa sela lepo gore","year": 1996,"rating": 8.7,"votes": 12099,"running_times": 6900},{"title": "Leprechaun","year": 1993,"rating": 4.7,"votes": 18932,"running_times": 5520},{"title": "Les Misérables","year": 1998,"rating": 7.5,"votes": 34086,"running_times": 8040},{"title": "Les Misérables","year": 2012,"rating": 7.6,"votes": 264958,"running_times": 9480},{"title": "Les amours imaginaires","year": 2010,"rating": 7.2,"votes": 21824,"running_times": 6060},{"title": "Les aventures extraordinaires d'Adèle Blanc-Sec","year": 2010,"rating": 6.3,"votes": 17227,"running_times": 6420},{"title": "Les diaboliques","year": 1955,"rating": 8.1,"votes": 47931,"running_times": 7020},{"title": "Les invasions barbares","year": 2003,"rating": 7.7,"votes": 25965,"running_times": 6720},{"title": "Les parapluies de Cherbourg","year": 1964,"rating": 7.8,"votes": 17936,"running_times": 5460},{"title": "Les poupées russes","year": 2005,"rating": 7,"votes": 17598,"running_times": 7740},{"title": "Les quatre cents coups","year": 1959,"rating": 8.1,"votes": 79751,"running_times": 5940},{"title": "Les triplettes de Belleville","year": 2003,"rating": 7.8,"votes": 45275,"running_times": 4800},{"title": "Les vacances de Monsieur Hulot","year": 1953,"rating": 7.6,"votes": 13779,"running_times": 6840},{"title": "Les visiteurs","year": 1993,"rating": 7,"votes": 27169,"running_times": 6420},{"title": "Lesbian Vampire Killers","year": 2009,"rating": 5.2,"votes": 18201,"running_times": 5280},{"title": "Less Than Zero","year": 1987,"rating": 6.4,"votes": 15649,"running_times": 5880},{"title": "Let Me In","year": 2010,"rating": 7.2,"votes": 100116,"running_times": 6960},{"title": "Let's Be Cops","year": 2014,"rating": 6.5,"votes": 115774,"running_times": 6240},{"title": "Let's Go to Prison","year": 2006,"rating": 6,"votes": 20966,"running_times": 5400},{"title": "Lethal Weapon","year": 1987,"rating": 7.6,"votes": 206476,"running_times": 7020},{"title": "Lethal Weapon 2","year": 1989,"rating": 7.2,"votes": 139179,"running_times": 7080},{"title": "Lethal Weapon 3","year": 1992,"rating": 6.7,"votes": 137501,"running_times": 7260},{"title": "Lethal Weapon 4","year": 1998,"rating": 6.6,"votes": 136125,"running_times": 7620},{"title": "Letters from Iwo Jima","year": 2006,"rating": 7.9,"votes": 139966,"running_times": 8460},{"title": "Letters to Juliet","year": 2010,"rating": 6.6,"votes": 80645,"running_times": 6300},{"title": "Leviathan","year": 1989,"rating": 5.8,"votes": 14534,"running_times": 5880},{"title": "Liar Liar","year": 1997,"rating": 6.8,"votes": 240776,"running_times": 5160},{"title": "Liberal Arts","year": 2012,"rating": 6.7,"votes": 31904,"running_times": 5820},{"title": "Licence to Kill","year": 1989,"rating": 6.6,"votes": 79978,"running_times": 7980},{"title": "License to Drive","year": 1988,"rating": 6.3,"votes": 15196,"running_times": 5280},{"title": "License to Wed","year": 2007,"rating": 5.3,"votes": 34018,"running_times": 5460},{"title": "Lie with Me","year": 2005,"rating": 5.4,"votes": 12624,"running_times": 5580},{"title": "Life","year": 1999,"rating": 6.7,"votes": 36663,"running_times": 6480},{"title": "Life","year": 2017,"rating": 6.6,"votes": 137763,"running_times": 6240},{"title": "Life After Beth","year": 2014,"rating": 5.6,"votes": 15831,"running_times": 5340},{"title": "Life Itself","year": 2014,"rating": 7.8,"votes": 13010,"running_times": 7200},{"title": "Life as We Know It","year": 2010,"rating": 6.6,"votes": 104933,"running_times": 6840},{"title": "Life as a House","year": 2001,"rating": 7.5,"votes": 40518,"running_times": 7620},{"title": "Life in a Day","year": 2011,"rating": 7.7,"votes": 13937,"running_times": 5700},{"title": "Life of Brian","year": 1979,"rating": 8.1,"votes": 300297,"running_times": 5640},{"title": "Life of Crime","year": 2013,"rating": 5.8,"votes": 14325,"running_times": 5880},{"title": "Life of Pi","year": 2012,"rating": 7.9,"votes": 489527,"running_times": 7620},{"title": "Life or Something Like It","year": 2002,"rating": 5.8,"votes": 20754,"running_times": 6300},{"title": "Lifeboat","year": 1944,"rating": 7.8,"votes": 22355,"running_times": 5820},{"title": "Lifeforce","year": 1985,"rating": 6.1,"votes": 17593,"running_times": 6960},{"title": "Lights Out","year": 2016,"rating": 6.3,"votes": 84024,"running_times": 4860},{"title": "Like Crazy","year": 2011,"rating": 6.7,"votes": 52116,"running_times": 5160},{"title": "Like Mike","year": 2002,"rating": 5.2,"votes": 16319,"running_times": 5940},{"title": "Lilja 4-ever","year": 2002,"rating": 7.9,"votes": 37844,"running_times": 6540},{"title": "Lilo & Stitch","year": 2002,"rating": 7.2,"votes": 133382,"running_times": 5100},{"title": "Limelight","year": 1952,"rating": 8.1,"votes": 14677,"running_times": 8820},{"title": "Limitless","year": 2011,"rating": 7.4,"votes": 459364,"running_times": 6300},{"title": "Lincoln","year": 2012,"rating": 7.4,"votes": 213471,"running_times": 9000},{"title": "Lion","year": 2016,"rating": 8.1,"votes": 143387,"running_times": 7080},{"title": "Lion of the Desert","year": 1980,"rating": 8.4,"votes": 11257,"running_times": 10380},{"title": "Lionheart","year": 1990,"rating": 6.2,"votes": 27363,"running_times": 6480},{"title": "Lions for Lambs","year": 2007,"rating": 6.2,"votes": 43204,"running_times": 5520},{"title": "Little Big Man","year": 1970,"rating": 7.6,"votes": 28772,"running_times": 8820},{"title": "Little Black Book","year": 2004,"rating": 5.3,"votes": 15930,"running_times": 6660},{"title": "Little Boy","year": 2015,"rating": 7.4,"votes": 19507,"running_times": 6360},{"title": "Little Buddha","year": 1993,"rating": 6,"votes": 13350,"running_times": 8460},{"title": "Little Children","year": 2006,"rating": 7.6,"votes": 96874,"running_times": 8220},{"title": "Little Fockers","year": 2010,"rating": 5.5,"votes": 92568,"running_times": 5880},{"title": "Little Giants","year": 1994,"rating": 6.3,"votes": 21322,"running_times": 6420},{"title": "Little Man Tate","year": 1991,"rating": 6.7,"votes": 12292,"running_times": 5940},{"title": "Little Manhattan","year": 2005,"rating": 7.6,"votes": 20074,"running_times": 5400},{"title": "Little Miss Sunshine","year": 2006,"rating": 7.8,"votes": 384705,"running_times": 6060},{"title": "Little Nicky","year": 2000,"rating": 5.3,"votes": 86181,"running_times": 5400},{"title": "Little Shop of Horrors","year": 1986,"rating": 6.9,"votes": 54010,"running_times": 6120},{"title": "Little Voice","year": 1998,"rating": 7,"votes": 14546,"running_times": 5820},{"title": "Little Women","year": 1994,"rating": 7.3,"votes": 39880,"running_times": 6900},{"title": "Littleman","year": 2006,"rating": 4.3,"votes": 42807,"running_times": 5880},{"title": "Live Free or Die Hard","year": 2007,"rating": 7.2,"votes": 354620,"running_times": 7740},{"title": "Live and Let Die","year": 1973,"rating": 6.8,"votes": 81462,"running_times": 7260},{"title": "Live by Night","year": 2016,"rating": 6.4,"votes": 37860,"running_times": 7740},{"title": "Living in Oblivion","year": 1995,"rating": 7.5,"votes": 13790,"running_times": 5400},{"title": "Lo imposible","year": 2012,"rating": 7.6,"votes": 162773,"running_times": 6840},{"title": "Loaded Weapon 1","year": 1993,"rating": 6.1,"votes": 39692,"running_times": 5040},{"title": "Local Hero","year": 1983,"rating": 7.5,"votes": 17301,"running_times": 6660},{"title": "Lock Up","year": 1989,"rating": 6.4,"votes": 32444,"running_times": 6540},{"title": "Lock, Stock and Two Smoking Barrels","year": 1998,"rating": 8.2,"votes": 455613,"running_times": 7200},{"title": "Locke","year": 2013,"rating": 7.1,"votes": 106566,"running_times": 5100},{"title": "Lockout","year": 2012,"rating": 6.1,"votes": 86175,"running_times": 5700},{"title": "Logan","year": 2017,"rating": 8.2,"votes": 417826,"running_times": 8220},{"title": "Logan Lucky","year": 2017,"rating": 7.1,"votes": 44509,"running_times": 7080},{"title": "Logan's Run","year": 1976,"rating": 6.8,"votes": 43654,"running_times": 7140},{"title": "Lola rennt","year": 1998,"rating": 7.7,"votes": 170737,"running_times": 4860},{"title": "Lolita","year": 1962,"rating": 7.6,"votes": 75313,"running_times": 9180},{"title": "Lolita","year": 1997,"rating": 6.9,"votes": 42179,"running_times": 8220},{"title": "London","year": 2005,"rating": 6.6,"votes": 20332,"running_times": 5520},{"title": "London Boulevard","year": 2010,"rating": 6.2,"votes": 42810,"running_times": 6180},{"title": "London Has Fallen","year": 2016,"rating": 5.9,"votes": 108802,"running_times": 5940},{"title": "Lone Star","year": 1996,"rating": 7.5,"votes": 24721,"running_times": 8100},{"title": "Lone Survivor","year": 2013,"rating": 7.5,"votes": 227936,"running_times": 7260},{"title": "Lonely Hearts","year": 2006,"rating": 6.5,"votes": 18568,"running_times": 6480},{"title": "Look Who's Talking","year": 1989,"rating": 5.8,"votes": 68218,"running_times": 5580},{"title": "Look Who's Talking Now","year": 1993,"rating": 4.2,"votes": 23987,"running_times": 5760},{"title": "Look Who's Talking Too","year": 1990,"rating": 4.5,"votes": 39326,"running_times": 4860},{"title": "Looking for Eric","year": 2009,"rating": 7.2,"votes": 13977,"running_times": 6960},{"title": "Looney Tunes: Back in Action","year": 2003,"rating": 5.7,"votes": 27194,"running_times": 5460},{"title": "Looper","year": 2012,"rating": 7.4,"votes": 467183,"running_times": 7140},{"title": "Lord of Illusions","year": 1995,"rating": 6.1,"votes": 12128,"running_times": 7260},{"title": "Lord of War","year": 2005,"rating": 7.6,"votes": 263932,"running_times": 7320},{"title": "Lord of the Flies","year": 1963,"rating": 7,"votes": 14798,"running_times": 5520},{"title": "Lord of the Flies","year": 1990,"rating": 6.4,"votes": 24260,"running_times": 5400},{"title": "Lords of Dogtown","year": 2005,"rating": 7.1,"votes": 46833,"running_times": 6420},{"title": "Lore","year": 2012,"rating": 7.1,"votes": 12480,"running_times": 6540},{"title": "Lorenzo's Oil","year": 1992,"rating": 7.2,"votes": 17664,"running_times": 7740},{"title": "Los abrazos rotos","year": 2009,"rating": 7.2,"votes": 33706,"running_times": 7620},{"title": "Los amantes del Círculo Polar","year": 1998,"rating": 7.8,"votes": 16141,"running_times": 6720},{"title": "Loser","year": 2000,"rating": 5.3,"votes": 24126,"running_times": 5880},{"title": "Lost Highway","year": 1997,"rating": 7.6,"votes": 108996,"running_times": 8040},{"title": "Lost Horizon","year": 1937,"rating": 7.8,"votes": 10155,"running_times": 7920},{"title": "Lost River","year": 2014,"rating": 5.8,"votes": 13919,"running_times": 6720},{"title": "Lost and Delirious","year": 2001,"rating": 7,"votes": 18057,"running_times": 6180},{"title": "Lost in Space","year": 1998,"rating": 5.1,"votes": 61812,"running_times": 7800},{"title": "Lost in Translation","year": 2003,"rating": 7.8,"votes": 349205,"running_times": 6120},{"title": "Love & Basketball","year": 2000,"rating": 7.2,"votes": 15596,"running_times": 7440},{"title": "Love & Friendship","year": 2016,"rating": 6.5,"votes": 18384,"running_times": 5400},{"title": "Love & Mercy","year": 2014,"rating": 7.4,"votes": 29208,"running_times": 7260},{"title": "Love & Other Drugs","year": 2010,"rating": 6.7,"votes": 156299,"running_times": 6720},{"title": "Love","year": 2015,"rating": 6,"votes": 27109,"running_times": 8100},{"title": "Love Actually","year": 2003,"rating": 7.7,"votes": 351260,"running_times": 8100},{"title": "Love Happens","year": 2009,"rating": 5.6,"votes": 27218,"running_times": 6540},{"title": "Love Is Strange","year": 2014,"rating": 6.7,"votes": 10779,"running_times": 5640},{"title": "Love Potion No. 9","year": 1992,"rating": 5.6,"votes": 11182,"running_times": 5520},{"title": "Love Story","year": 1970,"rating": 6.9,"votes": 24825,"running_times": 5940},{"title": "Love Wrecked","year": 2005,"rating": 4.9,"votes": 12563,"running_times": 5220},{"title": "Love and Death","year": 1975,"rating": 7.8,"votes": 30482,"running_times": 5100},{"title": "Love and Other Disasters","year": 2006,"rating": 6.2,"votes": 12430,"running_times": 5400},{"title": "Love and Other Impossible Pursuits","year": 2009,"rating": 6.4,"votes": 16603,"running_times": 7140},{"title": "Love in the Afternoon","year": 1957,"rating": 7.3,"votes": 11220,"running_times": 7800},{"title": "Love in the Time of Cholera","year": 2007,"rating": 6.4,"votes": 20278,"running_times": 8340},{"title": "Love the Coopers","year": 2015,"rating": 5.7,"votes": 14440,"running_times": 6420},{"title": "Love, Rosie","year": 2014,"rating": 7.2,"votes": 87349,"running_times": 6120},{"title": "Lovelace","year": 2013,"rating": 6.2,"votes": 33759,"running_times": 5580},{"title": "Loving","year": 2016,"rating": 7,"votes": 22583,"running_times": 7380},{"title": "Loving Annabelle","year": 2006,"rating": 6.6,"votes": 10150,"running_times": 4560},{"title": "Lucas","year": 1986,"rating": 6.8,"votes": 12451,"running_times": 6000},{"title": "Lucky Number Slevin","year": 2006,"rating": 7.8,"votes": 277942,"running_times": 6600},{"title": "Lucky You","year": 2007,"rating": 5.9,"votes": 18963,"running_times": 7440},{"title": "Lucy","year": 2014,"rating": 6.4,"votes": 368660,"running_times": 5340},{"title": "Lucía y el sexo","year": 2001,"rating": 7.2,"votes": 31388,"running_times": 7680},{"title": "Lung hing foo dai","year": 1986,"rating": 7.1,"votes": 14172,"running_times": 5880},{"title": "Luther","year": 2003,"rating": 6.6,"votes": 13543,"running_times": 7380},{"title": "Lymelife","year": 2008,"rating": 7,"votes": 13184,"running_times": 5700},{"title": "Léon","year": 1994,"rating": 8.6,"votes": 819957,"running_times": 8160},{"title": "MASH","year": 1970,"rating": 7.6,"votes": 59702,"running_times": 6960},{"title": "MSG: The Messenger","year": 2015,"rating": 6.8,"votes": 10998,"running_times": 11820},{"title": "MacGruber","year": 2010,"rating": 5.5,"votes": 37968,"running_times": 5700},{"title": "Macbeth","year": 2015,"rating": 6.7,"votes": 44443,"running_times": 6780},{"title": "Machete","year": 2010,"rating": 6.6,"votes": 174552,"running_times": 6300},{"title": "Machete Kills","year": 2013,"rating": 5.6,"votes": 64908,"running_times": 6420},{"title": "Machine Gun Preacher","year": 2011,"rating": 6.8,"votes": 57085,"running_times": 7740},{"title": "Mad City","year": 1997,"rating": 6.2,"votes": 17393,"running_times": 6900},{"title": "Mad Dog and Glory","year": 1993,"rating": 6.2,"votes": 18261,"running_times": 5820},{"title": "Mad Max","year": 1979,"rating": 7,"votes": 165182,"running_times": 5580},{"title": "Mad Max 2","year": 1981,"rating": 7.6,"votes": 145142,"running_times": 5760},{"title": "Mad Max Beyond Thunderdome","year": 1985,"rating": 6.3,"votes": 110404,"running_times": 6420},{"title": "Mad Max: Fury Road","year": 2015,"rating": 8.1,"votes": 676904,"running_times": 7200},{"title": "Mad Money","year": 2008,"rating": 5.8,"votes": 17870,"running_times": 6240},{"title": "Madagascar","year": 2005,"rating": 6.9,"votes": 298407,"running_times": 5160},{"title": "Madagascar 3: Europe's Most Wanted","year": 2012,"rating": 6.9,"votes": 132064,"running_times": 5580},{"title": "Madagascar: Escape 2 Africa","year": 2008,"rating": 6.7,"votes": 164323,"running_times": 5340},{"title": "Made","year": 2001,"rating": 6.4,"votes": 15671,"running_times": 5700},{"title": "Made in America","year": 1993,"rating": 4.9,"votes": 12814,"running_times": 6660},{"title": "Made in Dagenham","year": 2010,"rating": 7.2,"votes": 12016,"running_times": 6780},{"title": "Made of Honor","year": 2008,"rating": 5.9,"votes": 59008,"running_times": 6060},{"title": "Madea Goes to Jail","year": 2009,"rating": 4.3,"votes": 10213,"running_times": 6180},{"title": "Maggie","year": 2015,"rating": 5.6,"votes": 35761,"running_times": 5700},{"title": "Maggie's Plan","year": 2015,"rating": 6.2,"votes": 11381,"running_times": 5880},{"title": "Magic Mike","year": 2012,"rating": 6.1,"votes": 116802,"running_times": 6600},{"title": "Magic Mike XXL","year": 2015,"rating": 5.6,"votes": 44596,"running_times": 6900},{"title": "Magic in the Moonlight","year": 2014,"rating": 6.6,"votes": 54096,"running_times": 5820},{"title": "Magnolia","year": 1999,"rating": 8,"votes": 255829,"running_times": 11280},{"title": "Magnum Force","year": 1973,"rating": 7.2,"votes": 47198,"running_times": 7440},{"title": "Maid in Manhattan","year": 2002,"rating": 5.1,"votes": 73669,"running_times": 6300},{"title": "Majo no takkyûbin","year": 1989,"rating": 7.9,"votes": 87286,"running_times": 6180},{"title": "Major League","year": 1989,"rating": 7.2,"votes": 52776,"running_times": 6420},{"title": "Major League II","year": 1994,"rating": 5.5,"votes": 21849,"running_times": 6300},{"title": "Major Payne","year": 1995,"rating": 6.2,"votes": 24817,"running_times": 5700},{"title": "Malcolm X","year": 1992,"rating": 7.7,"votes": 69810,"running_times": 12120},{"title": "Maleficent","year": 2014,"rating": 7,"votes": 278768,"running_times": 5820},{"title": "Malibu's Most Wanted","year": 2003,"rating": 5.1,"votes": 16870,"running_times": 5160},{"title": "Malice","year": 1993,"rating": 6.4,"votes": 19587,"running_times": 6420},{"title": "Mallrats","year": 1995,"rating": 7.2,"votes": 104168,"running_times": 7380},{"title": "Malèna","year": 2000,"rating": 7.5,"votes": 72681,"running_times": 6540},{"title": "Mama","year": 2013,"rating": 6.2,"votes": 148340,"running_times": 6000},{"title": "Mamma Mia!","year": 2008,"rating": 6.4,"votes": 159125,"running_times": 6480},{"title": "Man Up","year": 2015,"rating": 6.8,"votes": 39572,"running_times": 5280},{"title": "Man of Steel","year": 2013,"rating": 7.1,"votes": 600877,"running_times": 8580},{"title": "Man of Tai Chi","year": 2013,"rating": 6.1,"votes": 30729,"running_times": 6300},{"title": "Man of the House","year": 2005,"rating": 5.4,"votes": 20850,"running_times": 6000},{"title": "Man of the Year","year": 2006,"rating": 6.2,"votes": 29232,"running_times": 6900},{"title": "Man on Fire","year": 2004,"rating": 7.7,"votes": 287637,"running_times": 8760},{"title": "Man on Wire","year": 2008,"rating": 7.8,"votes": 45633,"running_times": 5640},{"title": "Man on a Ledge","year": 2012,"rating": 6.6,"votes": 131789,"running_times": 6120},{"title": "Man on the Moon","year": 1999,"rating": 7.4,"votes": 108535,"running_times": 7080},{"title": "Management","year": 2008,"rating": 5.9,"votes": 15648,"running_times": 5640},{"title": "Manchester by the Sea","year": 2016,"rating": 7.9,"votes": 169860,"running_times": 8220},{"title": "Mandela: Long Walk to Freedom","year": 2013,"rating": 7.1,"votes": 23331,"running_times": 8460},{"title": "Manderlay","year": 2005,"rating": 7.4,"votes": 19865,"running_times": 8340},{"title": "Manhattan","year": 1979,"rating": 8,"votes": 114313,"running_times": 5760},{"title": "Manhattan Murder Mystery","year": 1993,"rating": 7.4,"votes": 31311,"running_times": 6240},{"title": "Manhunter","year": 1986,"rating": 7.2,"votes": 54697,"running_times": 7440},{"title": "Maniac","year": 1980,"rating": 6.5,"votes": 11244,"running_times": 5220},{"title": "Maniac","year": 2012,"rating": 6.1,"votes": 30088,"running_times": 5340},{"title": "Maniac Cop","year": 1988,"rating": 6,"votes": 11047,"running_times": 5460},{"title": "Mannequin","year": 1987,"rating": 5.8,"votes": 24870,"running_times": 5400},{"title": "Manos: The Hands of Fate","year": 1966,"rating": 1.9,"votes": 32272,"running_times": 4200},{"title": "Mansfield Park","year": 1999,"rating": 7.1,"votes": 18343,"running_times": 6720},{"title": "Maps to the Stars","year": 2014,"rating": 6.2,"votes": 32048,"running_times": 6660},{"title": "Marathon Man","year": 1976,"rating": 7.5,"votes": 48758,"running_times": 7500},{"title": "Marauders","year": 2016,"rating": 5.5,"votes": 12275,"running_times": 6420},{"title": "Margaret","year": 2011,"rating": 6.5,"votes": 13896,"running_times": 11160},{"title": "Margin Call","year": 2011,"rating": 7.1,"votes": 100514,"running_times": 6420},{"title": "Margot at the Wedding","year": 2007,"rating": 6.1,"votes": 17187,"running_times": 5580},{"title": "Maria Full of Grace","year": 2004,"rating": 7.5,"votes": 31731,"running_times": 6060},{"title": "Marie Antoinette","year": 2006,"rating": 6.4,"votes": 86766,"running_times": 7380},{"title": "Marked for Death","year": 1990,"rating": 5.9,"votes": 16524,"running_times": 5580},{"title": "Marley & Me","year": 2008,"rating": 7.1,"votes": 127015,"running_times": 6900},{"title": "Marley","year": 2012,"rating": 8,"votes": 11860,"running_times": 8640},{"title": "Marmaduke","year": 2010,"rating": 4.2,"votes": 12249,"running_times": 5220},{"title": "Marnie","year": 1964,"rating": 7.2,"votes": 37177,"running_times": 7800},{"title": "Married to the Mob","year": 1988,"rating": 6.1,"votes": 13549,"running_times": 6240},{"title": "Mars Attacks!","year": 1996,"rating": 6.3,"votes": 185254,"running_times": 6360},{"title": "Mars Needs Moms","year": 2011,"rating": 5.4,"votes": 18755,"running_times": 5280},{"title": "Martha Marcy May Marlene","year": 2011,"rating": 6.9,"votes": 43275,"running_times": 6120},{"title": "Martian Child","year": 2007,"rating": 6.8,"votes": 18295,"running_times": 6360},{"title": "Marty","year": 1955,"rating": 7.7,"votes": 17265,"running_times": 5640},{"title": "Marvin's Room","year": 1996,"rating": 6.7,"votes": 21938,"running_times": 5880},{"title": "Mary Poppins","year": 1964,"rating": 7.8,"votes": 120704,"running_times": 8340},{"title": "Mary Reilly","year": 1996,"rating": 5.8,"votes": 12578,"running_times": 6480},{"title": "Mary Shelley's Frankenstein","year": 1994,"rating": 6.4,"votes": 45406,"running_times": 7380},{"title": "Mary and Max","year": 2009,"rating": 8.1,"votes": 134929,"running_times": 5520},{"title": "Mask","year": 1985,"rating": 7.2,"votes": 22226,"running_times": 7620},{"title": "Master and Commander: The Far Side of the World","year": 2003,"rating": 7.4,"votes": 179736,"running_times": 8280},{"title": "Masterminds","year": 2016,"rating": 5.8,"votes": 36500,"running_times": 5700},{"title": "Masters of the Universe","year": 1987,"rating": 5.4,"votes": 30771,"running_times": 8340},{"title": "Match Point","year": 2005,"rating": 7.7,"votes": 180746,"running_times": 7440},{"title": "Matchstick Men","year": 2003,"rating": 7.3,"votes": 112733,"running_times": 6960},{"title": "Material Girls","year": 2006,"rating": 3.9,"votes": 19988,"running_times": 5880},{"title": "Matilda","year": 1996,"rating": 6.8,"votes": 99960,"running_times": 6120},{"title": "Maurice","year": 1987,"rating": 7.7,"votes": 12111,"running_times": 8400},{"title": "Maverick","year": 1994,"rating": 7,"votes": 89064,"running_times": 7620},{"title": "Max","year": 2015,"rating": 6.8,"votes": 22467,"running_times": 6660},{"title": "Max Manus","year": 2008,"rating": 7.3,"votes": 23654,"running_times": 7080},{"title": "Max Payne","year": 2008,"rating": 5.4,"votes": 113037,"running_times": 6180},{"title": "Max Steel","year": 2016,"rating": 4.6,"votes": 14154,"running_times": 5520},{"title": "Maximum Overdrive","year": 1986,"rating": 5.4,"votes": 25300,"running_times": 5880},{"title": "Maximum Risk","year": 1996,"rating": 5.5,"votes": 17162,"running_times": 6060},{"title": "May","year": 2002,"rating": 6.7,"votes": 28776,"running_times": 5580},{"title": "Maze Runner: The Scorch Trials","year": 2015,"rating": 6.3,"votes": 170192,"running_times": 7860},{"title": "McCabe & Mrs. Miller","year": 1971,"rating": 7.7,"votes": 18101,"running_times": 7260},{"title": "McFarland, USA","year": 2015,"rating": 7.4,"votes": 28260,"running_times": 7740},{"title": "McLintock!","year": 1963,"rating": 7.3,"votes": 10231,"running_times": 7620},{"title": "Me Before You","year": 2016,"rating": 7.4,"votes": 133986,"running_times": 6360},{"title": "Me and Earl and the Dying Girl","year": 2015,"rating": 7.8,"votes": 99372,"running_times": 6300},{"title": "Me and You and Everyone We Know","year": 2005,"rating": 7.3,"votes": 32526,"running_times": 5460},{"title": "Me, Myself & Irene","year": 2000,"rating": 6.6,"votes": 198415,"running_times": 6960},{"title": "Mean Creek","year": 2004,"rating": 7.3,"votes": 28002,"running_times": 5400},{"title": "Mean Girls","year": 2004,"rating": 7,"votes": 274107,"running_times": 5820},{"title": "Mean Machine","year": 2001,"rating": 6.5,"votes": 31492,"running_times": 5940},{"title": "Mean Streets","year": 1973,"rating": 7.4,"votes": 76168,"running_times": 6720},{"title": "Meatballs","year": 1979,"rating": 6.2,"votes": 15923,"running_times": 5640},{"title": "Mechanic: Resurrection","year": 2016,"rating": 5.7,"votes": 55890,"running_times": 5880},{"title": "Medianeras","year": 2011,"rating": 7.6,"votes": 11721,"running_times": 5700},{"title": "Medicine Man","year": 1992,"rating": 6,"votes": 18595,"running_times": 6360},{"title": "Mediterraneo","year": 1991,"rating": 7.4,"votes": 11592,"running_times": 5760},{"title": "Meet Dave","year": 2008,"rating": 4.9,"votes": 33803,"running_times": 5400},{"title": "Meet Joe Black","year": 1998,"rating": 7.2,"votes": 182493,"running_times": 10680},{"title": "Meet John Doe","year": 1941,"rating": 7.7,"votes": 10038,"running_times": 7320},{"title": "Meet Me in St. Louis","year": 1944,"rating": 7.7,"votes": 16521,"running_times": 6780},{"title": "Meet the Blacks","year": 2016,"rating": 5.8,"votes": 19571,"running_times": 5640},{"title": "Meet the Feebles","year": 1989,"rating": 6.7,"votes": 16761,"running_times": 5820},{"title": "Meet the Fockers","year": 2004,"rating": 6.3,"votes": 225530,"running_times": 6900},{"title": "Meet the Parents","year": 2000,"rating": 7,"votes": 277578,"running_times": 6480},{"title": "Meet the Robinsons","year": 2007,"rating": 6.9,"votes": 74057,"running_times": 5700},{"title": "Meet the Spartans","year": 2008,"rating": 2.7,"votes": 93548,"running_times": 5160},{"title": "Meeting Evil","year": 2012,"rating": 5.3,"votes": 10575,"running_times": 5340},{"title": "Megamind","year": 2010,"rating": 7.3,"votes": 190379,"running_times": 5700},{"title": "Megan Leavey","year": 2017,"rating": 7.1,"votes": 11096,"running_times": 6960},{"title": "Melancholia","year": 2011,"rating": 7.1,"votes": 141879,"running_times": 8100},{"title": "Melinda and Melinda","year": 2004,"rating": 6.5,"votes": 28638,"running_times": 5940},{"title": "Memento","year": 2000,"rating": 8.5,"votes": 942167,"running_times": 6780},{"title": "Memoirs of a Geisha","year": 2005,"rating": 7.4,"votes": 125653,"running_times": 8700},{"title": "Memoirs of an Invisible Man","year": 1992,"rating": 5.9,"votes": 18853,"running_times": 5940},{"title": "Memorîzu","year": 1995,"rating": 7.6,"votes": 12744,"running_times": 6780},{"title": "Memphis Belle","year": 1990,"rating": 6.9,"votes": 24107,"running_times": 6420},{"title": "Men at Work","year": 1990,"rating": 5.9,"votes": 19577,"running_times": 5880},{"title": "Men in Black","year": 1997,"rating": 7.3,"votes": 443481,"running_times": 5880},{"title": "Men in Black 3","year": 2012,"rating": 6.8,"votes": 285598,"running_times": 6360},{"title": "Men in Black II","year": 2002,"rating": 6.1,"votes": 287094,"running_times": 5280},{"title": "Men of Honor","year": 2000,"rating": 7.2,"votes": 95757,"running_times": 7740},{"title": "Men, Women & Children","year": 2014,"rating": 6.7,"votes": 25774,"running_times": 7140},{"title": "Menace II Society","year": 1993,"rating": 7.5,"votes": 43249,"running_times": 5820},{"title": "Meng long guo jiang","year": 1972,"rating": 7.3,"votes": 25866,"running_times": 7980},{"title": "Mercury Rising","year": 1998,"rating": 6.1,"votes": 58173,"running_times": 6660},{"title": "Mermaids","year": 1990,"rating": 6.6,"votes": 24084,"running_times": 6600},{"title": "Merry Christmas Mr. Lawrence","year": 1983,"rating": 7.3,"votes": 11952,"running_times": 7380},{"title": "Message in a Bottle","year": 1999,"rating": 6.2,"votes": 31337,"running_times": 7560},{"title": "Metal: A Headbanger's Journey","year": 2005,"rating": 8.1,"votes": 10570,"running_times": 5880},{"title": "Metallica Through the Never","year": 2013,"rating": 7.2,"votes": 14579,"running_times": 5580},{"title": "Metallica: Some Kind of Monster","year": 2004,"rating": 7.5,"votes": 14893,"running_times": 8460},{"title": "Metoroporisu","year": 2001,"rating": 7.3,"votes": 18053,"running_times": 6780},{"title": "Metro","year": 1997,"rating": 5.5,"votes": 22659,"running_times": 7020},{"title": "Miami Vice","year": 2006,"rating": 6,"votes": 98088,"running_times": 8400},{"title": "Michael","year": 1996,"rating": 5.7,"votes": 36663,"running_times": 6300},{"title": "Michael Clayton","year": 2007,"rating": 7.3,"votes": 142224,"running_times": 7140},{"title": "Michael Collins","year": 1996,"rating": 7.1,"votes": 25953,"running_times": 7980},{"title": "Mickey Blue Eyes","year": 1999,"rating": 5.8,"votes": 31377,"running_times": 6120},{"title": "Middle Men","year": 2009,"rating": 6.6,"votes": 34183,"running_times": 6300},{"title": "Midnight Cowboy","year": 1969,"rating": 7.9,"votes": 83242,"running_times": 6780},{"title": "Midnight Express","year": 1978,"rating": 7.6,"votes": 59898,"running_times": 7260},{"title": "Midnight Run","year": 1988,"rating": 7.6,"votes": 59112,"running_times": 7560},{"title": "Midnight Special","year": 2016,"rating": 6.7,"votes": 60015,"running_times": 6720},{"title": "Midnight in Paris","year": 2011,"rating": 7.7,"votes": 331832,"running_times": 6000},{"title": "Midnight in the Garden of Good and Evil","year": 1997,"rating": 6.6,"votes": 33568,"running_times": 9300},{"title": "Midway","year": 1976,"rating": 6.8,"votes": 14666,"running_times": 7920},{"title": "Mighty Aphrodite","year": 1995,"rating": 7.1,"votes": 34007,"running_times": 5700},{"title": "Mighty Joe Young","year": 1998,"rating": 5.6,"votes": 24571,"running_times": 6840},{"title": "Mighty Morphin Power Rangers: The Movie","year": 1995,"rating": 5.1,"votes": 21853,"running_times": 5700},{"title": "Mike and Dave Need Wedding Dates","year": 2016,"rating": 6,"votes": 63508,"running_times": 5880},{"title": "Mildred Pierce","year": 1945,"rating": 8,"votes": 18004,"running_times": 6660},{"title": "Milk","year": 2008,"rating": 7.6,"votes": 146757,"running_times": 7680},{"title": "Miller's Crossing","year": 1990,"rating": 7.8,"votes": 111289,"running_times": 6900},{"title": "Million Dollar Arm","year": 2014,"rating": 7,"votes": 38810,"running_times": 7440},{"title": "Million Dollar Baby","year": 2004,"rating": 8.1,"votes": 535783,"running_times": 7920},{"title": "Millions","year": 2004,"rating": 6.9,"votes": 22849,"running_times": 5880},{"title": "Mimi wo sumaseba","year": 1995,"rating": 8,"votes": 35076,"running_times": 6660},{"title": "Mimic","year": 1997,"rating": 5.9,"votes": 39674,"running_times": 6720},{"title": "Mindhunters","year": 2004,"rating": 6.4,"votes": 52528,"running_times": 6360},{"title": "Minions","year": 2015,"rating": 6.4,"votes": 172484,"running_times": 5460},{"title": "Minority Report","year": 2002,"rating": 7.7,"votes": 435364,"running_times": 8700},{"title": "Miracle","year": 2004,"rating": 7.5,"votes": 39564,"running_times": 8100},{"title": "Miracle at St. Anna","year": 2008,"rating": 6,"votes": 16362,"running_times": 9600},{"title": "Miracle on 34th Street","year": 1947,"rating": 7.9,"votes": 33497,"running_times": 6060},{"title": "Miracle on 34th Street","year": 1994,"rating": 6.4,"votes": 25109,"running_times": 6840},{"title": "Miracles from Heaven","year": 2016,"rating": 7,"votes": 13888,"running_times": 6540},{"title": "Mirror Mirror","year": 2012,"rating": 5.6,"votes": 75292,"running_times": 6360},{"title": "Mirrormask","year": 2005,"rating": 6.9,"votes": 21061,"running_times": 6060},{"title": "Mirrors","year": 2008,"rating": 6.2,"votes": 92362,"running_times": 6720},{"title": "Misconduct","year": 2016,"rating": 5.3,"votes": 11364,"running_times": 6360},{"title": "Misery","year": 1990,"rating": 7.8,"votes": 149872,"running_times": 6420},{"title": "Miss Congeniality","year": 2000,"rating": 6.2,"votes": 152953,"running_times": 6540},{"title": "Miss Congeniality 2: Armed and Fabulous","year": 2005,"rating": 5,"votes": 57183,"running_times": 6900},{"title": "Miss March","year": 2009,"rating": 5,"votes": 19250,"running_times": 5400},{"title": "Miss Peregrine's Home for Peculiar Children","year": 2016,"rating": 6.7,"votes": 121273,"running_times": 7620},{"title": "Miss Pettigrew Lives for a Day","year": 2008,"rating": 7.1,"votes": 23635,"running_times": 5520},{"title": "Miss Potter","year": 2006,"rating": 7,"votes": 25274,"running_times": 5280},{"title": "Miss Sloane","year": 2016,"rating": 7.4,"votes": 32325,"running_times": 7920},{"title": "Miss You Already","year": 2015,"rating": 6.8,"votes": 13120,"running_times": 6720},{"title": "Missing","year": 1982,"rating": 7.8,"votes": 15297,"running_times": 7320},{"title": "Missing in Action","year": 1984,"rating": 5.3,"votes": 11580,"running_times": 6060},{"title": "Mission to Mars","year": 2000,"rating": 5.6,"votes": 64003,"running_times": 6840},{"title": "Mission: Impossible","year": 1996,"rating": 7.1,"votes": 326602,"running_times": 6600},{"title": "Mission: Impossible - Ghost Protocol","year": 2011,"rating": 7.4,"votes": 391959,"running_times": 7920},{"title": "Mission: Impossible - Rogue Nation","year": 2015,"rating": 7.4,"votes": 269296,"running_times": 7860},{"title": "Mission: Impossible II","year": 2000,"rating": 6.1,"votes": 263036,"running_times": 14400},{"title": "Mission: Impossible III","year": 2006,"rating": 6.9,"votes": 278264,"running_times": 7560},{"title": "Mississippi Burning","year": 1988,"rating": 7.8,"votes": 71359,"running_times": 7680},{"title": "Mississippi Grind","year": 2015,"rating": 6.3,"votes": 13547,"running_times": 6480},{"title": "Mister Roberts","year": 1955,"rating": 7.8,"votes": 13571,"running_times": 7380},{"title": "Mistress America","year": 2015,"rating": 6.7,"votes": 19864,"running_times": 5040},{"title": "Moana","year": 2016,"rating": 7.6,"votes": 169284,"running_times": 6420},{"title": "Moby Dick","year": 1956,"rating": 7.4,"votes": 14561,"running_times": 6960},{"title": "Modern Times","year": 1936,"rating": 8.5,"votes": 165123,"running_times": 5220},{"title": "Momentum","year": 2015,"rating": 5.5,"votes": 10775,"running_times": 5760},{"title": "Mommie Dearest","year": 1981,"rating": 6.7,"votes": 12068,"running_times": 7740},{"title": "Mommy","year": 2014,"rating": 8.1,"votes": 36886,"running_times": 8340},{"title": "Moms' Night Out","year": 2014,"rating": 5.5,"votes": 11563,"running_times": 5880},{"title": "Mona Lisa","year": 1986,"rating": 7.4,"votes": 10846,"running_times": 6240},{"title": "Mona Lisa Smile","year": 2003,"rating": 6.4,"votes": 66594,"running_times": 7020},{"title": "Money Monster","year": 2016,"rating": 6.5,"votes": 74698,"running_times": 5880},{"title": "Money Talks","year": 1997,"rating": 6.2,"votes": 23953,"running_times": 5820},{"title": "Money Train","year": 1995,"rating": 5.6,"votes": 34379,"running_times": 6600},{"title": "Moneyball","year": 2011,"rating": 7.6,"votes": 305109,"running_times": 7980},{"title": "Monkey Business","year": 1952,"rating": 7,"votes": 10755,"running_times": 5820},{"title": "Monkeybone","year": 2001,"rating": 4.7,"votes": 15142,"running_times": 5580},{"title": "Monsieur Lazhar","year": 2011,"rating": 7.5,"votes": 17159,"running_times": 5640},{"title": "Monsieur Verdoux","year": 1947,"rating": 8,"votes": 12827,"running_times": 7440},{"title": "Monsoon Wedding","year": 2001,"rating": 7.4,"votes": 21016,"running_times": 6840},{"title": "Monster","year": 2003,"rating": 7.3,"votes": 115609,"running_times": 6540},{"title": "Monster House","year": 2006,"rating": 6.6,"votes": 80929,"running_times": 5460},{"title": "Monster Trucks","year": 2016,"rating": 5.7,"votes": 10288,"running_times": 6240},{"title": "Monster's Ball","year": 2001,"rating": 7.1,"votes": 75193,"running_times": 6720},{"title": "Monster-in-Law","year": 2005,"rating": 5.5,"votes": 47838,"running_times": 6060},{"title": "Monsters","year": 2010,"rating": 6.4,"votes": 80963,"running_times": 5640},{"title": "Monsters University","year": 2013,"rating": 7.3,"votes": 263070,"running_times": 6240},{"title": "Monsters vs. Aliens","year": 2009,"rating": 6.5,"votes": 125293,"running_times": 5640},{"title": "Monsters, Inc.","year": 2001,"rating": 8.1,"votes": 661782,"running_times": 5520},{"title": "Monte Carlo","year": 2011,"rating": 5.8,"votes": 36047,"running_times": 6540},{"title": "Monty Python Live at the Hollywood Bowl","year": 1982,"rating": 7.9,"votes": 12068,"running_times": 4620},{"title": "Monty Python and the Holy Grail","year": 1975,"rating": 8.3,"votes": 419568,"running_times": 5460},{"title": "Moon","year": 2009,"rating": 7.9,"votes": 286855,"running_times": 5820},{"title": "Moonlight","year": 2016,"rating": 7.5,"votes": 171817,"running_times": 6660},{"title": "Moonlight Mile","year": 2002,"rating": 6.7,"votes": 12518,"running_times": 8760},{"title": "Moonraker","year": 1979,"rating": 6.3,"votes": 75827,"running_times": 7560},{"title": "Moonrise Kingdom","year": 2012,"rating": 7.8,"votes": 264990,"running_times": 5640},{"title": "Moonstruck","year": 1987,"rating": 7.1,"votes": 39131,"running_times": 6120},{"title": "Moonwalker","year": 1988,"rating": 6,"votes": 13485,"running_times": 5580},{"title": "Morgan","year": 2016,"rating": 5.8,"votes": 28784,"running_times": 5520},{"title": "Morning Glory","year": 2010,"rating": 6.5,"votes": 63060,"running_times": 6420},{"title": "Mortal Kombat","year": 1995,"rating": 5.8,"votes": 87746,"running_times": 6060},{"title": "Mortal Kombat: Annihilation","year": 1997,"rating": 3.7,"votes": 39249,"running_times": 5700},{"title": "Mortdecai","year": 2015,"rating": 5.5,"votes": 54994,"running_times": 6420},{"title": "Morte a Venezia","year": 1971,"rating": 7.5,"votes": 15085,"running_times": 7800},{"title": "Mother and Child","year": 2009,"rating": 7.2,"votes": 10396,"running_times": 7500},{"title": "Mother!","year": 2017,"rating": 6.9,"votes": 65060,"running_times": 7260},{"title": "Mother's Day","year": 2010,"rating": 6.3,"votes": 14047,"running_times": 6720},{"title": "Mother's Day","year": 2016,"rating": 5.6,"votes": 23336,"running_times": 7080},{"title": "Mou gaan dou","year": 2002,"rating": 8.1,"votes": 101710,"running_times": 6060},{"title": "Mou gaan dou II","year": 2003,"rating": 7.4,"votes": 14467,"running_times": 7140},{"title": "Moulin Rouge!","year": 2001,"rating": 7.6,"votes": 238849,"running_times": 7620},{"title": "Mousehunt","year": 1997,"rating": 6.4,"votes": 44738,"running_times": 5880},{"title": "Movie 43","year": 2013,"rating": 4.3,"votes": 86504,"running_times": 5640},{"title": "Mr 3000","year": 2004,"rating": 5.5,"votes": 12827,"running_times": 6240},{"title": "Mr. & Mrs. Smith","year": 2005,"rating": 6.5,"votes": 384128,"running_times": 7560},{"title": "Mr. Bean's Holiday","year": 2007,"rating": 6.3,"votes": 97284,"running_times": 5400},{"title": "Mr. Brooks","year": 2007,"rating": 7.3,"votes": 130745,"running_times": 7200},{"title": "Mr. Church","year": 2016,"rating": 7.6,"votes": 18951,"running_times": 6240},{"title": "Mr. Deeds","year": 2002,"rating": 5.8,"votes": 119207,"running_times": 5760},{"title": "Mr. Deeds Goes to Town","year": 1936,"rating": 8,"votes": 16367,"running_times": 6900},{"title": "Mr. Destiny","year": 1990,"rating": 6.3,"votes": 10098,"running_times": 6600},{"title": "Mr. Holland's Opus","year": 1995,"rating": 7.3,"votes": 31822,"running_times": 8580},{"title": "Mr. Holmes","year": 2015,"rating": 6.9,"votes": 52427,"running_times": 6240},{"title": "Mr. Magoo","year": 1997,"rating": 3.9,"votes": 12824,"running_times": 5220},{"title": "Mr. Magorium's Wonder Emporium","year": 2007,"rating": 6.2,"votes": 37848,"running_times": 5580},{"title": "Mr. Mom","year": 1983,"rating": 6.5,"votes": 17571,"running_times": 5460},{"title": "Mr. Morgan's Last Love","year": 2013,"rating": 6.8,"votes": 10599,"running_times": 6660},{"title": "Mr. Nobody","year": 2009,"rating": 7.9,"votes": 176739,"running_times": 9420},{"title": "Mr. Peabody & Sherman","year": 2014,"rating": 6.8,"votes": 53028,"running_times": 5520},{"title": "Mr. Popper's Penguins","year": 2011,"rating": 6,"votes": 73897,"running_times": 5640},{"title": "Mr. Right","year": 2015,"rating": 6.3,"votes": 34544,"running_times": 5700},{"title": "Mr. Smith Goes to Washington","year": 1939,"rating": 8.2,"votes": 85911,"running_times": 7740},{"title": "Mr. Turner","year": 2014,"rating": 6.8,"votes": 20793,"running_times": 9000},{"title": "Mr. Woodcock","year": 2007,"rating": 5.1,"votes": 32431,"running_times": 5220},{"title": "Mrs Brown","year": 1997,"rating": 7.3,"votes": 11844,"running_times": 6060},{"title": "Mrs Henderson Presents","year": 2005,"rating": 7.1,"votes": 14089,"running_times": 6180},{"title": "Mrs. Doubtfire","year": 1993,"rating": 6.9,"votes": 201287,"running_times": 7500},{"title": "Mrs. Miniver","year": 1942,"rating": 7.6,"votes": 12803,"running_times": 8040},{"title": "Much Ado About Nothing","year": 1993,"rating": 7.4,"votes": 39702,"running_times": 6660},{"title": "Much Ado About Nothing","year": 2012,"rating": 7.2,"votes": 14790,"running_times": 6540},{"title": "Mud","year": 2012,"rating": 7.4,"votes": 147427,"running_times": 7800},{"title": "Mulan","year": 1998,"rating": 7.6,"votes": 196734,"running_times": 5280},{"title": "Mulholland Dr.","year": 2001,"rating": 8,"votes": 267364,"running_times": 8820},{"title": "Mulholland Falls","year": 1996,"rating": 6.2,"votes": 13844,"running_times": 6420},{"title": "Multiplicity","year": 1996,"rating": 6,"votes": 26392,"running_times": 7020},{"title": "Munich","year": 2005,"rating": 7.6,"votes": 188027,"running_times": 9840},{"title": "Muppet Treasure Island","year": 1996,"rating": 6.9,"votes": 17495,"running_times": 5940},{"title": "Muppets Most Wanted","year": 2014,"rating": 6.4,"votes": 26686,"running_times": 7140},{"title": "Muppets from Space","year": 1999,"rating": 6.3,"votes": 15770,"running_times": 5280},{"title": "Murder at 1600","year": 1997,"rating": 6.1,"votes": 25149,"running_times": 6480},{"title": "Murder by Death","year": 1976,"rating": 7.4,"votes": 27268,"running_times": 5640},{"title": "Murder by Numbers","year": 2002,"rating": 6.1,"votes": 46580,"running_times": 6900},{"title": "Murder in the First","year": 1995,"rating": 7.3,"votes": 23309,"running_times": 7320},{"title": "Murder on the Orient Express","year": 1974,"rating": 7.3,"votes": 43168,"running_times": 7680},{"title": "Murder on the Orient Express","year": 2017,"rating": 6.8,"votes": 55516,"running_times": 6840},{"title": "Muriel's Wedding","year": 1994,"rating": 7.2,"votes": 30018,"running_times": 6360},{"title": "Music and Lyrics","year": 2007,"rating": 6.5,"votes": 86957,"running_times": 6360},{"title": "Music of the Heart","year": 1999,"rating": 6.8,"votes": 10711,"running_times": 7440},{"title": "Must Love Dogs","year": 2005,"rating": 5.9,"votes": 27642,"running_times": 5880},{"title": "Mutant Chronicles","year": 2008,"rating": 5.2,"votes": 24332,"running_times": 6660},{"title": "Mutiny on the Bounty","year": 1935,"rating": 7.8,"votes": 17571,"running_times": 7920},{"title": "Mutiny on the Bounty","year": 1962,"rating": 7.2,"votes": 12571,"running_times": 11100},{"title": "My Beautiful Laundrette","year": 1985,"rating": 6.9,"votes": 11620,"running_times": 5820},{"title": "My Best Friend's Girl","year": 2008,"rating": 5.9,"votes": 39104,"running_times": 6720},{"title": "My Best Friend's Wedding","year": 1997,"rating": 6.3,"votes": 107518,"running_times": 6300},{"title": "My Big Fat Greek Wedding","year": 2002,"rating": 6.6,"votes": 108638,"running_times": 5700},{"title": "My Big Fat Greek Wedding 2","year": 2016,"rating": 6,"votes": 22601,"running_times": 5640},{"title": "My Bloody Valentine","year": 1981,"rating": 6.2,"votes": 13928,"running_times": 5580},{"title": "My Bloody Valentine","year": 2009,"rating": 5.5,"votes": 48197,"running_times": 6060},{"title": "My Blue Heaven","year": 1990,"rating": 6.2,"votes": 16465,"running_times": 5820},{"title": "My Blueberry Nights","year": 2007,"rating": 6.7,"votes": 47098,"running_times": 5700},{"title": "My Boss's Daughter","year": 2003,"rating": 4.7,"votes": 25546,"running_times": 5400},{"title": "My Cousin Vinny","year": 1992,"rating": 7.5,"votes": 89632,"running_times": 7200},{"title": "My Darling Clementine","year": 1946,"rating": 7.8,"votes": 17919,"running_times": 6180},{"title": "My Dinner with Andre","year": 1981,"rating": 7.8,"votes": 13680,"running_times": 6600},{"title": "My Dog Skip","year": 2000,"rating": 7,"votes": 17536,"running_times": 5700},{"title": "My Fair Lady","year": 1964,"rating": 7.9,"votes": 73415,"running_times": 10200},{"title": "My Favorite Martian","year": 1999,"rating": 5,"votes": 11486,"running_times": 5640},{"title": "My Fellow Americans","year": 1996,"rating": 6.5,"votes": 12910,"running_times": 6060},{"title": "My Girl","year": 1991,"rating": 6.8,"votes": 61084,"running_times": 6120},{"title": "My Girl 2","year": 1994,"rating": 5.2,"votes": 16062,"running_times": 5940},{"title": "My Left Foot: The Story of Christy Brown","year": 1989,"rating": 7.9,"votes": 55465,"running_times": 6180},{"title": "My Life Without Me","year": 2003,"rating": 7.6,"votes": 22176,"running_times": 6420},{"title": "My Life in Ruins","year": 2009,"rating": 5.9,"votes": 16255,"running_times": 5880},{"title": "My Little Eye","year": 2002,"rating": 5.6,"votes": 10696,"running_times": 5700},{"title": "My Man Godfrey","year": 1936,"rating": 8.1,"votes": 16984,"running_times": 5640},{"title": "My Name Is Bruce","year": 2007,"rating": 6.3,"votes": 22187,"running_times": 5040},{"title": "My Name Is Khan","year": 2010,"rating": 8,"votes": 82373,"running_times": 9900},{"title": "My Own Private Idaho","year": 1991,"rating": 7.1,"votes": 40621,"running_times": 6240},{"title": "My Sassy Girl","year": 2008,"rating": 6.3,"votes": 18325,"running_times": 5520},{"title": "My Sister's Keeper","year": 2009,"rating": 7.4,"votes": 80671,"running_times": 6540},{"title": "My Soul to Take","year": 2010,"rating": 4.8,"votes": 17463,"running_times": 6420},{"title": "My Stepmother Is an Alien","year": 1988,"rating": 5.2,"votes": 22451,"running_times": 6300},{"title": "My Summer of Love","year": 2004,"rating": 6.8,"votes": 17370,"running_times": 5160},{"title": "My Super Ex-Girlfriend","year": 2006,"rating": 5.1,"votes": 56499,"running_times": 5760},{"title": "My Week with Marilyn","year": 2011,"rating": 7,"votes": 75892,"running_times": 5940},{"title": "Mysterious Skin","year": 2004,"rating": 7.7,"votes": 60112,"running_times": 6420},{"title": "Mystery Men","year": 1999,"rating": 6.1,"votes": 56460,"running_times": 7260},{"title": "Mystery Science Theater 3000: The Movie","year": 1996,"rating": 7.4,"votes": 16482,"running_times": 4380},{"title": "Mystery Train","year": 1989,"rating": 7.6,"votes": 20535,"running_times": 6600},{"title": "Mystery, Alaska","year": 1999,"rating": 6.7,"votes": 23221,"running_times": 7140},{"title": "Mystic Pizza","year": 1988,"rating": 6.2,"votes": 20318,"running_times": 6240},{"title": "Mystic River","year": 2003,"rating": 8,"votes": 365071,"running_times": 8280},{"title": "Män som hatar kvinnor","year": 2009,"rating": 7.8,"votes": 186700,"running_times": 11160},{"title": "Nacho Libre","year": 2006,"rating": 5.7,"votes": 70536,"running_times": 5520},{"title": "Naked","year": 1993,"rating": 7.9,"votes": 26891,"running_times": 7920},{"title": "Naked Gun 33 1/3: The Final Insult","year": 1994,"rating": 6.5,"votes": 83247,"running_times": 4980},{"title": "Naked Lunch","year": 1991,"rating": 7.1,"votes": 39652,"running_times": 6900},{"title": "Nancy Drew","year": 2007,"rating": 5.9,"votes": 17051,"running_times": 5940},{"title": "Nanny McPhee","year": 2005,"rating": 6.6,"votes": 55817,"running_times": 5880},{"title": "Nanny McPhee and the Big Bang","year": 2010,"rating": 6.1,"votes": 22057,"running_times": 6540},{"title": "Napoleon Dynamite","year": 2004,"rating": 6.9,"votes": 172599,"running_times": 5760},{"title": "Narc","year": 2002,"rating": 7.2,"votes": 35543,"running_times": 6300},{"title": "Nashville","year": 1975,"rating": 7.8,"votes": 19364,"running_times": 9600},{"title": "National Lampoon's Christmas Vacation","year": 1989,"rating": 7.6,"votes": 118874,"running_times": 5820},{"title": "National Lampoon's European Vacation","year": 1985,"rating": 6.1,"votes": 47396,"running_times": 5700},{"title": "National Lampoon's Vacation","year": 1983,"rating": 7.4,"votes": 78815,"running_times": 5880},{"title": "National Security","year": 2003,"rating": 5.6,"votes": 41680,"running_times": 5280},{"title": "National Treasure","year": 2004,"rating": 6.9,"votes": 270548,"running_times": 7860},{"title": "National Treasure: Book of Secrets","year": 2007,"rating": 6.5,"votes": 194576,"running_times": 7440},{"title": "Natural Born Killers","year": 1994,"rating": 7.3,"votes": 187627,"running_times": 7320},{"title": "Navy Seals","year": 1990,"rating": 5.5,"votes": 13865,"running_times": 6780},{"title": "Nayakan","year": 1987,"rating": 8.8,"votes": 10378,"running_times": 9360},{"title": "Near Dark","year": 1987,"rating": 7,"votes": 27846,"running_times": 5640},{"title": "Nebraska","year": 2013,"rating": 7.7,"votes": 98852,"running_times": 6900},{"title": "Ned Kelly","year": 2003,"rating": 6.5,"votes": 23002,"running_times": 6600},{"title": "Need for Speed","year": 2014,"rating": 6.5,"votes": 146918,"running_times": 7920},{"title": "Needful Things","year": 1993,"rating": 6.2,"votes": 18544,"running_times": 10980},{"title": "Neerja","year": 2016,"rating": 7.8,"votes": 15336,"running_times": 7320},{"title": "Neighbors","year": 2014,"rating": 6.3,"votes": 246015,"running_times": 5820},{"title": "Neighbors 2: Sorority Rising","year": 2016,"rating": 5.7,"votes": 85986,"running_times": 5520},{"title": "Neko no ongaeshi","year": 2002,"rating": 7.3,"votes": 35049,"running_times": 4500},{"title": "Nell","year": 1994,"rating": 6.5,"votes": 24192,"running_times": 6720},{"title": "Nerve","year": 2016,"rating": 6.6,"votes": 84651,"running_times": 5760},{"title": "Network","year": 1976,"rating": 8.1,"votes": 116290,"running_times": 7260},{"title": "Never Back Down","year": 2008,"rating": 6.6,"votes": 86232,"running_times": 6600},{"title": "Never Been Kissed","year": 1999,"rating": 6,"votes": 73008,"running_times": 6420},{"title": "Never Let Me Go","year": 2010,"rating": 7.2,"votes": 120871,"running_times": 6180},{"title": "Never Say Never Again","year": 1983,"rating": 6.2,"votes": 52439,"running_times": 8040},{"title": "New Jack City","year": 1991,"rating": 6.6,"votes": 26155,"running_times": 6060},{"title": "New Nightmare","year": 1994,"rating": 6.4,"votes": 42203,"running_times": 6720},{"title": "New Year's Eve","year": 2011,"rating": 5.7,"votes": 71453,"running_times": 6780},{"title": "New York Minute","year": 2004,"rating": 4.9,"votes": 18985,"running_times": 5460},{"title": "New York Stories","year": 1989,"rating": 6.4,"votes": 14779,"running_times": 7440},{"title": "New York, I Love You","year": 2008,"rating": 6.3,"votes": 41493,"running_times": 6180},{"title": "New York, New York","year": 1977,"rating": 6.7,"votes": 14965,"running_times": 9780},{"title": "New in Town","year": 2009,"rating": 5.6,"votes": 18943,"running_times": 5820},{"title": "Newsies","year": 1992,"rating": 7,"votes": 16512,"running_times": 7260},{"title": "Next","year": 2007,"rating": 6.2,"votes": 132917,"running_times": 5760},{"title": "Next Friday","year": 2000,"rating": 6.1,"votes": 30612,"running_times": 5880},{"title": "Ngo si seoi","year": 1998,"rating": 6.8,"votes": 30599,"running_times": 7200},{"title": "Niagara","year": 1953,"rating": 7.1,"votes": 12158,"running_times": 5520},{"title": "Nicholas Nickleby","year": 2002,"rating": 7.2,"votes": 10065,"running_times": 7920},{"title": "Nick and Norah's Infinite Playlist","year": 2008,"rating": 6.7,"votes": 79582,"running_times": 5400},{"title": "Nick of Time","year": 1995,"rating": 6.3,"votes": 34746,"running_times": 5400},{"title": "Night Moves","year": 2013,"rating": 6,"votes": 11460,"running_times": 6720},{"title": "Night Shift","year": 1982,"rating": 6.5,"votes": 11930,"running_times": 6360},{"title": "Night Train to Lisbon","year": 2013,"rating": 6.8,"votes": 14887,"running_times": 6660},{"title": "Night at the Museum","year": 2006,"rating": 6.4,"votes": 261448,"running_times": 6480},{"title": "Night at the Museum: Battle of the Smithsonian","year": 2009,"rating": 5.9,"votes": 145596,"running_times": 6300},{"title": "Night at the Museum: Secret of the Tomb","year": 2014,"rating": 6.2,"votes": 79834,"running_times": 5880},{"title": "Night of the Comet","year": 1984,"rating": 6.4,"votes": 14499,"running_times": 5700},{"title": "Night of the Creeps","year": 1986,"rating": 6.8,"votes": 16397,"running_times": 5280},{"title": "Night of the Demons","year": 1988,"rating": 6.3,"votes": 10119,"running_times": 5400},{"title": "Night of the Living Dead","year": 1968,"rating": 7.9,"votes": 96882,"running_times": 5760},{"title": "Night of the Living Dead","year": 1990,"rating": 6.9,"votes": 33568,"running_times": 5520},{"title": "Night on Earth","year": 1991,"rating": 7.8,"votes": 45481,"running_times": 7740},{"title": "Nightbreed","year": 1990,"rating": 6.6,"votes": 15960,"running_times": 8700},{"title": "Nightcrawler","year": 2014,"rating": 7.9,"votes": 354755,"running_times": 7080},{"title": "Nighthawks","year": 1981,"rating": 6.4,"votes": 13721,"running_times": 5940},{"title": "Nights in Rodanthe","year": 2008,"rating": 6,"votes": 19672,"running_times": 5820},{"title": "Nightwatch","year": 1997,"rating": 6.2,"votes": 17099,"running_times": 6060},{"title": "Nikita","year": 1990,"rating": 7.4,"votes": 59142,"running_times": 7020},{"title": "Nim's Island","year": 2008,"rating": 6,"votes": 29823,"running_times": 5760},{"title": "Nine","year": 2009,"rating": 5.8,"votes": 39270,"running_times": 7080},{"title": "Nine 1/2 Weeks","year": 1986,"rating": 5.9,"votes": 32143,"running_times": 7020},{"title": "Nine Dead","year": 2010,"rating": 5.5,"votes": 10493,"running_times": 5880},{"title": "Nine Lives","year": 2016,"rating": 5.3,"votes": 15077,"running_times": 5220},{"title": "Nine Months","year": 1995,"rating": 5.5,"votes": 31636,"running_times": 6180},{"title": "Nine to Five","year": 1980,"rating": 6.7,"votes": 22127,"running_times": 6540},{"title": "Nineteen Eighty-Four","year": 1984,"rating": 7.2,"votes": 54961,"running_times": 6780},{"title": "Ninja","year": 2009,"rating": 5.5,"votes": 10491,"running_times": 5160},{"title": "Ninja Assassin","year": 2009,"rating": 6.4,"votes": 61464,"running_times": 5940},{"title": "Ninotchka","year": 1939,"rating": 8,"votes": 15743,"running_times": 6600},{"title": "Nirgendwo in Afrika","year": 2001,"rating": 7.7,"votes": 11252,"running_times": 8460},{"title": "Nixon","year": 1995,"rating": 7.1,"votes": 25610,"running_times": 12720},{"title": "No Country for Old Men","year": 2007,"rating": 8.1,"votes": 689593,"running_times": 7320},{"title": "No Escape","year": 1994,"rating": 6.1,"votes": 16664,"running_times": 7080},{"title": "No Escape","year": 2015,"rating": 6.8,"votes": 62445,"running_times": 6180},{"title": "No Good Deed","year": 2014,"rating": 5.6,"votes": 14427,"running_times": 5040},{"title": "No Man's Land","year": 2001,"rating": 8,"votes": 39957,"running_times": 5880},{"title": "No One Lives","year": 2012,"rating": 6,"votes": 15163,"running_times": 5160},{"title": "No Reservations","year": 2007,"rating": 6.3,"votes": 62975,"running_times": 6240},{"title": "No Retreat, No Surrender","year": 1986,"rating": 5.6,"votes": 12983,"running_times": 5640},{"title": "No Strings Attached","year": 2011,"rating": 6.2,"votes": 183855,"running_times": 6480},{"title": "No Way Out","year": 1987,"rating": 7.1,"votes": 29075,"running_times": 6840},{"title": "No se aceptan devoluciones","year": 2013,"rating": 7.6,"votes": 24684,"running_times": 7320},{"title": "Noah","year": 2014,"rating": 5.8,"votes": 215683,"running_times": 8280},{"title": "Nobody's Fool","year": 1994,"rating": 7.4,"votes": 15887,"running_times": 6600},{"title": "Nocturnal Animals","year": 2016,"rating": 7.5,"votes": 162493,"running_times": 6960},{"title": "Non-Stop","year": 2014,"rating": 7,"votes": 218748,"running_times": 6360},{"title": "Norbit","year": 2007,"rating": 4,"votes": 57358,"running_times": 6180},{"title": "North","year": 1994,"rating": 4.4,"votes": 11933,"running_times": 5220},{"title": "North Country","year": 2005,"rating": 7.3,"votes": 34946,"running_times": 7560},{"title": "North by Northwest","year": 1959,"rating": 8.4,"votes": 243659,"running_times": 8160},{"title": "Nosferatu: Phantom der Nacht","year": 1979,"rating": 7.6,"votes": 26121,"running_times": 6420},{"title": "Not Another Teen Movie","year": 2001,"rating": 5.7,"votes": 85688,"running_times": 5940},{"title": "Not Without My Daughter","year": 1991,"rating": 6.2,"votes": 10448,"running_times": 6960},{"title": "Notes on a Scandal","year": 2006,"rating": 7.4,"votes": 67788,"running_times": 5520},{"title": "Nothing But Trouble","year": 1991,"rating": 4.9,"votes": 18965,"running_times": 5640},{"title": "Nothing But the Truth","year": 2008,"rating": 7.2,"votes": 32564,"running_times": 6480},{"title": "Nothing Is Private","year": 2007,"rating": 7,"votes": 10724,"running_times": 7440},{"title": "Nothing to Lose","year": 1997,"rating": 6.7,"votes": 38436,"running_times": 5880},{"title": "Notorious","year": 1946,"rating": 8,"votes": 79583,"running_times": 6060},{"title": "Notorious","year": 2009,"rating": 6.7,"votes": 35329,"running_times": 7680},{"title": "Notting Hill","year": 1999,"rating": 7.1,"votes": 223479,"running_times": 7440},{"title": "Now Is Good","year": 2012,"rating": 7.2,"votes": 29452,"running_times": 6180},{"title": "Now You See Me","year": 2013,"rating": 7.3,"votes": 511818,"running_times": 7500},{"title": "Now You See Me 2","year": 2016,"rating": 6.5,"votes": 178217,"running_times": 7740},{"title": "Now and Then","year": 1995,"rating": 6.8,"votes": 22910,"running_times": 6000},{"title": "Now, Voyager","year": 1942,"rating": 8,"votes": 12379,"running_times": 7020},{"title": "Nowhere Boy","year": 2009,"rating": 7.2,"votes": 30853,"running_times": 5880},{"title": "Nowhere to Run","year": 1993,"rating": 5.6,"votes": 18740,"running_times": 5640},{"title": "Nurse Betty","year": 2000,"rating": 6.2,"votes": 30959,"running_times": 6600},{"title": "Nutty Professor II: The Klumps","year": 2000,"rating": 4.3,"votes": 42268,"running_times": 6540},{"title": "Nymphomaniac: Vol. I","year": 2013,"rating": 7,"votes": 95493,"running_times": 8700},{"title": "Nymphomaniac: Vol. II","year": 2013,"rating": 6.7,"votes": 69731,"running_times": 10800},{"title": "O","year": 2001,"rating": 6.2,"votes": 17881,"running_times": 5700},{"title": "O Brother, Where Art Thou?","year": 2000,"rating": 7.8,"votes": 244698,"running_times": 6420},{"title": "O.J.: Made in America","year": 2016,"rating": 9,"votes": 12449,"running_times": 28020},{"title": "OMG: Oh My God!","year": 2012,"rating": 8.2,"votes": 37128,"running_times": 7500},{"title": "OSS 117: Rio ne répond plus","year": 2009,"rating": 6.9,"votes": 10637,"running_times": 6060},{"title": "OXV: The Manual","year": 2013,"rating": 6.8,"votes": 11970,"running_times": 6300},{"title": "Oblivion","year": 2013,"rating": 7,"votes": 423224,"running_times": 7440},{"title": "Observe and Report","year": 2009,"rating": 5.8,"votes": 54722,"running_times": 5160},{"title": "Obsessed","year": 2009,"rating": 4.9,"votes": 24823,"running_times": 6480},{"title": "Obvious Child","year": 2014,"rating": 6.8,"votes": 19332,"running_times": 5040},{"title": "Ocean's Eleven","year": 1960,"rating": 6.6,"votes": 16596,"running_times": 7620},{"title": "Ocean's Eleven","year": 2001,"rating": 7.8,"votes": 439145,"running_times": 6960},{"title": "Ocean's Thirteen","year": 2007,"rating": 6.9,"votes": 277326,"running_times": 7320},{"title": "Ocean's Twelve","year": 2004,"rating": 6.5,"votes": 308751,"running_times": 7500},{"title": "October Sky","year": 1999,"rating": 7.8,"votes": 70134,"running_times": 6480},{"title": "Octopussy","year": 1983,"rating": 6.6,"votes": 80552,"running_times": 7860},{"title": "Oculus","year": 2013,"rating": 6.5,"votes": 97266,"running_times": 6240},{"title": "Odd Thomas","year": 2013,"rating": 6.9,"votes": 40221,"running_times": 5820},{"title": "Of Mice and Men","year": 1992,"rating": 7.5,"votes": 34644,"running_times": 6900},{"title": "Office Christmas Party","year": 2016,"rating": 5.8,"votes": 42454,"running_times": 6660},{"title": "Office Space","year": 1999,"rating": 7.8,"votes": 214446,"running_times": 5340},{"title": "Offret","year": 1986,"rating": 8.1,"votes": 16928,"running_times": 8940},{"title": "Oh Boy","year": 2012,"rating": 7.4,"votes": 12277,"running_times": 5160},{"title": "Okja","year": 2017,"rating": 7.4,"votes": 49130,"running_times": 7200},{"title": "Old Boy","year": 2013,"rating": 5.8,"votes": 56956,"running_times": 6240},{"title": "Old Dogs","year": 2009,"rating": 5.4,"votes": 32907,"running_times": 5280},{"title": "Old School","year": 2003,"rating": 7.2,"votes": 195016,"running_times": 5280},{"title": "Oliver & Company","year": 1988,"rating": 6.7,"votes": 36062,"running_times": 4440},{"title": "Oliver Twist","year": 2005,"rating": 6.9,"votes": 27382,"running_times": 7800},{"title": "Oliver!","year": 1968,"rating": 7.5,"votes": 28194,"running_times": 9180},{"title": "Olympus Has Fallen","year": 2013,"rating": 6.5,"votes": 220967,"running_times": 7140},{"title": "On Deadly Ground","year": 1994,"rating": 4.4,"votes": 19370,"running_times": 6060},{"title": "On Golden Pond","year": 1981,"rating": 7.7,"votes": 23306,"running_times": 6540},{"title": "On Her Majesty's Secret Service","year": 1969,"rating": 6.8,"votes": 65821,"running_times": 8520},{"title": "On the Beach","year": 1959,"rating": 7.3,"votes": 10197,"running_times": 8040},{"title": "On the Road","year": 2012,"rating": 6.1,"votes": 35856,"running_times": 8220},{"title": "On the Town","year": 1949,"rating": 7.6,"votes": 13300,"running_times": 5880},{"title": "On the Waterfront","year": 1954,"rating": 8.2,"votes": 113409,"running_times": 6480},{"title": "Once","year": 2007,"rating": 7.9,"votes": 99752,"running_times": 5160},{"title": "Once Bitten","year": 1985,"rating": 5.5,"votes": 11056,"running_times": 5640},{"title": "Once Upon a Time in America","year": 1984,"rating": 8.4,"votes": 247434,"running_times": 16140},{"title": "Once Upon a Time in Mexico","year": 2003,"rating": 6.4,"votes": 138307,"running_times": 6120},{"title": "Once Were Warriors","year": 1994,"rating": 7.9,"votes": 27379,"running_times": 6120},{"title": "Ondine","year": 2009,"rating": 6.8,"votes": 18057,"running_times": 6660},{"title": "One Crazy Summer","year": 1986,"rating": 6.4,"votes": 11705,"running_times": 5580},{"title": "One Day","year": 2011,"rating": 7,"votes": 117869,"running_times": 6420},{"title": "One Direction: This Is Us","year": 2013,"rating": 4.1,"votes": 22601,"running_times": 6360},{"title": "One Eight Seven","year": 1997,"rating": 6.7,"votes": 19395,"running_times": 7140},{"title": "One Fine Day","year": 1996,"rating": 6.5,"votes": 38432,"running_times": 6480},{"title": "One Flew Over the Cuckoo's Nest","year": 1975,"rating": 8.7,"votes": 753853,"running_times": 7980},{"title": "One Hour Photo","year": 2002,"rating": 6.8,"votes": 103023,"running_times": 5760},{"title": "One Hundred and One Dalmatians","year": 1961,"rating": 7.2,"votes": 125012,"running_times": 4740},{"title": "One Man Band","year": 2005,"rating": 7.8,"votes": 12130,"running_times": 240},{"title": "One Missed Call","year": 2008,"rating": 4,"votes": 28125,"running_times": 5220},{"title": "One Night at McCool's","year": 2001,"rating": 6.1,"votes": 26629,"running_times": 5580},{"title": "One True Thing","year": 1998,"rating": 7,"votes": 10049,"running_times": 7620},{"title": "One Week","year": 2008,"rating": 7.1,"votes": 10363,"running_times": 5640},{"title": "One for the Money","year": 2012,"rating": 5.3,"votes": 36462,"running_times": 5460},{"title": "One, Two, Three","year": 1961,"rating": 8,"votes": 16319,"running_times": 6900},{"title": "Ong-bak","year": 2003,"rating": 7.2,"votes": 64314,"running_times": 6480},{"title": "Only God Forgives","year": 2013,"rating": 5.7,"votes": 93136,"running_times": 5400},{"title": "Only Lovers Left Alive","year": 2013,"rating": 7.3,"votes": 72348,"running_times": 7380},{"title": "Only You","year": 1994,"rating": 6.5,"votes": 16908,"running_times": 6900},{"title": "Oorlogswinter","year": 2008,"rating": 7,"votes": 10942,"running_times": 6180},{"title": "Open Grave","year": 2013,"rating": 6.3,"votes": 23858,"running_times": 6120},{"title": "Open Range","year": 2003,"rating": 7.5,"votes": 57963,"running_times": 8340},{"title": "Open Season","year": 2006,"rating": 6.2,"votes": 72098,"running_times": 5160},{"title": "Open Water","year": 2003,"rating": 5.7,"votes": 45441,"running_times": 4740},{"title": "Open Water 2: Adrift","year": 2006,"rating": 5.1,"votes": 14864,"running_times": 5700},{"title": "Open Windows","year": 2014,"rating": 5.2,"votes": 11765,"running_times": 6000},{"title": "Opera","year": 1987,"rating": 7.1,"votes": 10995,"running_times": 6420},{"title": "Operation Petticoat","year": 1959,"rating": 7.3,"votes": 10205,"running_times": 7440},{"title": "Orange County","year": 2002,"rating": 6.2,"votes": 43196,"running_times": 4920},{"title": "Ordinary Decent Criminal","year": 2000,"rating": 6.4,"votes": 12289,"running_times": 5580},{"title": "Ordinary People","year": 1980,"rating": 7.8,"votes": 38597,"running_times": 7440},{"title": "Orgazmo","year": 1997,"rating": 6.2,"votes": 31683,"running_times": 5640},{"title": "Original Sin","year": 2001,"rating": 6,"votes": 47818,"running_times": 7080},{"title": "Orlando","year": 1992,"rating": 7.2,"votes": 11064,"running_times": 5640},{"title": "Orphan","year": 2009,"rating": 7,"votes": 160192,"running_times": 7380},{"title": "Oscar","year": 1991,"rating": 6.4,"votes": 25381,"running_times": 6540},{"title": "Oslo, 31. august","year": 2011,"rating": 7.6,"votes": 15463,"running_times": 5700},{"title": "Osmosis Jones","year": 2001,"rating": 6.3,"votes": 27537,"running_times": 5700},{"title": "Ouija","year": 2014,"rating": 4.5,"votes": 39770,"running_times": 5340},{"title": "Ouija: Origin of Evil","year": 2016,"rating": 6.1,"votes": 37746,"running_times": 5940},{"title": "Our Brand Is Crisis","year": 2015,"rating": 6.1,"votes": 16624,"running_times": 6420},{"title": "Our Idiot Brother","year": 2011,"rating": 6.4,"votes": 78146,"running_times": 5400},{"title": "Our Kind of Traitor","year": 2016,"rating": 6.2,"votes": 14386,"running_times": 6480},{"title": "Out Cold","year": 2001,"rating": 6.3,"votes": 15223,"running_times": 5520},{"title": "Out for Justice","year": 1991,"rating": 6,"votes": 18349,"running_times": 5460},{"title": "Out of Africa","year": 1985,"rating": 7.2,"votes": 58200,"running_times": 9660},{"title": "Out of Rosenheim","year": 1987,"rating": 7.5,"votes": 10376,"running_times": 6480},{"title": "Out of Sight","year": 1998,"rating": 7,"votes": 75694,"running_times": 7380},{"title": "Out of Time","year": 2003,"rating": 6.5,"votes": 49592,"running_times": 6840},{"title": "Out of the Furnace","year": 2013,"rating": 6.8,"votes": 92039,"running_times": 6960},{"title": "Out of the Past","year": 1947,"rating": 8.1,"votes": 26203,"running_times": 5820},{"title": "Outbreak","year": 1995,"rating": 6.6,"votes": 96205,"running_times": 7620},{"title": "Outcast","year": 2014,"rating": 4.6,"votes": 10400,"running_times": 5940},{"title": "Outland","year": 1981,"rating": 6.6,"votes": 23324,"running_times": 6720},{"title": "Outlander","year": 2008,"rating": 6.3,"votes": 66588,"running_times": 6900},{"title": "Outlaw","year": 2007,"rating": 5.8,"votes": 11667,"running_times": 6180},{"title": "Outpost","year": 2008,"rating": 5.9,"votes": 14748,"running_times": 5400},{"title": "Outsourced","year": 2006,"rating": 7,"votes": 10317,"running_times": 6180},{"title": "Over Her Dead Body","year": 2008,"rating": 5.2,"votes": 22239,"running_times": 5700},{"title": "Over the Hedge","year": 2006,"rating": 6.7,"votes": 137721,"running_times": 4980},{"title": "Over the Top","year": 1987,"rating": 5.7,"votes": 41447,"running_times": 5580},{"title": "Overboard","year": 1987,"rating": 6.8,"votes": 41039,"running_times": 6720},{"title": "Owning Mahowny","year": 2003,"rating": 7.1,"votes": 11196,"running_times": 6240},{"title": "Oz the Great and Powerful","year": 2013,"rating": 6.3,"votes": 184733,"running_times": 7800},{"title": "P.S. I Love You","year": 2007,"rating": 7.1,"votes": 181630,"running_times": 7560},{"title": "P2","year": 2007,"rating": 5.9,"votes": 27730,"running_times": 5880},{"title": "PCU","year": 1994,"rating": 6.6,"votes": 11008,"running_times": 4740},{"title": "PK","year": 2014,"rating": 8.2,"votes": 114769,"running_times": 9180},{"title": "Pacific Heights","year": 1990,"rating": 6.4,"votes": 15273,"running_times": 6120},{"title": "Pacific Rim","year": 2013,"rating": 7,"votes": 411837,"running_times": 7860},{"title": "Paddington","year": 2014,"rating": 7.2,"votes": 59473,"running_times": 5700},{"title": "Pain & Gain","year": 2013,"rating": 6.4,"votes": 174254,"running_times": 7740},{"title": "Paint Your Wagon","year": 1969,"rating": 6.7,"votes": 10108,"running_times": 9480},{"title": "Pale Rider","year": 1985,"rating": 7.3,"votes": 43605,"running_times": 6900},{"title": "Palindromes","year": 2004,"rating": 6.8,"votes": 11200,"running_times": 6000},{"title": "Palo Alto","year": 2013,"rating": 6.3,"votes": 23349,"running_times": 6000},{"title": "Pan","year": 2015,"rating": 5.8,"votes": 50647,"running_times": 6660},{"title": "Pandorum","year": 2009,"rating": 6.8,"votes": 130076,"running_times": 6480},{"title": "Panic Room","year": 2002,"rating": 6.8,"votes": 222719,"running_times": 6780},{"title": "Paparazzi","year": 2004,"rating": 5.8,"votes": 13659,"running_times": 5040},{"title": "Paper Man","year": 2009,"rating": 6.6,"votes": 16527,"running_times": 6600},{"title": "Paper Moon","year": 1973,"rating": 8.2,"votes": 27816,"running_times": 6120},{"title": "Paper Towns","year": 2015,"rating": 6.3,"votes": 78166,"running_times": 6540},{"title": "Paperman","year": 2012,"rating": 8.3,"votes": 27834,"running_times": 420},{"title": "Papillon","year": 1973,"rating": 8,"votes": 103847,"running_times": 9060},{"title": "Papurika","year": 2006,"rating": 7.7,"votes": 52914,"running_times": 5400},{"title": "ParaNorman","year": 2012,"rating": 7,"votes": 80672,"running_times": 5520},{"title": "Paradise Lost: The Child Murders at Robin Hood Hills","year": 1996,"rating": 8.3,"votes": 12193,"running_times": 9000},{"title": "Paradise Now","year": 2005,"rating": 7.5,"votes": 20638,"running_times": 5400},{"title": "Parallels","year": 2015,"rating": 6.2,"votes": 11937,"running_times": 4980},{"title": "Paranoia","year": 2013,"rating": 5.7,"votes": 31219,"running_times": 6360},{"title": "Paranoid Park","year": 2007,"rating": 6.7,"votes": 26408,"running_times": 5100},{"title": "Paranormal Activity","year": 2007,"rating": 6.3,"votes": 197558,"running_times": 5820},{"title": "Paranormal Activity 2","year": 2010,"rating": 5.7,"votes": 88097,"running_times": 5880},{"title": "Paranormal Activity 3","year": 2011,"rating": 5.8,"votes": 81597,"running_times": 5640},{"title": "Paranormal Activity 4","year": 2012,"rating": 4.6,"votes": 54864,"running_times": 5760},{"title": "Paranormal Activity: The Ghost Dimension","year": 2015,"rating": 4.6,"votes": 19766,"running_times": 5820},{"title": "Paranormal Activity: The Marked Ones","year": 2014,"rating": 5,"votes": 34682,"running_times": 6060},{"title": "Parental Guidance","year": 2012,"rating": 6.1,"votes": 22572,"running_times": 6300},{"title": "Parenthood","year": 1989,"rating": 7,"votes": 38263,"running_times": 7440},{"title": "Paris, Texas","year": 1984,"rating": 8.1,"votes": 59559,"running_times": 8700},{"title": "Paris, je t'aime","year": 2006,"rating": 7.3,"votes": 65668,"running_times": 7200},{"title": "Parker","year": 2013,"rating": 6.2,"votes": 98698,"running_times": 7080},{"title": "Parkland","year": 2013,"rating": 6.4,"votes": 12999,"running_times": 5580},{"title": "Party Monster","year": 2003,"rating": 6.3,"votes": 13409,"running_times": 5880},{"title": "Passenger 57","year": 1992,"rating": 5.8,"votes": 39514,"running_times": 5040},{"title": "Passengers","year": 2008,"rating": 5.9,"votes": 30068,"running_times": 5580},{"title": "Passengers","year": 2016,"rating": 7,"votes": 252052,"running_times": 6960},{"title": "Passion","year": 2012,"rating": 5.3,"votes": 18568,"running_times": 6120},{"title": "Pat Garrett & Billy the Kid","year": 1973,"rating": 7.4,"votes": 14838,"running_times": 7320},{"title": "Patch Adams","year": 1998,"rating": 6.7,"votes": 87776,"running_times": 6900},{"title": "Paterson","year": 2016,"rating": 7.4,"votes": 40047,"running_times": 7080},{"title": "Pathfinder","year": 2007,"rating": 5.4,"votes": 39123,"running_times": 6420},{"title": "Pathology","year": 2008,"rating": 6,"votes": 28272,"running_times": 5700},{"title": "Paths of Glory","year": 1957,"rating": 8.4,"votes": 137012,"running_times": 5280},{"title": "Patriot Games","year": 1992,"rating": 6.9,"votes": 87400,"running_times": 7020},{"title": "Patriots Day","year": 2016,"rating": 7.4,"votes": 56247,"running_times": 7980},{"title": "Patton","year": 1970,"rating": 8,"votes": 82663,"running_times": 10320},{"title": "Paul","year": 2011,"rating": 7,"votes": 207118,"running_times": 6540},{"title": "Paul Blart: Mall Cop","year": 2009,"rating": 5.2,"votes": 90028,"running_times": 5460},{"title": "Paul Blart: Mall Cop 2","year": 2015,"rating": 4.4,"votes": 27660,"running_times": 5640},{"title": "Paulie","year": 1998,"rating": 6.5,"votes": 12631,"running_times": 5460},{"title": "Paura nella città dei morti viventi","year": 1980,"rating": 6.3,"votes": 12796,"running_times": 5580},{"title": "Pawn Sacrifice","year": 2014,"rating": 7,"votes": 30186,"running_times": 6900},{"title": "Pay It Forward","year": 2000,"rating": 7.2,"votes": 102406,"running_times": 7380},{"title": "Pay the Ghost","year": 2015,"rating": 5.2,"votes": 12141,"running_times": 5640},{"title": "Payback","year": 1999,"rating": 7.1,"votes": 118738,"running_times": 6000},{"title": "Paycheck","year": 2003,"rating": 6.3,"votes": 94288,"running_times": 7140},{"title": "Peaceful Warrior","year": 2006,"rating": 7.3,"votes": 22771,"running_times": 7200},{"title": "Pearl Harbor","year": 2001,"rating": 6.1,"votes": 275248,"running_times": 11040},{"title": "Pecker","year": 1998,"rating": 6.4,"votes": 12166,"running_times": 5220},{"title": "Pee-wee's Big Adventure","year": 1985,"rating": 7,"votes": 43899,"running_times": 5460},{"title": "Peeping Tom","year": 1960,"rating": 7.7,"votes": 24338,"running_times": 6060},{"title": "Peggy Sue Got Married","year": 1986,"rating": 6.3,"votes": 28771,"running_times": 6180},{"title": "Pelé: Birth of a Legend","year": 2016,"rating": 7.3,"votes": 10201,"running_times": 6420},{"title": "Penelope","year": 2006,"rating": 6.8,"votes": 54278,"running_times": 6240},{"title": "Penguins of Madagascar","year": 2014,"rating": 6.7,"votes": 67051,"running_times": 5520},{"title": "People I Know","year": 2002,"rating": 5.5,"votes": 10276,"running_times": 6000},{"title": "People Like Us","year": 2012,"rating": 7.1,"votes": 36939,"running_times": 6840},{"title": "Percy Jackson & the Olympians: The Lightning Thief","year": 2010,"rating": 5.9,"votes": 153720,"running_times": 7080},{"title": "Percy Jackson: Sea of Monsters","year": 2013,"rating": 5.9,"votes": 94873,"running_times": 6360},{"title": "Perfect Sense","year": 2011,"rating": 7.1,"votes": 47213,"running_times": 5520},{"title": "Perfect Stranger","year": 2007,"rating": 5.7,"votes": 39925,"running_times": 6540},{"title": "Perfume: The Story of a Murderer","year": 2006,"rating": 7.5,"votes": 205252,"running_times": 8820},{"title": "Persepolis","year": 2007,"rating": 8.1,"votes": 76676,"running_times": 5760},{"title": "Persona","year": 1966,"rating": 8.1,"votes": 72326,"running_times": 5100},{"title": "Personal Shopper","year": 2016,"rating": 6.2,"votes": 19478,"running_times": 6300},{"title": "Pet","year": 2016,"rating": 5.7,"votes": 11079,"running_times": 5640},{"title": "Pet Sematary","year": 1989,"rating": 6.6,"votes": 71858,"running_times": 6180},{"title": "Pet Sematary II","year": 1992,"rating": 4.8,"votes": 14806,"running_times": 6000},{"title": "Pete's Dragon","year": 1977,"rating": 6.4,"votes": 19167,"running_times": 7800},{"title": "Pete's Dragon","year": 2016,"rating": 6.7,"votes": 42488,"running_times": 6120},{"title": "Peter Pan","year": 1953,"rating": 7.3,"votes": 99989,"running_times": 4620},{"title": "Peter Pan","year": 2003,"rating": 6.9,"votes": 57870,"running_times": 6780},{"title": "Phantasm","year": 1979,"rating": 6.8,"votes": 25806,"running_times": 5280},{"title": "Phantasm II","year": 1988,"rating": 6.5,"votes": 10962,"running_times": 5820},{"title": "Phantom","year": 2013,"rating": 5.9,"votes": 12224,"running_times": 5880},{"title": "Phantom of the Paradise","year": 1974,"rating": 7.4,"votes": 12668,"running_times": 5520},{"title": "Phantoms","year": 1998,"rating": 5.4,"votes": 17351,"running_times": 5760},{"title": "Phenomena","year": 1985,"rating": 6.9,"votes": 18132,"running_times": 6960},{"title": "Phenomenon","year": 1996,"rating": 6.4,"votes": 67376,"running_times": 7380},{"title": "Philadelphia","year": 1993,"rating": 7.7,"votes": 193319,"running_times": 7500},{"title": "Philomena","year": 2013,"rating": 7.6,"votes": 83559,"running_times": 5880},{"title": "Phoenix","year": 2014,"rating": 7.3,"votes": 12924,"running_times": 5880},{"title": "Phone Booth","year": 2002,"rating": 7.1,"votes": 224082,"running_times": 4860},{"title": "Pi","year": 1998,"rating": 7.5,"votes": 153048,"running_times": 5040},{"title": "Pickup on South Street","year": 1953,"rating": 7.8,"votes": 10140,"running_times": 4800},{"title": "Picnic at Hanging Rock","year": 1975,"rating": 7.6,"votes": 27566,"running_times": 6900},{"title": "Picture Perfect","year": 1997,"rating": 5.5,"votes": 17051,"running_times": 6300},{"title": "Pieces of April","year": 2003,"rating": 7.1,"votes": 18663,"running_times": 4800},{"title": "Pierrot le fou","year": 1965,"rating": 7.7,"votes": 22303,"running_times": 6600},{"title": "Pillow Talk","year": 1959,"rating": 7.5,"votes": 12447,"running_times": 6120},{"title": "Pina","year": 2011,"rating": 7.7,"votes": 12632,"running_times": 6180},{"title": "Pineapple Express","year": 2008,"rating": 7,"votes": 275544,"running_times": 7020},{"title": "Pink","year": 2016,"rating": 8.2,"votes": 25888,"running_times": 8160},{"title": "Pink Flamingos","year": 1972,"rating": 6.1,"votes": 18394,"running_times": 6480},{"title": "Pink Floyd: The Wall","year": 1982,"rating": 8,"votes": 65194,"running_times": 5700},{"title": "Pinocchio","year": 1940,"rating": 7.5,"votes": 103226,"running_times": 5280},{"title": "Piper","year": 2016,"rating": 8.4,"votes": 18635,"running_times": 360},{"title": "Piranha","year": 1978,"rating": 5.9,"votes": 15470,"running_times": 6360},{"title": "Piranha 3D","year": 2010,"rating": 5.5,"votes": 77156,"running_times": 5280},{"title": "Piranha 3DD","year": 2012,"rating": 3.8,"votes": 34412,"running_times": 4980},{"title": "Pirates of the Caribbean: At World's End","year": 2007,"rating": 7.1,"votes": 519696,"running_times": 10140},{"title": "Pirates of the Caribbean: Dead Man's Chest","year": 2006,"rating": 7.3,"votes": 573617,"running_times": 9060},{"title": "Pirates of the Caribbean: Dead Men Tell No Tales","year": 2017,"rating": 6.7,"votes": 163797,"running_times": 7740},{"title": "Pirates of the Caribbean: On Stranger Tides","year": 2011,"rating": 6.6,"votes": 414326,"running_times": 8220},{"title": "Pirates of the Caribbean: The Curse of the Black Pearl","year": 2003,"rating": 8,"votes": 897059,"running_times": 8580},{"title": "Pit and the Pendulum","year": 1961,"rating": 7.1,"votes": 10125,"running_times": 4800},{"title": "Pitch Black","year": 2000,"rating": 7.1,"votes": 204768,"running_times": 6720},{"title": "Pitch Perfect","year": 2012,"rating": 7.2,"votes": 234523,"running_times": 6720},{"title": "Pitch Perfect 2","year": 2015,"rating": 6.4,"votes": 114324,"running_times": 6900},{"title": "Pixels","year": 2015,"rating": 5.6,"votes": 107829,"running_times": 6300},{"title": "Plan 9 from Outer Space","year": 1959,"rating": 4,"votes": 31677,"running_times": 4740},{"title": "Planes","year": 2013,"rating": 5.7,"votes": 37645,"running_times": 5460},{"title": "Planes, Trains & Automobiles","year": 1987,"rating": 7.6,"votes": 100740,"running_times": 5580},{"title": "Planes: Fire & Rescue","year": 2014,"rating": 6,"votes": 13931,"running_times": 4980},{"title": "Planet 51","year": 2009,"rating": 6.1,"votes": 44168,"running_times": 5460},{"title": "Planet Terror","year": 2007,"rating": 7.1,"votes": 178980,"running_times": 6300},{"title": "Planet of the Apes","year": 1968,"rating": 8,"votes": 147852,"running_times": 6900},{"title": "Planet of the Apes","year": 2001,"rating": 5.7,"votes": 192073,"running_times": 7140},{"title": "Platoon","year": 1986,"rating": 8.1,"votes": 321392,"running_times": 7200},{"title": "Play It Again, Sam","year": 1972,"rating": 7.7,"votes": 21490,"running_times": 5100},{"title": "Play It to the Bone","year": 1999,"rating": 5.4,"votes": 10608,"running_times": 7440},{"title": "Play Misty for Me","year": 1971,"rating": 7,"votes": 21050,"running_times": 6120},{"title": "Playing It Cool","year": 2014,"rating": 6,"votes": 19829,"running_times": 5640},{"title": "Playing by Heart","year": 1998,"rating": 7.2,"votes": 17228,"running_times": 7260},{"title": "Playing for Keeps","year": 2012,"rating": 5.7,"votes": 25958,"running_times": 6300},{"title": "Playtime","year": 1967,"rating": 8,"votes": 14743,"running_times": 9300},{"title": "Pleasantville","year": 1998,"rating": 7.5,"votes": 109185,"running_times": 7440},{"title": "Please Give","year": 2010,"rating": 6.6,"votes": 10282,"running_times": 5220},{"title": "Pledge This!","year": 2006,"rating": 1.9,"votes": 16019,"running_times": 5460},{"title": "Plein soleil","year": 1960,"rating": 7.8,"votes": 10567,"running_times": 7080},{"title": "Pocahontas","year": 1995,"rating": 6.7,"votes": 136066,"running_times": 5040},{"title": "Point Blank","year": 1967,"rating": 7.4,"votes": 15037,"running_times": 5520},{"title": "Point Break","year": 1991,"rating": 7.2,"votes": 125538,"running_times": 7320},{"title": "Point Break","year": 2015,"rating": 5.3,"votes": 47981,"running_times": 6840},{"title": "Point of No Return","year": 1993,"rating": 6,"votes": 21871,"running_times": 6540},{"title": "Poison Ivy","year": 1992,"rating": 5.4,"votes": 14868,"running_times": 5580},{"title": "Police Academy","year": 1984,"rating": 6.7,"votes": 96285,"running_times": 5760},{"title": "Police Academy 2: Their First Assignment","year": 1985,"rating": 5.7,"votes": 43178,"running_times": 5220},{"title": "Police Academy 3: Back in Training","year": 1986,"rating": 5.3,"votes": 35865,"running_times": 4980},{"title": "Police Academy 4: Citizens on Patrol","year": 1987,"rating": 4.8,"votes": 34317,"running_times": 5280},{"title": "Police Academy 5: Assignment: Miami Beach","year": 1988,"rating": 4.4,"votes": 27792,"running_times": 5400},{"title": "Police Academy 6: City Under Siege","year": 1989,"rating": 4.2,"votes": 23963,"running_times": 5040},{"title": "Police Academy: Mission to Moscow","year": 1994,"rating": 3.3,"votes": 26893,"running_times": 4980},{"title": "Politiki kouzina","year": 2003,"rating": 7.6,"votes": 11043,"running_times": 6480},{"title": "Pollock","year": 2000,"rating": 7,"votes": 24386,"running_times": 7920},{"title": "Poltergeist","year": 1982,"rating": 7.4,"votes": 118112,"running_times": 7200},{"title": "Poltergeist","year": 2015,"rating": 4.9,"votes": 48044,"running_times": 6060},{"title": "Poltergeist II: The Other Side","year": 1986,"rating": 5.7,"votes": 20967,"running_times": 7800},{"title": "Poltergeist III","year": 1988,"rating": 4.6,"votes": 14343,"running_times": 5880},{"title": "Pompeii","year": 2014,"rating": 5.5,"votes": 93779,"running_times": 6300},{"title": "Pontypool","year": 2008,"rating": 6.7,"votes": 24835,"running_times": 5700},{"title": "Pootie Tang","year": 2001,"rating": 5.2,"votes": 12089,"running_times": 4860},{"title": "Popeye","year": 1980,"rating": 5.2,"votes": 25242,"running_times": 6840},{"title": "Popstar: Never Stop Never Stopping","year": 2016,"rating": 6.7,"votes": 36918,"running_times": 5220},{"title": "Porky's","year": 1981,"rating": 6.2,"votes": 33257,"running_times": 5640},{"title": "Poseidon","year": 2006,"rating": 5.6,"votes": 87174,"running_times": 5880},{"title": "Possession","year": 1981,"rating": 7.4,"votes": 16899,"running_times": 7440},{"title": "Possession","year": 2002,"rating": 6.4,"votes": 12023,"running_times": 6120},{"title": "Post Grad","year": 2009,"rating": 5.3,"votes": 12427,"running_times": 5280},{"title": "Postal","year": 2007,"rating": 4.5,"votes": 20844,"running_times": 7620},{"title": "Postcards from the Edge","year": 1990,"rating": 6.7,"votes": 12982,"running_times": 6060},{"title": "Powder","year": 1995,"rating": 6.6,"votes": 25831,"running_times": 6660},{"title": "Powder Blue","year": 2009,"rating": 6.3,"votes": 12943,"running_times": 6900},{"title": "Power Rangers","year": 2017,"rating": 6.1,"votes": 72174,"running_times": 7440},{"title": "Practical Magic","year": 1998,"rating": 6.2,"votes": 61056,"running_times": 6240},{"title": "Precious","year": 2009,"rating": 7.3,"votes": 94382,"running_times": 6600},{"title": "Predator","year": 1987,"rating": 7.8,"votes": 316518,"running_times": 6420},{"title": "Predator 2","year": 1990,"rating": 6.2,"votes": 118584,"running_times": 6480},{"title": "Predators","year": 2010,"rating": 6.4,"votes": 184408,"running_times": 6420},{"title": "Predestination","year": 2014,"rating": 7.5,"votes": 201124,"running_times": 5820},{"title": "Prem Ratan Dhan Payo","year": 2015,"rating": 4.7,"votes": 13854,"running_times": 11040},{"title": "Premium Rush","year": 2012,"rating": 6.5,"votes": 100986,"running_times": 5460},{"title": "Premonition","year": 2007,"rating": 5.9,"votes": 65837,"running_times": 5760},{"title": "Presto","year": 2008,"rating": 8.4,"votes": 18991,"running_times": 300},{"title": "Presumed Innocent","year": 1990,"rating": 6.9,"votes": 31863,"running_times": 7620},{"title": "Pretty Woman","year": 1990,"rating": 7,"votes": 236465,"running_times": 7500},{"title": "Pretty in Pink","year": 1986,"rating": 6.8,"votes": 61371,"running_times": 5760},{"title": "Pride & Prejudice","year": 2005,"rating": 7.8,"votes": 211990,"running_times": 8100},{"title": "Pride","year": 2014,"rating": 7.8,"votes": 41996,"running_times": 7140},{"title": "Pride and Glory","year": 2008,"rating": 6.7,"votes": 55332,"running_times": 7800},{"title": "Pride and Prejudice and Zombies","year": 2016,"rating": 5.8,"votes": 38692,"running_times": 6480},{"title": "Priest","year": 2011,"rating": 5.7,"votes": 102900,"running_times": 5220},{"title": "Primal Fear","year": 1996,"rating": 7.7,"votes": 146913,"running_times": 7740},{"title": "Primary Colors","year": 1998,"rating": 6.7,"votes": 24922,"running_times": 8580},{"title": "Prime","year": 2005,"rating": 6.2,"votes": 36846,"running_times": 6300},{"title": "Primer","year": 2004,"rating": 6.9,"votes": 82678,"running_times": 4620},{"title": "Primeval","year": 2007,"rating": 4.7,"votes": 11690,"running_times": 5580},{"title": "Prince Avalanche","year": 2013,"rating": 6.4,"votes": 16895,"running_times": 5640},{"title": "Prince of Darkness","year": 1987,"rating": 6.7,"votes": 28609,"running_times": 6120},{"title": "Prince of Persia: The Sands of Time","year": 2010,"rating": 6.6,"votes": 239656,"running_times": 6960},{"title": "Prisoners","year": 2013,"rating": 8.1,"votes": 460550,"running_times": 9180},{"title": "Private Benjamin","year": 1980,"rating": 6.1,"votes": 19888,"running_times": 6540},{"title": "Private Parts","year": 1997,"rating": 6.8,"votes": 30894,"running_times": 6540},{"title": "Prizzi's Honor","year": 1985,"rating": 6.8,"votes": 19835,"running_times": 7800},{"title": "Problem Child","year": 1990,"rating": 5.3,"votes": 24246,"running_times": 5580},{"title": "Problem Child 2","year": 1991,"rating": 4.6,"votes": 18047,"running_times": 5580},{"title": "Professione: reporter","year": 1975,"rating": 7.6,"votes": 16673,"running_times": 7560},{"title": "Project Almanac","year": 2015,"rating": 6.4,"votes": 66044,"running_times": 6360},{"title": "Project X","year": 2012,"rating": 6.7,"votes": 168277,"running_times": 5580},{"title": "Prom","year": 2011,"rating": 5.4,"votes": 13556,"running_times": 6240},{"title": "Prom Night","year": 1980,"rating": 5.4,"votes": 11621,"running_times": 5520},{"title": "Prom Night","year": 2008,"rating": 3.9,"votes": 29693,"running_times": 5340},{"title": "Prometheus","year": 2012,"rating": 7,"votes": 508408,"running_times": 7440},{"title": "Promised Land","year": 2012,"rating": 6.6,"votes": 32498,"running_times": 6360},{"title": "Proof","year": 2005,"rating": 6.8,"votes": 38792,"running_times": 6000},{"title": "Proof of Life","year": 2000,"rating": 6.2,"votes": 51236,"running_times": 8100},{"title": "Prozac Nation","year": 2001,"rating": 6.3,"votes": 15523,"running_times": 5940},{"title": "Prêt-à-Porter","year": 1994,"rating": 5.1,"votes": 13074,"running_times": 7980},{"title": "Psycho","year": 1960,"rating": 8.5,"votes": 476643,"running_times": 6540},{"title": "Psycho","year": 1998,"rating": 4.6,"votes": 40252,"running_times": 6300},{"title": "Psycho II","year": 1983,"rating": 6.4,"votes": 18625,"running_times": 6780},{"title": "Psycho III","year": 1986,"rating": 5.3,"votes": 10195,"running_times": 5580},{"title": "Public Enemies","year": 2009,"rating": 7,"votes": 246492,"running_times": 8400},{"title": "Pulp Fiction","year": 1994,"rating": 8.9,"votes": 1477112,"running_times": 10680},{"title": "Pulse","year": 2006,"rating": 4.7,"votes": 26072,"running_times": 5400},{"title": "Pump Up the Volume","year": 1990,"rating": 7.2,"votes": 22894,"running_times": 6120},{"title": "Pumping Iron","year": 1977,"rating": 7.4,"votes": 18176,"running_times": 5100},{"title": "Pumpkinhead","year": 1988,"rating": 6.2,"votes": 16002,"running_times": 5160},{"title": "Punch-Drunk Love","year": 2002,"rating": 7.3,"votes": 120491,"running_times": 5700},{"title": "Puncture","year": 2011,"rating": 6.9,"votes": 20440,"running_times": 6000},{"title": "Punisher: War Zone","year": 2008,"rating": 6,"votes": 53355,"running_times": 6180},{"title": "Purple Rain","year": 1984,"rating": 6.5,"votes": 16275,"running_times": 6660},{"title": "Push","year": 2009,"rating": 6.1,"votes": 95978,"running_times": 6660},{"title": "Pushing Tin","year": 1999,"rating": 6,"votes": 25855,"running_times": 7440},{"title": "Puss in Boots","year": 2011,"rating": 6.7,"votes": 123808,"running_times": 5400},{"title": "Quadrophenia","year": 1979,"rating": 7.3,"votes": 14308,"running_times": 7200},{"title": "Quantum of Solace","year": 2008,"rating": 6.6,"votes": 356741,"running_times": 6360},{"title": "Quarantine","year": 2008,"rating": 6,"votes": 61636,"running_times": 5340},{"title": "Quarantine 2: Terminal","year": 2011,"rating": 5.2,"votes": 16236,"running_times": 5160},{"title": "Quartet","year": 2012,"rating": 6.8,"votes": 16936,"running_times": 5640},{"title": "Queen","year": 2013,"rating": 8.3,"votes": 49130,"running_times": 8760},{"title": "Queen of the Damned","year": 2002,"rating": 5.3,"votes": 46758,"running_times": 6240},{"title": "Quest for Camelot","year": 1998,"rating": 6.3,"votes": 12346,"running_times": 5160},{"title": "Quick Change","year": 1990,"rating": 6.8,"votes": 17040,"running_times": 5340},{"title": "Quigley Down Under","year": 1990,"rating": 6.8,"votes": 16366,"running_times": 7140},{"title": "Quills","year": 2000,"rating": 7.3,"votes": 47045,"running_times": 7440},{"title": "Quiz Show","year": 1994,"rating": 7.5,"votes": 57548,"running_times": 7980},{"title": "Quo Vadis","year": 1951,"rating": 7.2,"votes": 10998,"running_times": 10260},{"title": "R.I.P.D.","year": 2013,"rating": 5.6,"votes": 100458,"running_times": 5760},{"title": "RED","year": 2010,"rating": 7.1,"votes": 256610,"running_times": 6660},{"title": "RED 2","year": 2013,"rating": 6.7,"votes": 138032,"running_times": 6960},{"title": "RV","year": 2006,"rating": 5.5,"votes": 49630,"running_times": 5940},{"title": "Ra.One","year": 2011,"rating": 4.8,"votes": 33460,"running_times": 9360},{"title": "Raajneeti","year": 2010,"rating": 7.1,"votes": 13482,"running_times": 9780},{"title": "Rabbit Hole","year": 2010,"rating": 7,"votes": 43298,"running_times": 5460},{"title": "Rabbit-Proof Fence","year": 2002,"rating": 7.5,"votes": 24721,"running_times": 5640},{"title": "Rabid","year": 1977,"rating": 6.4,"votes": 11872,"running_times": 5460},{"title": "Race","year": 2016,"rating": 7.1,"votes": 26655,"running_times": 8040},{"title": "Race to Witch Mountain","year": 2009,"rating": 5.7,"votes": 47231,"running_times": 5880},{"title": "Rachel Getting Married","year": 2008,"rating": 6.7,"votes": 43171,"running_times": 6780},{"title": "Racing Stripes","year": 2005,"rating": 5.2,"votes": 13663,"running_times": 6120},{"title": "Radio","year": 2003,"rating": 6.9,"votes": 34113,"running_times": 6540},{"title": "Radio Days","year": 1987,"rating": 7.6,"votes": 26747,"running_times": 5280},{"title": "Radio Flyer","year": 1992,"rating": 6.9,"votes": 11027,"running_times": 6840},{"title": "Raging Bull","year": 1980,"rating": 8.2,"votes": 260123,"running_times": 7740},{"title": "Raiders of the Lost Ark","year": 1981,"rating": 8.5,"votes": 733003,"running_times": 6900},{"title": "Rain Man","year": 1988,"rating": 8,"votes": 412533,"running_times": 7980},{"title": "Raise Your Voice","year": 2004,"rating": 5.9,"votes": 24163,"running_times": 6180},{"title": "Raising Arizona","year": 1987,"rating": 7.4,"votes": 108635,"running_times": 5640},{"title": "Raising Cain","year": 1992,"rating": 6,"votes": 11138,"running_times": 5460},{"title": "Raising Helen","year": 2004,"rating": 6,"votes": 32625,"running_times": 7140},{"title": "Rambo","year": 2008,"rating": 7,"votes": 191441,"running_times": 5940},{"title": "Rambo III","year": 1988,"rating": 5.7,"votes": 100754,"running_times": 6120},{"title": "Rambo: First Blood Part II","year": 1985,"rating": 6.4,"votes": 127949,"running_times": 5760},{"title": "Ramona and Beezus","year": 2010,"rating": 6.6,"votes": 14941,"running_times": 6180},{"title": "Rampage","year": 2009,"rating": 6.3,"votes": 16303,"running_times": 5100},{"title": "Rampart","year": 2011,"rating": 5.8,"votes": 21024,"running_times": 6480},{"title": "Random Hearts","year": 1999,"rating": 5.1,"votes": 17900,"running_times": 7980},{"title": "Rang De Basanti","year": 2006,"rating": 8.3,"votes": 85999,"running_times": 9420},{"title": "Rango","year": 2011,"rating": 7.2,"votes": 200511,"running_times": 6420},{"title": "Ransom","year": 1996,"rating": 6.6,"votes": 105375,"running_times": 8340},{"title": "Rare Exports","year": 2010,"rating": 6.7,"votes": 21947,"running_times": 5040},{"title": "Rat Race","year": 2001,"rating": 6.4,"votes": 98259,"running_times": 6720},{"title": "Ratatouille","year": 2007,"rating": 8,"votes": 523106,"running_times": 6660},{"title": "Ravenous","year": 1999,"rating": 7,"votes": 32355,"running_times": 6060},{"title": "Raw Deal","year": 1986,"rating": 5.5,"votes": 25144,"running_times": 6360},{"title": "Ray","year": 2004,"rating": 7.7,"votes": 119531,"running_times": 10680},{"title": "Re-Animator","year": 1985,"rating": 7.2,"votes": 45022,"running_times": 6300},{"title": "Ready","year": 2011,"rating": 4.7,"votes": 12187,"running_times": 8700},{"title": "Ready to Rumble","year": 2000,"rating": 5.3,"votes": 12339,"running_times": 6420},{"title": "Real Genius","year": 1985,"rating": 7,"votes": 25660,"running_times": 6480},{"title": "Real Steel","year": 2011,"rating": 7.1,"votes": 270279,"running_times": 7620},{"title": "Reality Bites","year": 1994,"rating": 6.6,"votes": 39032,"running_times": 5940},{"title": "Rear Window","year": 1954,"rating": 8.5,"votes": 355438,"running_times": 6720},{"title": "Reasonable Doubt","year": 2014,"rating": 5.7,"votes": 16005,"running_times": 5460},{"title": "Rebecca","year": 1940,"rating": 8.2,"votes": 97897,"running_times": 7800},{"title": "Rebel Without a Cause","year": 1955,"rating": 7.8,"votes": 69975,"running_times": 6660},{"title": "Rebound","year": 2005,"rating": 5.1,"votes": 11179,"running_times": 5340},{"title": "Red Corner","year": 1997,"rating": 6.3,"votes": 14011,"running_times": 7320},{"title": "Red Dawn","year": 1984,"rating": 6.4,"votes": 44560,"running_times": 6840},{"title": "Red Dawn","year": 2012,"rating": 5.4,"votes": 65921,"running_times": 5580},{"title": "Red Dog","year": 2011,"rating": 7.5,"votes": 14257,"running_times": 5520},{"title": "Red Dragon","year": 2002,"rating": 7.2,"votes": 217740,"running_times": 7440},{"title": "Red Eye","year": 2005,"rating": 6.5,"votes": 99780,"running_times": 5100},{"title": "Red Heat","year": 1988,"rating": 6,"votes": 54349,"running_times": 6240},{"title": "Red Lights","year": 2012,"rating": 6.2,"votes": 52128,"running_times": 6840},{"title": "Red Planet","year": 2000,"rating": 5.7,"votes": 50272,"running_times": 6360},{"title": "Red Riding Hood","year": 2011,"rating": 5.4,"votes": 97160,"running_times": 6000},{"title": "Red River","year": 1948,"rating": 7.8,"votes": 23384,"running_times": 7980},{"title": "Red Road","year": 2006,"rating": 6.8,"votes": 10717,"running_times": 6780},{"title": "Red Rock West","year": 1993,"rating": 7,"votes": 17017,"running_times": 5880},{"title": "Red Sonja","year": 1985,"rating": 5,"votes": 33004,"running_times": 5340},{"title": "Red State","year": 2011,"rating": 6.2,"votes": 56761,"running_times": 5280},{"title": "Red Tails","year": 2012,"rating": 5.9,"votes": 30318,"running_times": 7500},{"title": "Redbelt","year": 2008,"rating": 6.8,"votes": 19251,"running_times": 5940},{"title": "Redirected","year": 2014,"rating": 6.7,"votes": 31764,"running_times": 5940},{"title": "Reds","year": 1981,"rating": 7.5,"votes": 17827,"running_times": 11700},{"title": "Regarding Henry","year": 1991,"rating": 6.7,"votes": 25315,"running_times": 6480},{"title": "Regression","year": 2015,"rating": 5.7,"votes": 28731,"running_times": 6360},{"title": "Reign Over Me","year": 2007,"rating": 7.5,"votes": 87332,"running_times": 7440},{"title": "Reign of Fire","year": 2002,"rating": 6.2,"votes": 114037,"running_times": 6060},{"title": "Reindeer Games","year": 2000,"rating": 5.7,"votes": 33382,"running_times": 7440},{"title": "Religulous","year": 2008,"rating": 7.7,"votes": 54600,"running_times": 6060},{"title": "Remember","year": 2015,"rating": 7.4,"votes": 14905,"running_times": 5640},{"title": "Remember Me","year": 2010,"rating": 7.2,"votes": 122498,"running_times": 6780},{"title": "Remember the Titans","year": 2000,"rating": 7.8,"votes": 173395,"running_times": 7200},{"title": "Renaissance","year": 2006,"rating": 6.7,"votes": 14769,"running_times": 6300},{"title": "Renaissance Man","year": 1994,"rating": 6.1,"votes": 14806,"running_times": 7680},{"title": "Rendition","year": 2007,"rating": 6.8,"votes": 49989,"running_times": 7320},{"title": "Reno 911!: Miami","year": 2007,"rating": 5.9,"votes": 24620,"running_times": 5040},{"title": "Rent","year": 2005,"rating": 7,"votes": 44039,"running_times": 8280},{"title": "Replicant","year": 2001,"rating": 5.4,"votes": 12077,"running_times": 6000},{"title": "Repo Man","year": 1984,"rating": 6.9,"votes": 28026,"running_times": 5520},{"title": "Repo Men","year": 2010,"rating": 6.3,"votes": 92099,"running_times": 7140},{"title": "Repo! The Genetic Opera","year": 2008,"rating": 6.7,"votes": 21463,"running_times": 9000},{"title": "Repulsion","year": 1965,"rating": 7.8,"votes": 39557,"running_times": 6300},{"title": "Requiem for a Dream","year": 2000,"rating": 8.3,"votes": 639501,"running_times": 6120},{"title": "Rescue Dawn","year": 2006,"rating": 7.3,"votes": 90216,"running_times": 7200},{"title": "Reservation Road","year": 2007,"rating": 6.7,"votes": 19843,"running_times": 6120},{"title": "Reservoir Dogs","year": 1992,"rating": 8.3,"votes": 745833,"running_times": 5940},{"title": "Resident Evil","year": 2002,"rating": 6.7,"votes": 218227,"running_times": 6000},{"title": "Resident Evil: Afterlife","year": 2010,"rating": 5.9,"votes": 144971,"running_times": 5760},{"title": "Resident Evil: Apocalypse","year": 2004,"rating": 6.2,"votes": 166319,"running_times": 5880},{"title": "Resident Evil: Extinction","year": 2007,"rating": 6.3,"votes": 164112,"running_times": 5640},{"title": "Resident Evil: Retribution","year": 2012,"rating": 5.4,"votes": 118015,"running_times": 5700},{"title": "Resident Evil: The Final Chapter","year": 2016,"rating": 5.6,"votes": 61809,"running_times": 6420},{"title": "Restless","year": 2011,"rating": 6.8,"votes": 15983,"running_times": 5460},{"title": "Restrepo","year": 2010,"rating": 7.6,"votes": 18615,"running_times": 5580},{"title": "Resurrecting the Champ","year": 2007,"rating": 6.7,"votes": 19090,"running_times": 6720},{"title": "Return of the Living Dead III","year": 1993,"rating": 5.9,"votes": 11289,"running_times": 5820},{"title": "Return of the Living Dead: Part II","year": 1988,"rating": 5.8,"votes": 15201,"running_times": 5340},{"title": "Return to Me","year": 2000,"rating": 6.9,"votes": 17309,"running_times": 6900},{"title": "Return to Never Land","year": 2002,"rating": 5.8,"votes": 14877,"running_times": 4320},{"title": "Return to Oz","year": 1985,"rating": 6.7,"votes": 20915,"running_times": 6780},{"title": "Return to Paradise","year": 1998,"rating": 6.9,"votes": 12207,"running_times": 6660},{"title": "Return to the Blue Lagoon","year": 1991,"rating": 5.1,"votes": 15423,"running_times": 6120},{"title": "Revenge","year": 1990,"rating": 6.2,"votes": 13676,"running_times": 7440},{"title": "Revenge of the Nerds","year": 1984,"rating": 6.6,"votes": 42777,"running_times": 5400},{"title": "Revenge of the Nerds II: Nerds in Paradise","year": 1987,"rating": 5,"votes": 11544,"running_times": 5280},{"title": "Revenge of the Pink Panther","year": 1978,"rating": 6.7,"votes": 17146,"running_times": 5940},{"title": "Reversal of Fortune","year": 1990,"rating": 7.3,"votes": 12249,"running_times": 6660},{"title": "Revolutionary Road","year": 2008,"rating": 7.3,"votes": 164174,"running_times": 7140},{"title": "Revolver","year": 2005,"rating": 6.5,"votes": 79694,"running_times": 6660},{"title": "Richard III","year": 1995,"rating": 7.5,"votes": 12308,"running_times": 6600},{"title": "Ricki and the Flash","year": 2015,"rating": 6,"votes": 18749,"running_times": 6060},{"title": "Ricochet","year": 1991,"rating": 6.1,"votes": 13653,"running_times": 6120},{"title": "Riddick","year": 2013,"rating": 6.4,"votes": 135943,"running_times": 7620},{"title": "Ride Along","year": 2014,"rating": 6.2,"votes": 86287,"running_times": 5940},{"title": "Ride Along 2","year": 2016,"rating": 5.9,"votes": 41634,"running_times": 6120},{"title": "Ride the High Country","year": 1962,"rating": 7.6,"votes": 10117,"running_times": 5640},{"title": "Ride with the Devil","year": 1999,"rating": 6.8,"votes": 11657,"running_times": 8880},{"title": "Riding in Cars with Boys","year": 2001,"rating": 6.5,"votes": 24075,"running_times": 7920},{"title": "Rien à déclarer","year": 2010,"rating": 6.3,"votes": 11017,"running_times": 6480},{"title": "Right at Your Door","year": 2006,"rating": 6.2,"votes": 11536,"running_times": 5760},{"title": "Righteous Kill","year": 2008,"rating": 6,"votes": 76972,"running_times": 6060},{"title": "Rings","year": 2017,"rating": 4.5,"votes": 27042,"running_times": 6120},{"title": "Rio","year": 2011,"rating": 6.9,"votes": 178784,"running_times": 5760},{"title": "Rio 2","year": 2014,"rating": 6.3,"votes": 65342,"running_times": 6060},{"title": "Rio Bravo","year": 1959,"rating": 8,"votes": 46875,"running_times": 8460},{"title": "Rio Grande","year": 1950,"rating": 7.2,"votes": 11457,"running_times": 6300},{"title": "Ripley's Game","year": 2002,"rating": 6.7,"votes": 15479,"running_times": 6720},{"title": "Rise","year": 2007,"rating": 4.9,"votes": 10667,"running_times": 7320},{"title": "Rise of the Footsoldier","year": 2007,"rating": 6.9,"votes": 17199,"running_times": 7140},{"title": "Rise of the Guardians","year": 2012,"rating": 7.3,"votes": 134813,"running_times": 5820},{"title": "Rise of the Planet of the Apes","year": 2011,"rating": 7.6,"votes": 445858,"running_times": 6300},{"title": "Risen","year": 2016,"rating": 6.3,"votes": 19540,"running_times": 6420},{"title": "Rising Sun","year": 1993,"rating": 6.2,"votes": 37411,"running_times": 7740},{"title": "Risky Business","year": 1983,"rating": 6.8,"votes": 67266,"running_times": 5940},{"title": "Ritânâ","year": 2002,"rating": 6.5,"votes": 10556,"running_times": 6960},{"title": "River's Edge","year": 1986,"rating": 7.1,"votes": 13038,"running_times": 5940},{"title": "Ri¢hie Ri¢h","year": 1994,"rating": 5.3,"votes": 54239,"running_times": 5700},{"title": "Road House","year": 1989,"rating": 6.5,"votes": 47980,"running_times": 6840},{"title": "Road Trip","year": 2000,"rating": 6.5,"votes": 141478,"running_times": 5640},{"title": "Road to Perdition","year": 2002,"rating": 7.7,"votes": 215795,"running_times": 7020},{"title": "Rob Roy","year": 1995,"rating": 6.9,"votes": 36497,"running_times": 8340},{"title": "Robin Hood","year": 1973,"rating": 7.6,"votes": 93873,"running_times": 4980},{"title": "Robin Hood","year": 2010,"rating": 6.7,"votes": 226558,"running_times": 9360},{"title": "Robin Hood: Men in Tights","year": 1993,"rating": 6.7,"votes": 99320,"running_times": 6240},{"title": "Robin Hood: Prince of Thieves","year": 1991,"rating": 6.9,"votes": 155703,"running_times": 9300},{"title": "Robinson Crusoe","year": 1997,"rating": 5.9,"votes": 10501,"running_times": 6300},{"title": "RoboCop","year": 1987,"rating": 7.5,"votes": 198737,"running_times": 6180},{"title": "RoboCop","year": 2014,"rating": 6.2,"votes": 195203,"running_times": 7020},{"title": "RoboCop 2","year": 1990,"rating": 5.8,"votes": 69631,"running_times": 7020},{"title": "RoboCop 3","year": 1993,"rating": 4,"votes": 38462,"running_times": 6240},{"title": "Robot & Frank","year": 2012,"rating": 7.1,"votes": 56154,"running_times": 5340},{"title": "Robots","year": 2005,"rating": 6.3,"votes": 112952,"running_times": 5460},{"title": "Rock On!!","year": 2008,"rating": 7.8,"votes": 17454,"running_times": 8700},{"title": "Rock Star","year": 2001,"rating": 6.2,"votes": 36621,"running_times": 6300},{"title": "Rock of Ages","year": 2012,"rating": 5.9,"votes": 65978,"running_times": 8160},{"title": "Rocket Science","year": 2007,"rating": 6.7,"votes": 12132,"running_times": 6060},{"title": "RocknRolla","year": 2008,"rating": 7.3,"votes": 209034,"running_times": 6840},{"title": "Rocky","year": 1976,"rating": 8.1,"votes": 424316,"running_times": 8700},{"title": "Rocky Balboa","year": 2006,"rating": 7.2,"votes": 176163,"running_times": 8340},{"title": "Rocky II","year": 1979,"rating": 7.2,"votes": 154543,"running_times": 8520},{"title": "Rocky III","year": 1982,"rating": 6.8,"votes": 139274,"running_times": 5940},{"title": "Rocky IV","year": 1985,"rating": 6.8,"votes": 150879,"running_times": 6420},{"title": "Rocky V","year": 1990,"rating": 5.2,"votes": 103747,"running_times": 8160},{"title": "Roger & Me","year": 1989,"rating": 7.5,"votes": 23911,"running_times": 5460},{"title": "Roger Dodger","year": 2002,"rating": 7,"votes": 15871,"running_times": 6360},{"title": "Rogue","year": 2007,"rating": 6.2,"votes": 23552,"running_times": 5940},{"title": "Rogue One","year": 2016,"rating": 7.8,"votes": 386122,"running_times": 7980},{"title": "Role Models","year": 2008,"rating": 6.9,"votes": 203170,"running_times": 6060},{"title": "Rollerball","year": 1975,"rating": 6.6,"votes": 18882,"running_times": 7500},{"title": "Rollerball","year": 2002,"rating": 3,"votes": 23117,"running_times": 5880},{"title": "Roman Holiday","year": 1953,"rating": 8.1,"votes": 110260,"running_times": 7080},{"title": "Romance & Cigarettes","year": 2005,"rating": 6.3,"votes": 10506,"running_times": 6300},{"title": "Romancing the Stone","year": 1984,"rating": 6.9,"votes": 69846,"running_times": 6360},{"title": "Romeo + Juliet","year": 1996,"rating": 6.8,"votes": 182222,"running_times": 7200},{"title": "Romeo Is Bleeding","year": 1993,"rating": 6.6,"votes": 11503,"running_times": 6600},{"title": "Romeo Must Die","year": 2000,"rating": 6.1,"votes": 60228,"running_times": 6900},{"title": "Romeo and Juliet","year": 1968,"rating": 7.6,"votes": 25418,"running_times": 8940},{"title": "Romper Stomper","year": 1992,"rating": 6.8,"votes": 33659,"running_times": 5640},{"title": "Romy and Michele's High School Reunion","year": 1997,"rating": 6.2,"votes": 36333,"running_times": 5520},{"title": "Ronaldo","year": 2015,"rating": 6.4,"votes": 12330,"running_times": 6120},{"title": "Ronin","year": 1998,"rating": 7.3,"votes": 153925,"running_times": 7320},{"title": "Rookie of the Year","year": 1993,"rating": 5.9,"votes": 19871,"running_times": 6180},{"title": "Room","year": 2015,"rating": 8.2,"votes": 251090,"running_times": 7080},{"title": "Room 237","year": 2012,"rating": 6.2,"votes": 18379,"running_times": 6120},{"title": "Rope","year": 1948,"rating": 8,"votes": 105677,"running_times": 4800},{"title": "Rosemary's Baby","year": 1968,"rating": 8,"votes": 155168,"running_times": 8220},{"title": "Rosencrantz & Guildenstern Are Dead","year": 1990,"rating": 7.6,"votes": 18279,"running_times": 7020},{"title": "Rough Night","year": 2017,"rating": 5.2,"votes": 24406,"running_times": 6060},{"title": "Rounders","year": 1998,"rating": 7.3,"votes": 128998,"running_times": 7260},{"title": "Roxanne","year": 1987,"rating": 6.6,"votes": 35090,"running_times": 6420},{"title": "Ruang rak noi nid mahasan","year": 2003,"rating": 7.6,"votes": 10116,"running_times": 6720},{"title": "Rubber","year": 2010,"rating": 5.8,"votes": 28779,"running_times": 4920},{"title": "Ruby Sparks","year": 2012,"rating": 7.2,"votes": 86036,"running_times": 6240},{"title": "Rudderless","year": 2014,"rating": 7.5,"votes": 15129,"running_times": 6300},{"title": "Rudy","year": 1993,"rating": 7.5,"votes": 46289,"running_times": 6840},{"title": "Rules of Engagement","year": 2000,"rating": 6.4,"votes": 39708,"running_times": 7680},{"title": "Rumble Fish","year": 1983,"rating": 7.2,"votes": 26538,"running_times": 5640},{"title": "Rumor Has It...","year": 2005,"rating": 5.5,"votes": 44506,"running_times": 5820},{"title": "Run All Night","year": 2015,"rating": 6.6,"votes": 86466,"running_times": 6840},{"title": "Run Fatboy Run","year": 2007,"rating": 6.6,"votes": 61200,"running_times": 6000},{"title": "Runaway Bride","year": 1999,"rating": 5.5,"votes": 80848,"running_times": 6960},{"title": "Runaway Jury","year": 2003,"rating": 7.1,"votes": 81319,"running_times": 7620},{"title": "Runaway Train","year": 1985,"rating": 7.3,"votes": 22568,"running_times": 6660},{"title": "Runner Runner","year": 2013,"rating": 5.6,"votes": 55723,"running_times": 5280},{"title": "Running Scared","year": 2006,"rating": 7.4,"votes": 91408,"running_times": 7320},{"title": "Running on Empty","year": 1988,"rating": 7.7,"votes": 11450,"running_times": 6960},{"title": "Running with Scissors","year": 2006,"rating": 6.2,"votes": 20716,"running_times": 7320},{"title": "Rupan sansei: Kariosutoro no shiro","year": 1979,"rating": 7.8,"votes": 18456,"running_times": 6120},{"title": "Rush","year": 2013,"rating": 8.1,"votes": 355535,"running_times": 7380},{"title": "Rush Hour","year": 1998,"rating": 6.9,"votes": 204134,"running_times": 5880},{"title": "Rush Hour 2","year": 2001,"rating": 6.6,"votes": 173251,"running_times": 5640},{"title": "Rush Hour 3","year": 2007,"rating": 6.2,"votes": 131488,"running_times": 5460},{"title": "Rushmore","year": 1998,"rating": 7.7,"votes": 146456,"running_times": 5580},{"title": "Ruthless People","year": 1986,"rating": 6.9,"votes": 22745,"running_times": 5580},{"title": "S. Darko","year": 2009,"rating": 3.6,"votes": 11844,"running_times": 6180},{"title": "S.W.A.T.","year": 2003,"rating": 6,"votes": 126105,"running_times": 7020},{"title": "S1m0ne","year": 2002,"rating": 6.1,"votes": 54325,"running_times": 7020},{"title": "SLC Punk!","year": 1998,"rating": 7.5,"votes": 23433,"running_times": 5880},{"title": "Sabotage","year": 1936,"rating": 7.1,"votes": 12150,"running_times": 5400},{"title": "Sabotage","year": 2014,"rating": 5.7,"votes": 51832,"running_times": 6540},{"title": "Saboteur","year": 1942,"rating": 7.2,"votes": 19326,"running_times": 6540},{"title": "Sabrina","year": 1954,"rating": 7.7,"votes": 48886,"running_times": 6780},{"title": "Sabrina","year": 1995,"rating": 6.3,"votes": 31724,"running_times": 7620},{"title": "Safe","year": 2012,"rating": 6.5,"votes": 90797,"running_times": 5640},{"title": "Safe Haven","year": 2013,"rating": 6.7,"votes": 88397,"running_times": 6900},{"title": "Safe House","year": 2012,"rating": 6.8,"votes": 179229,"running_times": 6900},{"title": "Safety Last!","year": 1923,"rating": 8.2,"votes": 14595,"running_times": 4200},{"title": "Safety Not Guaranteed","year": 2012,"rating": 7,"votes": 107260,"running_times": 5160},{"title": "Sahara","year": 2005,"rating": 6,"votes": 82179,"running_times": 7440},{"title": "Saints and Soldiers","year": 2003,"rating": 6.8,"votes": 18629,"running_times": 5400},{"title": "Salinui chueok","year": 2003,"rating": 8.1,"votes": 82435,"running_times": 7920},{"title": "Salmon Fishing in the Yemen","year": 2011,"rating": 6.8,"votes": 55360,"running_times": 6420},{"title": "Salt","year": 2010,"rating": 6.4,"votes": 262295,"running_times": 6240},{"title": "Salvador","year": 1986,"rating": 7.5,"votes": 16538,"running_times": 7320},{"title": "Samba","year": 2014,"rating": 6.7,"votes": 12045,"running_times": 7080},{"title": "Samâ uôzu","year": 2009,"rating": 7.6,"votes": 19763,"running_times": 6840},{"title": "San Andreas","year": 2015,"rating": 6.1,"votes": 169965,"running_times": 6840},{"title": "San ging chaat goo si","year": 2004,"rating": 7,"votes": 21048,"running_times": 7380},{"title": "San wa","year": 2005,"rating": 6.2,"votes": 12519,"running_times": 7320},{"title": "Sanctum","year": 2011,"rating": 5.9,"votes": 49371,"running_times": 6480},{"title": "Sand Castle","year": 2017,"rating": 6.3,"votes": 10093,"running_times": 6780},{"title": "Santa sangre","year": 1989,"rating": 7.7,"votes": 15409,"running_times": 7380},{"title": "Sap ji sang ciu","year": 2012,"rating": 6.2,"votes": 17720,"running_times": 7380},{"title": "Saturday Night Fever","year": 1977,"rating": 6.8,"votes": 59027,"running_times": 7080},{"title": "Sausage Party","year": 2016,"rating": 6.2,"votes": 137395,"running_times": 5340},{"title": "Savages","year": 2012,"rating": 6.5,"votes": 110068,"running_times": 8460},{"title": "Save the Last Dance","year": 2001,"rating": 6.2,"votes": 51141,"running_times": 6720},{"title": "Saved!","year": 2004,"rating": 6.8,"votes": 41753,"running_times": 5520},{"title": "Saving Christmas","year": 2014,"rating": 1.5,"votes": 13258,"running_times": 4740},{"title": "Saving Grace","year": 2000,"rating": 6.9,"votes": 16103,"running_times": 5580},{"title": "Saving Mr. Banks","year": 2013,"rating": 7.5,"votes": 129499,"running_times": 7500},{"title": "Saving Private Ryan","year": 1998,"rating": 8.6,"votes": 993815,"running_times": 10140},{"title": "Saving Silverman","year": 2001,"rating": 5.9,"votes": 34937,"running_times": 5760},{"title": "Saw","year": 2004,"rating": 7.7,"votes": 328740,"running_times": 6180},{"title": "Saw 3D","year": 2010,"rating": 5.6,"votes": 76230,"running_times": 5400},{"title": "Saw II","year": 2005,"rating": 6.6,"votes": 204490,"running_times": 5700},{"title": "Saw III","year": 2006,"rating": 6.2,"votes": 155338,"running_times": 7260},{"title": "Saw IV","year": 2007,"rating": 5.9,"votes": 121889,"running_times": 5760},{"title": "Saw V","year": 2008,"rating": 5.8,"votes": 98150,"running_times": 5700},{"title": "Saw VI","year": 2009,"rating": 6,"votes": 85460,"running_times": 5520},{"title": "Say Anything...","year": 1989,"rating": 7.4,"votes": 71475,"running_times": 6000},{"title": "Say It Isn't So","year": 2001,"rating": 4.9,"votes": 11798,"running_times": 5700},{"title": "Scanners","year": 1981,"rating": 6.8,"votes": 39342,"running_times": 6180},{"title": "Scarecrow","year": 1973,"rating": 7.3,"votes": 12680,"running_times": 6720},{"title": "Scarface","year": 1932,"rating": 7.8,"votes": 21323,"running_times": 5580},{"title": "Scarface","year": 1983,"rating": 8.3,"votes": 599692,"running_times": 10200},{"title": "Scarlet Street","year": 1945,"rating": 7.9,"votes": 11212,"running_times": 6120},{"title": "Scary Movie","year": 2000,"rating": 6.2,"votes": 201518,"running_times": 5280},{"title": "Scary Movie 2","year": 2001,"rating": 5.3,"votes": 129387,"running_times": 4980},{"title": "Scary Movie 3","year": 2003,"rating": 5.5,"votes": 120113,"running_times": 5040},{"title": "Scary Movie 4","year": 2006,"rating": 5.1,"votes": 100457,"running_times": 5340},{"title": "Scary Movie 5","year": 2013,"rating": 3.5,"votes": 54977,"running_times": 5280},{"title": "Scent of a Woman","year": 1992,"rating": 8,"votes": 212640,"running_times": 9360},{"title": "Schindler's List","year": 1993,"rating": 8.9,"votes": 971107,"running_times": 11700},{"title": "School Ties","year": 1992,"rating": 6.9,"votes": 19369,"running_times": 6360},{"title": "School for Scoundrels","year": 2006,"rating": 5.9,"votes": 27341,"running_times": 6480},{"title": "Scooby-Doo","year": 2002,"rating": 5,"votes": 78942,"running_times": 5340},{"title": "Scooby-Doo 2: Monsters Unleashed","year": 2004,"rating": 5,"votes": 37459,"running_times": 5580},{"title": "Scoop","year": 2006,"rating": 6.7,"votes": 72462,"running_times": 5760},{"title": "Scott Pilgrim vs. the World","year": 2010,"rating": 7.5,"votes": 306142,"running_times": 6720},{"title": "Scouts Guide to the Zombie Apocalypse","year": 2015,"rating": 6.3,"votes": 35038,"running_times": 5580},{"title": "Scream","year": 1996,"rating": 7.2,"votes": 242085,"running_times": 6660},{"title": "Scream 2","year": 1997,"rating": 6.1,"votes": 134734,"running_times": 7200},{"title": "Scream 3","year": 2000,"rating": 5.5,"votes": 106429,"running_times": 6960},{"title": "Scream 4","year": 2011,"rating": 6.2,"votes": 111421,"running_times": 6660},{"title": "Screamers","year": 1995,"rating": 6.4,"votes": 21789,"running_times": 6480},{"title": "Scrooge","year": 1951,"rating": 8.1,"votes": 16428,"running_times": 5160},{"title": "Scrooged","year": 1988,"rating": 7,"votes": 69474,"running_times": 6060},{"title": "Se, jie","year": 2007,"rating": 7.6,"votes": 32595,"running_times": 9420},{"title": "Se7en","year": 1995,"rating": 8.6,"votes": 1151698,"running_times": 7620},{"title": "Sea of Love","year": 1989,"rating": 6.8,"votes": 32423,"running_times": 6780},{"title": "Seabiscuit","year": 2003,"rating": 7.3,"votes": 60328,"running_times": 8400},{"title": "Searching for Bobby Fischer","year": 1993,"rating": 7.5,"votes": 25503,"running_times": 6540},{"title": "Searching for Sugar Man","year": 2012,"rating": 8.2,"votes": 54182,"running_times": 5160},{"title": "Season of the Witch","year": 2011,"rating": 5.4,"votes": 80961,"running_times": 5700},{"title": "Secondhand Lions","year": 2003,"rating": 7.6,"votes": 46061,"running_times": 7200},{"title": "Seconds","year": 1966,"rating": 7.7,"votes": 12635,"running_times": 6420},{"title": "Secret Window","year": 2004,"rating": 6.6,"votes": 159468,"running_times": 5760},{"title": "Secret in Their Eyes","year": 2015,"rating": 6.2,"votes": 30327,"running_times": 6660},{"title": "Secretariat","year": 2010,"rating": 7.2,"votes": 22480,"running_times": 7380},{"title": "Secretary","year": 2002,"rating": 7,"votes": 72711,"running_times": 6420},{"title": "Secrets & Lies","year": 1996,"rating": 8,"votes": 31211,"running_times": 8160},{"title": "See No Evil","year": 2006,"rating": 5.1,"votes": 23294,"running_times": 5040},{"title": "See No Evil, Hear No Evil","year": 1989,"rating": 6.8,"votes": 40633,"running_times": 6180},{"title": "Seed of Chucky","year": 2004,"rating": 4.9,"votes": 31943,"running_times": 5280},{"title": "Seeking Justice","year": 2011,"rating": 6.2,"votes": 41086,"running_times": 6300},{"title": "Seeking a Friend for the End of the World","year": 2012,"rating": 6.7,"votes": 95893,"running_times": 6060},{"title": "Selena","year": 1997,"rating": 6.7,"votes": 20825,"running_times": 7620},{"title": "Self/less","year": 2015,"rating": 6.5,"votes": 71967,"running_times": 7020},{"title": "Selma","year": 2014,"rating": 7.5,"votes": 70669,"running_times": 7680},{"title": "Semi-Pro","year": 2008,"rating": 5.8,"votes": 70857,"running_times": 5940},{"title": "Sen to Chihiro no kamikakushi","year": 2001,"rating": 8.6,"votes": 485508,"running_times": 7500},{"title": "Senna","year": 2010,"rating": 8.6,"votes": 50116,"running_times": 9720},{"title": "Sennen joyû","year": 2001,"rating": 7.9,"votes": 17251,"running_times": 5220},{"title": "Sense and Sensibility","year": 1995,"rating": 7.7,"votes": 85268,"running_times": 8160},{"title": "Senseless","year": 1998,"rating": 6,"votes": 11518,"running_times": 6480},{"title": "Seraphim Falls","year": 2006,"rating": 6.7,"votes": 26207,"running_times": 6900},{"title": "Serena","year": 2014,"rating": 5.4,"votes": 21113,"running_times": 6540},{"title": "Serendipity","year": 2001,"rating": 6.9,"votes": 92682,"running_times": 5400},{"title": "Serenity","year": 2005,"rating": 7.9,"votes": 256866,"running_times": 7140},{"title": "Sergeant York","year": 1941,"rating": 7.8,"votes": 13214,"running_times": 8040},{"title": "Serial Mom","year": 1994,"rating": 6.7,"votes": 22738,"running_times": 5700},{"title": "Serpico","year": 1973,"rating": 7.8,"votes": 88491,"running_times": 7800},{"title": "Serving Sara","year": 2002,"rating": 5.3,"votes": 15137,"running_times": 6120},{"title": "Session 9","year": 2001,"rating": 6.5,"votes": 47139,"running_times": 6120},{"title": "Set It Off","year": 1996,"rating": 6.8,"votes": 11365,"running_times": 7380},{"title": "Setup","year": 2011,"rating": 4.4,"votes": 18941,"running_times": 5100},{"title": "Seven Brides for Seven Brothers","year": 1954,"rating": 7.4,"votes": 17609,"running_times": 6120},{"title": "Seven Days in May","year": 1964,"rating": 7.9,"votes": 10362,"running_times": 7080},{"title": "Seven Pounds","year": 2008,"rating": 7.7,"votes": 252535,"running_times": 7380},{"title": "Seven Psychopaths","year": 2012,"rating": 7.2,"votes": 203387,"running_times": 6600},{"title": "Seven Sisters","year": 2017,"rating": 6.9,"votes": 37842,"running_times": 7380},{"title": "Seven Years in Tibet","year": 1997,"rating": 7,"votes": 104958,"running_times": 8160},{"title": "Seventh Son","year": 2014,"rating": 5.5,"votes": 62169,"running_times": 6120},{"title": "Severance","year": 2006,"rating": 6.5,"votes": 33423,"running_times": 5760},{"title": "Sex Drive","year": 2008,"rating": 6.5,"votes": 76427,"running_times": 7740},{"title": "Sex Tape","year": 2014,"rating": 5.1,"votes": 93123,"running_times": 5640},{"title": "Sex and the City","year": 2008,"rating": 5.6,"votes": 104825,"running_times": 9060},{"title": "Sex and the City 2","year": 2010,"rating": 4.4,"votes": 64341,"running_times": 8760},{"title": "Sex, Lies, and Videotape","year": 1989,"rating": 7.2,"votes": 41140,"running_times": 6000},{"title": "Sexy Beast","year": 2000,"rating": 7.3,"votes": 46733,"running_times": 5340},{"title": "Sgt. Bilko","year": 1996,"rating": 5.7,"votes": 18882,"running_times": 5580},{"title": "Shade","year": 2003,"rating": 6.4,"votes": 11191,"running_times": 6060},{"title": "Shadow Dancer","year": 2012,"rating": 6.2,"votes": 10788,"running_times": 6060},{"title": "Shadow of a Doubt","year": 1943,"rating": 8,"votes": 49533,"running_times": 6480},{"title": "Shadow of the Vampire","year": 2000,"rating": 6.9,"votes": 35903,"running_times": 5520},{"title": "Shadowlands","year": 1993,"rating": 7.4,"votes": 14386,"running_times": 7860},{"title": "Shadows and Fog","year": 1991,"rating": 6.8,"votes": 14152,"running_times": 5100},{"title": "Shaft","year": 1971,"rating": 6.6,"votes": 13222,"running_times": 6000},{"title": "Shaft","year": 2000,"rating": 5.9,"votes": 62032,"running_times": 5940},{"title": "Shakespeare in Love","year": 1998,"rating": 7.2,"votes": 188788,"running_times": 7380},{"title": "Shall We Dance","year": 2004,"rating": 6.1,"votes": 38211,"running_times": 6360},{"title": "Shallow Grave","year": 1994,"rating": 7.3,"votes": 49609,"running_times": 5340},{"title": "Shallow Hal","year": 2001,"rating": 5.9,"votes": 115543,"running_times": 6840},{"title": "Shame","year": 2011,"rating": 7.2,"votes": 160333,"running_times": 6060},{"title": "Shane","year": 1953,"rating": 7.7,"votes": 30834,"running_times": 7080},{"title": "Shanghai Knights","year": 2003,"rating": 6.2,"votes": 88141,"running_times": 6840},{"title": "Shanghai Noon","year": 2000,"rating": 6.6,"votes": 104603,"running_times": 6600},{"title": "Shark Night 3D","year": 2011,"rating": 4,"votes": 22050,"running_times": 5400},{"title": "Shark Tale","year": 2004,"rating": 6,"votes": 143701,"running_times": 5400},{"title": "Shattered Glass","year": 2003,"rating": 7.2,"votes": 30336,"running_times": 5940},{"title": "Shaun of the Dead","year": 2004,"rating": 8,"votes": 433429,"running_times": 5940},{"title": "She Wore a Yellow Ribbon","year": 1949,"rating": 7.4,"votes": 13029,"running_times": 6180},{"title": "She's All That","year": 1999,"rating": 5.8,"votes": 72798,"running_times": 5700},{"title": "She's Funny That Way","year": 2014,"rating": 6.1,"votes": 20084,"running_times": 5580},{"title": "She's Out of My League","year": 2010,"rating": 6.4,"votes": 108427,"running_times": 6240},{"title": "She's the Man","year": 2006,"rating": 6.4,"votes": 127102,"running_times": 6300},{"title": "She's the One","year": 1996,"rating": 6,"votes": 14808,"running_times": 5760},{"title": "She-Devil","year": 1989,"rating": 5.5,"votes": 13645,"running_times": 5940},{"title": "Shelter","year": 2007,"rating": 7.8,"votes": 17698,"running_times": 5820},{"title": "Sherlock Holmes","year": 2009,"rating": 7.6,"votes": 516835,"running_times": 7680},{"title": "Sherlock Holmes: A Game of Shadows","year": 2011,"rating": 7.5,"votes": 368922,"running_times": 7740},{"title": "Sherlock Jr.","year": 1924,"rating": 8.3,"votes": 24468,"running_times": 2940},{"title": "Sherrybaby","year": 2006,"rating": 6.6,"votes": 10703,"running_times": 5760},{"title": "Shin Gojira","year": 2016,"rating": 6.7,"votes": 12838,"running_times": 7200},{"title": "Shine","year": 1996,"rating": 7.7,"votes": 45923,"running_times": 6300},{"title": "Shine a Light","year": 2008,"rating": 7.2,"votes": 10160,"running_times": 7320},{"title": "Shivers","year": 1975,"rating": 6.6,"votes": 13853,"running_times": 5220},{"title": "Shocker","year": 1989,"rating": 5.4,"votes": 12332,"running_times": 6540},{"title": "Shoot 'Em Up","year": 2007,"rating": 6.7,"votes": 135567,"running_times": 5160},{"title": "Shooter","year": 2007,"rating": 7.2,"votes": 275550,"running_times": 7440},{"title": "Shooting Dogs","year": 2005,"rating": 7.7,"votes": 10219,"running_times": 6900},{"title": "Shopgirl","year": 2005,"rating": 6.4,"votes": 21937,"running_times": 6360},{"title": "Short Circuit","year": 1986,"rating": 6.6,"votes": 47621,"running_times": 5880},{"title": "Short Circuit 2","year": 1988,"rating": 5.6,"votes": 20055,"running_times": 6600},{"title": "Short Cuts","year": 1993,"rating": 7.7,"votes": 37446,"running_times": 11400},{"title": "Short Term 12","year": 2013,"rating": 8,"votes": 65542,"running_times": 5760},{"title": "Shortbus","year": 2006,"rating": 6.5,"votes": 29029,"running_times": 6060},{"title": "Shot Caller","year": 2017,"rating": 7.4,"votes": 33834,"running_times": 7260},{"title": "Showdown in Little Tokyo","year": 1991,"rating": 6.1,"votes": 13607,"running_times": 4740},{"title": "Showgirls","year": 1995,"rating": 4.7,"votes": 53808,"running_times": 7860},{"title": "Showtime","year": 2002,"rating": 5.5,"votes": 55104,"running_times": 5760},{"title": "Shrek","year": 2001,"rating": 7.9,"votes": 512613,"running_times": 5400},{"title": "Shrek 2","year": 2004,"rating": 7.2,"votes": 346813,"running_times": 5580},{"title": "Shrek Forever After","year": 2010,"rating": 6.3,"votes": 152396,"running_times": 5580},{"title": "Shrek the Third","year": 2007,"rating": 6.1,"votes": 232828,"running_times": 5580},{"title": "Shrink","year": 2009,"rating": 6.7,"votes": 17142,"running_times": 6600},{"title": "Shrooms","year": 2007,"rating": 4.7,"votes": 14549,"running_times": 5160},{"title": "Shutter","year": 2008,"rating": 5.2,"votes": 28911,"running_times": 5400},{"title": "Shutter Island","year": 2010,"rating": 8.1,"votes": 898401,"running_times": 8280},{"title": "Sibirskiy tsiryulnik","year": 1998,"rating": 7.9,"votes": 10003,"running_times": 16500},{"title": "Sicario","year": 2015,"rating": 7.6,"votes": 266558,"running_times": 7260},{"title": "Sicko","year": 2007,"rating": 8,"votes": 69593,"running_times": 7380},{"title": "Sid and Nancy","year": 1986,"rating": 7.1,"votes": 25324,"running_times": 6720},{"title": "Side Effects","year": 2013,"rating": 7.1,"votes": 159048,"running_times": 6360},{"title": "Side by Side","year": 2012,"rating": 7.6,"votes": 11999,"running_times": 5940},{"title": "Sideways","year": 2004,"rating": 7.5,"votes": 159915,"running_times": 7560},{"title": "Sightseers","year": 2012,"rating": 6.5,"votes": 23052,"running_times": 5280},{"title": "Signs","year": 2002,"rating": 6.7,"votes": 294860,"running_times": 6360},{"title": "Silence","year": 2016,"rating": 7.2,"votes": 66803,"running_times": 9660},{"title": "Silent Hill","year": 2006,"rating": 6.6,"votes": 191211,"running_times": 7920},{"title": "Silent Hill: Revelation","year": 2012,"rating": 5,"votes": 53668,"running_times": 5700},{"title": "Silent House","year": 2011,"rating": 5.3,"votes": 19737,"running_times": 5160},{"title": "Silent Night, Deadly Night","year": 1984,"rating": 5.9,"votes": 10538,"running_times": 5760},{"title": "Silent Running","year": 1972,"rating": 6.7,"votes": 22780,"running_times": 5340},{"title": "Silk","year": 2007,"rating": 5.9,"votes": 10005,"running_times": 6720},{"title": "Silkwood","year": 1983,"rating": 7.2,"votes": 15363,"running_times": 7860},{"title": "Silver Bullet","year": 1985,"rating": 6.4,"votes": 18780,"running_times": 5700},{"title": "Silver Linings Playbook","year": 2012,"rating": 7.8,"votes": 581668,"running_times": 7320},{"title": "Silver Streak","year": 1976,"rating": 6.9,"votes": 15181,"running_times": 6840},{"title": "Silverado","year": 1985,"rating": 7.2,"votes": 30487,"running_times": 7980},{"title": "Simon Birch","year": 1998,"rating": 6.9,"votes": 19163,"running_times": 6840},{"title": "Simply Irresistible","year": 1999,"rating": 5.3,"votes": 12052,"running_times": 5760},{"title": "Sin City","year": 2005,"rating": 8,"votes": 693152,"running_times": 8820},{"title": "Sin City: A Dame to Kill For","year": 2014,"rating": 6.5,"votes": 127939,"running_times": 6120},{"title": "Sinbad: Legend of the Seven Seas","year": 2003,"rating": 6.7,"votes": 40341,"running_times": 5400},{"title": "Sing","year": 2016,"rating": 7.1,"votes": 88772,"running_times": 6840},{"title": "Sing Street","year": 2016,"rating": 8,"votes": 61913,"running_times": 6360},{"title": "Singham","year": 2011,"rating": 6.7,"votes": 11623,"running_times": 8580},{"title": "Singin' in the Rain","year": 1952,"rating": 8.3,"votes": 172852,"running_times": 6180},{"title": "Single White Female","year": 1992,"rating": 6.3,"votes": 26137,"running_times": 6420},{"title": "Singles","year": 1992,"rating": 6.7,"votes": 24370,"running_times": 5940},{"title": "Sinister","year": 2012,"rating": 6.8,"votes": 180429,"running_times": 6600},{"title": "Sinister 2","year": 2015,"rating": 5.3,"votes": 34973,"running_times": 5820},{"title": "Sister Act","year": 1992,"rating": 6.3,"votes": 71673,"running_times": 6000},{"title": "Sister Act 2: Back in the Habit","year": 1993,"rating": 5.4,"votes": 39947,"running_times": 6420},{"title": "Sisters","year": 1972,"rating": 7,"votes": 11910,"running_times": 5580},{"title": "Sisters","year": 2015,"rating": 6,"votes": 53056,"running_times": 7080},{"title": "Sivaji","year": 2007,"rating": 7.5,"votes": 13175,"running_times": 11280},{"title": "Six Days Seven Nights","year": 1998,"rating": 5.8,"votes": 64644,"running_times": 5880},{"title": "Six Degrees of Separation","year": 1993,"rating": 6.9,"votes": 17552,"running_times": 6720},{"title": "Sixteen Candles","year": 1984,"rating": 7.1,"votes": 83729,"running_times": 5580},{"title": "Skinwalkers","year": 2006,"rating": 4.6,"votes": 12097,"running_times": 6600},{"title": "Sky Captain and the World of Tomorrow","year": 2004,"rating": 6.1,"votes": 75817,"running_times": 6360},{"title": "Sky High","year": 2005,"rating": 6.2,"votes": 67093,"running_times": 6000},{"title": "Skyfall","year": 2012,"rating": 7.8,"votes": 560755,"running_times": 8580},{"title": "Skyline","year": 2010,"rating": 4.4,"votes": 79577,"running_times": 5820},{"title": "Slacker","year": 1991,"rating": 7.1,"votes": 16600,"running_times": 6000},{"title": "Slackers","year": 2002,"rating": 5.3,"votes": 12868,"running_times": 5160},{"title": "Slap Shot","year": 1977,"rating": 7.4,"votes": 30240,"running_times": 7380},{"title": "Slaughterhouse-Five","year": 1972,"rating": 7,"votes": 10444,"running_times": 6240},{"title": "Sleepaway Camp","year": 1983,"rating": 6.3,"votes": 18885,"running_times": 5040},{"title": "Sleeper","year": 1973,"rating": 7.3,"votes": 35717,"running_times": 5340},{"title": "Sleepers","year": 1996,"rating": 7.6,"votes": 165120,"running_times": 8820},{"title": "Sleeping Beauty","year": 1959,"rating": 7.3,"votes": 111600,"running_times": 4500},{"title": "Sleeping Beauty","year": 2011,"rating": 5.3,"votes": 27668,"running_times": 6060},{"title": "Sleeping with Other People","year": 2015,"rating": 6.5,"votes": 30768,"running_times": 6060},{"title": "Sleeping with the Enemy","year": 1991,"rating": 6.2,"votes": 41133,"running_times": 5940},{"title": "Sleepless","year": 2017,"rating": 5.6,"votes": 19069,"running_times": 5700},{"title": "Sleepless in Seattle","year": 1993,"rating": 6.8,"votes": 133798,"running_times": 6300},{"title": "Sleepover","year": 2004,"rating": 5.3,"votes": 13528,"running_times": 5340},{"title": "Sleepwalk with Me","year": 2012,"rating": 6.8,"votes": 10769,"running_times": 4860},{"title": "Sleepwalkers","year": 1992,"rating": 5.2,"votes": 16562,"running_times": 5460},{"title": "Sleepy Hollow","year": 1999,"rating": 7.4,"votes": 288484,"running_times": 6300},{"title": "Sleuth","year": 1972,"rating": 8.1,"votes": 39448,"running_times": 8280},{"title": "Sleuth","year": 2007,"rating": 6.5,"votes": 27574,"running_times": 5280},{"title": "Sliding Doors","year": 1998,"rating": 6.8,"votes": 55967,"running_times": 5940},{"title": "Sling Blade","year": 1996,"rating": 8,"votes": 77328,"running_times": 8880},{"title": "Slither","year": 2006,"rating": 6.5,"votes": 66043,"running_times": 5700},{"title": "Sliver","year": 1993,"rating": 4.9,"votes": 24667,"running_times": 6420},{"title": "Slow West","year": 2015,"rating": 6.9,"votes": 33707,"running_times": 5040},{"title": "Slumdog Millionaire","year": 2008,"rating": 8,"votes": 697092,"running_times": 7200},{"title": "Slums of Beverly Hills","year": 1998,"rating": 6.6,"votes": 10177,"running_times": 5520},{"title": "Small Soldiers","year": 1998,"rating": 6.1,"votes": 81823,"running_times": 6600},{"title": "Small Time Crooks","year": 2000,"rating": 6.7,"votes": 33129,"running_times": 5640},{"title": "Smart People","year": 2008,"rating": 6.2,"votes": 21359,"running_times": 5700},{"title": "Smashed","year": 2012,"rating": 6.8,"votes": 14793,"running_times": 4860},{"title": "Smiley Face","year": 2007,"rating": 5.8,"votes": 14734,"running_times": 5280},{"title": "Smilla's Sense of Snow","year": 1997,"rating": 6.4,"votes": 12278,"running_times": 7260},{"title": "Smoke","year": 1995,"rating": 7.4,"votes": 29719,"running_times": 6720},{"title": "Smokey and the Bandit","year": 1977,"rating": 6.9,"votes": 35477,"running_times": 5760},{"title": "Smokey and the Bandit II","year": 1980,"rating": 5.2,"votes": 12223,"running_times": 6000},{"title": "Smokin' Aces","year": 2006,"rating": 6.7,"votes": 126545,"running_times": 6540},{"title": "Smurfs: The Lost Village","year": 2017,"rating": 5.9,"votes": 11182,"running_times": 5400},{"title": "Snabba cash","year": 2010,"rating": 6.7,"votes": 14683,"running_times": 7440},{"title": "Snake Eyes","year": 1998,"rating": 6,"votes": 67876,"running_times": 5880},{"title": "Snakes on a Plane","year": 2006,"rating": 5.6,"votes": 120964,"running_times": 6300},{"title": "Snatch","year": 2000,"rating": 8.3,"votes": 662781,"running_times": 6240},{"title": "Snatched","year": 2017,"rating": 4.3,"votes": 20447,"running_times": 5400},{"title": "Sneakers","year": 1992,"rating": 7.1,"votes": 46445,"running_times": 7560},{"title": "Sniper","year": 1993,"rating": 6.1,"votes": 20484,"running_times": 5880},{"title": "Snitch","year": 2013,"rating": 6.5,"votes": 70259,"running_times": 6720},{"title": "Snow Angels","year": 2007,"rating": 6.9,"votes": 11437,"running_times": 6420},{"title": "Snow Cake","year": 2006,"rating": 7.6,"votes": 11373,"running_times": 6720},{"title": "Snow Day","year": 2000,"rating": 5,"votes": 10054,"running_times": 5340},{"title": "Snow Dogs","year": 2002,"rating": 5.1,"votes": 21931,"running_times": 5940},{"title": "Snow Falling on Cedars","year": 1999,"rating": 6.8,"votes": 12764,"running_times": 7620},{"title": "Snow White and the Huntsman","year": 2012,"rating": 6.1,"votes": 245114,"running_times": 7920},{"title": "Snow White and the Seven Dwarfs","year": 1937,"rating": 7.6,"votes": 149216,"running_times": 4980},{"title": "Snowden","year": 2016,"rating": 7.3,"votes": 97053,"running_times": 8040},{"title": "Snowpiercer","year": 2013,"rating": 7,"votes": 211297,"running_times": 7560},{"title": "Snowtown","year": 2011,"rating": 6.6,"votes": 14705,"running_times": 7140},{"title": "So I Married an Axe Murderer","year": 1993,"rating": 6.4,"votes": 29635,"running_times": 5580},{"title": "So Undercover","year": 2012,"rating": 5,"votes": 16254,"running_times": 5640},{"title": "Soaked in Bleach","year": 2015,"rating": 7.5,"votes": 11775,"running_times": 5400},{"title": "Soapdish","year": 1991,"rating": 6.5,"votes": 12426,"running_times": 5820},{"title": "Solace","year": 2015,"rating": 6.4,"votes": 40172,"running_times": 6060},{"title": "Solaris","year": 2002,"rating": 6.2,"votes": 71407,"running_times": 5940},{"title": "Soldier","year": 1998,"rating": 6,"votes": 46574,"running_times": 5940},{"title": "Solitary Man","year": 2009,"rating": 6.4,"votes": 14234,"running_times": 5400},{"title": "Solomon Kane","year": 2009,"rating": 6.1,"votes": 62676,"running_times": 6240},{"title": "Some Kind of Wonderful","year": 1987,"rating": 7.1,"votes": 22260,"running_times": 5700},{"title": "Some Like It Hot","year": 1959,"rating": 8.3,"votes": 196104,"running_times": 7260},{"title": "Someone Like You...","year": 2001,"rating": 6.1,"votes": 21215,"running_times": 5820},{"title": "Something Borrowed","year": 2011,"rating": 5.9,"votes": 51403,"running_times": 6720},{"title": "Something New","year": 2006,"rating": 6.8,"votes": 11183,"running_times": 5940},{"title": "Something Wild","year": 1986,"rating": 6.9,"votes": 13322,"running_times": 6840},{"title": "Something to Talk About","year": 1995,"rating": 5.7,"votes": 11196,"running_times": 6360},{"title": "Something's Gotta Give","year": 2003,"rating": 6.7,"votes": 97460,"running_times": 7680},{"title": "Somewhere","year": 2010,"rating": 6.3,"votes": 38373,"running_times": 5820},{"title": "Somewhere in Time","year": 1980,"rating": 7.3,"votes": 22652,"running_times": 6180},{"title": "Sommersby","year": 1993,"rating": 6.1,"votes": 16639,"running_times": 6840},{"title": "Son in Law","year": 1993,"rating": 5.7,"votes": 14621,"running_times": 5700},{"title": "Son of God","year": 2014,"rating": 5.7,"votes": 16625,"running_times": 10200},{"title": "Son of Rambow","year": 2007,"rating": 7,"votes": 28460,"running_times": 5760},{"title": "Son of a Gun","year": 2014,"rating": 6.5,"votes": 21903,"running_times": 6480},{"title": "Son of the Mask","year": 2005,"rating": 2.2,"votes": 44987,"running_times": 5640},{"title": "Song of the Sea","year": 2014,"rating": 8.1,"votes": 36215,"running_times": 5580},{"title": "Song to Song","year": 2017,"rating": 5.8,"votes": 10321,"running_times": 7740},{"title": "Sophie's Choice","year": 1982,"rating": 7.7,"votes": 32806,"running_times": 9420},{"title": "Sorcerer","year": 1977,"rating": 7.8,"votes": 11937,"running_times": 7260},{"title": "Sorority Boys","year": 2002,"rating": 5.4,"votes": 12562,"running_times": 5580},{"title": "Sorority Row","year": 2009,"rating": 5.1,"votes": 25521,"running_times": 6060},{"title": "Soul Kitchen","year": 2009,"rating": 7.3,"votes": 31562,"running_times": 5940},{"title": "Soul Plane","year": 2004,"rating": 4.4,"votes": 19355,"running_times": 5520},{"title": "Soul Surfer","year": 2011,"rating": 7.1,"votes": 38676,"running_times": 6720},{"title": "Sound of My Voice","year": 2011,"rating": 6.6,"votes": 18046,"running_times": 5100},{"title": "Source Code","year": 2011,"rating": 7.5,"votes": 420082,"running_times": 5580},{"title": "South Park: Bigger, Longer & Uncut","year": 1999,"rating": 7.8,"votes": 173169,"running_times": 4860},{"title": "Southbound","year": 2015,"rating": 5.9,"votes": 11805,"running_times": 5340},{"title": "Southern Comfort","year": 1981,"rating": 7.2,"votes": 13134,"running_times": 6360},{"title": "Southland Tales","year": 2006,"rating": 5.5,"votes": 33843,"running_times": 9600},{"title": "Southpaw","year": 2015,"rating": 7.4,"votes": 180071,"running_times": 7440},{"title": "Soylent Green","year": 1973,"rating": 7.1,"votes": 48661,"running_times": 5820},{"title": "Space Cowboys","year": 2000,"rating": 6.4,"votes": 64257,"running_times": 7800},{"title": "Space Jam","year": 1996,"rating": 6.3,"votes": 126652,"running_times": 5280},{"title": "SpaceCamp","year": 1986,"rating": 5.6,"votes": 11589,"running_times": 6420},{"title": "Spaceballs","year": 1987,"rating": 7.1,"votes": 148313,"running_times": 5760},{"title": "Spanglish","year": 2004,"rating": 6.4,"votes": 69742,"running_times": 7860},{"title": "Sparks","year": 2013,"rating": 5.9,"votes": 10225,"running_times": 5820},{"title": "Spartacus","year": 1960,"rating": 7.9,"votes": 105800,"running_times": 11820},{"title": "Spartan","year": 2004,"rating": 6.6,"votes": 27486,"running_times": 6360},{"title": "Spawn","year": 1997,"rating": 5.2,"votes": 56746,"running_times": 5880},{"title": "Speak","year": 2004,"rating": 7.4,"votes": 22204,"running_times": 5340},{"title": "Special Correspondents","year": 2016,"rating": 5.8,"votes": 13704,"running_times": 6060},{"title": "Species","year": 1995,"rating": 5.8,"votes": 65194,"running_times": 6480},{"title": "Species II","year": 1998,"rating": 4.3,"votes": 24126,"running_times": 5580},{"title": "Spectral","year": 2016,"rating": 6.3,"votes": 32422,"running_times": 6420},{"title": "Spectre","year": 2015,"rating": 6.8,"votes": 323174,"running_times": 8880},{"title": "Speed","year": 1994,"rating": 7.2,"votes": 282195,"running_times": 6960},{"title": "Speed 2: Cruise Control","year": 1997,"rating": 3.8,"votes": 64736,"running_times": 7260},{"title": "Speed Racer","year": 2008,"rating": 6,"votes": 61516,"running_times": 8100},{"title": "Spellbound","year": 1945,"rating": 7.6,"votes": 36085,"running_times": 7080},{"title": "Spellbound","year": 2002,"rating": 7.6,"votes": 11339,"running_times": 5820},{"title": "Sphere","year": 1998,"rating": 6.1,"votes": 88295,"running_times": 8040},{"title": "Spice World","year": 1997,"rating": 3.4,"votes": 29530,"running_times": 5580},{"title": "Spider","year": 2002,"rating": 6.8,"votes": 31954,"running_times": 5880},{"title": "Spider-Man","year": 2002,"rating": 7.3,"votes": 592886,"running_times": 7260},{"title": "Spider-Man 2","year": 2004,"rating": 7.3,"votes": 456912,"running_times": 8100},{"title": "Spider-Man 3","year": 2007,"rating": 6.2,"votes": 421570,"running_times": 8340},{"title": "Spider-Man: Homecoming","year": 2017,"rating": 7.6,"votes": 249739,"running_times": 7980},{"title": "Spies Like Us","year": 1985,"rating": 6.4,"votes": 37604,"running_times": 6120},{"title": "Spirit: Stallion of the Cimarron","year": 2002,"rating": 7.1,"votes": 51140,"running_times": 5160},{"title": "Splash","year": 1984,"rating": 6.2,"votes": 59128,"running_times": 6660},{"title": "Splendor in the Grass","year": 1961,"rating": 7.8,"votes": 14760,"running_times": 7440},{"title": "Splice","year": 2009,"rating": 5.8,"votes": 83775,"running_times": 6240},{"title": "Splinter","year": 2008,"rating": 6.1,"votes": 28948,"running_times": 4920},{"title": "Split","year": 2016,"rating": 7.3,"votes": 234221,"running_times": 7020},{"title": "Spooks: The Greater Good","year": 2015,"rating": 6.2,"votes": 16463,"running_times": 6240},{"title": "Spoorloos","year": 1988,"rating": 7.8,"votes": 27755,"running_times": 6420},{"title": "Spotlight","year": 2015,"rating": 8.1,"votes": 297395,"running_times": 7680},{"title": "Spread","year": 2009,"rating": 5.9,"votes": 34410,"running_times": 5820},{"title": "Spring","year": 2014,"rating": 6.7,"votes": 17755,"running_times": 6540},{"title": "Spring Breakers","year": 2012,"rating": 5.3,"votes": 117494,"running_times": 5640},{"title": "Spun","year": 2002,"rating": 6.8,"votes": 33594,"running_times": 6360},{"title": "Spy","year": 2015,"rating": 7,"votes": 196663,"running_times": 7800},{"title": "Spy Game","year": 2001,"rating": 7.1,"votes": 128296,"running_times": 7560},{"title": "Spy Hard","year": 1996,"rating": 5.3,"votes": 31921,"running_times": 4860},{"title": "Spy Kids","year": 2001,"rating": 5.4,"votes": 91900,"running_times": 5280},{"title": "Spy Kids 2: Island of Lost Dreams","year": 2002,"rating": 5.1,"votes": 49760,"running_times": 6000},{"title": "Spy Kids 3: Game Over","year": 2003,"rating": 4.2,"votes": 44716,"running_times": 5040},{"title": "Spy Kids: All the Time in the World in 4D","year": 2011,"rating": 3.6,"votes": 17547,"running_times": 5340},{"title": "Srpski film","year": 2010,"rating": 5.2,"votes": 45822,"running_times": 6240},{"title": "St. Elmo's Fire","year": 1985,"rating": 6.4,"votes": 30251,"running_times": 6600},{"title": "St. Trinian's","year": 2007,"rating": 5.8,"votes": 19445,"running_times": 6000},{"title": "St. Vincent","year": 2014,"rating": 7.3,"votes": 83606,"running_times": 6120},{"title": "Stage Fright","year": 1950,"rating": 7.1,"votes": 10406,"running_times": 6600},{"title": "Stagecoach","year": 1939,"rating": 7.9,"votes": 34419,"running_times": 5760},{"title": "Stake Land","year": 2010,"rating": 6.5,"votes": 37105,"running_times": 5880},{"title": "Stakeout","year": 1987,"rating": 6.6,"votes": 20222,"running_times": 7020},{"title": "Stalag 17","year": 1953,"rating": 8,"votes": 45605,"running_times": 7200},{"title": "Stan Helsing","year": 2009,"rating": 3.6,"votes": 10509,"running_times": 6480},{"title": "Stand Up Guys","year": 2012,"rating": 6.5,"votes": 48161,"running_times": 5700},{"title": "Stand and Deliver","year": 1988,"rating": 7.3,"votes": 13394,"running_times": 6180},{"title": "Stand by Me","year": 1986,"rating": 8.1,"votes": 303523,"running_times": 5340},{"title": "Star Trek","year": 2009,"rating": 8,"votes": 536248,"running_times": 7620},{"title": "Star Trek III: The Search for Spock","year": 1984,"rating": 6.7,"votes": 63865,"running_times": 6300},{"title": "Star Trek IV: The Voyage Home","year": 1986,"rating": 7.3,"votes": 67227,"running_times": 7140},{"title": "Star Trek V: The Final Frontier","year": 1989,"rating": 5.4,"votes": 47861,"running_times": 6420},{"title": "Star Trek VI: The Undiscovered Country","year": 1991,"rating": 7.2,"votes": 60259,"running_times": 6780},{"title": "Star Trek: Beyond","year": 2016,"rating": 7.1,"votes": 184977,"running_times": 7320},{"title": "Star Trek: First Contact","year": 1996,"rating": 7.6,"votes": 103993,"running_times": 6660},{"title": "Star Trek: Generations","year": 1994,"rating": 6.6,"votes": 65421,"running_times": 7080},{"title": "Star Trek: Insurrection","year": 1998,"rating": 6.4,"votes": 60876,"running_times": 6180},{"title": "Star Trek: Into Darkness","year": 2013,"rating": 7.8,"votes": 427145,"running_times": 7920},{"title": "Star Trek: Nemesis","year": 2002,"rating": 6.4,"votes": 63211,"running_times": 6960},{"title": "Star Trek: The Motion Picture","year": 1979,"rating": 6.4,"votes": 69315,"running_times": 8580},{"title": "Star Trek: The Wrath of Khan","year": 1982,"rating": 7.7,"votes": 98459,"running_times": 6960},{"title": "Star Wars","year": 1977,"rating": 8.7,"votes": 1017627,"running_times": 7500},{"title": "Star Wars: Episode I - The Phantom Menace","year": 1999,"rating": 6.5,"votes": 595846,"running_times": 8160},{"title": "Star Wars: Episode II - Attack of the Clones","year": 2002,"rating": 6.6,"votes": 521026,"running_times": 8520},{"title": "Star Wars: Episode III - Revenge of the Sith","year": 2005,"rating": 7.6,"votes": 581269,"running_times": 8400},{"title": "Star Wars: Episode V - The Empire Strikes Back","year": 1980,"rating": 8.8,"votes": 945421,"running_times": 7620},{"title": "Star Wars: Episode VI - Return of the Jedi","year": 1983,"rating": 8.4,"votes": 775825,"running_times": 8040},{"title": "Star Wars: Episode VII - The Force Awakens","year": 2015,"rating": 8.1,"votes": 707963,"running_times": 8160},{"title": "Star Wars: Episode VIII - The Last Jedi","year": 2017,"rating": 7.8,"votes": 151246,"running_times": 9120},{"title": "Star Wars: The Clone Wars","year": 2008,"rating": 5.9,"votes": 46331,"running_times": 5880},{"title": "Stardust","year": 2007,"rating": 7.7,"votes": 226118,"running_times": 7620},{"title": "Stardust Memories","year": 1980,"rating": 7.4,"votes": 18163,"running_times": 5340},{"title": "Stargate","year": 1994,"rating": 7.1,"votes": 157475,"running_times": 7800},{"title": "Starman","year": 1984,"rating": 7,"votes": 36137,"running_times": 6900},{"title": "Starred Up","year": 2013,"rating": 7.4,"votes": 36248,"running_times": 6360},{"title": "Starry Eyes","year": 2014,"rating": 6,"votes": 13931,"running_times": 5880},{"title": "Starship Troopers","year": 1997,"rating": 7.2,"votes": 237306,"running_times": 7740},{"title": "Starsky & Hutch","year": 2004,"rating": 6.1,"votes": 126352,"running_times": 6060},{"title": "Starter for 10","year": 2006,"rating": 6.7,"votes": 19276,"running_times": 5520},{"title": "State and Main","year": 2000,"rating": 6.8,"votes": 18956,"running_times": 6300},{"title": "State of Grace","year": 1990,"rating": 7.3,"votes": 17972,"running_times": 8040},{"title": "State of Play","year": 2009,"rating": 7.1,"votes": 119675,"running_times": 7620},{"title": "Stay","year": 2005,"rating": 6.9,"votes": 66125,"running_times": 5940},{"title": "Stay Alive","year": 2006,"rating": 5.1,"votes": 27146,"running_times": 6000},{"title": "Staying Alive","year": 1983,"rating": 4.5,"votes": 12227,"running_times": 5760},{"title": "Stealing Beauty","year": 1996,"rating": 6.6,"votes": 21983,"running_times": 7080},{"title": "Stealing Harvard","year": 2002,"rating": 5.1,"votes": 11543,"running_times": 5100},{"title": "Stealth","year": 2005,"rating": 5,"votes": 47402,"running_times": 7260},{"title": "Steamboat Bill, Jr.","year": 1928,"rating": 8,"votes": 10531,"running_times": 4200},{"title": "Steel Magnolias","year": 1989,"rating": 7.2,"votes": 37721,"running_times": 7140},{"title": "Step Brothers","year": 2008,"rating": 6.9,"votes": 229760,"running_times": 6360},{"title": "Step Up","year": 2006,"rating": 6.5,"votes": 98606,"running_times": 6240},{"title": "Step Up 2: The Streets","year": 2008,"rating": 6.2,"votes": 72340,"running_times": 5880},{"title": "Step Up 3D","year": 2010,"rating": 6.2,"votes": 50574,"running_times": 6420},{"title": "Step Up All In","year": 2014,"rating": 6,"votes": 28255,"running_times": 6720},{"title": "Step Up Revolution","year": 2012,"rating": 6.5,"votes": 48730,"running_times": 5940},{"title": "Stepmom","year": 1998,"rating": 6.7,"votes": 51070,"running_times": 7440},{"title": "Steve Jobs","year": 2015,"rating": 7.2,"votes": 124496,"running_times": 7320},{"title": "Stick It","year": 2006,"rating": 6.4,"votes": 24032,"running_times": 6180},{"title": "Stigmata","year": 1999,"rating": 6.2,"votes": 57586,"running_times": 6180},{"title": "Still Alice","year": 2014,"rating": 7.5,"votes": 104004,"running_times": 6060},{"title": "Stir Crazy","year": 1980,"rating": 6.8,"votes": 20418,"running_times": 6660},{"title": "Stir of Echoes","year": 1999,"rating": 7,"votes": 66144,"running_times": 5940},{"title": "Stoker","year": 2013,"rating": 6.8,"votes": 91869,"running_times": 5940},{"title": "Stolen","year": 2012,"rating": 5.5,"votes": 39431,"running_times": 5760},{"title": "Stomp the Yard","year": 2007,"rating": 5.3,"votes": 20324,"running_times": 6900},{"title": "Stone","year": 2010,"rating": 5.4,"votes": 36629,"running_times": 6300},{"title": "Stop! Or My Mom Will Shoot","year": 1992,"rating": 4.1,"votes": 33866,"running_times": 5220},{"title": "Stop-Loss","year": 2008,"rating": 6.5,"votes": 18497,"running_times": 6720},{"title": "Stories We Tell","year": 2012,"rating": 7.6,"votes": 10436,"running_times": 6480},{"title": "Storks","year": 2016,"rating": 6.8,"votes": 42746,"running_times": 5220},{"title": "Stormbreaker","year": 2006,"rating": 5.1,"votes": 21362,"running_times": 5580},{"title": "Storytelling","year": 2001,"rating": 6.9,"votes": 15914,"running_times": 5220},{"title": "Straight Outta Compton","year": 2015,"rating": 7.9,"votes": 149835,"running_times": 10020},{"title": "Strange Days","year": 1995,"rating": 7.2,"votes": 58409,"running_times": 8700},{"title": "Strange Wilderness","year": 2008,"rating": 5.3,"votes": 19489,"running_times": 5220},{"title": "Stranger Than Fiction","year": 2006,"rating": 7.6,"votes": 198359,"running_times": 6780},{"title": "Stranger Than Paradise","year": 1984,"rating": 7.6,"votes": 28124,"running_times": 5340},{"title": "Strangers on a Train","year": 1951,"rating": 8,"votes": 106706,"running_times": 6180},{"title": "Straw Dogs","year": 1971,"rating": 7.5,"votes": 48867,"running_times": 7080},{"title": "Straw Dogs","year": 2011,"rating": 5.8,"votes": 28934,"running_times": 6600},{"title": "Street Fighter","year": 1994,"rating": 3.8,"votes": 56501,"running_times": 6120},{"title": "Street Fighter: The Legend of Chun-Li","year": 2009,"rating": 3.7,"votes": 20710,"running_times": 5760},{"title": "Street Kings","year": 2008,"rating": 6.8,"votes": 99006,"running_times": 6540},{"title": "Streets of Fire","year": 1984,"rating": 6.7,"votes": 13960,"running_times": 5700},{"title": "Stretch","year": 2014,"rating": 6.5,"votes": 25506,"running_times": 5640},{"title": "Strictly Ballroom","year": 1992,"rating": 7.2,"votes": 21836,"running_times": 5640},{"title": "Striking Distance","year": 1993,"rating": 5.8,"votes": 35780,"running_times": 6120},{"title": "Stripes","year": 1981,"rating": 6.9,"votes": 53430,"running_times": 7320},{"title": "Striptease","year": 1996,"rating": 4.3,"votes": 37180,"running_times": 7020},{"title": "Stroszek","year": 1977,"rating": 8,"votes": 10592,"running_times": 6900},{"title": "Struck by Lightning","year": 2012,"rating": 6.3,"votes": 13599,"running_times": 5400},{"title": "Stuart Little","year": 1999,"rating": 5.9,"votes": 105005,"running_times": 5040},{"title": "Stuart Little 2","year": 2002,"rating": 5.4,"votes": 41063,"running_times": 4920},{"title": "Stuck in Love","year": 2012,"rating": 7.3,"votes": 73477,"running_times": 5820},{"title": "Stuck on You","year": 2003,"rating": 5.8,"votes": 46800,"running_times": 7080},{"title": "Submarine","year": 2010,"rating": 7.3,"votes": 74119,"running_times": 5820},{"title": "Suburra","year": 2015,"rating": 7.4,"votes": 11483,"running_times": 7800},{"title": "Suchîmubôi","year": 2004,"rating": 6.9,"votes": 14714,"running_times": 7620},{"title": "Sucker Punch","year": 2011,"rating": 6.1,"votes": 209381,"running_times": 7680},{"title": "Sudden Death","year": 1995,"rating": 5.7,"votes": 27751,"running_times": 6660},{"title": "Sudden Impact","year": 1983,"rating": 6.6,"votes": 34112,"running_times": 7020},{"title": "Suddenly, Last Summer","year": 1959,"rating": 7.6,"votes": 11425,"running_times": 6840},{"title": "Suffragette","year": 2015,"rating": 6.9,"votes": 28983,"running_times": 6360},{"title": "Sugar & Spice","year": 2001,"rating": 5.6,"votes": 12104,"running_times": 5040},{"title": "Suicide Kings","year": 1997,"rating": 7,"votes": 23626,"running_times": 6360},{"title": "Suicide Squad","year": 2016,"rating": 6.1,"votes": 453361,"running_times": 8040},{"title": "Suite Française","year": 2014,"rating": 6.9,"votes": 15697,"running_times": 6420},{"title": "Sukiyaki Western Django","year": 2007,"rating": 6.3,"votes": 13457,"running_times": 7260},{"title": "Sullivan's Travels","year": 1941,"rating": 8.1,"votes": 20038,"running_times": 5400},{"title": "Sully","year": 2016,"rating": 7.5,"votes": 165235,"running_times": 5760},{"title": "Summer Catch","year": 2001,"rating": 5,"votes": 13708,"running_times": 6480},{"title": "Summer Rental","year": 1985,"rating": 6.2,"votes": 11213,"running_times": 5280},{"title": "Summer School","year": 1987,"rating": 6.5,"votes": 14190,"running_times": 5820},{"title": "Summer of Sam","year": 1999,"rating": 6.6,"votes": 32643,"running_times": 8520},{"title": "Sunrise: A Song of Two Humans","year": 1927,"rating": 8.2,"votes": 34599,"running_times": 6360},{"title": "Sunset Blvd.","year": 1950,"rating": 8.5,"votes": 157474,"running_times": 6900},{"title": "Sunshine","year": 1999,"rating": 7.5,"votes": 11782,"running_times": 10860},{"title": "Sunshine","year": 2007,"rating": 7.3,"votes": 206210,"running_times": 6420},{"title": "Sunshine Cleaning","year": 2008,"rating": 6.9,"votes": 63947,"running_times": 5460},{"title": "Super","year": 2010,"rating": 6.8,"votes": 66282,"running_times": 5760},{"title": "Super 8","year": 2011,"rating": 7,"votes": 305903,"running_times": 6720},{"title": "Super High Me","year": 2007,"rating": 6.1,"votes": 12122,"running_times": 5640},{"title": "Super Mario Bros.","year": 1993,"rating": 4,"votes": 40962,"running_times": 6240},{"title": "Super Size Me","year": 2004,"rating": 7.2,"votes": 91271,"running_times": 6000},{"title": "Super Troopers","year": 2001,"rating": 7.1,"votes": 81588,"running_times": 6000},{"title": "Superbabies: Baby Geniuses 2","year": 2004,"rating": 2,"votes": 27008,"running_times": 5280},{"title": "Superbad","year": 2007,"rating": 7.6,"votes": 454499,"running_times": 7140},{"title": "Supergirl","year": 1984,"rating": 4.3,"votes": 15532,"running_times": 9000},{"title": "Superhero Movie","year": 2008,"rating": 4.5,"votes": 55895,"running_times": 4920},{"title": "Superman","year": 1978,"rating": 7.3,"votes": 137512,"running_times": 11280},{"title": "Superman II","year": 1980,"rating": 6.8,"votes": 83797,"running_times": 7620},{"title": "Superman III","year": 1983,"rating": 4.9,"votes": 54869,"running_times": 7500},{"title": "Superman IV: The Quest for Peace","year": 1987,"rating": 3.7,"votes": 36261,"running_times": 8040},{"title": "Superman Returns","year": 2006,"rating": 6.1,"votes": 251227,"running_times": 9240},{"title": "Supernova","year": 2000,"rating": 4.8,"votes": 15455,"running_times": 5460},{"title": "Superstar","year": 1999,"rating": 5,"votes": 15843,"running_times": 4860},{"title": "Surf's Up","year": 2007,"rating": 6.7,"votes": 58422,"running_times": 5100},{"title": "Surrogates","year": 2009,"rating": 6.3,"votes": 158065,"running_times": 5340},{"title": "Surveillance","year": 2008,"rating": 6.4,"votes": 15562,"running_times": 5820},{"title": "Survival of the Dead","year": 2009,"rating": 4.9,"votes": 18505,"running_times": 5400},{"title": "Surviving Christmas","year": 2004,"rating": 5.4,"votes": 19131,"running_times": 5460},{"title": "Survivor","year": 2015,"rating": 5.6,"votes": 25487,"running_times": 5760},{"title": "Suspect Zero","year": 2004,"rating": 5.9,"votes": 17272,"running_times": 5940},{"title": "Suspicion","year": 1941,"rating": 7.4,"votes": 26314,"running_times": 5940},{"title": "Suspiria","year": 1977,"rating": 7.5,"votes": 53227,"running_times": 5880},{"title": "Swades: We, the People","year": 2004,"rating": 8.3,"votes": 67127,"running_times": 12600},{"title": "Swamp Thing","year": 1982,"rating": 5.4,"votes": 10572,"running_times": 5580},{"title": "Sweeney Todd: The Demon Barber of Fleet Street","year": 2007,"rating": 7.4,"votes": 304578,"running_times": 6960},{"title": "Sweet Home Alabama","year": 2002,"rating": 6.2,"votes": 89850,"running_times": 6480},{"title": "Sweet November","year": 2001,"rating": 6.7,"votes": 75538,"running_times": 7140},{"title": "Sweet Sixteen","year": 2002,"rating": 7.5,"votes": 11509,"running_times": 6360},{"title": "Sweet Smell of Success","year": 1957,"rating": 8.2,"votes": 22137,"running_times": 5760},{"title": "Sweet and Lowdown","year": 1999,"rating": 7.3,"votes": 29295,"running_times": 5700},{"title": "Swept Away","year": 2002,"rating": 3.6,"votes": 13837,"running_times": 5340},{"title": "Swimfan","year": 2002,"rating": 5,"votes": 17194,"running_times": 5100},{"title": "Swimming Pool","year": 2003,"rating": 6.8,"votes": 37303,"running_times": 6120},{"title": "Swimming with Sharks","year": 1994,"rating": 7.1,"votes": 20150,"running_times": 5580},{"title": "Swing Kids","year": 1993,"rating": 6.8,"votes": 13991,"running_times": 6720},{"title": "Swing Vote","year": 2008,"rating": 6.1,"votes": 15920,"running_times": 7200},{"title": "Swingers","year": 1996,"rating": 7.3,"votes": 67695,"running_times": 5760},{"title": "Swiss Army Man","year": 2016,"rating": 7,"votes": 73349,"running_times": 5820},{"title": "Swiss Family Robinson","year": 1960,"rating": 7.2,"votes": 11259,"running_times": 7560},{"title": "Switchback","year": 1997,"rating": 6.4,"votes": 10691,"running_times": 7080},{"title": "Swordfish","year": 2001,"rating": 6.5,"votes": 162723,"running_times": 5940},{"title": "Sydney","year": 1996,"rating": 7.3,"votes": 31752,"running_times": 6120},{"title": "Sydney White","year": 2007,"rating": 6.3,"votes": 40517,"running_times": 6480},{"title": "Synecdoche, New York","year": 2008,"rating": 7.5,"votes": 64501,"running_times": 7440},{"title": "Syriana","year": 2005,"rating": 7,"votes": 115584,"running_times": 7680},{"title": "Så som i himmelen","year": 2004,"rating": 7.6,"votes": 14507,"running_times": 7980},{"title": "T2 Trainspotting","year": 2017,"rating": 7.3,"votes": 71133,"running_times": 7020},{"title": "THX 1138","year": 1971,"rating": 6.8,"votes": 42170,"running_times": 5280},{"title": "TMNT","year": 2007,"rating": 6.3,"votes": 56090,"running_times": 5220},{"title": "TRON","year": 1982,"rating": 6.8,"votes": 100273,"running_times": 5760},{"title": "Taare Zameen Par","year": 2007,"rating": 8.5,"votes": 113334,"running_times": 9900},{"title": "Table 19","year": 2017,"rating": 5.8,"votes": 13202,"running_times": 5220},{"title": "Take Me Home Tonight","year": 2011,"rating": 6.3,"votes": 46354,"running_times": 5820},{"title": "Take Shelter","year": 2011,"rating": 7.4,"votes": 77009,"running_times": 7260},{"title": "Take This Waltz","year": 2011,"rating": 6.6,"votes": 24404,"running_times": 6960},{"title": "Take the Lead","year": 2006,"rating": 6.7,"votes": 22877,"running_times": 7080},{"title": "Take the Money and Run","year": 1969,"rating": 7.3,"votes": 24562,"running_times": 5100},{"title": "Taken","year": 2008,"rating": 7.8,"votes": 513482,"running_times": 5580},{"title": "Taken 2","year": 2012,"rating": 6.3,"votes": 257220,"running_times": 5880},{"title": "Taken 3","year": 2014,"rating": 6,"votes": 151174,"running_times": 6900},{"title": "Takers","year": 2010,"rating": 6.2,"votes": 50191,"running_times": 6420},{"title": "Taking Lives","year": 2004,"rating": 6.2,"votes": 69873,"running_times": 6540},{"title": "Taking Woodstock","year": 2009,"rating": 6.7,"votes": 26011,"running_times": 7200},{"title": "Talaash","year": 2012,"rating": 7.3,"votes": 32847,"running_times": 8400},{"title": "Tales from the Crypt: Demon Knight","year": 1995,"rating": 6.7,"votes": 17987,"running_times": 5520},{"title": "Tales from the Darkside: The Movie","year": 1990,"rating": 6.2,"votes": 12283,"running_times": 5580},{"title": "Talk Radio","year": 1988,"rating": 7.3,"votes": 10822,"running_times": 6600},{"title": "Talladega Nights: The Ballad of Ricky Bobby","year": 2006,"rating": 6.6,"votes": 141841,"running_times": 7320},{"title": "Tallulah","year": 2016,"rating": 6.8,"votes": 11732,"running_times": 6660},{"title": "Tamara Drewe","year": 2010,"rating": 6.2,"votes": 18287,"running_times": 6540},{"title": "También la lluvia","year": 2010,"rating": 7.5,"votes": 10848,"running_times": 6180},{"title": "Tammy","year": 2014,"rating": 4.9,"votes": 40482,"running_times": 6000},{"title": "Tangerine","year": 2015,"rating": 7.1,"votes": 17459,"running_times": 5280},{"title": "Tangled","year": 2010,"rating": 7.8,"votes": 330137,"running_times": 6000},{"title": "Tangled Ever After","year": 2012,"rating": 7.7,"votes": 14090,"running_times": 360},{"title": "Tango & Cash","year": 1989,"rating": 6.3,"votes": 82157,"running_times": 6240},{"title": "Tank Girl","year": 1995,"rating": 5.3,"votes": 26488,"running_times": 6240},{"title": "Tape","year": 2001,"rating": 7.3,"votes": 16803,"running_times": 5160},{"title": "Taps","year": 1981,"rating": 6.7,"votes": 14164,"running_times": 7560},{"title": "Tarzan","year": 1999,"rating": 7.2,"votes": 163076,"running_times": 5280},{"title": "Tarzan","year": 2013,"rating": 4.8,"votes": 11169,"running_times": 5640},{"title": "Taxi","year": 2004,"rating": 4.4,"votes": 35435,"running_times": 6240},{"title": "Taxi Driver","year": 1976,"rating": 8.3,"votes": 571416,"running_times": 6780},{"title": "Taxi to the Dark Side","year": 2007,"rating": 7.6,"votes": 12445,"running_times": 6360},{"title": "Taxidermia","year": 2006,"rating": 7,"votes": 14280,"running_times": 5460},{"title": "Te wu mi cheng","year": 2001,"rating": 5.9,"votes": 13830,"running_times": 6480},{"title": "Teaching Mrs. Tingle","year": 1999,"rating": 5.2,"votes": 18065,"running_times": 5760},{"title": "Team America: World Police","year": 2004,"rating": 7.2,"votes": 143954,"running_times": 5880},{"title": "Tears of the Sun","year": 2003,"rating": 6.6,"votes": 100114,"running_times": 8520},{"title": "Ted","year": 2012,"rating": 7,"votes": 507957,"running_times": 6720},{"title": "Ted 2","year": 2015,"rating": 6.3,"votes": 146086,"running_times": 7500},{"title": "Teen Wolf","year": 1985,"rating": 6,"votes": 38362,"running_times": 5460},{"title": "Teenage Mutant Ninja Turtles","year": 1990,"rating": 6.7,"votes": 74041,"running_times": 5580},{"title": "Teenage Mutant Ninja Turtles","year": 2014,"rating": 5.8,"votes": 183023,"running_times": 6060},{"title": "Teenage Mutant Ninja Turtles II: The Secret of the Ooze","year": 1991,"rating": 6,"votes": 45238,"running_times": 5280},{"title": "Teenage Mutant Ninja Turtles III","year": 1993,"rating": 4.8,"votes": 26894,"running_times": 5760},{"title": "Teenage Mutant Ninja Turtles: Out of the Shadows","year": 2016,"rating": 6,"votes": 66805,"running_times": 6720},{"title": "Teeth","year": 2007,"rating": 5.4,"votes": 36765,"running_times": 5640},{"title": "Tekken","year": 2010,"rating": 4.8,"votes": 23706,"running_times": 5520},{"title": "Temptation: Confessions of a Marriage Counselor","year": 2013,"rating": 5,"votes": 10536,"running_times": 6660},{"title": "Ten Inch Hero","year": 2007,"rating": 7.5,"votes": 10805,"running_times": 6120},{"title": "Tenacious D in The Pick of Destiny","year": 2006,"rating": 6.8,"votes": 91597,"running_times": 5580},{"title": "Tenebre","year": 1982,"rating": 7.2,"votes": 16000,"running_times": 6060},{"title": "Tequila Sunrise","year": 1988,"rating": 6,"votes": 24950,"running_times": 6900},{"title": "Terminal Velocity","year": 1994,"rating": 5.4,"votes": 11461,"running_times": 6120},{"title": "Terminator 2: Judgment Day","year": 1991,"rating": 8.5,"votes": 824332,"running_times": 9360},{"title": "Terminator 3: Rise of the Machines","year": 2003,"rating": 6.3,"votes": 328905,"running_times": 6540},{"title": "Terminator Genisys","year": 2015,"rating": 6.5,"votes": 215687,"running_times": 7560},{"title": "Terminator Salvation","year": 2009,"rating": 6.6,"votes": 304237,"running_times": 7080},{"title": "Terms of Endearment","year": 1983,"rating": 7.4,"votes": 44741,"running_times": 7920},{"title": "Terra","year": 2007,"rating": 6.6,"votes": 10448,"running_times": 5100},{"title": "Tess","year": 1979,"rating": 7.3,"votes": 12322,"running_times": 11160},{"title": "Testament of Youth","year": 2014,"rating": 7.3,"votes": 19729,"running_times": 7800},{"title": "Tetro","year": 2009,"rating": 6.9,"votes": 11124,"running_times": 7620},{"title": "Texas Chainsaw 3D","year": 2013,"rating": 4.8,"votes": 38655,"running_times": 5520},{"title": "Texas Killing Fields","year": 2011,"rating": 5.7,"votes": 16211,"running_times": 6300},{"title": "Thank You for Smoking","year": 2005,"rating": 7.6,"votes": 199541,"running_times": 5520},{"title": "Thanks for Sharing","year": 2012,"rating": 6.4,"votes": 22550,"running_times": 6720},{"title": "That Awkward Moment","year": 2014,"rating": 6.2,"votes": 84885,"running_times": 5640},{"title": "That Thing You Do!","year": 1996,"rating": 6.9,"votes": 53878,"running_times": 8940},{"title": "That's My Boy","year": 2012,"rating": 5.6,"votes": 76768,"running_times": 6960},{"title": "The 'Burbs","year": 1989,"rating": 6.9,"votes": 56541,"running_times": 6060},{"title": "The 13th Warrior","year": 1999,"rating": 6.6,"votes": 106127,"running_times": 6120},{"title": "The 33","year": 2015,"rating": 6.9,"votes": 28594,"running_times": 7620},{"title": "The 39 Steps","year": 1935,"rating": 7.8,"votes": 43400,"running_times": 5160},{"title": "The 40 Year Old Virgin","year": 2005,"rating": 7.1,"votes": 337621,"running_times": 7980},{"title": "The 51st State","year": 2001,"rating": 6.3,"votes": 44500,"running_times": 5580},{"title": "The 5th Wave","year": 2016,"rating": 5.2,"votes": 78607,"running_times": 6720},{"title": "The 6th Day","year": 2000,"rating": 5.9,"votes": 105516,"running_times": 7380},{"title": "The A-Team","year": 2010,"rating": 6.8,"votes": 224171,"running_times": 7980},{"title": "The ABCs of Death","year": 2012,"rating": 4.7,"votes": 15744,"running_times": 7740},{"title": "The Abandoned","year": 2006,"rating": 5.6,"votes": 11545,"running_times": 5940},{"title": "The Abominable Dr. Phibes","year": 1971,"rating": 7.2,"votes": 11188,"running_times": 5640},{"title": "The Abyss","year": 1989,"rating": 7.6,"votes": 141969,"running_times": 10260},{"title": "The Accidental Husband","year": 2008,"rating": 5.6,"votes": 20747,"running_times": 5400},{"title": "The Accidental Tourist","year": 1988,"rating": 6.8,"votes": 13149,"running_times": 7260},{"title": "The Accountant","year": 2016,"rating": 7.4,"votes": 198484,"running_times": 7680},{"title": "The Accused","year": 1988,"rating": 7.1,"votes": 26442,"running_times": 6660},{"title": "The Act of Killing","year": 2012,"rating": 8.2,"votes": 28060,"running_times": 9600},{"title": "The Addams Family","year": 1991,"rating": 6.8,"votes": 106391,"running_times": 5940},{"title": "The Adjustment Bureau","year": 2011,"rating": 7.1,"votes": 213923,"running_times": 6360},{"title": "The Adventures of Baron Munchausen","year": 1988,"rating": 7.2,"votes": 44289,"running_times": 7560},{"title": "The Adventures of Bob & Doug McKenzie: Strange Brew","year": 1983,"rating": 6.8,"votes": 13716,"running_times": 5400},{"title": "The Adventures of Buckaroo Banzai Across the 8th Dimension","year": 1984,"rating": 6.4,"votes": 19401,"running_times": 6180},{"title": "The Adventures of Ford Fairlane","year": 1990,"rating": 6.3,"votes": 15293,"running_times": 6240},{"title": "The Adventures of Pluto Nash","year": 2002,"rating": 3.8,"votes": 21371,"running_times": 5700},{"title": "The Adventures of Priscilla, Queen of the Desert","year": 1994,"rating": 7.5,"votes": 39960,"running_times": 6240},{"title": "The Adventures of Robin Hood","year": 1938,"rating": 8,"votes": 41275,"running_times": 6120},{"title": "The Adventures of Rocky & Bullwinkle","year": 2000,"rating": 4.2,"votes": 17533,"running_times": 5520},{"title": "The Adventures of Sharkboy and Lavagirl 3-D","year": 2005,"rating": 3.5,"votes": 23046,"running_times": 5580},{"title": "The Adventures of Tintin","year": 2011,"rating": 7.4,"votes": 189928,"running_times": 6420},{"title": "The African Queen","year": 1951,"rating": 7.9,"votes": 62420,"running_times": 6300},{"title": "The Age of Adaline","year": 2015,"rating": 7.2,"votes": 121718,"running_times": 6720},{"title": "The Age of Innocence","year": 1993,"rating": 7.2,"votes": 39664,"running_times": 8340},{"title": "The Air I Breathe","year": 2007,"rating": 6.9,"votes": 32248,"running_times": 5700},{"title": "The Alamo","year": 1960,"rating": 6.9,"votes": 11909,"running_times": 12180},{"title": "The Alamo","year": 2004,"rating": 6,"votes": 17754,"running_times": 8220},{"title": "The Amazing Spider-Man","year": 2012,"rating": 7,"votes": 489511,"running_times": 8160},{"title": "The Amazing Spider-Man 2","year": 2014,"rating": 6.7,"votes": 356578,"running_times": 8520},{"title": "The American","year": 2010,"rating": 6.3,"votes": 83595,"running_times": 6300},{"title": "The American President","year": 1995,"rating": 6.8,"votes": 45620,"running_times": 6840},{"title": "The Amityville Horror","year": 1979,"rating": 6.2,"votes": 30078,"running_times": 7020},{"title": "The Amityville Horror","year": 2005,"rating": 6,"votes": 92636,"running_times": 5400},{"title": "The Andromeda Strain","year": 1971,"rating": 7.2,"votes": 28205,"running_times": 7860},{"title": "The Angels' Share","year": 2012,"rating": 7,"votes": 20149,"running_times": 6060},{"title": "The Angriest Man in Brooklyn","year": 2014,"rating": 5.7,"votes": 18298,"running_times": 4980},{"title": "The Animal","year": 2001,"rating": 4.8,"votes": 50589,"running_times": 5040},{"title": "The Ant Bully","year": 2006,"rating": 5.9,"votes": 32279,"running_times": 5280},{"title": "The Apartment","year": 1960,"rating": 8.3,"votes": 124560,"running_times": 7500},{"title": "The Apostle","year": 1997,"rating": 7.2,"votes": 12080,"running_times": 8040},{"title": "The Apparition","year": 2012,"rating": 4.1,"votes": 17285,"running_times": 4980},{"title": "The AristoCats","year": 1970,"rating": 7.1,"votes": 73750,"running_times": 4680},{"title": "The Aristocrats","year": 2005,"rating": 6.4,"votes": 15362,"running_times": 5340},{"title": "The Arrival","year": 1996,"rating": 6.3,"votes": 27998,"running_times": 6900},{"title": "The Art of Getting By","year": 2011,"rating": 6.6,"votes": 50390,"running_times": 4980},{"title": "The Art of War","year": 2000,"rating": 5.7,"votes": 26345,"running_times": 7020},{"title": "The Art of the Steal","year": 2013,"rating": 6.3,"votes": 20660,"running_times": 5400},{"title": "The Artist","year": 2011,"rating": 7.9,"votes": 204685,"running_times": 6000},{"title": "The Asphalt Jungle","year": 1950,"rating": 7.9,"votes": 19607,"running_times": 6720},{"title": "The Assassination of Jesse James by the Coward Robert Ford","year": 2007,"rating": 7.5,"votes": 148086,"running_times": 9600},{"title": "The Assassination of Richard Nixon","year": 2004,"rating": 7,"votes": 24037,"running_times": 5700},{"title": "The Astronaut Farmer","year": 2006,"rating": 6.3,"votes": 20721,"running_times": 6240},{"title": "The Astronaut's Wife","year": 1999,"rating": 5.3,"votes": 48379,"running_times": 6540},{"title": "The Autopsy of Jane Doe","year": 2016,"rating": 6.8,"votes": 53254,"running_times": 5160},{"title": "The Avengers","year": 1998,"rating": 3.7,"votes": 36996,"running_times": 6900},{"title": "The Avengers","year": 2012,"rating": 8.1,"votes": 1076167,"running_times": 10380},{"title": "The Aviator","year": 2004,"rating": 7.5,"votes": 287186,"running_times": 10200},{"title": "The Awakening","year": 2011,"rating": 6.5,"votes": 56034,"running_times": 6120},{"title": "The Awful Truth","year": 1937,"rating": 7.9,"votes": 14615,"running_times": 5460},{"title": "The BFG","year": 2016,"rating": 6.4,"votes": 58384,"running_times": 7020},{"title": "The Babadook","year": 2014,"rating": 6.8,"votes": 145814,"running_times": 5580},{"title": "The Babysitter","year": 2017,"rating": 6.4,"votes": 23750,"running_times": 5100},{"title": "The Bachelor","year": 1999,"rating": 5,"votes": 15389,"running_times": 6060},{"title": "The Back-up Plan","year": 2010,"rating": 5.3,"votes": 43572,"running_times": 6240},{"title": "The Bad Batch","year": 2016,"rating": 5.3,"votes": 12315,"running_times": 7080},{"title": "The Bad Lieutenant: Port of Call - New Orleans","year": 2009,"rating": 6.7,"votes": 67911,"running_times": 7320},{"title": "The Bad News Bears","year": 1976,"rating": 7.3,"votes": 17548,"running_times": 6120},{"title": "The Bad Seed","year": 1956,"rating": 7.5,"votes": 10625,"running_times": 7740},{"title": "The Bad and the Beautiful","year": 1952,"rating": 7.9,"votes": 10767,"running_times": 7080},{"title": "The Bag Man","year": 2014,"rating": 5.3,"votes": 14481,"running_times": 6480},{"title": "The Banger Sisters","year": 2002,"rating": 5.6,"votes": 13118,"running_times": 5880},{"title": "The Bank Job","year": 2008,"rating": 7.3,"votes": 159896,"running_times": 6660},{"title": "The Basketball Diaries","year": 1995,"rating": 7.3,"votes": 87598,"running_times": 6120},{"title": "The Bay","year": 2012,"rating": 5.6,"votes": 21848,"running_times": 5040},{"title": "The Baytown Outlaws","year": 2012,"rating": 6.4,"votes": 12067,"running_times": 5880},{"title": "The Beach","year": 2000,"rating": 6.6,"votes": 193605,"running_times": 7140},{"title": "The Beastmaster","year": 1982,"rating": 6.2,"votes": 16843,"running_times": 7080},{"title": "The Beaver","year": 2011,"rating": 6.7,"votes": 42970,"running_times": 5460},{"title": "The Beguiled","year": 1971,"rating": 7.2,"votes": 12372,"running_times": 6300},{"title": "The Beguiled","year": 2017,"rating": 6.5,"votes": 25372,"running_times": 5580},{"title": "The Believer","year": 2001,"rating": 7.2,"votes": 32765,"running_times": 5880},{"title": "The Belko Experiment","year": 2016,"rating": 6.1,"votes": 26349,"running_times": 5340},{"title": "The Benchwarmers","year": 2006,"rating": 5.6,"votes": 43224,"running_times": 4800},{"title": "The Best Exotic Marigold Hotel","year": 2011,"rating": 7.3,"votes": 80701,"running_times": 7440},{"title": "The Best Man Holiday","year": 2013,"rating": 6.7,"votes": 12444,"running_times": 7380},{"title": "The Best Years of Our Lives","year": 1946,"rating": 8.1,"votes": 45211,"running_times": 10200},{"title": "The Best of Me","year": 2014,"rating": 6.7,"votes": 52301,"running_times": 7080},{"title": "The Beverly Hillbillies","year": 1993,"rating": 4.9,"votes": 15413,"running_times": 5520},{"title": "The Big Bounce","year": 2004,"rating": 4.9,"votes": 16572,"running_times": 5280},{"title": "The Big Chill","year": 1983,"rating": 7.2,"votes": 27814,"running_times": 6300},{"title": "The Big Country","year": 1958,"rating": 7.9,"votes": 12621,"running_times": 9960},{"title": "The Big Easy","year": 1986,"rating": 6.6,"votes": 10097,"running_times": 6120},{"title": "The Big Heat","year": 1953,"rating": 8,"votes": 18479,"running_times": 5400},{"title": "The Big Hit","year": 1998,"rating": 6.1,"votes": 25926,"running_times": 5460},{"title": "The Big Kahuna","year": 1999,"rating": 6.6,"votes": 12791,"running_times": 5400},{"title": "The Big Lebowski","year": 1998,"rating": 8.2,"votes": 601049,"running_times": 7020},{"title": "The Big Red One","year": 1980,"rating": 7.2,"votes": 16487,"running_times": 9720},{"title": "The Big Short","year": 2015,"rating": 7.8,"votes": 267728,"running_times": 7800},{"title": "The Big Sick","year": 2017,"rating": 7.7,"votes": 53386,"running_times": 7200},{"title": "The Big Sleep","year": 1946,"rating": 8,"votes": 69100,"running_times": 6960},{"title": "The Big Wedding","year": 2013,"rating": 5.6,"votes": 41213,"running_times": 5340},{"title": "The Big White","year": 2005,"rating": 6.4,"votes": 12913,"running_times": 6300},{"title": "The Big Year","year": 2011,"rating": 6.2,"votes": 37408,"running_times": 6000},{"title": "The Birdcage","year": 1996,"rating": 7,"votes": 67196,"running_times": 7020},{"title": "The Birds","year": 1963,"rating": 7.7,"votes": 142556,"running_times": 7140},{"title": "The Birth of a Nation","year": 2016,"rating": 6.3,"votes": 15740,"running_times": 7200},{"title": "The Bishop's Wife","year": 1947,"rating": 7.6,"votes": 11115,"running_times": 6540},{"title": "The Black Cauldron","year": 1985,"rating": 6.5,"votes": 24726,"running_times": 4800},{"title": "The Black Dahlia","year": 2006,"rating": 5.6,"votes": 65934,"running_times": 7260},{"title": "The Black Hole","year": 1979,"rating": 5.9,"votes": 19648,"running_times": 5880},{"title": "The Blair Witch Project","year": 1999,"rating": 6.4,"votes": 204574,"running_times": 5280},{"title": "The Blind Side","year": 2009,"rating": 7.7,"votes": 245570,"running_times": 7740},{"title": "The Bling Ring","year": 2013,"rating": 5.6,"votes": 73490,"running_times": 5400},{"title": "The Blob","year": 1958,"rating": 6.4,"votes": 18288,"running_times": 5160},{"title": "The Blob","year": 1988,"rating": 6.4,"votes": 25457,"running_times": 5700},{"title": "The Blue Lagoon","year": 1980,"rating": 5.7,"votes": 54458,"running_times": 6240},{"title": "The Blues Brothers","year": 1980,"rating": 7.9,"votes": 155256,"running_times": 8880},{"title": "The Boat That Rocked","year": 2009,"rating": 7.4,"votes": 96541,"running_times": 8100},{"title": "The Bodyguard","year": 1992,"rating": 6.2,"votes": 99144,"running_times": 7740},{"title": "The Bone Collector","year": 1999,"rating": 6.7,"votes": 131239,"running_times": 7080},{"title": "The Bonfire of the Vanities","year": 1990,"rating": 5.5,"votes": 19027,"running_times": 7500},{"title": "The Book Thief","year": 2013,"rating": 7.6,"votes": 110378,"running_times": 7860},{"title": "The Book of Eli","year": 2010,"rating": 6.9,"votes": 249346,"running_times": 7080},{"title": "The Book of Life","year": 2014,"rating": 7.3,"votes": 53590,"running_times": 5700},{"title": "The Boondock Saints","year": 1999,"rating": 7.9,"votes": 208050,"running_times": 6480},{"title": "The Boondock Saints II: All Saints Day","year": 2009,"rating": 6.3,"votes": 56167,"running_times": 8280},{"title": "The Borrowers","year": 1997,"rating": 5.8,"votes": 17522,"running_times": 5340},{"title": "The Boss","year": 2016,"rating": 5.4,"votes": 32380,"running_times": 6240},{"title": "The Boss Baby","year": 2017,"rating": 6.4,"votes": 63831,"running_times": 5820},{"title": "The Bounty","year": 1984,"rating": 7.1,"votes": 19851,"running_times": 7920},{"title": "The Bounty Hunter","year": 2010,"rating": 5.5,"votes": 104853,"running_times": 6600},{"title": "The Bourne Identity","year": 2002,"rating": 7.9,"votes": 446706,"running_times": 7140},{"title": "The Bourne Legacy","year": 2012,"rating": 6.7,"votes": 252525,"running_times": 8100},{"title": "The Bourne Supremacy","year": 2004,"rating": 7.8,"votes": 383149,"running_times": 6480},{"title": "The Bourne Ultimatum","year": 2007,"rating": 8.1,"votes": 543338,"running_times": 6900},{"title": "The Box","year": 2009,"rating": 5.6,"votes": 81032,"running_times": 6900},{"title": "The Boxer","year": 1997,"rating": 7.1,"votes": 15626,"running_times": 6780},{"title": "The Boxtrolls","year": 2014,"rating": 6.8,"votes": 47051,"running_times": 5760},{"title": "The Boy","year": 2016,"rating": 6,"votes": 57479,"running_times": 5820},{"title": "The Boy Next Door","year": 2015,"rating": 4.7,"votes": 31552,"running_times": 5460},{"title": "The Boy in the Striped Pyjamas","year": 2008,"rating": 7.8,"votes": 152019,"running_times": 5640},{"title": "The Boys from Brazil","year": 1978,"rating": 7,"votes": 22147,"running_times": 7500},{"title": "The Brady Bunch Movie","year": 1995,"rating": 5.9,"votes": 18341,"running_times": 5400},{"title": "The Brass Teapot","year": 2012,"rating": 6.4,"votes": 12898,"running_times": 6060},{"title": "The Brave Little Toaster","year": 1987,"rating": 7.3,"votes": 21079,"running_times": 5400},{"title": "The Brave One","year": 2007,"rating": 6.8,"votes": 53271,"running_times": 7320},{"title": "The Break-Up","year": 2006,"rating": 5.8,"votes": 109364,"running_times": 6360},{"title": "The Breakfast Club","year": 1985,"rating": 7.9,"votes": 288451,"running_times": 5820},{"title": "The Breed","year": 2006,"rating": 5.1,"votes": 10967,"running_times": 5460},{"title": "The Bridge","year": 2006,"rating": 7.3,"votes": 10012,"running_times": 5640},{"title": "The Bridge on the River Kwai","year": 1957,"rating": 8.2,"votes": 166597,"running_times": 9660},{"title": "The Bridges of Madison County","year": 1995,"rating": 7.6,"votes": 59681,"running_times": 8100},{"title": "The Broken Circle Breakdown","year": 2012,"rating": 7.8,"votes": 33487,"running_times": 6660},{"title": "The Brood","year": 1979,"rating": 6.9,"votes": 20386,"running_times": 5520},{"title": "The Brothers Bloom","year": 2008,"rating": 6.8,"votes": 44152,"running_times": 6840},{"title": "The Brothers Grimm","year": 2005,"rating": 5.9,"votes": 104533,"running_times": 7080},{"title": "The Brown Bunny","year": 2003,"rating": 5,"votes": 12246,"running_times": 5580},{"title": "The Bucket List","year": 2007,"rating": 7.4,"votes": 200761,"running_times": 5820},{"title": "The Burning","year": 1981,"rating": 6.5,"votes": 12063,"running_times": 5460},{"title": "The Burning Plain","year": 2008,"rating": 6.8,"votes": 16532,"running_times": 6660},{"title": "The Business","year": 2005,"rating": 6.7,"votes": 11837,"running_times": 5820},{"title": "The Butler","year": 2013,"rating": 7.2,"votes": 95749,"running_times": 7920},{"title": "The Butterfly Effect","year": 2004,"rating": 7.7,"votes": 391975,"running_times": 7200},{"title": "The Butterfly Effect 3: Revelations","year": 2009,"rating": 5.6,"votes": 16592,"running_times": 6300},{"title": "The Bye Bye Man","year": 2017,"rating": 4.3,"votes": 11949,"running_times": 6060},{"title": "The Cabin in the Woods","year": 2012,"rating": 7,"votes": 308636,"running_times": 5700},{"title": "The Cable Guy","year": 1996,"rating": 6.1,"votes": 132035,"running_times": 5760},{"title": "The Caine Mutiny","year": 1954,"rating": 7.9,"votes": 21348,"running_times": 7500},{"title": "The Call","year": 2013,"rating": 6.7,"votes": 96999,"running_times": 5640},{"title": "The Campaign","year": 2012,"rating": 6.1,"votes": 112910,"running_times": 5760},{"title": "The Canal","year": 2014,"rating": 5.9,"votes": 10928,"running_times": 5520},{"title": "The Cannonball Run","year": 1981,"rating": 6.2,"votes": 27997,"running_times": 5700},{"title": "The Captive","year": 2014,"rating": 5.9,"votes": 22667,"running_times": 6720},{"title": "The Castle","year": 1997,"rating": 7.7,"votes": 12869,"running_times": 5100},{"title": "The Cat in the Hat","year": 2003,"rating": 3.8,"votes": 40048,"running_times": 4920},{"title": "The Cave","year": 2005,"rating": 5.1,"votes": 30609,"running_times": 5820},{"title": "The Cell","year": 2000,"rating": 6.3,"votes": 84984,"running_times": 6540},{"title": "The Chamber","year": 1996,"rating": 6,"votes": 11124,"running_times": 6780},{"title": "The Change-Up","year": 2011,"rating": 6.3,"votes": 145281,"running_times": 7080},{"title": "The Changeling","year": 1980,"rating": 7.3,"votes": 23916,"running_times": 6420},{"title": "The Chase","year": 1994,"rating": 5.8,"votes": 15334,"running_times": 5640},{"title": "The Children","year": 2008,"rating": 6,"votes": 15438,"running_times": 5040},{"title": "The Children's Hour","year": 1961,"rating": 7.8,"votes": 11701,"running_times": 6480},{"title": "The China Syndrome","year": 1979,"rating": 7.4,"votes": 22339,"running_times": 7320},{"title": "The Choice","year": 2016,"rating": 6.6,"votes": 24018,"running_times": 6660},{"title": "The Chronicles of Narnia: Prince Caspian","year": 2008,"rating": 6.6,"votes": 164777,"running_times": 9000},{"title": "The Chronicles of Narnia: The Lion, the Witch and the Wardrobe","year": 2005,"rating": 6.9,"votes": 314354,"running_times": 9000},{"title": "The Chronicles of Narnia: The Voyage of the Dawn Treader","year": 2010,"rating": 6.3,"votes": 117763,"running_times": 6780},{"title": "The Chronicles of Riddick","year": 2004,"rating": 6.7,"votes": 195033,"running_times": 8040},{"title": "The Chumscrubber","year": 2005,"rating": 7,"votes": 16830,"running_times": 6480},{"title": "The Cider House Rules","year": 1999,"rating": 7.4,"votes": 83846,"running_times": 7560},{"title": "The Cincinnati Kid","year": 1965,"rating": 7.3,"votes": 12747,"running_times": 6120},{"title": "The Circle","year": 2017,"rating": 5.3,"votes": 49927,"running_times": 6600},{"title": "The Circus","year": 1928,"rating": 8.1,"votes": 20578,"running_times": 4320},{"title": "The Clearing","year": 2004,"rating": 5.9,"votes": 12264,"running_times": 5700},{"title": "The Client","year": 1994,"rating": 6.7,"votes": 50194,"running_times": 7140},{"title": "The Cobbler","year": 2014,"rating": 5.8,"votes": 42876,"running_times": 5940},{"title": "The Cold Light of Day","year": 2012,"rating": 4.9,"votes": 31139,"running_times": 5580},{"title": "The Collection","year": 2012,"rating": 6.1,"votes": 39094,"running_times": 4920},{"title": "The Collector","year": 2009,"rating": 6.4,"votes": 47976,"running_times": 5400},{"title": "The Colony","year": 2013,"rating": 5.3,"votes": 38078,"running_times": 5700},{"title": "The Color Purple","year": 1985,"rating": 7.8,"votes": 66127,"running_times": 9240},{"title": "The Color of Money","year": 1986,"rating": 7,"votes": 63117,"running_times": 7140},{"title": "The Comebacks","year": 2007,"rating": 4.2,"votes": 10359,"running_times": 6420},{"title": "The Commitments","year": 1991,"rating": 7.6,"votes": 28042,"running_times": 7080},{"title": "The Company Men","year": 2010,"rating": 6.8,"votes": 38949,"running_times": 6240},{"title": "The Company You Keep","year": 2012,"rating": 6.4,"votes": 28047,"running_times": 7500},{"title": "The Company of Wolves","year": 1984,"rating": 6.8,"votes": 12490,"running_times": 5700},{"title": "The Condemned","year": 2007,"rating": 6.1,"votes": 46846,"running_times": 6840},{"title": "The Congress","year": 2013,"rating": 6.5,"votes": 14545,"running_times": 7320},{"title": "The Conjuring","year": 2013,"rating": 7.5,"votes": 348698,"running_times": 6720},{"title": "The Conjuring 2","year": 2016,"rating": 7.4,"votes": 157206,"running_times": 8040},{"title": "The Conspirator","year": 2010,"rating": 6.9,"votes": 25221,"running_times": 7320},{"title": "The Constant Gardener","year": 2005,"rating": 7.5,"votes": 118632,"running_times": 7740},{"title": "The Contender","year": 2000,"rating": 7,"votes": 21284,"running_times": 7560},{"title": "The Contract","year": 2006,"rating": 5.7,"votes": 21488,"running_times": 5760},{"title": "The Conversation","year": 1974,"rating": 7.9,"votes": 81291,"running_times": 6780},{"title": "The Cook, the Thief, His Wife & Her Lover","year": 1989,"rating": 7.6,"votes": 29255,"running_times": 7440},{"title": "The Cooler","year": 2003,"rating": 7,"votes": 29684,"running_times": 6060},{"title": "The Core","year": 2003,"rating": 5.5,"votes": 81833,"running_times": 8100},{"title": "The Corporation","year": 2003,"rating": 8.1,"votes": 18984,"running_times": 9900},{"title": "The Corruptor","year": 1999,"rating": 6,"votes": 16047,"running_times": 6600},{"title": "The Cottage","year": 2008,"rating": 6.1,"votes": 10703,"running_times": 5520},{"title": "The Cotton Club","year": 1984,"rating": 6.5,"votes": 13741,"running_times": 7620},{"title": "The Counselor","year": 2013,"rating": 5.3,"votes": 87224,"running_times": 8280},{"title": "The Count of Monte Cristo","year": 2002,"rating": 7.8,"votes": 112596,"running_times": 8040},{"title": "The Cove","year": 2009,"rating": 8.5,"votes": 43055,"running_times": 5520},{"title": "The Covenant","year": 2006,"rating": 5.3,"votes": 41822,"running_times": 5820},{"title": "The Cowboys","year": 1972,"rating": 7.4,"votes": 11123,"running_times": 8040},{"title": "The Craft","year": 1996,"rating": 6.3,"votes": 63253,"running_times": 6060},{"title": "The Crazies","year": 2010,"rating": 6.5,"votes": 99111,"running_times": 6060},{"title": "The Croods","year": 2013,"rating": 7.2,"votes": 164945,"running_times": 5880},{"title": "The Crossing Guard","year": 1995,"rating": 6.3,"votes": 11372,"running_times": 6660},{"title": "The Crow","year": 1994,"rating": 7.6,"votes": 146355,"running_times": 6120},{"title": "The Crow: City of Angels","year": 1996,"rating": 4.6,"votes": 16864,"running_times": 5040},{"title": "The Crucible","year": 1996,"rating": 6.8,"votes": 31119,"running_times": 7440},{"title": "The Crush","year": 1993,"rating": 5.7,"votes": 13065,"running_times": 5340},{"title": "The Crying Game","year": 1992,"rating": 7.3,"votes": 44414,"running_times": 6720},{"title": "The Curious Case of Benjamin Button","year": 2008,"rating": 7.8,"votes": 501739,"running_times": 9960},{"title": "The Curse of the Jade Scorpion","year": 2001,"rating": 6.8,"votes": 34156,"running_times": 6180},{"title": "The Curse of the Were-Rabbit","year": 2005,"rating": 7.5,"votes": 106749,"running_times": 5100},{"title": "The Cutting Edge","year": 1992,"rating": 6.9,"votes": 16136,"running_times": 6060},{"title": "The DUFF","year": 2015,"rating": 6.5,"votes": 61918,"running_times": 6060},{"title": "The Da Vinci Code","year": 2006,"rating": 6.6,"votes": 348542,"running_times": 10440},{"title": "The Damned United","year": 2009,"rating": 7.6,"votes": 35342,"running_times": 5880},{"title": "The Dangerous Lives of Altar Boys","year": 2002,"rating": 7.1,"votes": 12389,"running_times": 6300},{"title": "The Danish Girl","year": 2015,"rating": 7.1,"votes": 121304,"running_times": 7140},{"title": "The Darjeeling Limited","year": 2007,"rating": 7.2,"votes": 151549,"running_times": 5460},{"title": "The Dark Crystal","year": 1982,"rating": 7.2,"votes": 45775,"running_times": 5580},{"title": "The Dark Half","year": 1993,"rating": 5.9,"votes": 13163,"running_times": 7320},{"title": "The Dark Knight","year": 2008,"rating": 9,"votes": 1864164,"running_times": 9120},{"title": "The Dark Knight Rises","year": 2012,"rating": 8.4,"votes": 1269255,"running_times": 9840},{"title": "The Dark Tower","year": 2017,"rating": 5.7,"votes": 69330,"running_times": 5700},{"title": "The Darkest Hour","year": 2011,"rating": 4.9,"votes": 52123,"running_times": 5340},{"title": "The Day","year": 2011,"rating": 5.2,"votes": 11245,"running_times": 5760},{"title": "The Day After Tomorrow","year": 2004,"rating": 6.4,"votes": 360260,"running_times": 7440},{"title": "The Day of the Jackal","year": 1973,"rating": 7.8,"votes": 31843,"running_times": 8580},{"title": "The Day the Earth Stood Still","year": 1951,"rating": 7.8,"votes": 68463,"running_times": 5520},{"title": "The Day the Earth Stood Still","year": 2008,"rating": 5.5,"votes": 147772,"running_times": 6240},{"title": "The Dead Girl","year": 2006,"rating": 6.7,"votes": 13077,"running_times": 6600},{"title": "The Dead Pool","year": 1988,"rating": 6.3,"votes": 33680,"running_times": 5460},{"title": "The Dead Zone","year": 1983,"rating": 7.2,"votes": 49908,"running_times": 6180},{"title": "The Death and Life of Bobby Z","year": 2007,"rating": 5.9,"votes": 12779,"running_times": 5820},{"title": "The Deaths of Ian Stone","year": 2007,"rating": 5.6,"votes": 11779,"running_times": 5220},{"title": "The Debt","year": 2010,"rating": 6.9,"votes": 58446,"running_times": 6780},{"title": "The Deep Blue Sea","year": 2011,"rating": 6.3,"votes": 12745,"running_times": 5880},{"title": "The Deep End","year": 2001,"rating": 6.7,"votes": 10170,"running_times": 6060},{"title": "The Deep End of the Ocean","year": 1999,"rating": 6.3,"votes": 11230,"running_times": 6360},{"title": "The Deer Hunter","year": 1978,"rating": 8.2,"votes": 257892,"running_times": 10980},{"title": "The Defiant Ones","year": 1958,"rating": 7.7,"votes": 10512,"running_times": 5760},{"title": "The Delta Force","year": 1986,"rating": 5.6,"votes": 16009,"running_times": 7740},{"title": "The Den","year": 2013,"rating": 6.1,"votes": 10840,"running_times": 4860},{"title": "The Departed","year": 2006,"rating": 8.5,"votes": 975301,"running_times": 9060},{"title": "The Descendants","year": 2011,"rating": 7.3,"votes": 215007,"running_times": 6900},{"title": "The Descent","year": 2005,"rating": 7.2,"votes": 170442,"running_times": 6000},{"title": "The Descent: Part 2","year": 2009,"rating": 5.8,"votes": 35987,"running_times": 5640},{"title": "The Devil Inside","year": 2012,"rating": 4.2,"votes": 32082,"running_times": 4980},{"title": "The Devil Wears Prada","year": 2006,"rating": 6.8,"votes": 311658,"running_times": 6540},{"title": "The Devil's Advocate","year": 1997,"rating": 7.5,"votes": 282173,"running_times": 8640},{"title": "The Devil's Double","year": 2011,"rating": 7.1,"votes": 56407,"running_times": 6540},{"title": "The Devil's Own","year": 1997,"rating": 6.1,"votes": 49873,"running_times": 6660},{"title": "The Devil's Rejects","year": 2005,"rating": 6.9,"votes": 81531,"running_times": 6540},{"title": "The Devils","year": 1971,"rating": 7.8,"votes": 10094,"running_times": 7020},{"title": "The Diary of Anne Frank","year": 1959,"rating": 7.4,"votes": 10181,"running_times": 10800},{"title": "The Diary of a Teenage Girl","year": 2015,"rating": 6.9,"votes": 23775,"running_times": 6120},{"title": "The Dictator","year": 2012,"rating": 6.4,"votes": 232383,"running_times": 5940},{"title": "The Dilemma","year": 2011,"rating": 5.3,"votes": 46181,"running_times": 6660},{"title": "The Dirty Dozen","year": 1967,"rating": 7.8,"votes": 57460,"running_times": 9000},{"title": "The Disappearance of Alice Creed","year": 2009,"rating": 6.8,"votes": 22306,"running_times": 6000},{"title": "The Disaster Artist","year": 2017,"rating": 8.1,"votes": 13911,"running_times": 6240},{"title": "The Discovery","year": 2017,"rating": 6.3,"votes": 18069,"running_times": 6120},{"title": "The Dish","year": 2000,"rating": 7.2,"votes": 13534,"running_times": 6060},{"title": "The Distinguished Gentleman","year": 1992,"rating": 5.9,"votes": 13275,"running_times": 6720},{"title": "The Divide","year": 2011,"rating": 5.8,"votes": 32184,"running_times": 7320},{"title": "The Do-Over","year": 2016,"rating": 5.7,"votes": 27382,"running_times": 6480},{"title": "The Doom Generation","year": 1995,"rating": 6,"votes": 12220,"running_times": 4980},{"title": "The Door in the Floor","year": 2004,"rating": 6.7,"votes": 14022,"running_times": 6660},{"title": "The Doors","year": 1991,"rating": 7.2,"votes": 73120,"running_times": 8400},{"title": "The Double","year": 2011,"rating": 5.9,"votes": 25630,"running_times": 5880},{"title": "The Double","year": 2013,"rating": 6.5,"votes": 40539,"running_times": 5580},{"title": "The Dream Team","year": 1989,"rating": 6.5,"votes": 10878,"running_times": 6780},{"title": "The Dreamers","year": 2003,"rating": 7.2,"votes": 91059,"running_times": 6900},{"title": "The Dressmaker","year": 2015,"rating": 7.1,"votes": 38252,"running_times": 7140},{"title": "The Driver","year": 1978,"rating": 7.2,"votes": 10892,"running_times": 7860},{"title": "The Drop","year": 2014,"rating": 7.1,"votes": 121549,"running_times": 6360},{"title": "The Duchess","year": 2008,"rating": 6.9,"votes": 67201,"running_times": 6600},{"title": "The Duellists","year": 1977,"rating": 7.5,"votes": 16242,"running_times": 6000},{"title": "The Dukes of Hazzard","year": 2005,"rating": 5.1,"votes": 69430,"running_times": 6420},{"title": "The Dyatlov Pass Incident","year": 2013,"rating": 5.7,"votes": 18197,"running_times": 6000},{"title": "The Eagle","year": 2011,"rating": 6.2,"votes": 57714,"running_times": 6840},{"title": "The Eagle Has Landed","year": 1976,"rating": 6.9,"votes": 15561,"running_times": 8700},{"title": "The East","year": 2013,"rating": 6.8,"votes": 44769,"running_times": 6960},{"title": "The Edge","year": 1997,"rating": 6.9,"votes": 60012,"running_times": 7020},{"title": "The Edge of Love","year": 2008,"rating": 6.3,"votes": 14525,"running_times": 6600},{"title": "The Edge of Seventeen","year": 2016,"rating": 7.4,"votes": 64320,"running_times": 6240},{"title": "The Eiger Sanction","year": 1975,"rating": 6.4,"votes": 14326,"running_times": 7740},{"title": "The Elephant Man","year": 1980,"rating": 8.2,"votes": 180762,"running_times": 7440},{"title": "The Emoji Movie","year": 2017,"rating": 2.9,"votes": 30594,"running_times": 5160},{"title": "The Emperor's Club","year": 2002,"rating": 6.9,"votes": 15186,"running_times": 6540},{"title": "The Emperor's New Groove","year": 2000,"rating": 7.3,"votes": 143961,"running_times": 4680},{"title": "The End of the Affair","year": 1999,"rating": 7.2,"votes": 18879,"running_times": 6120},{"title": "The End of the Tour","year": 2015,"rating": 7.3,"votes": 22666,"running_times": 6360},{"title": "The Enforcer","year": 1976,"rating": 6.8,"votes": 34977,"running_times": 5760},{"title": "The English Patient","year": 1996,"rating": 7.4,"votes": 154290,"running_times": 15000},{"title": "The English Teacher","year": 2013,"rating": 5.8,"votes": 10264,"running_times": 5580},{"title": "The Englishman Who Went Up a Hill But Came Down a Mountain","year": 1995,"rating": 6.6,"votes": 14515,"running_times": 5940},{"title": "The Entity","year": 1982,"rating": 6.6,"votes": 12185,"running_times": 7500},{"title": "The Equalizer","year": 2014,"rating": 7.2,"votes": 257869,"running_times": 7920},{"title": "The Escapist","year": 2008,"rating": 6.8,"votes": 15325,"running_times": 6120},{"title": "The Evil Dead","year": 1981,"rating": 7.5,"votes": 156301,"running_times": 5100},{"title": "The Exorcism of Emily Rose","year": 2005,"rating": 6.7,"votes": 104459,"running_times": 7320},{"title": "The Exorcist","year": 1973,"rating": 8,"votes": 308000,"running_times": 7920},{"title": "The Exorcist III","year": 1990,"rating": 6.3,"votes": 19690,"running_times": 6600},{"title": "The Expendables","year": 2010,"rating": 6.5,"votes": 291039,"running_times": 6780},{"title": "The Expendables 2","year": 2012,"rating": 6.6,"votes": 263602,"running_times": 6180},{"title": "The Expendables 3","year": 2014,"rating": 6.1,"votes": 143428,"running_times": 7860},{"title": "The Experiment","year": 2010,"rating": 6.4,"votes": 45286,"running_times": 5760},{"title": "The Express","year": 2008,"rating": 7.3,"votes": 17692,"running_times": 7800},{"title": "The Eye","year": 2008,"rating": 5.4,"votes": 46769,"running_times": 5880},{"title": "The F Word","year": 2013,"rating": 6.8,"votes": 58518,"running_times": 5880},{"title": "The Fabulous Baker Boys","year": 1989,"rating": 6.8,"votes": 18943,"running_times": 6840},{"title": "The Faculty","year": 1998,"rating": 6.5,"votes": 97855,"running_times": 6240},{"title": "The Fall","year": 2006,"rating": 7.9,"votes": 95904,"running_times": 7020},{"title": "The Family","year": 2013,"rating": 6.3,"votes": 96336,"running_times": 6660},{"title": "The Family Man","year": 2000,"rating": 6.7,"votes": 91526,"running_times": 7500},{"title": "The Family Stone","year": 2005,"rating": 6.3,"votes": 52823,"running_times": 6180},{"title": "The Fan","year": 1996,"rating": 5.8,"votes": 41100,"running_times": 6960},{"title": "The Fast and the Furious","year": 2001,"rating": 6.7,"votes": 298782,"running_times": 6360},{"title": "The Fast and the Furious: Tokyo Drift","year": 2006,"rating": 6,"votes": 201378,"running_times": 6240},{"title": "The Fate of the Furious","year": 2017,"rating": 6.8,"votes": 145524,"running_times": 8940},{"title": "The Fault in Our Stars","year": 2014,"rating": 7.8,"votes": 284557,"running_times": 7980},{"title": "The Fifth Estate","year": 2013,"rating": 6.2,"votes": 33032,"running_times": 7680},{"title": "The Fighter","year": 2010,"rating": 7.8,"votes": 297659,"running_times": 6960},{"title": "The Final Conflict","year": 1981,"rating": 5.6,"votes": 15344,"running_times": 6480},{"title": "The Final Countdown","year": 1980,"rating": 6.7,"votes": 17625,"running_times": 6180},{"title": "The Final Cut","year": 2004,"rating": 6.2,"votes": 28220,"running_times": 5700},{"title": "The Final Destination","year": 2009,"rating": 5.2,"votes": 82313,"running_times": 4920},{"title": "The Final Girls","year": 2015,"rating": 6.6,"votes": 25800,"running_times": 5280},{"title": "The Finest Hours","year": 2016,"rating": 6.8,"votes": 49089,"running_times": 7020},{"title": "The Firm","year": 1993,"rating": 6.8,"votes": 96653,"running_times": 9240},{"title": "The First Great Train Robbery","year": 1978,"rating": 7,"votes": 12833,"running_times": 6600},{"title": "The First Time","year": 2012,"rating": 6.9,"votes": 56573,"running_times": 5700},{"title": "The First Wives Club","year": 1996,"rating": 6.2,"votes": 35126,"running_times": 6180},{"title": "The Fisher King","year": 1991,"rating": 7.6,"votes": 68514,"running_times": 8220},{"title": "The Five-Year Engagement","year": 2012,"rating": 6.2,"votes": 83519,"running_times": 7860},{"title": "The Flight of the Phoenix","year": 1965,"rating": 7.6,"votes": 16592,"running_times": 8520},{"title": "The Flintstones","year": 1994,"rating": 4.8,"votes": 65040,"running_times": 5460},{"title": "The Flintstones in Viva Rock Vegas","year": 2000,"rating": 3.6,"votes": 17059,"running_times": 5400},{"title": "The Flock","year": 2007,"rating": 5.7,"votes": 10214,"running_times": 6300},{"title": "The Fly","year": 1958,"rating": 7.1,"votes": 17323,"running_times": 5640},{"title": "The Fly","year": 1986,"rating": 7.5,"votes": 131951,"running_times": 5760},{"title": "The Fly II","year": 1989,"rating": 4.9,"votes": 18231,"running_times": 6300},{"title": "The Fog","year": 1980,"rating": 6.8,"votes": 51466,"running_times": 5340},{"title": "The Fog","year": 2005,"rating": 3.6,"votes": 31194,"running_times": 6180},{"title": "The Fog of War: Eleven Lessons from the Life of Robert S. McNamara","year": 2003,"rating": 8.2,"votes": 20482,"running_times": 6420},{"title": "The Football Factory","year": 2004,"rating": 6.9,"votes": 25482,"running_times": 5460},{"title": "The Forbidden Kingdom","year": 2008,"rating": 6.6,"votes": 92869,"running_times": 6240},{"title": "The Foreigner","year": 2017,"rating": 7.2,"votes": 20056,"running_times": 6780},{"title": "The Forest","year": 2016,"rating": 4.8,"votes": 31517,"running_times": 5580},{"title": "The Forgotten","year": 2004,"rating": 5.8,"votes": 59837,"running_times": 5640},{"title": "The Fortune Cookie","year": 1966,"rating": 7.4,"votes": 10116,"running_times": 7500},{"title": "The Founder","year": 2016,"rating": 7.2,"votes": 69763,"running_times": 6900},{"title": "The Fountain","year": 2006,"rating": 7.3,"votes": 205452,"running_times": 5760},{"title": "The Four Feathers","year": 2002,"rating": 6.5,"votes": 29710,"running_times": 7920},{"title": "The Fourth Kind","year": 2009,"rating": 5.9,"votes": 66763,"running_times": 5880},{"title": "The Fox and the Hound","year": 1981,"rating": 7.3,"votes": 70116,"running_times": 4980},{"title": "The French Connection","year": 1971,"rating": 7.8,"votes": 91035,"running_times": 6240},{"title": "The Freshman","year": 1990,"rating": 6.5,"votes": 16664,"running_times": 6120},{"title": "The Frighteners","year": 1996,"rating": 7.1,"votes": 72402,"running_times": 7380},{"title": "The Front Page","year": 1974,"rating": 7.4,"votes": 10029,"running_times": 6300},{"title": "The Frozen Ground","year": 2013,"rating": 6.4,"votes": 47639,"running_times": 6300},{"title": "The Fugitive","year": 1993,"rating": 7.8,"votes": 229254,"running_times": 7800},{"title": "The Full Monty","year": 1997,"rating": 7.2,"votes": 87658,"running_times": 5460},{"title": "The Fundamentals of Caring","year": 2016,"rating": 7.3,"votes": 37504,"running_times": 5820},{"title": "The Fury","year": 1978,"rating": 6.4,"votes": 10870,"running_times": 7080},{"title": "The Gallows","year": 2015,"rating": 4.2,"votes": 16251,"running_times": 4860},{"title": "The Gambler","year": 2014,"rating": 6,"votes": 54739,"running_times": 6660},{"title": "The Game","year": 1997,"rating": 7.8,"votes": 289122,"running_times": 7740},{"title": "The Game Plan","year": 2007,"rating": 6.2,"votes": 48546,"running_times": 6600},{"title": "The Gate","year": 1987,"rating": 6,"votes": 11654,"running_times": 5100},{"title": "The Gauntlet","year": 1977,"rating": 6.4,"votes": 17358,"running_times": 6540},{"title": "The General","year": 1926,"rating": 8.2,"votes": 60825,"running_times": 6420},{"title": "The General's Daughter","year": 1999,"rating": 6.3,"votes": 45863,"running_times": 6960},{"title": "The Getaway","year": 1972,"rating": 7.5,"votes": 23131,"running_times": 7380},{"title": "The Getaway","year": 1994,"rating": 5.7,"votes": 15013,"running_times": 6960},{"title": "The Ghost Writer","year": 2010,"rating": 7.2,"votes": 141312,"running_times": 7680},{"title": "The Ghost and Mrs. Muir","year": 1947,"rating": 7.9,"votes": 12874,"running_times": 6240},{"title": "The Ghost and the Darkness","year": 1996,"rating": 6.8,"votes": 49449,"running_times": 6600},{"title": "The Gift","year": 2000,"rating": 6.7,"votes": 55680,"running_times": 6720},{"title": "The Gift","year": 2015,"rating": 7.1,"votes": 105875,"running_times": 6480},{"title": "The Girl Next Door","year": 2004,"rating": 6.8,"votes": 181517,"running_times": 6600},{"title": "The Girl Next Door","year": 2007,"rating": 6.7,"votes": 19959,"running_times": 5460},{"title": "The Girl on the Train","year": 2016,"rating": 6.5,"votes": 122564,"running_times": 6720},{"title": "The Girl with All the Gifts","year": 2016,"rating": 6.7,"votes": 35303,"running_times": 6660},{"title": "The Girl with the Dragon Tattoo","year": 2011,"rating": 7.8,"votes": 360665,"running_times": 9480},{"title": "The Girlfriend Experience","year": 2009,"rating": 5.5,"votes": 14540,"running_times": 4620},{"title": "The Giver","year": 2014,"rating": 6.5,"votes": 97577,"running_times": 5820},{"title": "The Glass House","year": 2001,"rating": 5.8,"votes": 27338,"running_times": 6360},{"title": "The Glimmer Man","year": 1996,"rating": 5.3,"votes": 16552,"running_times": 5460},{"title": "The Godfather","year": 1972,"rating": 9.2,"votes": 1289428,"running_times": 10500},{"title": "The Godfather: Part II","year": 1974,"rating": 9,"votes": 889607,"running_times": 13200},{"title": "The Godfather: Part III","year": 1990,"rating": 7.6,"votes": 299652,"running_times": 10200},{"title": "The Gods Must Be Crazy","year": 1980,"rating": 7.3,"votes": 46369,"running_times": 6540},{"title": "The Gods Must Be Crazy II","year": 1989,"rating": 6.8,"votes": 13913,"running_times": 5880},{"title": "The Gold Rush","year": 1925,"rating": 8.2,"votes": 77314,"running_times": 5700},{"title": "The Golden Child","year": 1986,"rating": 5.9,"votes": 43511,"running_times": 5640},{"title": "The Golden Compass","year": 2007,"rating": 6.1,"votes": 158622,"running_times": 6780},{"title": "The Good Dinosaur","year": 2015,"rating": 6.7,"votes": 82278,"running_times": 5580},{"title": "The Good German","year": 2006,"rating": 6.1,"votes": 22383,"running_times": 6300},{"title": "The Good Girl","year": 2002,"rating": 6.5,"votes": 39827,"running_times": 5580},{"title": "The Good Lie","year": 2014,"rating": 7.4,"votes": 23071,"running_times": 6600},{"title": "The Good Neighbor","year": 2016,"rating": 6.3,"votes": 10679,"running_times": 5880},{"title": "The Good Shepherd","year": 2006,"rating": 6.7,"votes": 90768,"running_times": 10020},{"title": "The Good Son","year": 1993,"rating": 6.4,"votes": 30990,"running_times": 5220},{"title": "The Goodbye Girl","year": 1977,"rating": 7.4,"votes": 10241,"running_times": 6660},{"title": "The Goods: Live Hard, Sell Hard","year": 2009,"rating": 5.8,"votes": 18442,"running_times": 5340},{"title": "The Goonies","year": 1985,"rating": 7.8,"votes": 197148,"running_times": 6840},{"title": "The Graduate","year": 1967,"rating": 8,"votes": 224868,"running_times": 6360},{"title": "The Grand Budapest Hotel","year": 2014,"rating": 8.1,"votes": 561138,"running_times": 5940},{"title": "The Grand Seduction","year": 2013,"rating": 7,"votes": 13205,"running_times": 6780},{"title": "The Grapes of Wrath","year": 1940,"rating": 8.1,"votes": 70651,"running_times": 7740},{"title": "The Great Buck Howard","year": 2008,"rating": 6.5,"votes": 12430,"running_times": 5400},{"title": "The Great Debaters","year": 2007,"rating": 7.6,"votes": 50698,"running_times": 7560},{"title": "The Great Dictator","year": 1940,"rating": 8.5,"votes": 157821,"running_times": 7500},{"title": "The Great Escape","year": 1963,"rating": 8.2,"votes": 184206,"running_times": 10320},{"title": "The Great Gatsby","year": 1974,"rating": 6.4,"votes": 20793,"running_times": 8640},{"title": "The Great Gatsby","year": 2013,"rating": 7.3,"votes": 399342,"running_times": 8580},{"title": "The Great Mouse Detective","year": 1986,"rating": 7.2,"votes": 37022,"running_times": 4440},{"title": "The Great Muppet Caper","year": 1981,"rating": 7.2,"votes": 11033,"running_times": 5820},{"title": "The Great Outdoors","year": 1988,"rating": 6.6,"votes": 31809,"running_times": 5460},{"title": "The Great Race","year": 1965,"rating": 7.3,"votes": 13583,"running_times": 9600},{"title": "The Great Raid","year": 2005,"rating": 6.7,"votes": 19473,"running_times": 7920},{"title": "The Great Train Robbery","year": 1903,"rating": 7.3,"votes": 13461,"running_times": 660},{"title": "The Great Wall","year": 2016,"rating": 6,"votes": 89046,"running_times": 6180},{"title": "The Greatest Game Ever Played","year": 2005,"rating": 7.5,"votes": 24027,"running_times": 7200},{"title": "The Greatest Movie Ever Sold","year": 2011,"rating": 6.6,"votes": 13836,"running_times": 5400},{"title": "The Greatest Show on Earth","year": 1952,"rating": 6.7,"votes": 10459,"running_times": 9120},{"title": "The Green Berets","year": 1968,"rating": 5.7,"votes": 10562,"running_times": 8520},{"title": "The Green Hornet","year": 2011,"rating": 5.8,"votes": 142985,"running_times": 7140},{"title": "The Green Inferno","year": 2013,"rating": 5.3,"votes": 29044,"running_times": 6000},{"title": "The Green Mile","year": 1999,"rating": 8.5,"votes": 894678,"running_times": 11340},{"title": "The Grey","year": 2011,"rating": 6.8,"votes": 216353,"running_times": 7020},{"title": "The Grifters","year": 1990,"rating": 7,"votes": 22164,"running_times": 6600},{"title": "The Grudge","year": 2004,"rating": 5.9,"votes": 124345,"running_times": 5880},{"title": "The Grudge 2","year": 2006,"rating": 5,"votes": 41766,"running_times": 8220},{"title": "The Grudge 3","year": 2009,"rating": 4.7,"votes": 14317,"running_times": 5400},{"title": "The Guard","year": 2011,"rating": 7.3,"votes": 70283,"running_times": 5760},{"title": "The Guardian","year": 2006,"rating": 6.9,"votes": 79495,"running_times": 8340},{"title": "The Guest","year": 2014,"rating": 6.7,"votes": 74941,"running_times": 6000},{"title": "The Guilt Trip","year": 2012,"rating": 5.8,"votes": 32258,"running_times": 5700},{"title": "The Gunman","year": 2015,"rating": 5.8,"votes": 32856,"running_times": 6900},{"title": "The Guns of Navarone","year": 1961,"rating": 7.6,"votes": 38967,"running_times": 9480},{"title": "The Guru","year": 2002,"rating": 5.4,"votes": 13997,"running_times": 5640},{"title": "The Hallow","year": 2015,"rating": 5.7,"votes": 11871,"running_times": 5820},{"title": "The Hand That Rocks the Cradle","year": 1992,"rating": 6.6,"votes": 32195,"running_times": 6600},{"title": "The Hangover","year": 2009,"rating": 7.7,"votes": 628581,"running_times": 6480},{"title": "The Hangover Part II","year": 2011,"rating": 6.5,"votes": 405784,"running_times": 6120},{"title": "The Hangover Part III","year": 2013,"rating": 5.9,"votes": 248444,"running_times": 6000},{"title": "The Happening","year": 2008,"rating": 5,"votes": 175416,"running_times": 5460},{"title": "The Hard Way","year": 1991,"rating": 6.3,"votes": 15713,"running_times": 6660},{"title": "The Hateful Eight","year": 2015,"rating": 7.8,"votes": 371314,"running_times": 11220},{"title": "The Haunted Mansion","year": 2003,"rating": 4.9,"votes": 35158,"running_times": 5280},{"title": "The Haunting","year": 1963,"rating": 7.6,"votes": 28813,"running_times": 6720},{"title": "The Haunting","year": 1999,"rating": 4.9,"votes": 62383,"running_times": 6780},{"title": "The Haunting in Connecticut","year": 2009,"rating": 5.9,"votes": 53737,"running_times": 6120},{"title": "The Haunting in Connecticut 2: Ghosts of Georgia","year": 2013,"rating": 5.3,"votes": 14226,"running_times": 6060},{"title": "The Heartbreak Kid","year": 2007,"rating": 5.8,"votes": 76510,"running_times": 6960},{"title": "The Heat","year": 2013,"rating": 6.6,"votes": 143870,"running_times": 7200},{"title": "The Heiress","year": 1949,"rating": 8.2,"votes": 10798,"running_times": 6900},{"title": "The Help","year": 2011,"rating": 8.1,"votes": 355833,"running_times": 8760},{"title": "The Hidden","year": 1987,"rating": 7,"votes": 14177,"running_times": 5760},{"title": "The Hill","year": 1965,"rating": 7.9,"votes": 10218,"running_times": 7380},{"title": "The Hills Have Eyes","year": 1977,"rating": 6.4,"votes": 24184,"running_times": 5340},{"title": "The Hills Have Eyes","year": 2006,"rating": 6.4,"votes": 140564,"running_times": 6480},{"title": "The Hills Have Eyes II","year": 2007,"rating": 5.1,"votes": 53674,"running_times": 5340},{"title": "The History Boys","year": 2006,"rating": 6.9,"votes": 18686,"running_times": 6540},{"title": "The Hit List","year": 2011,"rating": 5.4,"votes": 10708,"running_times": 5400},{"title": "The Hitcher","year": 1986,"rating": 7.3,"votes": 36646,"running_times": 5820},{"title": "The Hitcher","year": 2007,"rating": 5.6,"votes": 36919,"running_times": 5400},{"title": "The Hitchhiker's Guide to the Galaxy","year": 2005,"rating": 6.8,"votes": 166812,"running_times": 6540},{"title": "The Hitman's Bodyguard","year": 2017,"rating": 7,"votes": 96031,"running_times": 7080},{"title": "The Hoax","year": 2006,"rating": 6.7,"votes": 15075,"running_times": 6960},{"title": "The Hobbit: An Unexpected Journey","year": 2012,"rating": 7.9,"votes": 685564,"running_times": 10920},{"title": "The Hobbit: The Battle of the Five Armies","year": 2014,"rating": 7.4,"votes": 402317,"running_times": 9840},{"title": "The Hobbit: The Desolation of Smaug","year": 2013,"rating": 7.9,"votes": 530117,"running_times": 11160},{"title": "The Hole","year": 2001,"rating": 6.2,"votes": 40802,"running_times": 6120},{"title": "The Hole","year": 2009,"rating": 5.7,"votes": 20485,"running_times": 5520},{"title": "The Holiday","year": 2006,"rating": 6.9,"votes": 201183,"running_times": 8280},{"title": "The Homesman","year": 2014,"rating": 6.6,"votes": 25011,"running_times": 7320},{"title": "The Horse Whisperer","year": 1998,"rating": 6.6,"votes": 34548,"running_times": 10200},{"title": "The Host","year": 2013,"rating": 5.9,"votes": 99595,"running_times": 7500},{"title": "The Hot Chick","year": 2002,"rating": 5.5,"votes": 80111,"running_times": 6240},{"title": "The Hottie & the Nottie","year": 2008,"rating": 1.9,"votes": 34344,"running_times": 5460},{"title": "The Hours","year": 2002,"rating": 7.6,"votes": 109423,"running_times": 6600},{"title": "The House","year": 2017,"rating": 5.6,"votes": 16827,"running_times": 5280},{"title": "The House Bunny","year": 2008,"rating": 5.5,"votes": 69088,"running_times": 5820},{"title": "The House of the Devil","year": 2009,"rating": 6.4,"votes": 33789,"running_times": 5700},{"title": "The House of the Spirits","year": 1993,"rating": 6.9,"votes": 18218,"running_times": 8760},{"title": "The Howling","year": 1981,"rating": 6.6,"votes": 25122,"running_times": 5460},{"title": "The Hudsucker Proxy","year": 1994,"rating": 7.3,"votes": 69082,"running_times": 6660},{"title": "The Human Centipede (First Sequence)","year": 2009,"rating": 4.4,"votes": 62836,"running_times": 5520},{"title": "The Human Centipede II (Full Sequence)","year": 2011,"rating": 3.9,"votes": 29662,"running_times": 5460},{"title": "The Human Centipede III (Final Sequence)","year": 2015,"rating": 2.8,"votes": 10385,"running_times": 6120},{"title": "The Human Race","year": 2013,"rating": 5.3,"votes": 10292,"running_times": 5220},{"title": "The Human Stain","year": 2003,"rating": 6.3,"votes": 26760,"running_times": 6360},{"title": "The Hunchback of Notre Dame","year": 1996,"rating": 6.9,"votes": 115443,"running_times": 5460},{"title": "The Hundred-Foot Journey","year": 2014,"rating": 7.3,"votes": 62251,"running_times": 7320},{"title": "The Hunger","year": 1983,"rating": 6.7,"votes": 19245,"running_times": 5820},{"title": "The Hunger Games","year": 2012,"rating": 7.2,"votes": 754986,"running_times": 8520},{"title": "The Hunger Games: Catching Fire","year": 2013,"rating": 7.5,"votes": 541328,"running_times": 8760},{"title": "The Hunger Games: Mockingjay - Part 1","year": 2014,"rating": 6.7,"votes": 346570,"running_times": 7380},{"title": "The Hunger Games: Mockingjay - Part 2","year": 2015,"rating": 6.6,"votes": 218419,"running_times": 8220},{"title": "The Hunt for Red October","year": 1990,"rating": 7.6,"votes": 153965,"running_times": 8100},{"title": "The Hunted","year": 2003,"rating": 6,"votes": 38171,"running_times": 5640},{"title": "The Hunter","year": 2011,"rating": 6.8,"votes": 33016,"running_times": 6120},{"title": "The Hunting Party","year": 2007,"rating": 6.9,"votes": 22998,"running_times": 6060},{"title": "The Huntsman: Winter's War","year": 2016,"rating": 6.1,"votes": 73796,"running_times": 7200},{"title": "The Hurricane","year": 1999,"rating": 7.6,"votes": 81748,"running_times": 8760},{"title": "The Hurt Locker","year": 2008,"rating": 7.6,"votes": 363360,"running_times": 7860},{"title": "The Hustler","year": 1961,"rating": 8,"votes": 66871,"running_times": 8040},{"title": "The Ice Harvest","year": 2005,"rating": 6.3,"votes": 21621,"running_times": 5520},{"title": "The Ice Storm","year": 1997,"rating": 7.5,"votes": 48839,"running_times": 6720},{"title": "The Iceman","year": 2012,"rating": 6.9,"votes": 60972,"running_times": 6360},{"title": "The Ides of March","year": 2011,"rating": 7.1,"votes": 199959,"running_times": 6060},{"title": "The Illusionist","year": 2006,"rating": 7.6,"votes": 319514,"running_times": 6600},{"title": "The Imaginarium of Doctor Parnassus","year": 2009,"rating": 6.8,"votes": 132579,"running_times": 7380},{"title": "The Imitation Game","year": 2014,"rating": 8,"votes": 557214,"running_times": 6840},{"title": "The Immigrant","year": 2013,"rating": 6.6,"votes": 24241,"running_times": 7200},{"title": "The Importance of Being Earnest","year": 2002,"rating": 6.9,"votes": 20040,"running_times": 5820},{"title": "The Imposter","year": 2012,"rating": 7.5,"votes": 39049,"running_times": 5940},{"title": "The In-Laws","year": 2003,"rating": 5.7,"votes": 14691,"running_times": 5880},{"title": "The Inbetweeners Movie","year": 2011,"rating": 6.8,"votes": 68706,"running_times": 5820},{"title": "The Incredible Burt Wonderstone","year": 2013,"rating": 5.9,"votes": 64175,"running_times": 6000},{"title": "The Incredible Hulk","year": 2008,"rating": 6.8,"votes": 355393,"running_times": 8100},{"title": "The Incredible Shrinking Man","year": 1957,"rating": 7.7,"votes": 12983,"running_times": 4860},{"title": "The Incredibles","year": 2004,"rating": 8,"votes": 528232,"running_times": 6900},{"title": "The Indian in the Cupboard","year": 1995,"rating": 5.9,"votes": 22226,"running_times": 5760},{"title": "The Infiltrator","year": 2016,"rating": 7,"votes": 52466,"running_times": 7620},{"title": "The Informant!","year": 2009,"rating": 6.5,"votes": 55888,"running_times": 6480},{"title": "The Informers","year": 2008,"rating": 5,"votes": 14859,"running_times": 5880},{"title": "The Innkeepers","year": 2011,"rating": 5.5,"votes": 29339,"running_times": 6060},{"title": "The Innocents","year": 1961,"rating": 7.9,"votes": 21569,"running_times": 6000},{"title": "The Insider","year": 1999,"rating": 7.9,"votes": 142214,"running_times": 9420},{"title": "The Intern","year": 2015,"rating": 7.1,"votes": 170025,"running_times": 7260},{"title": "The International","year": 2009,"rating": 6.5,"votes": 83532,"running_times": 7080},{"title": "The Internet's Own Boy: The Story of Aaron Swartz","year": 2014,"rating": 8.1,"votes": 13666,"running_times": 6300},{"title": "The Internship","year": 2013,"rating": 6.3,"votes": 170490,"running_times": 7500},{"title": "The Interpreter","year": 2005,"rating": 6.4,"votes": 89818,"running_times": 7680},{"title": "The Interview","year": 2014,"rating": 6.6,"votes": 269477,"running_times": 6720},{"title": "The Invasion","year": 2007,"rating": 5.9,"votes": 68278,"running_times": 5940},{"title": "The Invention of Lying","year": 2009,"rating": 6.4,"votes": 100451,"running_times": 6000},{"title": "The Invisible","year": 2007,"rating": 6.3,"votes": 32411,"running_times": 6120},{"title": "The Invisible Man","year": 1933,"rating": 7.7,"votes": 23608,"running_times": 4260},{"title": "The Invitation","year": 2015,"rating": 6.7,"votes": 49850,"running_times": 6000},{"title": "The Ipcress File","year": 1965,"rating": 7.3,"votes": 11333,"running_times": 6540},{"title": "The Iron Giant","year": 1999,"rating": 8,"votes": 142069,"running_times": 5400},{"title": "The Iron Lady","year": 2011,"rating": 6.4,"votes": 89826,"running_times": 6300},{"title": "The Island","year": 2005,"rating": 6.9,"votes": 277513,"running_times": 8160},{"title": "The Island of Dr. Moreau","year": 1996,"rating": 4.4,"votes": 27744,"running_times": 5940},{"title": "The Italian Job","year": 1969,"rating": 7.4,"votes": 33958,"running_times": 5940},{"title": "The Italian Job","year": 2003,"rating": 7,"votes": 305232,"running_times": 6660},{"title": "The Jackal","year": 1997,"rating": 6.4,"votes": 93573,"running_times": 7440},{"title": "The Jacket","year": 2005,"rating": 7.1,"votes": 98859,"running_times": 6180},{"title": "The Jane Austen Book Club","year": 2007,"rating": 6.8,"votes": 22992,"running_times": 6360},{"title": "The Jerk","year": 1979,"rating": 7.2,"votes": 46074,"running_times": 5640},{"title": "The Jewel of the Nile","year": 1985,"rating": 6.1,"votes": 42960,"running_times": 6360},{"title": "The Joneses","year": 2009,"rating": 6.5,"votes": 35379,"running_times": 5760},{"title": "The Joy Luck Club","year": 1993,"rating": 7.6,"votes": 13162,"running_times": 8340},{"title": "The Judge","year": 2014,"rating": 7.4,"votes": 151986,"running_times": 8460},{"title": "The Jungle Book","year": 1967,"rating": 7.6,"votes": 137104,"running_times": 4680},{"title": "The Jungle Book","year": 1994,"rating": 6,"votes": 14136,"running_times": 6660},{"title": "The Jungle Book","year": 2016,"rating": 7.5,"votes": 214632,"running_times": 6360},{"title": "The Jungle Book 2","year": 2003,"rating": 5.4,"votes": 12654,"running_times": 4320},{"title": "The Juror","year": 1996,"rating": 5.6,"votes": 14913,"running_times": 7080},{"title": "The Karate Kid","year": 1984,"rating": 7.2,"votes": 143057,"running_times": 7560},{"title": "The Karate Kid","year": 2010,"rating": 6.2,"votes": 133659,"running_times": 8400},{"title": "The Karate Kid Part II","year": 1986,"rating": 5.9,"votes": 59233,"running_times": 6780},{"title": "The Karate Kid Part III","year": 1989,"rating": 5,"votes": 39191,"running_times": 6720},{"title": "The Kentucky Fried Movie","year": 1977,"rating": 6.5,"votes": 14750,"running_times": 4980},{"title": "The Kid","year": 1921,"rating": 8.3,"votes": 80699,"running_times": 4080},{"title": "The Kid","year": 2000,"rating": 6.1,"votes": 36333,"running_times": 6240},{"title": "The Kids Are All Right","year": 2010,"rating": 7.1,"votes": 116244,"running_times": 6360},{"title": "The Killer Inside Me","year": 2010,"rating": 6.1,"votes": 30253,"running_times": 6540},{"title": "The Killers","year": 1946,"rating": 7.8,"votes": 15492,"running_times": 6180},{"title": "The Killing","year": 1956,"rating": 8,"votes": 67769,"running_times": 5100},{"title": "The Killing Fields","year": 1984,"rating": 7.9,"votes": 44901,"running_times": 8460},{"title": "The Killing Room","year": 2009,"rating": 5.7,"votes": 12284,"running_times": 5580},{"title": "The Killing of a Sacred Deer","year": 2017,"rating": 7.5,"votes": 17681,"running_times": 7260},{"title": "The King and I","year": 1956,"rating": 7.5,"votes": 20645,"running_times": 7980},{"title": "The King of Comedy","year": 1982,"rating": 7.8,"votes": 60357,"running_times": 6540},{"title": "The King of Kong","year": 2007,"rating": 8.2,"votes": 32123,"running_times": 4740},{"title": "The King's Speech","year": 2010,"rating": 8,"votes": 550814,"running_times": 7080},{"title": "The Kingdom","year": 2007,"rating": 7.1,"votes": 107076,"running_times": 6600},{"title": "The Kings of Summer","year": 2013,"rating": 7.2,"votes": 68006,"running_times": 5700},{"title": "The Kite Runner","year": 2007,"rating": 7.6,"votes": 71569,"running_times": 7680},{"title": "The LEGO Batman Movie","year": 2017,"rating": 7.3,"votes": 87348,"running_times": 6240},{"title": "The LEGO Movie","year": 2014,"rating": 7.8,"votes": 277876,"running_times": 6000},{"title": "The Ladies Man","year": 2000,"rating": 5.1,"votes": 11284,"running_times": 5040},{"title": "The Lady Eve","year": 1941,"rating": 8,"votes": 16038,"running_times": 5640},{"title": "The Lady Vanishes","year": 1938,"rating": 7.9,"votes": 39168,"running_times": 5760},{"title": "The Lady from Shanghai","year": 1947,"rating": 7.7,"votes": 21256,"running_times": 5520},{"title": "The Lady in the Van","year": 2015,"rating": 6.7,"votes": 18691,"running_times": 6240},{"title": "The Ladykillers","year": 1955,"rating": 7.8,"votes": 22382,"running_times": 5460},{"title": "The Ladykillers","year": 2004,"rating": 6.2,"votes": 89327,"running_times": 6240},{"title": "The Lake House","year": 2006,"rating": 6.8,"votes": 122280,"running_times": 5940},{"title": "The Land Before Time","year": 1988,"rating": 7.4,"votes": 67462,"running_times": 4140},{"title": "The Last Airbender","year": 2010,"rating": 4.2,"votes": 128562,"running_times": 6180},{"title": "The Last Boy Scout","year": 1991,"rating": 6.9,"votes": 81045,"running_times": 6300},{"title": "The Last Castle","year": 2001,"rating": 6.9,"votes": 60790,"running_times": 7860},{"title": "The Last Days of Disco","year": 1998,"rating": 6.6,"votes": 10594,"running_times": 6780},{"title": "The Last Days on Mars","year": 2013,"rating": 5.5,"votes": 31366,"running_times": 5880},{"title": "The Last Detail","year": 1973,"rating": 7.6,"votes": 18086,"running_times": 6240},{"title": "The Last Dragon","year": 1985,"rating": 6.9,"votes": 10341,"running_times": 6540},{"title": "The Last Emperor","year": 1987,"rating": 7.8,"votes": 77398,"running_times": 13140},{"title": "The Last Exorcism","year": 2010,"rating": 5.6,"votes": 43905,"running_times": 5220},{"title": "The Last Exorcism Part II","year": 2013,"rating": 4,"votes": 14396,"running_times": 5580},{"title": "The Last House on the Left","year": 1972,"rating": 6,"votes": 27511,"running_times": 5460},{"title": "The Last House on the Left","year": 2009,"rating": 6.6,"votes": 73887,"running_times": 6840},{"title": "The Last King of Scotland","year": 2006,"rating": 7.7,"votes": 156424,"running_times": 7380},{"title": "The Last Kiss","year": 2006,"rating": 6.5,"votes": 39056,"running_times": 6900},{"title": "The Last Legion","year": 2007,"rating": 5.4,"votes": 31238,"running_times": 6120},{"title": "The Last Man on Earth","year": 1964,"rating": 6.9,"votes": 14115,"running_times": 5160},{"title": "The Last Mimzy","year": 2007,"rating": 6.3,"votes": 19614,"running_times": 5760},{"title": "The Last Picture Show","year": 1971,"rating": 8.1,"votes": 34547,"running_times": 7620},{"title": "The Last Samurai","year": 2003,"rating": 7.7,"votes": 343858,"running_times": 9240},{"title": "The Last Seduction","year": 1994,"rating": 7.1,"votes": 17490,"running_times": 7740},{"title": "The Last Song","year": 2010,"rating": 5.9,"votes": 67037,"running_times": 6420},{"title": "The Last Stand","year": 2013,"rating": 6.4,"votes": 121189,"running_times": 6420},{"title": "The Last Starfighter","year": 1984,"rating": 6.7,"votes": 31850,"running_times": 6060},{"title": "The Last Station","year": 2009,"rating": 7,"votes": 16168,"running_times": 6720},{"title": "The Last Supper","year": 1995,"rating": 6.8,"votes": 12803,"running_times": 5520},{"title": "The Last Temptation of Christ","year": 1988,"rating": 7.6,"votes": 43169,"running_times": 9840},{"title": "The Last Unicorn","year": 1982,"rating": 7.5,"votes": 20743,"running_times": 5520},{"title": "The Last Waltz","year": 1978,"rating": 8.2,"votes": 13674,"running_times": 7020},{"title": "The Last Witch Hunter","year": 2015,"rating": 6,"votes": 76521,"running_times": 6360},{"title": "The Last of the Mohicans","year": 1992,"rating": 7.8,"votes": 124618,"running_times": 7020},{"title": "The Lavender Hill Mob","year": 1951,"rating": 7.7,"votes": 10460,"running_times": 4860},{"title": "The Lawnmower Man","year": 1992,"rating": 5.4,"votes": 29850,"running_times": 8400},{"title": "The Lazarus Effect","year": 2015,"rating": 5.2,"votes": 33199,"running_times": 4980},{"title": "The Lazarus Project","year": 2008,"rating": 6.2,"votes": 15187,"running_times": 6000},{"title": "The League of Extraordinary Gentlemen","year": 2003,"rating": 5.8,"votes": 149821,"running_times": 6600},{"title": "The Ledge","year": 2011,"rating": 6.6,"votes": 16738,"running_times": 6060},{"title": "The Legend of Bagger Vance","year": 2000,"rating": 6.7,"votes": 48336,"running_times": 7560},{"title": "The Legend of Bhagat Singh","year": 2002,"rating": 8.1,"votes": 11090,"running_times": 9300},{"title": "The Legend of Hell House","year": 1973,"rating": 6.8,"votes": 10186,"running_times": 5700},{"title": "The Legend of Hercules","year": 2014,"rating": 4.2,"votes": 47928,"running_times": 5940},{"title": "The Legend of Tarzan","year": 2016,"rating": 6.3,"votes": 132022,"running_times": 6600},{"title": "The Legend of Zorro","year": 2005,"rating": 5.9,"votes": 78734,"running_times": 7740},{"title": "The Libertine","year": 2004,"rating": 6.4,"votes": 32595,"running_times": 6840},{"title": "The Life Aquatic with Steve Zissou","year": 2004,"rating": 7.3,"votes": 153261,"running_times": 7140},{"title": "The Life Before Her Eyes","year": 2007,"rating": 6.4,"votes": 12657,"running_times": 5400},{"title": "The Life and Death of Colonel Blimp","year": 1943,"rating": 8.2,"votes": 10828,"running_times": 9780},{"title": "The Life and Death of Peter Sellers","year": 2004,"rating": 6.9,"votes": 13563,"running_times": 7320},{"title": "The Life of David Gale","year": 2003,"rating": 7.6,"votes": 95802,"running_times": 7800},{"title": "The Lifeguard","year": 2013,"rating": 5.7,"votes": 12490,"running_times": 5880},{"title": "The Light Between Oceans","year": 2016,"rating": 7.2,"votes": 34727,"running_times": 7980},{"title": "The Limey","year": 1999,"rating": 7.1,"votes": 26116,"running_times": 5340},{"title": "The Limits of Control","year": 2009,"rating": 6.3,"votes": 17145,"running_times": 6960},{"title": "The Lincoln Lawyer","year": 2011,"rating": 7.3,"votes": 186192,"running_times": 7080},{"title": "The Lion King","year": 1994,"rating": 8.5,"votes": 735442,"running_times": 5280},{"title": "The Lion in Winter","year": 1968,"rating": 8.1,"votes": 24882,"running_times": 8220},{"title": "The Little Death","year": 2014,"rating": 7.1,"votes": 21713,"running_times": 5880},{"title": "The Little Girl Who Lives Down the Lane","year": 1976,"rating": 7.1,"votes": 10499,"running_times": 6000},{"title": "The Little Mermaid","year": 1989,"rating": 7.6,"votes": 191159,"running_times": 4980},{"title": "The Little Prince","year": 2015,"rating": 7.8,"votes": 42970,"running_times": 6480},{"title": "The Little Rascals","year": 1994,"rating": 6.3,"votes": 37088,"running_times": 4920},{"title": "The Little Shop of Horrors","year": 1960,"rating": 6.3,"votes": 13565,"running_times": 4320},{"title": "The Living Daylights","year": 1987,"rating": 6.7,"votes": 75085,"running_times": 7800},{"title": "The Lizzie McGuire Movie","year": 2003,"rating": 5.4,"votes": 30483,"running_times": 5640},{"title": "The Lobster","year": 2015,"rating": 7.1,"votes": 138204,"running_times": 7140},{"title": "The Loft","year": 2014,"rating": 6.3,"votes": 41266,"running_times": 6480},{"title": "The Lone Ranger","year": 2013,"rating": 6.5,"votes": 196792,"running_times": 9000},{"title": "The Long Good Friday","year": 1980,"rating": 7.7,"votes": 15439,"running_times": 6840},{"title": "The Long Goodbye","year": 1973,"rating": 7.7,"votes": 20432,"running_times": 6720},{"title": "The Long Kiss Goodnight","year": 1996,"rating": 6.7,"votes": 64190,"running_times": 7260},{"title": "The Longest Day","year": 1962,"rating": 7.8,"votes": 46242,"running_times": 10680},{"title": "The Longest Ride","year": 2015,"rating": 7.1,"votes": 62410,"running_times": 7380},{"title": "The Longest Yard","year": 1974,"rating": 7.1,"votes": 14139,"running_times": 7320},{"title": "The Longest Yard","year": 2005,"rating": 6.4,"votes": 141183,"running_times": 6780},{"title": "The Lookout","year": 2007,"rating": 7.1,"votes": 53036,"running_times": 5940},{"title": "The Lorax","year": 2012,"rating": 6.4,"votes": 83985,"running_times": 5160},{"title": "The Lord of the Rings","year": 1978,"rating": 6.2,"votes": 25910,"running_times": 7920},{"title": "The Lord of the Rings: The Fellowship of the Ring","year": 2001,"rating": 8.8,"votes": 1369632,"running_times": 13680},{"title": "The Lord of the Rings: The Return of the King","year": 2003,"rating": 8.9,"votes": 1349449,"running_times": 15780},{"title": "The Lord of the Rings: The Two Towers","year": 2002,"rating": 8.7,"votes": 1221456,"running_times": 14100},{"title": "The Lords of Salem","year": 2012,"rating": 5.1,"votes": 22967,"running_times": 6060},{"title": "The Losers","year": 2010,"rating": 6.4,"votes": 79049,"running_times": 5820},{"title": "The Lost Boys","year": 1987,"rating": 7.3,"votes": 102017,"running_times": 5820},{"title": "The Lost City of Z","year": 2016,"rating": 6.6,"votes": 45774,"running_times": 8460},{"title": "The Lost Weekend","year": 1945,"rating": 8,"votes": 27909,"running_times": 6060},{"title": "The Lost World: Jurassic Park","year": 1997,"rating": 6.5,"votes": 308796,"running_times": 7740},{"title": "The Love Bug","year": 1968,"rating": 6.5,"votes": 11610,"running_times": 6480},{"title": "The Love Guru","year": 2008,"rating": 3.8,"votes": 45254,"running_times": 5220},{"title": "The Love Punch","year": 2013,"rating": 5.7,"votes": 10551,"running_times": 5640},{"title": "The Loved Ones","year": 2009,"rating": 6.7,"votes": 31227,"running_times": 5040},{"title": "The Lovely Bones","year": 2009,"rating": 6.7,"votes": 134513,"running_times": 8100},{"title": "The Lucky One","year": 2012,"rating": 6.5,"votes": 86309,"running_times": 6060},{"title": "The Lucky Ones","year": 2008,"rating": 7,"votes": 12384,"running_times": 6900},{"title": "The Machine","year": 2013,"rating": 6.1,"votes": 27158,"running_times": 5460},{"title": "The Machinist","year": 2004,"rating": 7.7,"votes": 307967,"running_times": 6060},{"title": "The Madness of King George","year": 1994,"rating": 7.2,"votes": 13102,"running_times": 6240},{"title": "The Magdalene Sisters","year": 2002,"rating": 7.8,"votes": 23532,"running_times": 6840},{"title": "The Magic of Belle Isle","year": 2012,"rating": 7,"votes": 14905,"running_times": 6540},{"title": "The Magnificent Ambersons","year": 1942,"rating": 7.9,"votes": 18255,"running_times": 8880},{"title": "The Magnificent Seven","year": 1960,"rating": 7.8,"votes": 75093,"running_times": 7680},{"title": "The Magnificent Seven","year": 2016,"rating": 6.9,"votes": 144193,"running_times": 7920},{"title": "The Maiden Heist","year": 2009,"rating": 6.1,"votes": 13687,"running_times": 5400},{"title": "The Majestic","year": 2001,"rating": 6.9,"votes": 47475,"running_times": 9120},{"title": "The Maltese Falcon","year": 1941,"rating": 8.1,"votes": 125756,"running_times": 6000},{"title": "The Man","year": 2005,"rating": 5.5,"votes": 22837,"running_times": 4980},{"title": "The Man Who Cried","year": 2000,"rating": 6.2,"votes": 13144,"running_times": 6000},{"title": "The Man Who Fell to Earth","year": 1976,"rating": 6.7,"votes": 19563,"running_times": 8340},{"title": "The Man Who Knew Infinity","year": 2015,"rating": 7.2,"votes": 35156,"running_times": 6480},{"title": "The Man Who Knew Too Little","year": 1997,"rating": 6.6,"votes": 25635,"running_times": 5640},{"title": "The Man Who Knew Too Much","year": 1934,"rating": 6.9,"votes": 13970,"running_times": 4500},{"title": "The Man Who Knew Too Much","year": 1956,"rating": 7.5,"votes": 47038,"running_times": 7200},{"title": "The Man Who Shot Liberty Valance","year": 1962,"rating": 8.1,"votes": 58224,"running_times": 7440},{"title": "The Man Who Wasn't There","year": 2001,"rating": 7.6,"votes": 91464,"running_times": 7080},{"title": "The Man Who Would Be King","year": 1975,"rating": 7.9,"votes": 38413,"running_times": 7740},{"title": "The Man Without a Face","year": 1993,"rating": 6.7,"votes": 24519,"running_times": 6900},{"title": "The Man from Earth","year": 2007,"rating": 8,"votes": 146211,"running_times": 5220},{"title": "The Man from U.N.C.L.E.","year": 2015,"rating": 7.3,"votes": 216468,"running_times": 6960},{"title": "The Man in the Iron Mask","year": 1998,"rating": 6.5,"votes": 136416,"running_times": 7920},{"title": "The Man in the Moon","year": 1991,"rating": 7.4,"votes": 13109,"running_times": 5940},{"title": "The Man with One Red Shoe","year": 1985,"rating": 5.7,"votes": 12850,"running_times": 5520},{"title": "The Man with Two Brains","year": 1983,"rating": 6.4,"votes": 21124,"running_times": 5580},{"title": "The Man with the Golden Gun","year": 1974,"rating": 6.8,"votes": 80331,"running_times": 7500},{"title": "The Man with the Iron Fists","year": 2012,"rating": 5.4,"votes": 56139,"running_times": 6420},{"title": "The Manchurian Candidate","year": 1962,"rating": 8,"votes": 64529,"running_times": 7560},{"title": "The Manchurian Candidate","year": 2004,"rating": 6.6,"votes": 92180,"running_times": 7740},{"title": "The Many Adventures of Winnie the Pooh","year": 1977,"rating": 7.6,"votes": 27101,"running_times": 4440},{"title": "The Marine","year": 2006,"rating": 4.7,"votes": 29126,"running_times": 5520},{"title": "The Martian","year": 2015,"rating": 8,"votes": 592557,"running_times": 9060},{"title": "The Mask","year": 1994,"rating": 6.9,"votes": 290014,"running_times": 6840},{"title": "The Mask of Zorro","year": 1998,"rating": 6.7,"votes": 146223,"running_times": 8160},{"title": "The Master","year": 2012,"rating": 7.1,"votes": 117674,"running_times": 8280},{"title": "The Master of Disguise","year": 2002,"rating": 3.3,"votes": 19140,"running_times": 4800},{"title": "The Matador","year": 2005,"rating": 6.8,"votes": 41655,"running_times": 5760},{"title": "The Matrix","year": 1999,"rating": 8.7,"votes": 1358510,"running_times": 8160},{"title": "The Matrix Reloaded","year": 2003,"rating": 7.2,"votes": 450569,"running_times": 8280},{"title": "The Matrix Revolutions","year": 2003,"rating": 6.7,"votes": 390666,"running_times": 7740},{"title": "The Maze Runner","year": 2014,"rating": 6.8,"votes": 349853,"running_times": 6780},{"title": "The Meaning of Life","year": 1983,"rating": 7.6,"votes": 95426,"running_times": 6720},{"title": "The Mechanic","year": 2011,"rating": 6.6,"votes": 132870,"running_times": 5580},{"title": "The Medallion","year": 2003,"rating": 5.2,"votes": 33182,"running_times": 6480},{"title": "The Men Who Stare at Goats","year": 2009,"rating": 6.2,"votes": 115503,"running_times": 5640},{"title": "The Merchant of Venice","year": 2004,"rating": 7.1,"votes": 31425,"running_times": 8040},{"title": "The Message","year": 1976,"rating": 8.3,"votes": 37406,"running_times": 10620},{"title": "The Messenger","year": 2009,"rating": 7.1,"votes": 31080,"running_times": 6780},{"title": "The Messengers","year": 2007,"rating": 5.4,"votes": 35223,"running_times": 5400},{"title": "The Mexican","year": 2001,"rating": 6.1,"votes": 92498,"running_times": 7380},{"title": "The Meyerowitz Stories (New and Selected)","year": 2017,"rating": 7.1,"votes": 15162,"running_times": 6720},{"title": "The Midnight Meat Train","year": 2008,"rating": 6.1,"votes": 52051,"running_times": 6180},{"title": "The Mighty","year": 1998,"rating": 7.3,"votes": 11094,"running_times": 6000},{"title": "The Mighty Ducks","year": 1992,"rating": 6.5,"votes": 48711,"running_times": 6000},{"title": "The Million Dollar Hotel","year": 2000,"rating": 5.9,"votes": 19243,"running_times": 7320},{"title": "The Miracle Worker","year": 1962,"rating": 8.1,"votes": 13427,"running_times": 6360},{"title": "The Mirror Has Two Faces","year": 1996,"rating": 6.5,"votes": 12283,"running_times": 7560},{"title": "The Misfits","year": 1961,"rating": 7.4,"votes": 14251,"running_times": 7500},{"title": "The Missing","year": 2003,"rating": 6.5,"votes": 29324,"running_times": 9240},{"title": "The Mission","year": 1986,"rating": 7.5,"votes": 48098,"running_times": 7500},{"title": "The Mist","year": 2007,"rating": 7.2,"votes": 242656,"running_times": 7560},{"title": "The Money Pit","year": 1986,"rating": 6.3,"votes": 41778,"running_times": 5460},{"title": "The Monster","year": 2016,"rating": 5.4,"votes": 10461,"running_times": 5460},{"title": "The Monster Squad","year": 1987,"rating": 7.1,"votes": 21965,"running_times": 4740},{"title": "The Monuments Men","year": 2014,"rating": 6.1,"votes": 111036,"running_times": 7080},{"title": "The Mortal Instruments: City of Bones","year": 2013,"rating": 5.9,"votes": 115406,"running_times": 7800},{"title": "The Mosquito Coast","year": 1986,"rating": 6.6,"votes": 23286,"running_times": 7020},{"title": "The Mothman Prophecies","year": 2002,"rating": 6.5,"votes": 67631,"running_times": 7680},{"title": "The Mountain Between Us","year": 2017,"rating": 6.3,"votes": 12554,"running_times": 6720},{"title": "The Mummy","year": 1932,"rating": 7.2,"votes": 18569,"running_times": 4380},{"title": "The Mummy","year": 1999,"rating": 7,"votes": 343729,"running_times": 7440},{"title": "The Mummy","year": 2017,"rating": 5.5,"votes": 114356,"running_times": 6600},{"title": "The Mummy Returns","year": 2001,"rating": 6.3,"votes": 266813,"running_times": 7800},{"title": "The Mummy: Tomb of the Dragon Emperor","year": 2008,"rating": 5.2,"votes": 129879,"running_times": 6720},{"title": "The Muppet Christmas Carol","year": 1992,"rating": 7.7,"votes": 38106,"running_times": 5340},{"title": "The Muppet Movie","year": 1979,"rating": 7.6,"votes": 27403,"running_times": 5700},{"title": "The Muppets","year": 2011,"rating": 7.1,"votes": 78899,"running_times": 6180},{"title": "The Muppets Take Manhattan","year": 1984,"rating": 6.9,"votes": 16510,"running_times": 5640},{"title": "The Music Man","year": 1962,"rating": 7.7,"votes": 13834,"running_times": 9060},{"title": "The Musketeer","year": 2001,"rating": 4.7,"votes": 13252,"running_times": 6240},{"title": "The Naked Gun 2½: The Smell of Fear","year": 1991,"rating": 6.8,"votes": 90089,"running_times": 5100},{"title": "The Naked Gun: From the Files of Police Squad!","year": 1988,"rating": 7.6,"votes": 126110,"running_times": 5100},{"title": "The Namesake","year": 2006,"rating": 7.6,"votes": 17432,"running_times": 7320},{"title": "The Nanny Diaries","year": 2007,"rating": 6.2,"votes": 51391,"running_times": 6360},{"title": "The Natural","year": 1984,"rating": 7.5,"votes": 36890,"running_times": 8640},{"title": "The Necessary Death of Charlie Countryman","year": 2013,"rating": 6.4,"votes": 23761,"running_times": 6180},{"title": "The Negotiator","year": 1998,"rating": 7.3,"votes": 114963,"running_times": 8400},{"title": "The Neon Demon","year": 2016,"rating": 6.2,"votes": 59341,"running_times": 7080},{"title": "The Net","year": 1995,"rating": 5.9,"votes": 52305,"running_times": 6840},{"title": "The NeverEnding Story II: The Next Chapter","year": 1990,"rating": 5.1,"votes": 19978,"running_times": 5400},{"title": "The New Daughter","year": 2009,"rating": 5.3,"votes": 12381,"running_times": 6480},{"title": "The New Guy","year": 2002,"rating": 5.9,"votes": 30223,"running_times": 5520},{"title": "The New World","year": 2005,"rating": 6.7,"votes": 75203,"running_times": 10320},{"title": "The Next Karate Kid","year": 1994,"rating": 4.3,"votes": 20316,"running_times": 6420},{"title": "The Next Three Days","year": 2010,"rating": 7.4,"votes": 156806,"running_times": 7980},{"title": "The Nice Guys","year": 2016,"rating": 7.4,"votes": 200979,"running_times": 6960},{"title": "The Night Before","year": 2015,"rating": 6.4,"votes": 49476,"running_times": 6060},{"title": "The Night Listener","year": 2006,"rating": 5.9,"votes": 13514,"running_times": 5460},{"title": "The Night of the Hunter","year": 1955,"rating": 8,"votes": 70141,"running_times": 5520},{"title": "The Nightmare Before Christmas","year": 1993,"rating": 8,"votes": 247257,"running_times": 4560},{"title": "The Nines","year": 2007,"rating": 6.4,"votes": 30202,"running_times": 6000},{"title": "The Ninth Gate","year": 1999,"rating": 6.7,"votes": 146217,"running_times": 7980},{"title": "The Notebook","year": 2004,"rating": 7.9,"votes": 436020,"running_times": 7380},{"title": "The November Man","year": 2014,"rating": 6.3,"votes": 55446,"running_times": 6480},{"title": "The Number 23","year": 2007,"rating": 6.4,"votes": 175665,"running_times": 6060},{"title": "The Numbers Station","year": 2013,"rating": 5.6,"votes": 17235,"running_times": 5340},{"title": "The Nut Job","year": 2014,"rating": 5.8,"votes": 22351,"running_times": 5100},{"title": "The Nutty Professor","year": 1963,"rating": 6.7,"votes": 13282,"running_times": 6420},{"title": "The Nutty Professor","year": 1996,"rating": 5.6,"votes": 93784,"running_times": 5700},{"title": "The Object of My Affection","year": 1998,"rating": 6,"votes": 16633,"running_times": 6660},{"title": "The Odd Couple","year": 1968,"rating": 7.7,"votes": 27013,"running_times": 6300},{"title": "The Odd Life of Timothy Green","year": 2012,"rating": 6.6,"votes": 40357,"running_times": 6300},{"title": "The Omega Man","year": 1971,"rating": 6.6,"votes": 24872,"running_times": 5880},{"title": "The Omen","year": 1976,"rating": 7.6,"votes": 89724,"running_times": 6660},{"title": "The Omen","year": 2006,"rating": 5.5,"votes": 51300,"running_times": 6600},{"title": "The One","year": 2001,"rating": 5.9,"votes": 82216,"running_times": 5220},{"title": "The One I Love","year": 2014,"rating": 7.1,"votes": 27718,"running_times": 5460},{"title": "The Onion Movie","year": 2008,"rating": 6.3,"votes": 14278,"running_times": 4800},{"title": "The Oogieloves in the Big Balloon Adventure","year": 2012,"rating": 6.3,"votes": 14494,"running_times": 5280},{"title": "The Opposite of Sex","year": 1998,"rating": 6.5,"votes": 18864,"running_times": 6300},{"title": "The Oranges","year": 2011,"rating": 5.9,"votes": 11158,"running_times": 5400},{"title": "The Order","year": 2003,"rating": 5.2,"votes": 15687,"running_times": 6120},{"title": "The Other Boleyn Girl","year": 2008,"rating": 6.7,"votes": 90521,"running_times": 6900},{"title": "The Other Guys","year": 2010,"rating": 6.7,"votes": 206139,"running_times": 6960},{"title": "The Other Side of the Door","year": 2016,"rating": 5.3,"votes": 14034,"running_times": 5760},{"title": "The Other Sister","year": 1999,"rating": 6.5,"votes": 10939,"running_times": 7740},{"title": "The Other Woman","year": 2014,"rating": 6,"votes": 114420,"running_times": 6540},{"title": "The Others","year": 2001,"rating": 7.6,"votes": 294127,"running_times": 6240},{"title": "The Ottoman Lieutenant","year": 2017,"rating": 6.9,"votes": 19405,"running_times": 6360},{"title": "The Out-of-Towners","year": 1999,"rating": 5.3,"votes": 11334,"running_times": 5400},{"title": "The Outlaw Josey Wales","year": 1976,"rating": 7.9,"votes": 55131,"running_times": 8100},{"title": "The Outsiders","year": 1983,"rating": 7.2,"votes": 62501,"running_times": 6840},{"title": "The Overnight","year": 2015,"rating": 6.1,"votes": 13121,"running_times": 4740},{"title": "The Ox-Bow Incident","year": 1943,"rating": 8.1,"votes": 17397,"running_times": 4500},{"title": "The Oxford Murders","year": 2008,"rating": 6.1,"votes": 24510,"running_times": 6240},{"title": "The Pacifier","year": 2005,"rating": 5.6,"votes": 73772,"running_times": 5700},{"title": "The Pact","year": 2012,"rating": 5.8,"votes": 21193,"running_times": 5340},{"title": "The Pagemaster","year": 1994,"rating": 6,"votes": 17586,"running_times": 4800},{"title": "The Painted Veil","year": 2006,"rating": 7.5,"votes": 82205,"running_times": 7500},{"title": "The Panic in Needle Park","year": 1971,"rating": 7.1,"votes": 13115,"running_times": 6600},{"title": "The Paper","year": 1994,"rating": 6.6,"votes": 11209,"running_times": 6720},{"title": "The Paperboy","year": 2012,"rating": 5.8,"votes": 31446,"running_times": 6420},{"title": "The Parallax View","year": 1974,"rating": 7.2,"votes": 12309,"running_times": 6120},{"title": "The Parent Trap","year": 1961,"rating": 7.1,"votes": 15693,"running_times": 7740},{"title": "The Parent Trap","year": 1998,"rating": 6.5,"votes": 97899,"running_times": 7680},{"title": "The Party","year": 1968,"rating": 7.6,"votes": 32463,"running_times": 5940},{"title": "The Patriot","year": 1998,"rating": 4.1,"votes": 10623,"running_times": 5640},{"title": "The Patriot","year": 2000,"rating": 7.2,"votes": 223677,"running_times": 10500},{"title": "The Peacemaker","year": 1997,"rating": 5.9,"votes": 48800,"running_times": 7440},{"title": "The Peanuts Movie","year": 2015,"rating": 7.1,"votes": 35551,"running_times": 5280},{"title": "The Pelican Brief","year": 1993,"rating": 6.6,"votes": 64563,"running_times": 8460},{"title": "The People Under the Stairs","year": 1991,"rating": 6.3,"votes": 26112,"running_times": 6120},{"title": "The People vs. Larry Flynt","year": 1996,"rating": 7.3,"votes": 76653,"running_times": 7740},{"title": "The Perfect Host","year": 2010,"rating": 6.8,"votes": 22080,"running_times": 5580},{"title": "The Perfect Man","year": 2005,"rating": 5.5,"votes": 25126,"running_times": 6000},{"title": "The Perfect Score","year": 2004,"rating": 5.7,"votes": 20986,"running_times": 5580},{"title": "The Perfect Storm","year": 2000,"rating": 6.4,"votes": 140346,"running_times": 7800},{"title": "The Perks of Being a Wallflower","year": 2012,"rating": 8,"votes": 391846,"running_times": 6120},{"title": "The Petrified Forest","year": 1936,"rating": 7.6,"votes": 10327,"running_times": 4920},{"title": "The Phantom","year": 1996,"rating": 4.9,"votes": 29100,"running_times": 6000},{"title": "The Phantom of the Opera","year": 2004,"rating": 7.3,"votes": 103249,"running_times": 8580},{"title": "The Philadelphia Experiment","year": 1984,"rating": 6.1,"votes": 12160,"running_times": 6120},{"title": "The Philadelphia Story","year": 1940,"rating": 8,"votes": 54146,"running_times": 6720},{"title": "The Physician","year": 2013,"rating": 7.2,"votes": 29595,"running_times": 9000},{"title": "The Pianist","year": 2002,"rating": 8.5,"votes": 567718,"running_times": 9000},{"title": "The Piano","year": 1993,"rating": 7.6,"votes": 68631,"running_times": 7260},{"title": "The Pillow Book","year": 1996,"rating": 6.7,"votes": 11158,"running_times": 7560},{"title": "The Pink Panther","year": 1963,"rating": 7.2,"votes": 41425,"running_times": 6900},{"title": "The Pink Panther","year": 2006,"rating": 5.6,"votes": 70795,"running_times": 5580},{"title": "The Pink Panther 2","year": 2009,"rating": 5.6,"votes": 36263,"running_times": 5520},{"title": "The Pink Panther Strikes Again","year": 1976,"rating": 7.3,"votes": 23815,"running_times": 6180},{"title": "The Pirates! In an Adventure with Scientists!","year": 2012,"rating": 6.7,"votes": 39134,"running_times": 5280},{"title": "The Place Beyond the Pines","year": 2012,"rating": 7.3,"votes": 208561,"running_times": 8400},{"title": "The Player","year": 1992,"rating": 7.6,"votes": 45754,"running_times": 7440},{"title": "The Pleasure of Your Company","year": 2006,"rating": 5.7,"votes": 13637,"running_times": 5400},{"title": "The Pledge","year": 2001,"rating": 6.8,"votes": 46026,"running_times": 7440},{"title": "The Polar Express","year": 2004,"rating": 6.6,"votes": 137765,"running_times": 6000},{"title": "The Poseidon Adventure","year": 1972,"rating": 7.1,"votes": 35192,"running_times": 7020},{"title": "The Possession","year": 2012,"rating": 5.9,"votes": 50728,"running_times": 5520},{"title": "The Postman","year": 1997,"rating": 6,"votes": 60345,"running_times": 10620},{"title": "The Postman Always Rings Twice","year": 1946,"rating": 7.6,"votes": 15385,"running_times": 6780},{"title": "The Postman Always Rings Twice","year": 1981,"rating": 6.6,"votes": 18313,"running_times": 7320},{"title": "The Poughkeepsie Tapes","year": 2007,"rating": 6.1,"votes": 11016,"running_times": 4860},{"title": "The Presidio","year": 1988,"rating": 6,"votes": 14000,"running_times": 5820},{"title": "The Prestige","year": 2006,"rating": 8.5,"votes": 958889,"running_times": 7800},{"title": "The Prince & Me","year": 2004,"rating": 5.9,"votes": 34100,"running_times": 6660},{"title": "The Prince","year": 2014,"rating": 4.6,"votes": 14635,"running_times": 5580},{"title": "The Prince of Egypt","year": 1998,"rating": 7,"votes": 99560,"running_times": 5940},{"title": "The Prince of Tides","year": 1991,"rating": 6.7,"votes": 13542,"running_times": 7920},{"title": "The Princess Bride","year": 1987,"rating": 8.1,"votes": 325463,"running_times": 5880},{"title": "The Princess Diaries","year": 2001,"rating": 6.3,"votes": 105164,"running_times": 6660},{"title": "The Princess Diaries 2: Royal Engagement","year": 2004,"rating": 5.7,"votes": 60658,"running_times": 6780},{"title": "The Princess and the Frog","year": 2009,"rating": 7.1,"votes": 99027,"running_times": 5820},{"title": "The Private Lives of Pippa Lee","year": 2009,"rating": 6.4,"votes": 11693,"running_times": 5880},{"title": "The Producers","year": 1967,"rating": 7.7,"votes": 43152,"running_times": 5280},{"title": "The Producers","year": 2005,"rating": 6.4,"votes": 36865,"running_times": 8040},{"title": "The Professionals","year": 1966,"rating": 7.4,"votes": 11097,"running_times": 7380},{"title": "The Program","year": 2015,"rating": 6.5,"votes": 12447,"running_times": 5940},{"title": "The Promise","year": 2016,"rating": 6,"votes": 158352,"running_times": 7980},{"title": "The Promotion","year": 2008,"rating": 5.7,"votes": 17075,"running_times": 5160},{"title": "The Prophecy","year": 1995,"rating": 6.6,"votes": 25816,"running_times": 5880},{"title": "The Proposal","year": 2009,"rating": 6.7,"votes": 250312,"running_times": 6480},{"title": "The Proposition","year": 2005,"rating": 7.4,"votes": 45238,"running_times": 6240},{"title": "The Public Enemy","year": 1931,"rating": 7.7,"votes": 14696,"running_times": 4980},{"title": "The Punisher","year": 1989,"rating": 5.7,"votes": 18060,"running_times": 5340},{"title": "The Punisher","year": 2004,"rating": 6.5,"votes": 134403,"running_times": 8400},{"title": "The Purge","year": 2013,"rating": 5.7,"votes": 161386,"running_times": 5100},{"title": "The Purge: Anarchy","year": 2014,"rating": 6.5,"votes": 111618,"running_times": 6180},{"title": "The Purge: Election Year","year": 2016,"rating": 6,"votes": 62579,"running_times": 6480},{"title": "The Purple Rose of Cairo","year": 1985,"rating": 7.7,"votes": 40054,"running_times": 4920},{"title": "The Pursuit of Happyness","year": 2006,"rating": 8,"votes": 374451,"running_times": 7020},{"title": "The Pyramid","year": 2014,"rating": 4.6,"votes": 19641,"running_times": 5340},{"title": "The Queen","year": 2006,"rating": 7.3,"votes": 92368,"running_times": 6180},{"title": "The Queen of Versailles","year": 2012,"rating": 7.1,"votes": 11417,"running_times": 6000},{"title": "The Quest","year": 1996,"rating": 5.5,"votes": 20623,"running_times": 5700},{"title": "The Quick and the Dead","year": 1995,"rating": 6.4,"votes": 73840,"running_times": 6420},{"title": "The Quiet","year": 2005,"rating": 6.4,"votes": 14028,"running_times": 5760},{"title": "The Quiet American","year": 2002,"rating": 7.1,"votes": 24933,"running_times": 6060},{"title": "The Quiet Earth","year": 1985,"rating": 6.8,"votes": 21712,"running_times": 5460},{"title": "The Quiet Man","year": 1952,"rating": 7.9,"votes": 29304,"running_times": 7740},{"title": "The Quiet Ones","year": 2014,"rating": 5.1,"votes": 16808,"running_times": 5880},{"title": "The Rage: Carrie 2","year": 1999,"rating": 4.6,"votes": 13798,"running_times": 6240},{"title": "The Raid 2: Berandal","year": 2014,"rating": 8,"votes": 95124,"running_times": 9000},{"title": "The Railway Man","year": 2013,"rating": 7.1,"votes": 31511,"running_times": 6960},{"title": "The Rainmaker","year": 1997,"rating": 7.1,"votes": 50689,"running_times": 8100},{"title": "The Raven","year": 2012,"rating": 6.4,"votes": 76793,"running_times": 6600},{"title": "The Reader","year": 2008,"rating": 7.6,"votes": 204566,"running_times": 7440},{"title": "The Reaping","year": 2007,"rating": 5.7,"votes": 39200,"running_times": 5940},{"title": "The Rebound","year": 2009,"rating": 6.3,"votes": 42033,"running_times": 5820},{"title": "The Recruit","year": 2003,"rating": 6.6,"votes": 119599,"running_times": 6900},{"title": "The Red Shoes","year": 1948,"rating": 8.3,"votes": 22241,"running_times": 8160},{"title": "The Reef","year": 2010,"rating": 5.8,"votes": 13613,"running_times": 5640},{"title": "The Ref","year": 1994,"rating": 6.9,"votes": 20844,"running_times": 5760},{"title": "The Relic","year": 1997,"rating": 5.7,"votes": 20776,"running_times": 6600},{"title": "The Reluctant Fundamentalist","year": 2012,"rating": 6.9,"votes": 11665,"running_times": 7800},{"title": "The Remains of the Day","year": 1993,"rating": 7.9,"votes": 50598,"running_times": 8040},{"title": "The Replacement Killers","year": 1998,"rating": 6.1,"votes": 24445,"running_times": 5760},{"title": "The Replacements","year": 2000,"rating": 6.5,"votes": 51436,"running_times": 7080},{"title": "The Rescuers","year": 1977,"rating": 6.9,"votes": 47886,"running_times": 4680},{"title": "The Rescuers Down Under","year": 1990,"rating": 6.9,"votes": 30652,"running_times": 4620},{"title": "The Resident","year": 2011,"rating": 5.3,"votes": 22986,"running_times": 5460},{"title": "The Return","year": 2006,"rating": 4.8,"votes": 10496,"running_times": 5100},{"title": "The Return of the Living Dead","year": 1985,"rating": 7.3,"votes": 44081,"running_times": 6480},{"title": "The Return of the Pink Panther","year": 1975,"rating": 7.1,"votes": 21148,"running_times": 6780},{"title": "The Return of the Texas Chainsaw Massacre","year": 1994,"rating": 3.2,"votes": 16423,"running_times": 5700},{"title": "The Revenant","year": 2015,"rating": 8,"votes": 534685,"running_times": 9360},{"title": "The Rewrite","year": 2014,"rating": 6.2,"votes": 14434,"running_times": 6420},{"title": "The Ridiculous 6","year": 2015,"rating": 4.8,"votes": 33152,"running_times": 7140},{"title": "The Right Stuff","year": 1983,"rating": 7.9,"votes": 48740,"running_times": 11580},{"title": "The Ring","year": 2002,"rating": 7.1,"votes": 278872,"running_times": 6900},{"title": "The Ring Two","year": 2005,"rating": 5.4,"votes": 79526,"running_times": 7680},{"title": "The Ringer","year": 2005,"rating": 5.8,"votes": 32454,"running_times": 5700},{"title": "The Riot Club","year": 2014,"rating": 6,"votes": 17763,"running_times": 6420},{"title": "The Rite","year": 2011,"rating": 6,"votes": 81084,"running_times": 6840},{"title": "The River Wild","year": 1994,"rating": 6.3,"votes": 35528,"running_times": 6660},{"title": "The Road","year": 2009,"rating": 7.3,"votes": 193198,"running_times": 6660},{"title": "The Road Within","year": 2014,"rating": 7.1,"votes": 11272,"running_times": 6000},{"title": "The Road to El Dorado","year": 2000,"rating": 6.9,"votes": 67039,"running_times": 5340},{"title": "The Road to Guantanamo","year": 2006,"rating": 7.5,"votes": 10739,"running_times": 5700},{"title": "The Road to Wellville","year": 1994,"rating": 5.8,"votes": 10290,"running_times": 7080},{"title": "The Roaring Twenties","year": 1939,"rating": 7.9,"votes": 10363,"running_times": 6360},{"title": "The Rock","year": 1996,"rating": 7.4,"votes": 276498,"running_times": 8160},{"title": "The Rocker","year": 2008,"rating": 6.2,"votes": 34007,"running_times": 6120},{"title": "The Rocketeer","year": 1991,"rating": 6.4,"votes": 45916,"running_times": 6480},{"title": "The Rocky Horror Picture Show","year": 1975,"rating": 7.4,"votes": 113940,"running_times": 6000},{"title": "The Romantics","year": 2010,"rating": 5.1,"votes": 10614,"running_times": 5700},{"title": "The Rookie","year": 1990,"rating": 5.8,"votes": 21836,"running_times": 7200},{"title": "The Rookie","year": 2002,"rating": 7,"votes": 28296,"running_times": 7620},{"title": "The Room","year": 2003,"rating": 3.6,"votes": 47057,"running_times": 5940},{"title": "The Roommate","year": 2011,"rating": 4.9,"votes": 31218,"running_times": 5460},{"title": "The Rover","year": 2014,"rating": 6.4,"votes": 37334,"running_times": 6180},{"title": "The Royal Tenenbaums","year": 2001,"rating": 7.6,"votes": 227998,"running_times": 6600},{"title": "The Rugrats Movie","year": 1998,"rating": 5.9,"votes": 15377,"running_times": 5400},{"title": "The Ruins","year": 2008,"rating": 5.9,"votes": 63013,"running_times": 5580},{"title": "The Rules of Attraction","year": 2002,"rating": 6.7,"votes": 46137,"running_times": 6600},{"title": "The Rum Diary","year": 2011,"rating": 6.2,"votes": 91193,"running_times": 7140},{"title": "The Runaways","year": 2010,"rating": 6.6,"votes": 41923,"running_times": 6360},{"title": "The Rundown","year": 2003,"rating": 6.7,"votes": 87944,"running_times": 6240},{"title": "The Running Man","year": 1987,"rating": 6.7,"votes": 121624,"running_times": 6060},{"title": "The Russia House","year": 1990,"rating": 6.1,"votes": 12429,"running_times": 7380},{"title": "The Sacrament","year": 2013,"rating": 6.1,"votes": 13925,"running_times": 5940},{"title": "The Saint","year": 1997,"rating": 6.2,"votes": 54873,"running_times": 6960},{"title": "The Salt of the Earth","year": 2014,"rating": 8.4,"votes": 15191,"running_times": 6600},{"title": "The Salton Sea","year": 2002,"rating": 7.2,"votes": 27675,"running_times": 6180},{"title": "The Salvation","year": 2014,"rating": 6.8,"votes": 29594,"running_times": 5520},{"title": "The Sand Pebbles","year": 1966,"rating": 7.7,"votes": 11150,"running_times": 11760},{"title": "The Sandlot","year": 1993,"rating": 7.8,"votes": 64212,"running_times": 6060},{"title": "The Santa Clause","year": 1994,"rating": 6.4,"votes": 74291,"running_times": 5820},{"title": "The Santa Clause 2","year": 2002,"rating": 5.6,"votes": 39364,"running_times": 6240},{"title": "The Santa Clause 3: The Escape Clause","year": 2006,"rating": 4.7,"votes": 25133,"running_times": 5820},{"title": "The Sapphires","year": 2012,"rating": 7.1,"votes": 11309,"running_times": 6180},{"title": "The Savages","year": 2007,"rating": 7.2,"votes": 33269,"running_times": 6840},{"title": "The Scarlet Letter","year": 1995,"rating": 5.2,"votes": 12823,"running_times": 8100},{"title": "The School of Rock","year": 2003,"rating": 7.1,"votes": 226397,"running_times": 6480},{"title": "The Score","year": 2001,"rating": 6.8,"votes": 107813,"running_times": 7440},{"title": "The Scorpion King","year": 2002,"rating": 5.5,"votes": 112073,"running_times": 6000},{"title": "The Searchers","year": 1956,"rating": 8,"votes": 67908,"running_times": 7140},{"title": "The Second Best Exotic Marigold Hotel","year": 2015,"rating": 6.6,"votes": 26293,"running_times": 7320},{"title": "The Secret Garden","year": 1993,"rating": 7.3,"votes": 31316,"running_times": 6060},{"title": "The Secret Life of Bees","year": 2008,"rating": 7.3,"votes": 21358,"running_times": 6840},{"title": "The Secret Life of Pets","year": 2016,"rating": 6.6,"votes": 137977,"running_times": 5220},{"title": "The Secret Life of Walter Mitty","year": 2013,"rating": 7.3,"votes": 257706,"running_times": 6780},{"title": "The Secret Life of Words","year": 2005,"rating": 7.5,"votes": 10709,"running_times": 6900},{"title": "The Secret of Kells","year": 2009,"rating": 7.7,"votes": 25776,"running_times": 4500},{"title": "The Secret of My Succe$s","year": 1987,"rating": 6.5,"votes": 24924,"running_times": 6660},{"title": "The Secret of NIMH","year": 1982,"rating": 7.6,"votes": 30265,"running_times": 4920},{"title": "The Seeker: The Dark Is Rising","year": 2007,"rating": 4.8,"votes": 13743,"running_times": 5940},{"title": "The Sentinel","year": 2006,"rating": 6.1,"votes": 44185,"running_times": 6480},{"title": "The Serpent and the Rainbow","year": 1988,"rating": 6.5,"votes": 18758,"running_times": 5880},{"title": "The Sessions","year": 2012,"rating": 7.2,"votes": 38256,"running_times": 5700},{"title": "The Seven Year Itch","year": 1955,"rating": 7.2,"votes": 28217,"running_times": 6300},{"title": "The Seventh Sign","year": 1988,"rating": 5.9,"votes": 11175,"running_times": 5820},{"title": "The Shack","year": 2017,"rating": 6.3,"votes": 18221,"running_times": 7920},{"title": "The Shadow","year": 1994,"rating": 6,"votes": 20129,"running_times": 6480},{"title": "The Shaggy Dog","year": 2006,"rating": 4.4,"votes": 15990,"running_times": 5880},{"title": "The Shallows","year": 2016,"rating": 6.3,"votes": 89641,"running_times": 5160},{"title": "The Shape of Things","year": 2003,"rating": 6.7,"votes": 10095,"running_times": 5760},{"title": "The Shawshank Redemption","year": 1994,"rating": 9.3,"votes": 1888533,"running_times": 8520},{"title": "The Shining","year": 1980,"rating": 8.4,"votes": 692021,"running_times": 8760},{"title": "The Shipping News","year": 2001,"rating": 6.8,"votes": 29935,"running_times": 6660},{"title": "The Shootist","year": 1976,"rating": 7.7,"votes": 18572,"running_times": 6000},{"title": "The Shop Around the Corner","year": 1940,"rating": 8.1,"votes": 22183,"running_times": 5940},{"title": "The Siege","year": 1998,"rating": 6.3,"votes": 61557,"running_times": 6960},{"title": "The Siege of Jadotville","year": 2016,"rating": 7.3,"votes": 17814,"running_times": 6480},{"title": "The Signal","year": 2007,"rating": 6.1,"votes": 18972,"running_times": 6180},{"title": "The Signal","year": 2014,"rating": 6.1,"votes": 53979,"running_times": 5820},{"title": "The Silence of the Lambs","year": 1991,"rating": 8.6,"votes": 1005824,"running_times": 8280},{"title": "The Simpsons Movie","year": 2007,"rating": 7.4,"votes": 275789,"running_times": 5220},{"title": "The Sisterhood of the Traveling Pants","year": 2005,"rating": 6.5,"votes": 48049,"running_times": 7140},{"title": "The Sisterhood of the Traveling Pants 2","year": 2008,"rating": 6.2,"votes": 23987,"running_times": 7140},{"title": "The Sitter","year": 2011,"rating": 5.7,"votes": 63242,"running_times": 5220},{"title": "The Sixth Sense","year": 1999,"rating": 8.1,"votes": 776053,"running_times": 6420},{"title": "The Skeleton Key","year": 2005,"rating": 6.5,"votes": 94403,"running_times": 6240},{"title": "The Skeleton Twins","year": 2014,"rating": 6.8,"votes": 34525,"running_times": 5580},{"title": "The Skulls","year": 2000,"rating": 5.6,"votes": 28314,"running_times": 6360},{"title": "The Slammin' Salmon","year": 2009,"rating": 6.5,"votes": 11416,"running_times": 5400},{"title": "The Smurfs","year": 2011,"rating": 5.5,"votes": 72567,"running_times": 6180},{"title": "The Smurfs 2","year": 2013,"rating": 5.4,"votes": 31061,"running_times": 6300},{"title": "The Snowman","year": 2017,"rating": 5.1,"votes": 14779,"running_times": 7140},{"title": "The Social Network","year": 2010,"rating": 7.7,"votes": 528377,"running_times": 7200},{"title": "The Soloist","year": 2009,"rating": 6.7,"votes": 46174,"running_times": 7020},{"title": "The Son of No One","year": 2011,"rating": 5.1,"votes": 15063,"running_times": 5400},{"title": "The Sons of Katie Elder","year": 1965,"rating": 7.2,"votes": 11668,"running_times": 7320},{"title": "The Sorcerer's Apprentice","year": 2010,"rating": 6.1,"votes": 134792,"running_times": 6540},{"title": "The Sound of Music","year": 1965,"rating": 8,"votes": 163945,"running_times": 10440},{"title": "The Space Between Us","year": 2017,"rating": 6.4,"votes": 29211,"running_times": 7200},{"title": "The Spanish Prisoner","year": 1997,"rating": 7.3,"votes": 19572,"running_times": 6600},{"title": "The Specialist","year": 1994,"rating": 5.5,"votes": 54437,"running_times": 6600},{"title": "The Spectacular Now","year": 2013,"rating": 7.1,"votes": 121292,"running_times": 5700},{"title": "The Spiderwick Chronicles","year": 2008,"rating": 6.6,"votes": 75232,"running_times": 6420},{"title": "The Spirit","year": 2008,"rating": 4.8,"votes": 55852,"running_times": 6180},{"title": "The SpongeBob Movie: Sponge Out of Water","year": 2015,"rating": 6,"votes": 39185,"running_times": 5520},{"title": "The SpongeBob SquarePants Movie","year": 2004,"rating": 7,"votes": 64917,"running_times": 5220},{"title": "The Spy Next Door","year": 2010,"rating": 5.4,"votes": 33445,"running_times": 5640},{"title": "The Spy Who Came in from the Cold","year": 1965,"rating": 7.7,"votes": 11988,"running_times": 6720},{"title": "The Spy Who Loved Me","year": 1977,"rating": 7.1,"votes": 83086,"running_times": 7500},{"title": "The Square","year": 2017,"rating": 7.7,"votes": 10452,"running_times": 8520},{"title": "The Squid and the Whale","year": 2005,"rating": 7.4,"votes": 65586,"running_times": 5280},{"title": "The Stanford Prison Experiment","year": 2015,"rating": 6.9,"votes": 24929,"running_times": 7320},{"title": "The Starving Games","year": 2013,"rating": 3.3,"votes": 15908,"running_times": 5580},{"title": "The Station Agent","year": 2003,"rating": 7.7,"votes": 61383,"running_times": 5340},{"title": "The Stepfather","year": 1987,"rating": 6.8,"votes": 10118,"running_times": 5340},{"title": "The Stepfather","year": 2009,"rating": 5.6,"votes": 25548,"running_times": 6060},{"title": "The Stepford Wives","year": 1975,"rating": 6.9,"votes": 13376,"running_times": 6900},{"title": "The Stepford Wives","year": 2004,"rating": 5.2,"votes": 52642,"running_times": 5580},{"title": "The Sting","year": 1973,"rating": 8.3,"votes": 196224,"running_times": 7740},{"title": "The Stoning of Soraya M.","year": 2008,"rating": 8,"votes": 15633,"running_times": 6840},{"title": "The Story of Us","year": 1999,"rating": 5.9,"votes": 19337,"running_times": 5700},{"title": "The Straight Story","year": 1999,"rating": 8,"votes": 69476,"running_times": 6720},{"title": "The Stranger","year": 1946,"rating": 7.4,"votes": 14987,"running_times": 5700},{"title": "The Strangers","year": 2008,"rating": 6.2,"votes": 100210,"running_times": 5280},{"title": "The Substitute","year": 1996,"rating": 5.9,"votes": 10182,"running_times": 6840},{"title": "The Sugarland Express","year": 1974,"rating": 6.8,"votes": 12491,"running_times": 6600},{"title": "The Sum of All Fears","year": 2002,"rating": 6.4,"votes": 91728,"running_times": 7680},{"title": "The Sure Thing","year": 1985,"rating": 7,"votes": 16657,"running_times": 6000},{"title": "The Survivalist","year": 2015,"rating": 6.3,"votes": 11292,"running_times": 6240},{"title": "The Swan Princess","year": 1994,"rating": 6.4,"votes": 19213,"running_times": 5400},{"title": "The Sweeney","year": 2012,"rating": 6.1,"votes": 17373,"running_times": 6720},{"title": "The Sweet Hereafter","year": 1997,"rating": 7.6,"votes": 28526,"running_times": 6720},{"title": "The Sweetest Thing","year": 2002,"rating": 5.1,"votes": 49102,"running_times": 5400},{"title": "The Switch","year": 2010,"rating": 6.1,"votes": 84752,"running_times": 6060},{"title": "The Sword in the Stone","year": 1963,"rating": 7.2,"votes": 72723,"running_times": 4740},{"title": "The Tailor of Panama","year": 2001,"rating": 6.1,"votes": 25172,"running_times": 6540},{"title": "The Taking","year": 2014,"rating": 6,"votes": 19155,"running_times": 5400},{"title": "The Taking of Pelham 123","year": 2009,"rating": 6.4,"votes": 162021,"running_times": 6360},{"title": "The Taking of Pelham One Two Three","year": 1974,"rating": 7.7,"votes": 21595,"running_times": 6240},{"title": "The Tale of Despereaux","year": 2008,"rating": 6.1,"votes": 32678,"running_times": 5580},{"title": "The Talented Mr. Ripley","year": 1999,"rating": 7.3,"votes": 150246,"running_times": 8340},{"title": "The Tall Man","year": 2012,"rating": 5.9,"votes": 33866,"running_times": 6360},{"title": "The Ten","year": 2007,"rating": 5,"votes": 15676,"running_times": 5760},{"title": "The Ten Commandments","year": 1956,"rating": 7.9,"votes": 52473,"running_times": 13200},{"title": "The Terminal","year": 2004,"rating": 7.3,"votes": 335257,"running_times": 7680},{"title": "The Terminator","year": 1984,"rating": 8,"votes": 665696,"running_times": 6420},{"title": "The Texas Chain Saw Massacre","year": 1974,"rating": 7.5,"votes": 109598,"running_times": 5280},{"title": "The Texas Chainsaw Massacre","year": 2003,"rating": 6.2,"votes": 116056,"running_times": 5880},{"title": "The Texas Chainsaw Massacre 2","year": 1986,"rating": 5.6,"votes": 21886,"running_times": 6060},{"title": "The Texas Chainsaw Massacre: The Beginning","year": 2006,"rating": 5.9,"votes": 60550,"running_times": 5760},{"title": "The Thaw","year": 2009,"rating": 5.2,"votes": 10084,"running_times": 5400},{"title": "The Theory of Everything","year": 2014,"rating": 7.7,"votes": 316106,"running_times": 7380},{"title": "The Thin Blue Line","year": 1988,"rating": 8.1,"votes": 17925,"running_times": 6060},{"title": "The Thin Man","year": 1934,"rating": 8.1,"votes": 22285,"running_times": 5460},{"title": "The Thin Red Line","year": 1998,"rating": 7.6,"votes": 150404,"running_times": 12900},{"title": "The Thing","year": 1982,"rating": 8.2,"votes": 293518,"running_times": 6540},{"title": "The Thing","year": 2011,"rating": 6.2,"votes": 103362,"running_times": 6180},{"title": "The Thing from Another World","year": 1951,"rating": 7.2,"votes": 20919,"running_times": 5220},{"title": "The Third Man","year": 1949,"rating": 8.2,"votes": 127466,"running_times": 6240},{"title": "The Thirteenth Floor","year": 1999,"rating": 7,"votes": 57011,"running_times": 6000},{"title": "The Thomas Crown Affair","year": 1968,"rating": 7,"votes": 18269,"running_times": 6120},{"title": "The Thomas Crown Affair","year": 1999,"rating": 6.8,"votes": 77349,"running_times": 6780},{"title": "The Three Burials of Melquiades Estrada","year": 2005,"rating": 7.4,"votes": 35698,"running_times": 7260},{"title": "The Three Musketeers","year": 1973,"rating": 7.3,"votes": 13230,"running_times": 6360},{"title": "The Three Musketeers","year": 1993,"rating": 6.4,"votes": 44143,"running_times": 6300},{"title": "The Three Musketeers","year": 2011,"rating": 5.8,"votes": 94299,"running_times": 6600},{"title": "The Three Stooges","year": 2012,"rating": 5.1,"votes": 26998,"running_times": 5520},{"title": "The Tigger Movie","year": 2000,"rating": 6.3,"votes": 14400,"running_times": 4620},{"title": "The Time Machine","year": 1960,"rating": 7.6,"votes": 30163,"running_times": 6180},{"title": "The Time Machine","year": 2002,"rating": 5.9,"votes": 108614,"running_times": 5760},{"title": "The Time Traveler's Wife","year": 2009,"rating": 7.1,"votes": 124143,"running_times": 6420},{"title": "The To Do List","year": 2013,"rating": 5.8,"votes": 32406,"running_times": 6240},{"title": "The Tourist","year": 2010,"rating": 6,"votes": 192546,"running_times": 6180},{"title": "The Tournament","year": 2009,"rating": 6.1,"votes": 32011,"running_times": 5700},{"title": "The Towering Inferno","year": 1974,"rating": 6.9,"votes": 32856,"running_times": 9900},{"title": "The Town","year": 2010,"rating": 7.6,"votes": 302386,"running_times": 9180},{"title": "The Town That Dreaded Sundown","year": 2014,"rating": 5.6,"votes": 11248,"running_times": 5160},{"title": "The Toxic Avenger","year": 1984,"rating": 6.2,"votes": 20890,"running_times": 5460},{"title": "The Tragedy of Macbeth","year": 1971,"rating": 7.5,"votes": 10629,"running_times": 8400},{"title": "The Train","year": 1964,"rating": 7.9,"votes": 11335,"running_times": 8400},{"title": "The Transformers: The Movie","year": 1986,"rating": 7.3,"votes": 33807,"running_times": 5100},{"title": "The Transporter","year": 2002,"rating": 6.8,"votes": 255330,"running_times": 5520},{"title": "The Transporter Refueled","year": 2015,"rating": 5.1,"votes": 32968,"running_times": 5760},{"title": "The Treasure of the Sierra Madre","year": 1948,"rating": 8.3,"votes": 88818,"running_times": 7560},{"title": "The Tree of Life","year": 2011,"rating": 6.8,"votes": 147663,"running_times": 8340},{"title": "The Trip","year": 2010,"rating": 7,"votes": 19086,"running_times": 6720},{"title": "The Trip to Italy","year": 2014,"rating": 6.6,"votes": 12519,"running_times": 10500},{"title": "The Trouble with Harry","year": 1955,"rating": 7.2,"votes": 27605,"running_times": 5940},{"title": "The Truman Show","year": 1998,"rating": 8.1,"votes": 752414,"running_times": 6180},{"title": "The Trust","year": 2016,"rating": 5.4,"votes": 13898,"running_times": 5520},{"title": "The Truth About Cats & Dogs","year": 1996,"rating": 6.3,"votes": 23194,"running_times": 5820},{"title": "The Tunnel","year": 2011,"rating": 5.9,"votes": 16883,"running_times": 5400},{"title": "The Tuxedo","year": 2002,"rating": 5.3,"votes": 67876,"running_times": 5880},{"title": "The Twilight Saga: Breaking Dawn - Part 1","year": 2011,"rating": 4.9,"votes": 194719,"running_times": 7500},{"title": "The Twilight Saga: Breaking Dawn - Part 2","year": 2012,"rating": 5.5,"votes": 199491,"running_times": 7320},{"title": "The Twilight Saga: Eclipse","year": 2010,"rating": 4.9,"votes": 197473,"running_times": 7860},{"title": "The Twilight Saga: New Moon","year": 2009,"rating": 4.7,"votes": 234090,"running_times": 7800},{"title": "The Two Faces of January","year": 2014,"rating": 6.2,"votes": 25170,"running_times": 5760},{"title": "The Ugly Truth","year": 2009,"rating": 6.5,"votes": 177843,"running_times": 5760},{"title": "The Ultimate Gift","year": 2006,"rating": 7.4,"votes": 15293,"running_times": 6840},{"title": "The Unbearable Lightness of Being","year": 1988,"rating": 7.4,"votes": 29201,"running_times": 10260},{"title": "The Unborn","year": 2009,"rating": 4.8,"votes": 44583,"running_times": 5340},{"title": "The Uninvited","year": 2009,"rating": 6.4,"votes": 67429,"running_times": 5220},{"title": "The United States of Leland","year": 2003,"rating": 7.1,"votes": 21022,"running_times": 6480},{"title": "The Untouchables","year": 1987,"rating": 7.9,"votes": 236735,"running_times": 7140},{"title": "The Upside of Anger","year": 2005,"rating": 6.9,"votes": 19799,"running_times": 7080},{"title": "The Usual Suspects","year": 1995,"rating": 8.6,"votes": 825415,"running_times": 6360},{"title": "The VVitch: A New-England Folktale","year": 2015,"rating": 6.8,"votes": 116302,"running_times": 5520},{"title": "The Vanishing","year": 1993,"rating": 6.3,"votes": 20064,"running_times": 6540},{"title": "The Vatican Tapes","year": 2015,"rating": 5,"votes": 14242,"running_times": 5460},{"title": "The Verdict","year": 1982,"rating": 7.8,"votes": 29321,"running_times": 7740},{"title": "The Vikings","year": 1958,"rating": 7.1,"votes": 10339,"running_times": 6960},{"title": "The Village","year": 2004,"rating": 6.5,"votes": 211351,"running_times": 6480},{"title": "The Virgin Suicides","year": 1999,"rating": 7.2,"votes": 126377,"running_times": 5820},{"title": "The Visit","year": 2015,"rating": 6.2,"votes": 89398,"running_times": 5640},{"title": "The Visitor","year": 2007,"rating": 7.7,"votes": 38887,"running_times": 6240},{"title": "The Voices","year": 2014,"rating": 6.4,"votes": 42329,"running_times": 6180},{"title": "The Void","year": 2016,"rating": 5.8,"votes": 17759,"running_times": 5400},{"title": "The Vow","year": 2012,"rating": 6.8,"votes": 161595,"running_times": 6240},{"title": "The Wackness","year": 2008,"rating": 7,"votes": 28228,"running_times": 5940},{"title": "The Walk","year": 2015,"rating": 7.3,"votes": 99230,"running_times": 7380},{"title": "The Wall","year": 2017,"rating": 6.1,"votes": 13630,"running_times": 5280},{"title": "The War","year": 1994,"rating": 6.7,"votes": 10819,"running_times": 7560},{"title": "The War of the Roses","year": 1989,"rating": 6.8,"votes": 41078,"running_times": 6960},{"title": "The War of the Worlds","year": 1953,"rating": 7.1,"votes": 27465,"running_times": 5100},{"title": "The Ward","year": 2010,"rating": 5.6,"votes": 36222,"running_times": 5340},{"title": "The Warrior's Way","year": 2010,"rating": 6.3,"votes": 23298,"running_times": 6000},{"title": "The Warriors","year": 1979,"rating": 7.7,"votes": 78567,"running_times": 5520},{"title": "The Watch","year": 2012,"rating": 5.7,"votes": 110365,"running_times": 6120},{"title": "The Watcher","year": 2000,"rating": 5.3,"votes": 23272,"running_times": 5820},{"title": "The Water Diviner","year": 2014,"rating": 7.1,"votes": 61571,"running_times": 6660},{"title": "The Water Horse","year": 2007,"rating": 6.5,"votes": 33841,"running_times": 6720},{"title": "The Waterboy","year": 1998,"rating": 6.1,"votes": 128608,"running_times": 5400},{"title": "The Way","year": 2010,"rating": 7.4,"votes": 25485,"running_times": 7380},{"title": "The Way Back","year": 2010,"rating": 7.3,"votes": 95405,"running_times": 7980},{"title": "The Way Way Back","year": 2013,"rating": 7.4,"votes": 125222,"running_times": 6180},{"title": "The Way We Were","year": 1973,"rating": 7.1,"votes": 18180,"running_times": 7080},{"title": "The Way of the Gun","year": 2000,"rating": 6.7,"votes": 28622,"running_times": 7200},{"title": "The Weather Man","year": 2005,"rating": 6.6,"votes": 72135,"running_times": 6120},{"title": "The Wedding Date","year": 2005,"rating": 6.1,"votes": 41956,"running_times": 5400},{"title": "The Wedding Planner","year": 2001,"rating": 5.2,"votes": 66485,"running_times": 6180},{"title": "The Wedding Ringer","year": 2015,"rating": 6.7,"votes": 61464,"running_times": 6060},{"title": "The Wedding Singer","year": 1998,"rating": 6.8,"votes": 117472,"running_times": 5700},{"title": "The Whistleblower","year": 2010,"rating": 7.2,"votes": 27422,"running_times": 6720},{"title": "The Whole Nine Yards","year": 2000,"rating": 6.7,"votes": 96501,"running_times": 5880},{"title": "The Whole Ten Yards","year": 2004,"rating": 5.5,"votes": 48689,"running_times": 5880},{"title": "The Whole Truth","year": 2016,"rating": 6.2,"votes": 14683,"running_times": 5640},{"title": "The Wicker Man","year": 1973,"rating": 7.6,"votes": 53387,"running_times": 5940},{"title": "The Wicker Man","year": 2006,"rating": 3.7,"votes": 56687,"running_times": 6120},{"title": "The Wild","year": 2006,"rating": 5.3,"votes": 20527,"running_times": 4920},{"title": "The Wild Bunch","year": 1969,"rating": 8,"votes": 67529,"running_times": 8700},{"title": "The Wild Geese","year": 1978,"rating": 6.8,"votes": 10009,"running_times": 8040},{"title": "The Wild One","year": 1953,"rating": 6.9,"votes": 12360,"running_times": 4740},{"title": "The Wild Thornberrys Movie","year": 2002,"rating": 5.3,"votes": 12815,"running_times": 5100},{"title": "The Wind That Shakes the Barley","year": 2006,"rating": 7.5,"votes": 39810,"running_times": 7620},{"title": "The Witches","year": 1990,"rating": 6.8,"votes": 27846,"running_times": 5460},{"title": "The Witches of Eastwick","year": 1987,"rating": 6.5,"votes": 52381,"running_times": 7080},{"title": "The Wiz","year": 1978,"rating": 5.3,"votes": 11821,"running_times": 8160},{"title": "The Wizard","year": 1989,"rating": 6,"votes": 11413,"running_times": 6000},{"title": "The Wizard of Oz","year": 1939,"rating": 8.1,"votes": 321107,"running_times": 6120},{"title": "The Wolf Man","year": 1941,"rating": 7.4,"votes": 18812,"running_times": 4200},{"title": "The Wolf of Wall Street","year": 2013,"rating": 8.2,"votes": 911859,"running_times": 14400},{"title": "The Wolfman","year": 2010,"rating": 5.8,"votes": 93751,"running_times": 7140},{"title": "The Wolverine","year": 2013,"rating": 6.7,"votes": 369113,"running_times": 8280},{"title": "The Woman","year": 2011,"rating": 6,"votes": 18754,"running_times": 6060},{"title": "The Woman in Black","year": 2012,"rating": 6.4,"votes": 155529,"running_times": 5700},{"title": "The Woman in Black 2: Angel of Death","year": 2014,"rating": 4.9,"votes": 22594,"running_times": 5880},{"title": "The Woman in Red","year": 1984,"rating": 5.9,"votes": 11392,"running_times": 5220},{"title": "The Woman in the Window","year": 1944,"rating": 7.8,"votes": 10497,"running_times": 6420},{"title": "The Women","year": 1939,"rating": 8,"votes": 10584,"running_times": 7980},{"title": "The Women","year": 2008,"rating": 4.9,"votes": 18004,"running_times": 6840},{"title": "The Woodsman","year": 2004,"rating": 7.2,"votes": 29060,"running_times": 5220},{"title": "The Words","year": 2012,"rating": 7.1,"votes": 65538,"running_times": 6120},{"title": "The World According to Garp","year": 1982,"rating": 7.2,"votes": 22128,"running_times": 8160},{"title": "The World Is Not Enough","year": 1999,"rating": 6.4,"votes": 166771,"running_times": 9600},{"title": "The World's End","year": 2013,"rating": 7,"votes": 210573,"running_times": 6540},{"title": "The World's Fastest Indian","year": 2005,"rating": 7.8,"votes": 46860,"running_times": 7620},{"title": "The Wraith","year": 1986,"rating": 5.9,"votes": 11815,"running_times": 5580},{"title": "The Wrestler","year": 2008,"rating": 7.9,"votes": 266299,"running_times": 6540},{"title": "The Wrong Man","year": 1956,"rating": 7.5,"votes": 21010,"running_times": 6300},{"title": "The Wrong Trousers","year": 1993,"rating": 8.4,"votes": 44121,"running_times": 1800},{"title": "The X Files","year": 1998,"rating": 7,"votes": 91195,"running_times": 7260},{"title": "The X Files: I Want to Believe","year": 2008,"rating": 5.9,"votes": 82186,"running_times": 6480},{"title": "The Yards","year": 2000,"rating": 6.4,"votes": 17330,"running_times": 6900},{"title": "The Year of Living Dangerously","year": 1982,"rating": 7.2,"votes": 16789,"running_times": 6900},{"title": "The Young Victoria","year": 2009,"rating": 7.3,"votes": 49898,"running_times": 6300},{"title": "The Young and Prodigious T.S. Spivet","year": 2013,"rating": 7.1,"votes": 13735,"running_times": 6300},{"title": "The Zero Theorem","year": 2013,"rating": 6.1,"votes": 38906,"running_times": 6420},{"title": "The Zookeeper's Wife","year": 2017,"rating": 7,"votes": 18921,"running_times": 7620},{"title": "Their Finest","year": 2016,"rating": 6.8,"votes": 10101,"running_times": 7020},{"title": "Thelma & Louise","year": 1991,"rating": 7.4,"votes": 111181,"running_times": 7800},{"title": "Them!","year": 1954,"rating": 7.3,"votes": 16401,"running_times": 5640},{"title": "There Will Be Blood","year": 2007,"rating": 8.1,"votes": 418664,"running_times": 9480},{"title": "There's Something About Mary","year": 1998,"rating": 7.1,"votes": 261762,"running_times": 7800},{"title": "These Final Hours","year": 2013,"rating": 6.7,"votes": 12815,"running_times": 5220},{"title": "They","year": 2002,"rating": 4.8,"votes": 11399,"running_times": 5340},{"title": "They Came Together","year": 2014,"rating": 5.5,"votes": 18600,"running_times": 4980},{"title": "They Live","year": 1988,"rating": 7.3,"votes": 85066,"running_times": 5640},{"title": "They Shoot Horses, Don't They?","year": 1969,"rating": 7.9,"votes": 13393,"running_times": 7740},{"title": "Thick as Thieves","year": 2009,"rating": 6,"votes": 30544,"running_times": 6240},{"title": "Thief","year": 1981,"rating": 7.4,"votes": 18773,"running_times": 7320},{"title": "Things We Lost in the Fire","year": 2007,"rating": 7.2,"votes": 25533,"running_times": 7080},{"title": "Things to Do in Denver When You're Dead","year": 1995,"rating": 6.8,"votes": 23523,"running_times": 6900},{"title": "Think Like a Man","year": 2012,"rating": 6.6,"votes": 37687,"running_times": 7320},{"title": "Think Like a Man Too","year": 2014,"rating": 5.8,"votes": 16909,"running_times": 6360},{"title": "Thinner","year": 1996,"rating": 5.7,"votes": 22657,"running_times": 5580},{"title": "Thir13en Ghosts","year": 2001,"rating": 5.6,"votes": 69826,"running_times": 5460},{"title": "Third Person","year": 2013,"rating": 6.4,"votes": 23048,"running_times": 8220},{"title": "Thirteen","year": 2003,"rating": 6.8,"votes": 72716,"running_times": 6000},{"title": "Thirteen Days","year": 2000,"rating": 7.3,"votes": 48091,"running_times": 8700},{"title": "This Boy's Life","year": 1993,"rating": 7.3,"votes": 39017,"running_times": 6900},{"title": "This Film Is Not Yet Rated","year": 2006,"rating": 7.5,"votes": 26134,"running_times": 5880},{"title": "This Is 40","year": 2012,"rating": 6.2,"votes": 110651,"running_times": 8040},{"title": "This Is England","year": 2006,"rating": 7.7,"votes": 104758,"running_times": 6060},{"title": "This Is It","year": 2009,"rating": 7.3,"votes": 34810,"running_times": 6660},{"title": "This Is Spinal Tap","year": 1984,"rating": 8,"votes": 113091,"running_times": 4920},{"title": "This Is Where I Leave You","year": 2014,"rating": 6.6,"votes": 60539,"running_times": 6180},{"title": "This Is the End","year": 2013,"rating": 6.6,"votes": 338167,"running_times": 6420},{"title": "This Means War","year": 2012,"rating": 6.3,"votes": 158614,"running_times": 6180},{"title": "This Must Be the Place","year": 2011,"rating": 6.7,"votes": 28430,"running_times": 7080},{"title": "Thor","year": 2011,"rating": 7,"votes": 597270,"running_times": 6900},{"title": "Thor: Ragnarok","year": 2017,"rating": 8.1,"votes": 170098,"running_times": 7800},{"title": "Thor: The Dark World","year": 2013,"rating": 7,"votes": 466861,"running_times": 6720},{"title": "Three Billboards Outside Ebbing, Missouri","year": 2017,"rating": 8.5,"votes": 12269,"running_times": 6900},{"title": "Three Days of the Condor","year": 1975,"rating": 7.5,"votes": 38865,"running_times": 7020},{"title": "Three Kings","year": 1999,"rating": 7.1,"votes": 146204,"running_times": 6840},{"title": "Three to Tango","year": 1999,"rating": 6.1,"votes": 16986,"running_times": 5880},{"title": "Threesome","year": 1994,"rating": 6.2,"votes": 11466,"running_times": 5340},{"title": "Throw Momma from the Train","year": 1987,"rating": 6.2,"votes": 28749,"running_times": 5280},{"title": "Thumbelina","year": 1994,"rating": 6.4,"votes": 12645,"running_times": 5220},{"title": "Thumbsucker","year": 2005,"rating": 6.6,"votes": 19455,"running_times": 5760},{"title": "Thunderball","year": 1965,"rating": 7,"votes": 88693,"running_times": 7800},{"title": "Thunderbirds","year": 2004,"rating": 4.2,"votes": 11828,"running_times": 5700},{"title": "Thunderbolt and Lightfoot","year": 1974,"rating": 7.1,"votes": 17590,"running_times": 6900},{"title": "Thunderheart","year": 1992,"rating": 6.8,"votes": 12172,"running_times": 7140},{"title": "Thursday","year": 1998,"rating": 7.2,"votes": 15020,"running_times": 5220},{"title": "TiMER","year": 2009,"rating": 6.6,"votes": 11302,"running_times": 5940},{"title": "Tian jiang xiong shi","year": 2015,"rating": 6.1,"votes": 14550,"running_times": 7620},{"title": "Tideland","year": 2005,"rating": 6.5,"votes": 28552,"running_times": 7200},{"title": "Tigerland","year": 2000,"rating": 7,"votes": 34855,"running_times": 6060},{"title": "Tightrope","year": 1984,"rating": 6.3,"votes": 12721,"running_times": 6840},{"title": "Timbuktu","year": 2014,"rating": 7.2,"votes": 13276,"running_times": 5820},{"title": "Time After Time","year": 1979,"rating": 7.2,"votes": 12886,"running_times": 6720},{"title": "Time Bandits","year": 1981,"rating": 7,"votes": 49534,"running_times": 6960},{"title": "Time Lapse","year": 2014,"rating": 6.5,"votes": 33700,"running_times": 6240},{"title": "Timecop","year": 1994,"rating": 5.8,"votes": 48177,"running_times": 5940},{"title": "Timeline","year": 2003,"rating": 5.6,"votes": 55343,"running_times": 6960},{"title": "Tin Cup","year": 1996,"rating": 6.3,"votes": 40422,"running_times": 8100},{"title": "Tinker Tailor Soldier Spy","year": 2011,"rating": 7.1,"votes": 162349,"running_times": 7320},{"title": "Tiny Furniture","year": 2010,"rating": 6.2,"votes": 12833,"running_times": 5880},{"title": "Titan A.E.","year": 2000,"rating": 6.6,"votes": 54378,"running_times": 5640},{"title": "Titanic","year": 1997,"rating": 7.8,"votes": 872744,"running_times": 11640},{"title": "Titus","year": 1999,"rating": 7.2,"votes": 18157,"running_times": 9720},{"title": "To Be or Not to Be","year": 1942,"rating": 8.2,"votes": 21156,"running_times": 5940},{"title": "To Catch a Thief","year": 1955,"rating": 7.5,"votes": 51136,"running_times": 6360},{"title": "To Die For","year": 1995,"rating": 6.8,"votes": 37325,"running_times": 6600},{"title": "To Have and Have Not","year": 1944,"rating": 8,"votes": 25610,"running_times": 6000},{"title": "To Kill a Mockingbird","year": 1962,"rating": 8.3,"votes": 243039,"running_times": 7740},{"title": "To Live and Die in L.A.","year": 1985,"rating": 7.3,"votes": 23530,"running_times": 6960},{"title": "To Rome with Love","year": 2012,"rating": 6.3,"votes": 74663,"running_times": 6720},{"title": "To Sir, with Love","year": 1967,"rating": 7.7,"votes": 13076,"running_times": 6300},{"title": "To Wong Foo Thanks for Everything, Julie Newmar","year": 1995,"rating": 6.4,"votes": 23230,"running_times": 6540},{"title": "To the Bone","year": 2017,"rating": 6.9,"votes": 21942,"running_times": 6420},{"title": "To the Wonder","year": 2012,"rating": 5.9,"votes": 23641,"running_times": 6720},{"title": "Tokarev","year": 2014,"rating": 5,"votes": 20189,"running_times": 5880},{"title": "Tokyo Goddofazazu","year": 2003,"rating": 7.9,"votes": 22743,"running_times": 5580},{"title": "Tom yum goong","year": 2005,"rating": 7.1,"votes": 31950,"running_times": 6660},{"title": "Tombstone","year": 1993,"rating": 7.8,"votes": 104882,"running_times": 8040},{"title": "Tomcats","year": 2001,"rating": 5.3,"votes": 16003,"running_times": 5700},{"title": "Tommy","year": 1975,"rating": 6.6,"votes": 16577,"running_times": 6660},{"title": "Tommy Boy","year": 1995,"rating": 7.1,"votes": 66806,"running_times": 5820},{"title": "Tomorrow Never Dies","year": 1997,"rating": 6.5,"votes": 159140,"running_times": 7140},{"title": "Tomorrow, When the War Began","year": 2010,"rating": 6.2,"votes": 28223,"running_times": 6180},{"title": "Tomorrowland","year": 2015,"rating": 6.5,"votes": 149378,"running_times": 7800},{"title": "Toni Erdmann","year": 2016,"rating": 7.5,"votes": 30830,"running_times": 9720},{"title": "Tooth Fairy","year": 2010,"rating": 5,"votes": 33791,"running_times": 6060},{"title": "Tootsie","year": 1982,"rating": 7.4,"votes": 83730,"running_times": 6960},{"title": "Top Five","year": 2014,"rating": 6.4,"votes": 23587,"running_times": 6120},{"title": "Top Gun","year": 1986,"rating": 6.9,"votes": 239755,"running_times": 6600},{"title": "Top Hat","year": 1935,"rating": 7.8,"votes": 14522,"running_times": 6060},{"title": "Top Secret!","year": 1984,"rating": 7.2,"votes": 50375,"running_times": 5400},{"title": "Topaz","year": 1969,"rating": 6.3,"votes": 13928,"running_times": 8580},{"title": "Topsy-Turvy","year": 1999,"rating": 7.4,"votes": 10533,"running_times": 9240},{"title": "Tora! Tora! Tora!","year": 1970,"rating": 7.5,"votes": 27158,"running_times": 8940},{"title": "Torn Curtain","year": 1966,"rating": 6.7,"votes": 20568,"running_times": 7680},{"title": "Torque","year": 2004,"rating": 4,"votes": 24817,"running_times": 5040},{"title": "Total Eclipse","year": 1995,"rating": 6.6,"votes": 11463,"running_times": 6660},{"title": "Total Recall","year": 1990,"rating": 7.5,"votes": 260008,"running_times": 6780},{"title": "Total Recall","year": 2012,"rating": 6.3,"votes": 216376,"running_times": 7800},{"title": "Touch of Evil","year": 1958,"rating": 8.1,"votes": 80814,"running_times": 6720},{"title": "Touching the Void","year": 2003,"rating": 8.1,"votes": 29255,"running_times": 6360},{"title": "Tower Heist","year": 2011,"rating": 6.2,"votes": 117332,"running_times": 6240},{"title": "Town Creek","year": 2009,"rating": 5.4,"votes": 10254,"running_times": 5400},{"title": "Toy Soldiers","year": 1991,"rating": 6.5,"votes": 17221,"running_times": 6660},{"title": "Toy Story","year": 1995,"rating": 8.3,"votes": 704806,"running_times": 4860},{"title": "Toy Story 2","year": 1999,"rating": 7.9,"votes": 425458,"running_times": 5520},{"title": "Toy Story 3","year": 2010,"rating": 8.3,"votes": 612021,"running_times": 6180},{"title": "Toys","year": 1992,"rating": 5,"votes": 27937,"running_times": 7320},{"title": "Tracers","year": 2015,"rating": 5.6,"votes": 15688,"running_times": 5640},{"title": "Tracks","year": 2013,"rating": 7.2,"votes": 22926,"running_times": 6720},{"title": "Trade","year": 2007,"rating": 7.4,"votes": 15564,"running_times": 7200},{"title": "Trading Places","year": 1983,"rating": 7.5,"votes": 113180,"running_times": 6960},{"title": "Traffic","year": 2000,"rating": 7.6,"votes": 178628,"running_times": 11400},{"title": "Trailer Park Boys: The Movie","year": 2006,"rating": 7.3,"votes": 10730,"running_times": 5700},{"title": "Training Day","year": 2001,"rating": 7.7,"votes": 332078,"running_times": 7320},{"title": "Trainspotting","year": 1996,"rating": 8.2,"votes": 538219,"running_times": 5640},{"title": "Trainwreck","year": 2015,"rating": 6.2,"votes": 111924,"running_times": 7740},{"title": "Traitor","year": 2008,"rating": 7,"votes": 51231,"running_times": 6840},{"title": "Trance","year": 2013,"rating": 6.9,"votes": 100012,"running_times": 6060},{"title": "Transamerica","year": 2005,"rating": 7.4,"votes": 37802,"running_times": 6180},{"title": "Transcendence","year": 2014,"rating": 6.3,"votes": 191749,"running_times": 7140},{"title": "Transformers","year": 2007,"rating": 7.1,"votes": 544522,"running_times": 8640},{"title": "Transformers: Age of Extinction","year": 2014,"rating": 5.7,"votes": 266571,"running_times": 9900},{"title": "Transformers: Dark of the Moon","year": 2011,"rating": 6.3,"votes": 348266,"running_times": 9240},{"title": "Transformers: Revenge of the Fallen","year": 2009,"rating": 6,"votes": 346287,"running_times": 9000},{"title": "Transformers: The Last Knight","year": 2017,"rating": 5.2,"votes": 83297,"running_times": 9300},{"title": "Transporter 2","year": 2005,"rating": 6.3,"votes": 169325,"running_times": 5220},{"title": "Transporter 3","year": 2008,"rating": 6.1,"votes": 137799,"running_times": 6240},{"title": "Transsiberian","year": 2008,"rating": 6.7,"votes": 45274,"running_times": 6660},{"title": "Trapped","year": 2002,"rating": 6.2,"votes": 20815,"running_times": 6360},{"title": "Trapped in Paradise","year": 1994,"rating": 5.9,"votes": 10743,"running_times": 6660},{"title": "Trash","year": 2014,"rating": 7.2,"votes": 17202,"running_times": 6840},{"title": "Treasure Planet","year": 2002,"rating": 7.1,"votes": 81221,"running_times": 5700},{"title": "Trees Lounge","year": 1996,"rating": 7.2,"votes": 12006,"running_times": 5700},{"title": "Tremors","year": 1990,"rating": 7.1,"votes": 99377,"running_times": 5760},{"title": "Trespass","year": 2011,"rating": 5.3,"votes": 37084,"running_times": 5460},{"title": "Triangle","year": 2009,"rating": 6.9,"votes": 78209,"running_times": 5940},{"title": "Trick 'r Treat","year": 2007,"rating": 6.8,"votes": 69181,"running_times": 4920},{"title": "Triple 9","year": 2016,"rating": 6.3,"votes": 52847,"running_times": 6900},{"title": "Tristan + Isolde","year": 2006,"rating": 6.8,"votes": 47170,"running_times": 7500},{"title": "Troll 2","year": 1990,"rating": 2.8,"votes": 26609,"running_times": 5700},{"title": "Trolljegeren","year": 2010,"rating": 7,"votes": 59467,"running_times": 6180},{"title": "Trolls","year": 2016,"rating": 6.5,"votes": 52257,"running_times": 5520},{"title": "Tron","year": 2010,"rating": 6.8,"votes": 280444,"running_times": 7500},{"title": "Tropic Thunder","year": 2008,"rating": 7,"votes": 330614,"running_times": 7260},{"title": "Trouble in Paradise","year": 1932,"rating": 8.2,"votes": 10603,"running_times": 4980},{"title": "Trouble with the Curve","year": 2012,"rating": 6.8,"votes": 52238,"running_times": 6660},{"title": "Troy","year": 2004,"rating": 7.2,"votes": 418856,"running_times": 11760},{"title": "True Crime","year": 1999,"rating": 6.6,"votes": 27548,"running_times": 7620},{"title": "True Grit","year": 1969,"rating": 7.4,"votes": 36110,"running_times": 7680},{"title": "True Grit","year": 2010,"rating": 7.6,"votes": 262595,"running_times": 6600},{"title": "True Lies","year": 1994,"rating": 7.2,"votes": 204843,"running_times": 8460},{"title": "True Romance","year": 1993,"rating": 7.9,"votes": 176419,"running_times": 7260},{"title": "True Story","year": 2015,"rating": 6.3,"votes": 45075,"running_times": 5940},{"title": "Trumbo","year": 2015,"rating": 7.5,"votes": 61971,"running_times": 7440},{"title": "Trust","year": 2010,"rating": 6.9,"votes": 37077,"running_times": 6360},{"title": "Truth","year": 2015,"rating": 6.8,"votes": 14963,"running_times": 7500},{"title": "Tsotsi","year": 2005,"rating": 7.3,"votes": 25959,"running_times": 5640},{"title": "Tuck Everlasting","year": 2002,"rating": 6.7,"votes": 19122,"running_times": 5760},{"title": "Tucker and Dale vs Evil","year": 2010,"rating": 7.6,"votes": 142633,"running_times": 5340},{"title": "Tucker: The Man and His Dream","year": 1988,"rating": 6.9,"votes": 12569,"running_times": 6600},{"title": "Turbo","year": 2013,"rating": 6.5,"votes": 68370,"running_times": 5760},{"title": "Turbo Kid","year": 2015,"rating": 6.7,"votes": 20823,"running_times": 5580},{"title": "Turist","year": 2014,"rating": 7.3,"votes": 35515,"running_times": 7200},{"title": "Turistas","year": 2006,"rating": 5.4,"votes": 32784,"running_times": 5760},{"title": "Turner & Hooch","year": 1989,"rating": 6.1,"votes": 53216,"running_times": 5820},{"title": "Tusk","year": 2014,"rating": 5.4,"votes": 36058,"running_times": 6120},{"title": "Twelve","year": 2010,"rating": 5.7,"votes": 11188,"running_times": 5700},{"title": "Twelve Monkeys","year": 1995,"rating": 8,"votes": 506089,"running_times": 7740},{"title": "Twelve O'Clock High","year": 1949,"rating": 7.8,"votes": 10789,"running_times": 7920},{"title": "Twenty Feet from Stardom","year": 2013,"rating": 7.4,"votes": 10501,"running_times": 5460},{"title": "Twilight","year": 2008,"rating": 5.2,"votes": 369363,"running_times": 7320},{"title": "Twilight Zone: The Movie","year": 1983,"rating": 6.5,"votes": 28051,"running_times": 6060},{"title": "Twin Peaks: Fire Walk with Me","year": 1992,"rating": 7.2,"votes": 68624,"running_times": 8100},{"title": "Twins","year": 1988,"rating": 6,"votes": 95388,"running_times": 6420},{"title": "Twisted","year": 2004,"rating": 5.2,"votes": 18116,"running_times": 5820},{"title": "Twister","year": 1996,"rating": 6.3,"votes": 153606,"running_times": 6780},{"title": "Two Lovers","year": 2008,"rating": 7.1,"votes": 31847,"running_times": 6600},{"title": "Two Mules for Sister Sara","year": 1970,"rating": 7,"votes": 19054,"running_times": 6960},{"title": "Two Night Stand","year": 2014,"rating": 6.4,"votes": 53970,"running_times": 5160},{"title": "Two Weeks Notice","year": 2002,"rating": 6.1,"votes": 92598,"running_times": 6060},{"title": "Two for the Money","year": 2005,"rating": 6.2,"votes": 38961,"running_times": 7320},{"title": "Tyrannosaur","year": 2011,"rating": 7.6,"votes": 26375,"running_times": 5520},{"title": "Tyson","year": 2008,"rating": 7.5,"votes": 11211,"running_times": 5400},{"title": "Tystnaden","year": 1963,"rating": 8,"votes": 13626,"running_times": 5760},{"title": "Tôkyô monogatari","year": 1953,"rating": 8.2,"votes": 33514,"running_times": 8160},{"title": "U Turn","year": 1997,"rating": 6.8,"votes": 44393,"running_times": 7500},{"title": "U-571","year": 2000,"rating": 6.6,"votes": 69146,"running_times": 6960},{"title": "U.S. Marshals","year": 1998,"rating": 6.5,"votes": 83366,"running_times": 7860},{"title": "UHF","year": 1989,"rating": 7,"votes": 22543,"running_times": 9000},{"title": "Udaan","year": 2010,"rating": 8.2,"votes": 35711,"running_times": 8040},{"title": "Ultimo tango a Parigi","year": 1972,"rating": 7.1,"votes": 40747,"running_times": 15000},{"title": "Ultraviolet","year": 2006,"rating": 4.4,"votes": 73834,"running_times": 5640},{"title": "Un monstre à Paris","year": 2011,"rating": 6.7,"votes": 17120,"running_times": 5400},{"title": "Unbreakable","year": 2000,"rating": 7.2,"votes": 284513,"running_times": 6360},{"title": "Unbroken","year": 2014,"rating": 7.2,"votes": 119486,"running_times": 8220},{"title": "Uncle Buck","year": 1989,"rating": 7,"votes": 69088,"running_times": 6000},{"title": "Undead","year": 2003,"rating": 5.5,"votes": 11859,"running_times": 6240},{"title": "Under Siege","year": 1992,"rating": 6.5,"votes": 66049,"running_times": 6180},{"title": "Under Siege 2: Dark Territory","year": 1995,"rating": 5.4,"votes": 38553,"running_times": 6000},{"title": "Under Suspicion","year": 2000,"rating": 6.5,"votes": 19443,"running_times": 6660},{"title": "Under sandet","year": 2015,"rating": 7.8,"votes": 19375,"running_times": 6000},{"title": "Under the Skin","year": 2013,"rating": 6.3,"votes": 100131,"running_times": 6480},{"title": "Under the Tuscan Sun","year": 2003,"rating": 6.8,"votes": 39571,"running_times": 6780},{"title": "Undercover Brother","year": 2002,"rating": 5.8,"votes": 30747,"running_times": 5280},{"title": "Underdog","year": 2007,"rating": 4.8,"votes": 16932,"running_times": 5040},{"title": "Underground","year": 1995,"rating": 8.1,"votes": 47977,"running_times": 19200},{"title": "Underworld","year": 2003,"rating": 7,"votes": 227288,"running_times": 7980},{"title": "Underworld Awakening","year": 2012,"rating": 6.4,"votes": 131014,"running_times": 5280},{"title": "Underworld: Blood Wars","year": 2016,"rating": 5.8,"votes": 52723,"running_times": 5460},{"title": "Underworld: Evolution","year": 2006,"rating": 6.7,"votes": 171177,"running_times": 6360},{"title": "Underworld: Rise of the Lycans","year": 2009,"rating": 6.6,"votes": 133868,"running_times": 5520},{"title": "Undisputed","year": 2002,"rating": 6.2,"votes": 24816,"running_times": 5760},{"title": "Unfaithful","year": 2002,"rating": 6.7,"votes": 68502,"running_times": 7500},{"title": "Unfinished Business","year": 2015,"rating": 5.4,"votes": 26311,"running_times": 5460},{"title": "Unforgiven","year": 1992,"rating": 8.2,"votes": 308492,"running_times": 7800},{"title": "Unfriended","year": 2014,"rating": 5.6,"votes": 54063,"running_times": 4980},{"title": "United 93","year": 2006,"rating": 7.6,"votes": 88351,"running_times": 6660},{"title": "Universal Soldier","year": 1992,"rating": 6,"votes": 73321,"running_times": 6120},{"title": "Universal Soldier: Day of Reckoning","year": 2012,"rating": 5,"votes": 17251,"running_times": 6840},{"title": "Universal Soldier: Regeneration","year": 2009,"rating": 5.2,"votes": 22922,"running_times": 5820},{"title": "Universal Soldier: The Return","year": 1999,"rating": 4.1,"votes": 25435,"running_times": 4980},{"title": "Unknown","year": 2006,"rating": 6.5,"votes": 27168,"running_times": 5100},{"title": "Unknown","year": 2011,"rating": 6.9,"votes": 223409,"running_times": 6780},{"title": "Unlawful Entry","year": 1992,"rating": 6.3,"votes": 12116,"running_times": 7020},{"title": "Unleashed","year": 2005,"rating": 7,"votes": 90174,"running_times": 6180},{"title": "Unlocked","year": 2017,"rating": 6.2,"votes": 12382,"running_times": 5880},{"title": "Unstoppable","year": 2010,"rating": 6.8,"votes": 162057,"running_times": 5880},{"title": "Untamed Heart","year": 1993,"rating": 6.8,"votes": 10899,"running_times": 6120},{"title": "Unthinkable","year": 2010,"rating": 7.1,"votes": 76928,"running_times": 5820},{"title": "Untraceable","year": 2008,"rating": 6.2,"votes": 43124,"running_times": 6060},{"title": "Up","year": 2009,"rating": 8.3,"votes": 754724,"running_times": 5760},{"title": "Up Close & Personal","year": 1996,"rating": 6.1,"votes": 12047,"running_times": 7440},{"title": "Up in Smoke","year": 1978,"rating": 7,"votes": 31136,"running_times": 5160},{"title": "Up in the Air","year": 2009,"rating": 7.4,"votes": 285417,"running_times": 6540},{"title": "Upside Down","year": 2012,"rating": 6.4,"votes": 63039,"running_times": 6540},{"title": "Upstream Color","year": 2013,"rating": 6.7,"votes": 26189,"running_times": 5760},{"title": "Uptown Girls","year": 2003,"rating": 6.1,"votes": 31104,"running_times": 5520},{"title": "Urban Cowboy","year": 1980,"rating": 6.2,"votes": 10991,"running_times": 7920},{"title": "Urban Legend","year": 1998,"rating": 5.5,"votes": 51232,"running_times": 5940},{"title": "Urban Legends: Final Cut","year": 2000,"rating": 4.2,"votes": 13917,"running_times": 5820},{"title": "Used Cars","year": 1980,"rating": 6.8,"votes": 11538,"running_times": 6780},{"title": "V for Vendetta","year": 2005,"rating": 8.2,"votes": 878025,"running_times": 7920},{"title": "V/H/S","year": 2012,"rating": 5.8,"votes": 49302,"running_times": 6960},{"title": "V/H/S Viral","year": 2014,"rating": 4.2,"votes": 12558,"running_times": 5880},{"title": "V/H/S/2","year": 2013,"rating": 6.1,"votes": 30647,"running_times": 5760},{"title": "Vacancy","year": 2007,"rating": 6.2,"votes": 84820,"running_times": 5100},{"title": "Vacation","year": 2015,"rating": 6.1,"votes": 78709,"running_times": 5940},{"title": "Valentine","year": 2001,"rating": 4.7,"votes": 21677,"running_times": 5760},{"title": "Valentine's Day","year": 2010,"rating": 5.7,"votes": 101218,"running_times": 7500},{"title": "Valerian and the City of a Thousand Planets","year": 2017,"rating": 6.6,"votes": 81807,"running_times": 8220},{"title": "Valhalla Rising","year": 2009,"rating": 6,"votes": 47989,"running_times": 5580},{"title": "Valiant","year": 2005,"rating": 5.6,"votes": 17433,"running_times": 4560},{"title": "Valkyrie","year": 2008,"rating": 7.1,"votes": 199643,"running_times": 7260},{"title": "Valley Girl","year": 1983,"rating": 6.4,"votes": 10847,"running_times": 5940},{"title": "Valmont","year": 1989,"rating": 7,"votes": 10895,"running_times": 8220},{"title": "Vals Im Bashir","year": 2008,"rating": 8,"votes": 49445,"running_times": 5400},{"title": "Vampire Academy","year": 2014,"rating": 5.6,"votes": 45777,"running_times": 6240},{"title": "Vampire Hunter D: Bloodlust","year": 2000,"rating": 7.7,"votes": 24820,"running_times": 6180},{"title": "Vampire in Brooklyn","year": 1995,"rating": 4.5,"votes": 18539,"running_times": 6000},{"title": "Vampire's Kiss","year": 1988,"rating": 5.9,"votes": 10620,"running_times": 6180},{"title": "Vampires","year": 1998,"rating": 6.1,"votes": 45850,"running_times": 6480},{"title": "Vampires Suck","year": 2010,"rating": 3.5,"votes": 41417,"running_times": 4920},{"title": "Van Helsing","year": 2004,"rating": 6.1,"votes": 213927,"running_times": 7860},{"title": "Van Wilder","year": 2002,"rating": 6.4,"votes": 93922,"running_times": 5640},{"title": "Van Wilder 2: The Rise of Taj","year": 2006,"rating": 4.8,"votes": 20342,"running_times": 5820},{"title": "Vanilla Sky","year": 2001,"rating": 6.9,"votes": 220421,"running_times": 8460},{"title": "Vanishing Point","year": 1971,"rating": 7.3,"votes": 23211,"running_times": 6360},{"title": "Vanishing on 7th Street","year": 2010,"rating": 4.9,"votes": 22968,"running_times": 5520},{"title": "Vanity Fair","year": 2004,"rating": 6.2,"votes": 18278,"running_times": 8460},{"title": "Vantage Point","year": 2008,"rating": 6.6,"votes": 133654,"running_times": 5400},{"title": "Varsity Blues","year": 1999,"rating": 6.4,"votes": 37306,"running_times": 6360},{"title": "Vegas Vacation","year": 1997,"rating": 5.9,"votes": 36659,"running_times": 5580},{"title": "Vehicle 19","year": 2013,"rating": 4.9,"votes": 13186,"running_times": 5100},{"title": "Velvet Goldmine","year": 1998,"rating": 7,"votes": 29482,"running_times": 7080},{"title": "Venus","year": 2006,"rating": 7.1,"votes": 11555,"running_times": 5700},{"title": "Venuto al mondo","year": 2012,"rating": 7.4,"votes": 13309,"running_times": 7620},{"title": "Vera Drake","year": 2004,"rating": 7.7,"votes": 21374,"running_times": 7500},{"title": "Veronica Guerin","year": 2003,"rating": 6.9,"votes": 17197,"running_times": 5880},{"title": "Veronica Mars","year": 2014,"rating": 6.8,"votes": 44371,"running_times": 6420},{"title": "Veronika Decides to Die","year": 2009,"rating": 6.5,"votes": 10862,"running_times": 6180},{"title": "Versus","year": 2000,"rating": 6.5,"votes": 11539,"running_times": 7140},{"title": "Vertical Limit","year": 2000,"rating": 5.9,"votes": 52544,"running_times": 7440},{"title": "Vertigo","year": 1958,"rating": 8.4,"votes": 282823,"running_times": 7740},{"title": "Very Bad Things","year": 1998,"rating": 6.3,"votes": 41265,"running_times": 6000},{"title": "Very Good Girls","year": 2013,"rating": 6,"votes": 12016,"running_times": 5460},{"title": "Vice","year": 2015,"rating": 4.2,"votes": 13323,"running_times": 5760},{"title": "Vicky Cristina Barcelona","year": 2008,"rating": 7.1,"votes": 214956,"running_times": 5760},{"title": "Victor Frankenstein","year": 2015,"rating": 6,"votes": 41566,"running_times": 6600},{"title": "Victor Victoria","year": 1982,"rating": 7.6,"votes": 16492,"running_times": 8040},{"title": "Victoria","year": 2015,"rating": 7.7,"votes": 37987,"running_times": 8280},{"title": "Victory","year": 1981,"rating": 6.6,"votes": 22838,"running_times": 6960},{"title": "Videodrome","year": 1983,"rating": 7.3,"votes": 67766,"running_times": 5340},{"title": "View from the Top","year": 2003,"rating": 5.2,"votes": 22568,"running_times": 5220},{"title": "Village of the Damned","year": 1960,"rating": 7.3,"votes": 12036,"running_times": 4620},{"title": "Village of the Damned","year": 1995,"rating": 5.6,"votes": 23863,"running_times": 5940},{"title": "Vincent","year": 1982,"rating": 8.4,"votes": 19267,"running_times": 360},{"title": "Violet & Daisy","year": 2011,"rating": 6.1,"votes": 10176,"running_times": 5280},{"title": "Viridiana","year": 1961,"rating": 8.2,"votes": 18029,"running_times": 5400},{"title": "Virtuosity","year": 1995,"rating": 5.6,"votes": 24921,"running_times": 6360},{"title": "Virus","year": 1999,"rating": 4.9,"votes": 23377,"running_times": 5940},{"title": "Vizontele Tuuba","year": 2003,"rating": 6.5,"votes": 10727,"running_times": 6660},{"title": "Volcano","year": 1997,"rating": 5.4,"votes": 63055,"running_times": 6240},{"title": "Von Ryan's Express","year": 1965,"rating": 7.1,"votes": 11050,"running_times": 7020},{"title": "W.","year": 2008,"rating": 6.3,"votes": 42728,"running_times": 7740},{"title": "W.E.","year": 2011,"rating": 6.3,"votes": 10607,"running_times": 7140},{"title": "WALL·E","year": 2008,"rating": 8.4,"votes": 812013,"running_times": 5880},{"title": "Waar","year": 2013,"rating": 8.2,"votes": 28439,"running_times": 7800},{"title": "Wag the Dog","year": 1997,"rating": 7.1,"votes": 71281,"running_times": 5820},{"title": "Wait Until Dark","year": 1967,"rating": 7.9,"votes": 22782,"running_times": 6480},{"title": "Waiting for 'Superman'","year": 2010,"rating": 7.5,"votes": 10027,"running_times": 6660},{"title": "Waiting for Forever","year": 2010,"rating": 6,"votes": 18719,"running_times": 5700},{"title": "Waiting for Guffman","year": 1996,"rating": 7.6,"votes": 23751,"running_times": 5040},{"title": "Waiting...","year": 2005,"rating": 6.8,"votes": 79927,"running_times": 5640},{"title": "Waitress","year": 2007,"rating": 7,"votes": 39505,"running_times": 6480},{"title": "Wake Up Sid","year": 2009,"rating": 7.6,"votes": 21957,"running_times": 8280},{"title": "Waking Life","year": 2001,"rating": 7.8,"votes": 53627,"running_times": 6060},{"title": "Waking Ned","year": 1998,"rating": 7.3,"votes": 22591,"running_times": 5520},{"title": "Walk Hard: The Dewey Cox Story","year": 2007,"rating": 6.8,"votes": 58599,"running_times": 7200},{"title": "Walk of Shame","year": 2014,"rating": 6,"votes": 44953,"running_times": 5700},{"title": "Walk the Line","year": 2005,"rating": 7.9,"votes": 200422,"running_times": 9180},{"title": "Walkabout","year": 1971,"rating": 7.7,"votes": 18963,"running_times": 6000},{"title": "Walking Tall","year": 2004,"rating": 6.2,"votes": 57700,"running_times": 5160},{"title": "Wall Street","year": 1987,"rating": 7.4,"votes": 127432,"running_times": 7560},{"title": "Wall Street: Money Never Sleeps","year": 2010,"rating": 6.2,"votes": 89241,"running_times": 8160},{"title": "Wanderlust","year": 2012,"rating": 5.6,"votes": 65787,"running_times": 5880},{"title": "Wanted","year": 2008,"rating": 6.7,"votes": 320677,"running_times": 6600},{"title": "War","year": 2007,"rating": 6.3,"votes": 77054,"running_times": 6180},{"title": "War Dogs","year": 2016,"rating": 7.1,"votes": 128613,"running_times": 6840},{"title": "War Horse","year": 2011,"rating": 7.2,"votes": 126737,"running_times": 8760},{"title": "War Machine","year": 2017,"rating": 6.1,"votes": 26077,"running_times": 7320},{"title": "War Room","year": 2015,"rating": 6.4,"votes": 10436,"running_times": 7200},{"title": "War for the Planet of the Apes","year": 2017,"rating": 7.5,"votes": 137537,"running_times": 8400},{"title": "War of the Worlds","year": 2005,"rating": 6.5,"votes": 361418,"running_times": 6960},{"title": "War on Everyone","year": 2016,"rating": 5.9,"votes": 12576,"running_times": 5880},{"title": "War, Inc.","year": 2008,"rating": 5.7,"votes": 20478,"running_times": 6420},{"title": "WarGames","year": 1983,"rating": 7.1,"votes": 77419,"running_times": 6840},{"title": "Warcraft","year": 2016,"rating": 6.9,"votes": 201525,"running_times": 7380},{"title": "Warlock","year": 1989,"rating": 6.2,"votes": 12599,"running_times": 6180},{"title": "Warm Bodies","year": 2013,"rating": 6.9,"votes": 198209,"running_times": 5880},{"title": "Warrior","year": 2011,"rating": 8.2,"votes": 369802,"running_times": 8400},{"title": "Watchmen","year": 2009,"rating": 7.6,"votes": 423383,"running_times": 12900},{"title": "Water for Elephants","year": 2011,"rating": 6.9,"votes": 100901,"running_times": 7200},{"title": "Watership Down","year": 1978,"rating": 7.7,"votes": 27768,"running_times": 5460},{"title": "Waterworld","year": 1995,"rating": 6.1,"votes": 155351,"running_times": 10560},{"title": "Wayne's World","year": 1992,"rating": 7,"votes": 123659,"running_times": 5640},{"title": "Wayne's World 2","year": 1993,"rating": 6.1,"votes": 67102,"running_times": 5700},{"title": "We Are Marshall","year": 2006,"rating": 7.1,"votes": 50569,"running_times": 7860},{"title": "We Are Still Here","year": 2015,"rating": 5.7,"votes": 13867,"running_times": 5040},{"title": "We Are What We Are","year": 2013,"rating": 5.9,"votes": 17047,"running_times": 6300},{"title": "We Are Your Friends","year": 2015,"rating": 6.2,"votes": 28314,"running_times": 5760},{"title": "We Bought a Zoo","year": 2011,"rating": 7.1,"votes": 119778,"running_times": 7440},{"title": "We Need to Talk About Kevin","year": 2011,"rating": 7.5,"votes": 110469,"running_times": 6720},{"title": "We Own the Night","year": 2007,"rating": 6.9,"votes": 76188,"running_times": 7020},{"title": "We Were Soldiers","year": 2002,"rating": 7.2,"votes": 112887,"running_times": 8580},{"title": "We're Back! A Dinosaur's Story","year": 1993,"rating": 6.1,"votes": 11500,"running_times": 4320},{"title": "We're No Angels","year": 1989,"rating": 6.1,"votes": 18713,"running_times": 6360},{"title": "We're the Millers","year": 2013,"rating": 7,"votes": 346039,"running_times": 7680},{"title": "Wedding Crashers","year": 2005,"rating": 7,"votes": 297708,"running_times": 7680},{"title": "Weekend","year": 2011,"rating": 7.7,"votes": 22804,"running_times": 5820},{"title": "Weekend at Bernie's","year": 1989,"rating": 6.4,"votes": 41289,"running_times": 5820},{"title": "Weekend at Bernie's II","year": 1993,"rating": 4.6,"votes": 11096,"running_times": 5820},{"title": "Weird Science","year": 1985,"rating": 6.6,"votes": 66176,"running_times": 5640},{"title": "Welcome Home, Roscoe Jenkins","year": 2008,"rating": 5.4,"votes": 11552,"running_times": 6840},{"title": "Welcome to Collinwood","year": 2002,"rating": 6.4,"votes": 13020,"running_times": 5160},{"title": "Welcome to Me","year": 2014,"rating": 5.9,"votes": 15623,"running_times": 5220},{"title": "Welcome to Mooseport","year": 2004,"rating": 5.2,"votes": 11146,"running_times": 7020},{"title": "Welcome to the Dollhouse","year": 1995,"rating": 7.4,"votes": 28328,"running_times": 5280},{"title": "Welcome to the Jungle","year": 2013,"rating": 5,"votes": 10638,"running_times": 5700},{"title": "Welcome to the Punch","year": 2013,"rating": 6.1,"votes": 29070,"running_times": 6000},{"title": "Welcome to the Rileys","year": 2010,"rating": 7,"votes": 21278,"running_times": 6600},{"title": "Wendy and Lucy","year": 2008,"rating": 7.1,"votes": 13530,"running_times": 4800},{"title": "West Side Story","year": 1961,"rating": 7.6,"votes": 79399,"running_times": 9180},{"title": "Westworld","year": 1973,"rating": 7,"votes": 41034,"running_times": 5280},{"title": "Wet Hot American Summer","year": 2001,"rating": 6.7,"votes": 45977,"running_times": 5820},{"title": "Whale Rider","year": 2002,"rating": 7.6,"votes": 36011,"running_times": 6060},{"title": "What About Bob?","year": 1991,"rating": 7,"votes": 54257,"running_times": 5940},{"title": "What Doesn't Kill You","year": 2008,"rating": 6.6,"votes": 10317,"running_times": 6000},{"title": "What Dreams May Come","year": 1998,"rating": 7,"votes": 89534,"running_times": 6780},{"title": "What Ever Happened to Baby Jane?","year": 1962,"rating": 8.1,"votes": 40325,"running_times": 8100},{"title": "What Happens in Vegas","year": 2008,"rating": 6.1,"votes": 150102,"running_times": 6060},{"title": "What Just Happened","year": 2008,"rating": 5.7,"votes": 24650,"running_times": 6240},{"title": "What Lies Beneath","year": 2000,"rating": 6.6,"votes": 104333,"running_times": 7800},{"title": "What Maisie Knew","year": 2012,"rating": 7.5,"votes": 23733,"running_times": 5940},{"title": "What We Did on Our Holiday","year": 2014,"rating": 6.9,"votes": 14692,"running_times": 5700},{"title": "What We Do in the Shadows","year": 2014,"rating": 7.6,"votes": 97317,"running_times": 5160},{"title": "What Women Want","year": 2000,"rating": 6.4,"votes": 170689,"running_times": 7620},{"title": "What a Girl Wants","year": 2003,"rating": 5.8,"votes": 51761,"running_times": 6300},{"title": "What the #$*! Do We (K)now!?","year": 2004,"rating": 5.3,"votes": 12450,"running_times": 6780},{"title": "What the Health","year": 2017,"rating": 8,"votes": 18833,"running_times": 5820},{"title": "What to Expect When You're Expecting","year": 2012,"rating": 5.7,"votes": 61745,"running_times": 6600},{"title": "What's Eating Gilbert Grape","year": 1993,"rating": 7.8,"votes": 185200,"running_times": 7080},{"title": "What's Love Got to Do with It","year": 1993,"rating": 7.2,"votes": 14393,"running_times": 7080},{"title": "What's Up, Doc?","year": 1972,"rating": 7.8,"votes": 15727,"running_times": 5640},{"title": "What's Your Number?","year": 2011,"rating": 6.1,"votes": 64002,"running_times": 7020},{"title": "What's the Worst That Could Happen?","year": 2001,"rating": 5.5,"votes": 13371,"running_times": 5640},{"title": "Whatever Works","year": 2009,"rating": 7.2,"votes": 63720,"running_times": 5580},{"title": "When Harry Met Sally...","year": 1989,"rating": 7.6,"votes": 163450,"running_times": 5760},{"title": "When We Were Kings","year": 1996,"rating": 8,"votes": 13204,"running_times": 5280},{"title": "When a Man Loves a Woman","year": 1994,"rating": 6.5,"votes": 17885,"running_times": 7560},{"title": "When a Stranger Calls","year": 2006,"rating": 5.1,"votes": 37689,"running_times": 5220},{"title": "When in Rome","year": 2010,"rating": 5.6,"votes": 54300,"running_times": 5460},{"title": "When the Game Stands Tall","year": 2014,"rating": 6.7,"votes": 13756,"running_times": 6900},{"title": "Where Eagles Dare","year": 1968,"rating": 7.7,"votes": 43900,"running_times": 9480},{"title": "Where the Buffalo Roam","year": 1980,"rating": 6.7,"votes": 10050,"running_times": 5760},{"title": "Where the Heart Is","year": 2000,"rating": 6.8,"votes": 28717,"running_times": 7200},{"title": "Where the Truth Lies","year": 2005,"rating": 6.5,"votes": 15715,"running_times": 6420},{"title": "Where the Wild Things Are","year": 2009,"rating": 6.8,"votes": 92375,"running_times": 6060},{"title": "Where to Invade Next","year": 2015,"rating": 7.6,"votes": 17948,"running_times": 7200},{"title": "While We're Young","year": 2014,"rating": 6.3,"votes": 36693,"running_times": 5820},{"title": "While You Were Sleeping","year": 1995,"rating": 6.7,"votes": 77975,"running_times": 6180},{"title": "Whip It","year": 2009,"rating": 6.9,"votes": 58495,"running_times": 6660},{"title": "Whiplash","year": 2014,"rating": 8.5,"votes": 517001,"running_times": 6420},{"title": "Whiskey Tango Foxtrot","year": 2016,"rating": 6.6,"votes": 40192,"running_times": 6720},{"title": "White Bird in a Blizzard","year": 2014,"rating": 6.4,"votes": 23569,"running_times": 5460},{"title": "White Chicks","year": 2004,"rating": 5.5,"votes": 108969,"running_times": 6900},{"title": "White Christmas","year": 1954,"rating": 7.6,"votes": 24345,"running_times": 7200},{"title": "White Fang","year": 1991,"rating": 6.7,"votes": 16867,"running_times": 6420},{"title": "White Heat","year": 1949,"rating": 8.2,"votes": 22555,"running_times": 6840},{"title": "White House Down","year": 2013,"rating": 6.4,"votes": 178695,"running_times": 7860},{"title": "White Men Can't Jump","year": 1992,"rating": 6.7,"votes": 63633,"running_times": 7080},{"title": "White Noise","year": 2005,"rating": 5.5,"votes": 43784,"running_times": 6060},{"title": "White Noise 2: The Light","year": 2007,"rating": 5.7,"votes": 11785,"running_times": 5940},{"title": "White Oleander","year": 2002,"rating": 7.2,"votes": 26933,"running_times": 6540},{"title": "White Squall","year": 1996,"rating": 6.6,"votes": 19008,"running_times": 7740},{"title": "Whiteout","year": 2009,"rating": 5.5,"votes": 33828,"running_times": 6060},{"title": "Who Am I - Kein System ist sicher","year": 2014,"rating": 7.6,"votes": 33183,"running_times": 6120},{"title": "Who Framed Roger Rabbit","year": 1988,"rating": 7.7,"votes": 155219,"running_times": 6240},{"title": "Who Killed the Electric Car?","year": 2006,"rating": 7.7,"votes": 11606,"running_times": 5520},{"title": "Who's Afraid of Virginia Woolf?","year": 1966,"rating": 8.1,"votes": 60336,"running_times": 7860},{"title": "Who's Harry Crumb?","year": 1989,"rating": 5.8,"votes": 13504,"running_times": 5640},{"title": "Who's Your Caddy?","year": 2007,"rating": 2.1,"votes": 14081,"running_times": 5580},{"title": "Why Did I Get Married?","year": 2007,"rating": 5.7,"votes": 10391,"running_times": 6780},{"title": "Why Him?","year": 2016,"rating": 6.2,"votes": 71669,"running_times": 6660},{"title": "Wicker Park","year": 2004,"rating": 7,"votes": 47786,"running_times": 6840},{"title": "Wild","year": 2014,"rating": 7.1,"votes": 100424,"running_times": 6900},{"title": "Wild Bill","year": 2011,"rating": 7.2,"votes": 10888,"running_times": 5880},{"title": "Wild Card","year": 2015,"rating": 5.6,"votes": 42106,"running_times": 6120},{"title": "Wild Child","year": 2008,"rating": 6.1,"votes": 40936,"running_times": 7440},{"title": "Wild Hogs","year": 2007,"rating": 5.9,"votes": 104851,"running_times": 6000},{"title": "Wild Target","year": 2010,"rating": 6.9,"votes": 32102,"running_times": 5880},{"title": "Wild Things","year": 1998,"rating": 6.5,"votes": 96058,"running_times": 6900},{"title": "Wild Wild West","year": 1999,"rating": 4.8,"votes": 137656,"running_times": 6360},{"title": "Wild at Heart","year": 1990,"rating": 7.2,"votes": 68263,"running_times": 7500},{"title": "Wildcats","year": 1986,"rating": 5.9,"votes": 10337,"running_times": 6360},{"title": "Wilde","year": 1997,"rating": 6.9,"votes": 13098,"running_times": 7080},{"title": "Willard","year": 2003,"rating": 6.2,"votes": 15937,"running_times": 6000},{"title": "Willow","year": 1988,"rating": 7.3,"votes": 86915,"running_times": 7560},{"title": "Willy Wonka & the Chocolate Factory","year": 1971,"rating": 7.8,"votes": 144970,"running_times": 6000},{"title": "Wimbledon","year": 2004,"rating": 6.3,"votes": 54516,"running_times": 5880},{"title": "Win Win","year": 2011,"rating": 7.2,"votes": 50308,"running_times": 6360},{"title": "Win a Date with Tad Hamilton!","year": 2004,"rating": 5.6,"votes": 24089,"running_times": 5700},{"title": "Winchester '73","year": 1950,"rating": 7.7,"votes": 13765,"running_times": 5520},{"title": "Wind Chill","year": 2007,"rating": 5.9,"votes": 19074,"running_times": 5460},{"title": "Wind River","year": 2017,"rating": 7.8,"votes": 74682,"running_times": 6420},{"title": "Windtalkers","year": 2002,"rating": 6,"votes": 59346,"running_times": 9180},{"title": "Wing Commander","year": 1999,"rating": 4.2,"votes": 15194,"running_times": 6000},{"title": "Winnie the Pooh","year": 2011,"rating": 7.2,"votes": 17196,"running_times": 3780},{"title": "Winter's Bone","year": 2010,"rating": 7.2,"votes": 119512,"running_times": 6000},{"title": "Winter's Tale","year": 2014,"rating": 6.2,"votes": 45570,"running_times": 7080},{"title": "Wish I Was Here","year": 2014,"rating": 6.7,"votes": 32549,"running_times": 6360},{"title": "Wishmaster","year": 1997,"rating": 5.8,"votes": 16578,"running_times": 5400},{"title": "With Honors","year": 1994,"rating": 6.7,"votes": 11663,"running_times": 6180},{"title": "Withnail & I","year": 1987,"rating": 7.8,"votes": 33730,"running_times": 6420},{"title": "Without a Paddle","year": 2004,"rating": 5.9,"votes": 39444,"running_times": 5700},{"title": "Witness","year": 1985,"rating": 7.4,"votes": 72313,"running_times": 6720},{"title": "Witness for the Prosecution","year": 1957,"rating": 8.4,"votes": 75714,"running_times": 6960},{"title": "Wolf","year": 1994,"rating": 6.2,"votes": 46491,"running_times": 7500},{"title": "Wolf Creek","year": 2005,"rating": 6.3,"votes": 59931,"running_times": 6240},{"title": "Wolf Creek 2","year": 2013,"rating": 6.1,"votes": 14313,"running_times": 6360},{"title": "Woman in Gold","year": 2015,"rating": 7.3,"votes": 43004,"running_times": 6540},{"title": "Womb","year": 2010,"rating": 6.4,"votes": 11453,"running_times": 6660},{"title": "Wonder","year": 2017,"rating": 8.1,"votes": 13471,"running_times": 6780},{"title": "Wonder Boys","year": 2000,"rating": 7.4,"votes": 56829,"running_times": 6420},{"title": "Wonder Woman","year": 2017,"rating": 7.6,"votes": 343600,"running_times": 8460},{"title": "Wonderland","year": 2003,"rating": 6.6,"votes": 19519,"running_times": 6240},{"title": "Wong Fei Hung","year": 1991,"rating": 7.4,"votes": 14953,"running_times": 8040},{"title": "Woodstock","year": 1970,"rating": 8.1,"votes": 13696,"running_times": 21360},{"title": "Working Girl","year": 1988,"rating": 6.7,"votes": 44715,"running_times": 6780},{"title": "World Trade Center","year": 2006,"rating": 6,"votes": 71119,"running_times": 7740},{"title": "World War Z","year": 2013,"rating": 7,"votes": 513324,"running_times": 7380},{"title": "World's Greatest Dad","year": 2009,"rating": 6.9,"votes": 33881,"running_times": 5940},{"title": "Would You Rather","year": 2012,"rating": 5.8,"votes": 28237,"running_times": 5580},{"title": "Wrath of the Titans","year": 2012,"rating": 5.8,"votes": 163085,"running_times": 5940},{"title": "Wreck-It Ralph","year": 2012,"rating": 7.7,"votes": 302045,"running_times": 6060},{"title": "Wrecked","year": 2010,"rating": 5.3,"votes": 13726,"running_times": 5460},{"title": "Wristcutters: A Love Story","year": 2006,"rating": 7.3,"votes": 48932,"running_times": 5280},{"title": "Wrong Turn","year": 2003,"rating": 6.1,"votes": 94754,"running_times": 5040},{"title": "Wrong Turn 4: Bloody Beginnings","year": 2011,"rating": 4.6,"votes": 18867,"running_times": 5640},{"title": "Wrongfully Accused","year": 1998,"rating": 6.1,"votes": 19976,"running_times": 5220},{"title": "Wuthering Heights","year": 1939,"rating": 7.7,"votes": 13761,"running_times": 6240},{"title": "Wuthering Heights","year": 1992,"rating": 6.9,"votes": 10432,"running_times": 6300},{"title": "Wyatt Earp","year": 1994,"rating": 6.7,"votes": 38522,"running_times": 12720},{"title": "Wyrmwood","year": 2014,"rating": 6.3,"votes": 13514,"running_times": 5880},{"title": "X+Y","year": 2014,"rating": 7.2,"votes": 23033,"running_times": 6660},{"title": "X-Men","year": 2000,"rating": 7.4,"votes": 498117,"running_times": 6240},{"title": "X-Men Origins: Wolverine","year": 2009,"rating": 6.7,"votes": 402237,"running_times": 7140},{"title": "X-Men: Apocalypse","year": 2016,"rating": 7,"votes": 304132,"running_times": 8640},{"title": "X-Men: Days of Future Past","year": 2014,"rating": 8,"votes": 572280,"running_times": 9060},{"title": "X-Men: The Last Stand","year": 2006,"rating": 6.7,"votes": 419674,"running_times": 6240},{"title": "X2","year": 2003,"rating": 7.5,"votes": 445905,"running_times": 8040},{"title": "X: First Class","year": 2011,"rating": 7.8,"votes": 566878,"running_times": 7860},{"title": "Xi yan","year": 1993,"rating": 7.7,"votes": 11724,"running_times": 6360},{"title": "Yahsi Bati","year": 2009,"rating": 7.3,"votes": 20851,"running_times": 6720},{"title": "Yankee Doodle Dandy","year": 1942,"rating": 7.8,"votes": 11975,"running_times": 7560},{"title": "Yat goh ho yan","year": 1997,"rating": 6.2,"votes": 21626,"running_times": 5820},{"title": "Year One","year": 2009,"rating": 4.9,"votes": 80852,"running_times": 6000},{"title": "Year of the Dragon","year": 1985,"rating": 6.9,"votes": 11575,"running_times": 8040},{"title": "Yeh Jawaani Hai Deewani","year": 2013,"rating": 7,"votes": 30273,"running_times": 10560},{"title": "Yellow Submarine","year": 1968,"rating": 7.4,"votes": 20412,"running_times": 5400},{"title": "Yentl","year": 1983,"rating": 6.6,"votes": 10319,"running_times": 7980},{"title": "Yeopgijeogin geunyeo","year": 2001,"rating": 8.1,"votes": 39868,"running_times": 8220},{"title": "Yes Boss","year": 1997,"rating": 6.9,"votes": 10757,"running_times": 9780},{"title": "Yes Man","year": 2008,"rating": 6.8,"votes": 291926,"running_times": 6240},{"title": "Yi yi","year": 2000,"rating": 8.1,"votes": 14903,"running_times": 10380},{"title": "Ying hung boon sik","year": 1986,"rating": 7.6,"votes": 17056,"running_times": 5700},{"title": "Yip Man 2","year": 2010,"rating": 7.6,"votes": 79871,"running_times": 6480},{"title": "Yip Man 3","year": 2015,"rating": 7.1,"votes": 32614,"running_times": 6300},{"title": "Yogi Bear","year": 2010,"rating": 4.6,"votes": 17693,"running_times": 4800},{"title": "You Again","year": 2010,"rating": 5.8,"votes": 43923,"running_times": 6300},{"title": "You Can Count on Me","year": 2000,"rating": 7.7,"votes": 24603,"running_times": 6660},{"title": "You Can't Take It with You","year": 1938,"rating": 8,"votes": 19430,"running_times": 7560},{"title": "You Don't Mess with the Zohan","year": 2008,"rating": 5.5,"votes": 167599,"running_times": 6780},{"title": "You Got Served","year": 2004,"rating": 3.5,"votes": 24231,"running_times": 5700},{"title": "You Kill Me","year": 2007,"rating": 6.5,"votes": 16698,"running_times": 5580},{"title": "You Only Live Twice","year": 1967,"rating": 6.9,"votes": 81773,"running_times": 7020},{"title": "You Will Meet a Tall Dark Stranger","year": 2010,"rating": 6.3,"votes": 39424,"running_times": 5880},{"title": "You're Next","year": 2011,"rating": 6.5,"votes": 71913,"running_times": 5700},{"title": "You're Not You","year": 2014,"rating": 7.4,"votes": 19583,"running_times": 6120},{"title": "You've Got Mail","year": 1998,"rating": 6.6,"votes": 165458,"running_times": 7140},{"title": "You, Me and Dupree","year": 2006,"rating": 5.6,"votes": 71919,"running_times": 6600},{"title": "Young Adam","year": 2003,"rating": 6.5,"votes": 12131,"running_times": 5880},{"title": "Young Adult","year": 2011,"rating": 6.3,"votes": 68568,"running_times": 5640},{"title": "Young Frankenstein","year": 1974,"rating": 8,"votes": 125087,"running_times": 6360},{"title": "Young Guns","year": 1988,"rating": 6.8,"votes": 46301,"running_times": 6420},{"title": "Young Guns II","year": 1990,"rating": 6.5,"votes": 26020,"running_times": 6240},{"title": "Young People Fucking","year": 2007,"rating": 6.3,"votes": 18254,"running_times": 5400},{"title": "Young Sherlock Holmes","year": 1985,"rating": 6.8,"votes": 16098,"running_times": 6540},{"title": "Youngblood","year": 1986,"rating": 6.1,"votes": 10495,"running_times": 6600},{"title": "Your Highness","year": 2011,"rating": 5.5,"votes": 89650,"running_times": 6120},{"title": "Your Sister's Sister","year": 2011,"rating": 6.7,"votes": 23443,"running_times": 5400},{"title": "Yours, Mine & Ours","year": 2005,"rating": 5.4,"votes": 23439,"running_times": 5280},{"title": "Youth","year": 2015,"rating": 7.3,"votes": 56877,"running_times": 7440},{"title": "Youth Without Youth","year": 2007,"rating": 6.3,"votes": 11953,"running_times": 7440},{"title": "Youth in Revolt","year": 2009,"rating": 6.5,"votes": 68119,"running_times": 5400},{"title": "Yume","year": 1990,"rating": 7.8,"votes": 19868,"running_times": 7140},{"title": "Z","year": 1969,"rating": 8.2,"votes": 19513,"running_times": 7620},{"title": "Z for Zachariah","year": 2015,"rating": 6,"votes": 22333,"running_times": 5880},{"title": "Zabriskie Point","year": 1970,"rating": 7.1,"votes": 12201,"running_times": 6780},{"title": "Zack and Miri Make a Porno","year": 2008,"rating": 6.6,"votes": 157803,"running_times": 6060},{"title": "Zardoz","year": 1974,"rating": 5.8,"votes": 16295,"running_times": 6300},{"title": "Zathura: A Space Adventure","year": 2005,"rating": 6.1,"votes": 75323,"running_times": 6060},{"title": "Zeitgeist: Moving Forward","year": 2011,"rating": 8.2,"votes": 16308,"running_times": 9660},{"title": "Zelig","year": 1983,"rating": 7.8,"votes": 34767,"running_times": 4740},{"title": "Zero Dark Thirty","year": 2012,"rating": 7.4,"votes": 233700,"running_times": 9420},{"title": "Zero Effect","year": 1998,"rating": 7,"votes": 12886,"running_times": 6960},{"title": "Zindagi Na Milegi Dobara","year": 2011,"rating": 8.1,"votes": 51369,"running_times": 9300},{"title": "Zivot je cudo","year": 2004,"rating": 7.7,"votes": 10794,"running_times": 9300},{"title": "Zodiac","year": 2007,"rating": 7.7,"votes": 349834,"running_times": 9720},{"title": "Zombeavers","year": 2014,"rating": 4.8,"votes": 13180,"running_times": 4620},{"title": "Zombi 2","year": 1979,"rating": 6.9,"votes": 21569,"running_times": 5640},{"title": "Zombie Strippers","year": 2008,"rating": 4.1,"votes": 16387,"running_times": 5640},{"title": "Zombieland","year": 2009,"rating": 7.7,"votes": 423925,"running_times": 5280},{"title": "Zookeeper","year": 2011,"rating": 5.2,"votes": 48679,"running_times": 6120},{"title": "Zoolander","year": 2001,"rating": 6.6,"votes": 217408,"running_times": 5400},{"title": "Zoolander 2","year": 2016,"rating": 4.7,"votes": 52589,"running_times": 6480},{"title": "Zoom","year": 2006,"rating": 4.3,"votes": 16260,"running_times": 5580},{"title": "Zootopia","year": 2016,"rating": 8,"votes": 326111,"running_times": 6480},{"title": "Zulu","year": 1964,"rating": 7.8,"votes": 31229,"running_times": 8280},{"title": "Zulu","year": 2013,"rating": 6.7,"votes": 15316,"running_times": 6600},{"title": "Zwartboek","year": 2006,"rating": 7.8,"votes": 64568,"running_times": 8700},{"title": "eXistenZ","year": 1999,"rating": 6.8,"votes": 82881,"running_times": 6900},{"title": "iBoy","year": 2017,"rating": 6,"votes": 12217,"running_times": 5400},{"title": "xXx","year": 2002,"rating": 5.8,"votes": 157358,"running_times": 7920},{"title": "xXx: Return of Xander Cage","year": 2017,"rating": 5.2,"votes": 63918,"running_times": 6420},{"title": "xXx: State of the Union","year": 2005,"rating": 4.4,"votes": 59449,"running_times": 6060},{"title": "¡Three Amigos!","year": 1986,"rating": 6.4,"votes": 58003,"running_times": 6240},{"title": "À bout de souffle","year": 1960,"rating": 7.9,"votes": 58379,"running_times": 5400},{"title": "Æon Flux","year": 2005,"rating": 5.5,"votes": 115131,"running_times": 5580}] \ No newline at end of file diff --git a/courses/frontend/advanced-javascript/week-1/Working with movies/script.js b/courses/frontend/advanced-javascript/week-1/Working with movies/script.js new file mode 100644 index 000000000..2d9c733c2 --- /dev/null +++ b/courses/frontend/advanced-javascript/week-1/Working with movies/script.js @@ -0,0 +1,212 @@ +const container = document.getElementById("movies-container") + +////////////////////////////////////////////////////// +// RENDER MOVIES +////////////////////////////////////////////////////// + +function renderMovies(arr){ + +container.innerHTML="" + +arr.forEach(movie=>{ + +const card=document.createElement("div") + +card.classList.add("movie-card") + +card.innerHTML=` +

        ${movie.title}

        +

        Year: ${movie.year}

        +

        Rating: ${movie.rating}

        +${movie.tag ? `

        Tag: ${movie.tag}

        ` : ""} +` + +container.appendChild(card) + +}) + +} + +function renderText(text){ + +container.innerHTML=`

        ${text}

        ` + +} + +////////////////////////////////////////////////////// +// SHORT TITLES +////////////////////////////////////////////////////// + +function showShortTitles(){ + +const shortMovies = movies.filter(movie => +movie.title.length <= 10 +) + +renderMovies(shortMovies) + +} + +////////////////////////////////////////////////////// +// LONG TITLES +////////////////////////////////////////////////////// + +function showLongTitles(){ + +const longTitles = movies.filter(movie => +movie.title.length > 20 +) + +renderMovies(longTitles) + +} + +////////////////////////////////////////////////////// +// MOVIES 1980-1989 +////////////////////////////////////////////////////// + +function count80sMovies(){ + +const count = movies.filter(movie => +movie.year >= 1980 && movie.year <= 1989 +).length + +renderText(`Movies from 1980-1989: ${count}`) + +} + +////////////////////////////////////////////////////// +// TAG MOVIES +////////////////////////////////////////////////////// + +function showTaggedMovies(){ + +const tagged = movies.map(movie=>{ + +let tag + +if(movie.rating >=7){ +tag="Good" +} +else if(movie.rating >=4){ +tag="Average" +} +else{ +tag="Bad" +} + +return {...movie, tag} + +}) + +renderMovies(tagged) + +} + + +// RATING ABOVE 6 + + +function showRatingsAbove6(){ + +const result = movies +.filter(movie => movie.rating > 6) +.map(movie => ({ +title: movie.title, +year: movie.year, +rating: movie.rating +})) + +renderMovies(result) + +} + + +// KEYWORD COUNT + + +function countKeywords(){ + +const keywords=["surfer","alien","benjamin"] + +const count = movies.reduce((total,movie)=>{ + +const title = movie.title.toLowerCase() + +keywords.forEach(word=>{ +if(title.includes(word)){ +total++ +} +}) + +return total + +},0) + +renderText(`Keyword matches: ${count}`) + +} + + +// DUPLICATE WORDS + + +function duplicatedWords(){ + +const result = movies.filter(movie=>{ + +const words = movie.title +.toLowerCase() +.split(" ") + +return new Set(words).size !== words.length + +}) + +renderMovies(result) + +} + +////////////////////////////////////////////////////// +// AVERAGE RATING +////////////////////////////////////////////////////// + +function averageRating(){ + +const avg = movies.reduce((sum,movie)=> +sum + movie.rating +,0) / movies.length + +renderText(`Average rating: ${avg.toFixed(2)}`) + +} + +////////////////////////////////////////////////////// +// COUNT GOOD/AVERAGE/BAD +////////////////////////////////////////////////////// + +function countRatings(){ + +const result = movies.reduce((acc,movie)=>{ + +if(movie.rating >=7){ +acc.goodMovies++ +} +else if(movie.rating >=4){ +acc.averageMovies++ +} +else{ +acc.badMovies++ +} + +return acc + +},{ +goodMovies:0, +averageMovies:0, +badMovies:0 +}) + +renderText(JSON.stringify(result,null,2)) + +} \ No newline at end of file diff --git a/courses/frontend/advanced-javascript/week-1/Working with movies/style.css b/courses/frontend/advanced-javascript/week-1/Working with movies/style.css new file mode 100644 index 000000000..ff2a4b150 --- /dev/null +++ b/courses/frontend/advanced-javascript/week-1/Working with movies/style.css @@ -0,0 +1,49 @@ +body{ +font-family:Arial; +background:#f5f5f5; +padding:20px; +} + +h1{ +text-align:center; +} + +.buttons{ +text-align:center; +margin-bottom:20px; +} + +button{ +padding:10px 15px; +margin:5px; +border:none; +background:#222; +color:white; +cursor:pointer; +border-radius:5px; +} + +button:hover{ +background:#555; +} + +.movies-container{ +display:grid; +grid-template-columns:repeat(auto-fill,minmax(200px,1fr)); +gap:20px; +} + +.movie-card{ +background:white; +padding:15px; +border-radius:10px; +box-shadow:0 3px 10px rgba(0,0,0,0.2); +} + +.movie-card h3{ +margin:0 0 10px 0; +} + +.movie-card p{ +margin:3px 0; +} \ No newline at end of file From de42aea0e63770c356776a8b57c5dc135bc41348 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Thu, 12 Mar 2026 10:30:52 +0100 Subject: [PATCH 60/62] Clean up code --- .../week-1/Working with movies/index.html | 4 ++-- .../week-1/Working with movies/script.js | 19 +++---------------- .../week-1/Working with movies/style.css | 8 ++++---- 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/courses/frontend/advanced-javascript/week-1/Working with movies/index.html b/courses/frontend/advanced-javascript/week-1/Working with movies/index.html index 71c7d9730..c5d4bf9a0 100644 --- a/courses/frontend/advanced-javascript/week-1/Working with movies/index.html +++ b/courses/frontend/advanced-javascript/week-1/Working with movies/index.html @@ -13,7 +13,7 @@

        Movie Dashboard

        - + @@ -21,7 +21,7 @@

        Movie Dashboard

        -
        +
        diff --git a/courses/frontend/advanced-javascript/week-1/Working with movies/script.js b/courses/frontend/advanced-javascript/week-1/Working with movies/script.js index 2d9c733c2..4aab7e96a 100644 --- a/courses/frontend/advanced-javascript/week-1/Working with movies/script.js +++ b/courses/frontend/advanced-javascript/week-1/Working with movies/script.js @@ -1,8 +1,6 @@ -const container = document.getElementById("movies-container") +const container = document.getElementById("moviesContainer") -////////////////////////////////////////////////////// // RENDER MOVIES -////////////////////////////////////////////////////// function renderMovies(arr){ @@ -12,7 +10,7 @@ arr.forEach(movie=>{ const card=document.createElement("div") -card.classList.add("movie-card") +card.classList.add("movieCard") card.innerHTML=`

        ${movie.title}

        @@ -33,9 +31,7 @@ container.innerHTML=`

        ${text}

        ` } -////////////////////////////////////////////////////// // SHORT TITLES -////////////////////////////////////////////////////// function showShortTitles(){ @@ -47,9 +43,7 @@ renderMovies(shortMovies) } -////////////////////////////////////////////////////// // LONG TITLES -////////////////////////////////////////////////////// function showLongTitles(){ @@ -61,9 +55,7 @@ renderMovies(longTitles) } -////////////////////////////////////////////////////// // MOVIES 1980-1989 -////////////////////////////////////////////////////// function count80sMovies(){ @@ -75,9 +67,7 @@ renderText(`Movies from 1980-1989: ${count}`) } -////////////////////////////////////////////////////// // TAG MOVIES -////////////////////////////////////////////////////// function showTaggedMovies(){ @@ -167,9 +157,7 @@ renderMovies(result) } -////////////////////////////////////////////////////// // AVERAGE RATING -////////////////////////////////////////////////////// function averageRating(){ @@ -181,9 +169,8 @@ renderText(`Average rating: ${avg.toFixed(2)}`) } -////////////////////////////////////////////////////// + // COUNT GOOD/AVERAGE/BAD -////////////////////////////////////////////////////// function countRatings(){ diff --git a/courses/frontend/advanced-javascript/week-1/Working with movies/style.css b/courses/frontend/advanced-javascript/week-1/Working with movies/style.css index ff2a4b150..9c177ecc7 100644 --- a/courses/frontend/advanced-javascript/week-1/Working with movies/style.css +++ b/courses/frontend/advanced-javascript/week-1/Working with movies/style.css @@ -27,23 +27,23 @@ button:hover{ background:#555; } -.movies-container{ +.moviesContainer{ display:grid; grid-template-columns:repeat(auto-fill,minmax(200px,1fr)); gap:20px; } -.movie-card{ +.movieCard{ background:white; padding:15px; border-radius:10px; box-shadow:0 3px 10px rgba(0,0,0,0.2); } -.movie-card h3{ +.movieCard h3{ margin:0 0 10px 0; } -.movie-card p{ +.movieCard p{ margin:3px 0; } \ No newline at end of file From 64b22cbdbede98e67f879030a62ab7427af1deb8 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Thu, 19 Mar 2026 11:13:27 +0100 Subject: [PATCH 61/62] Add Week-2 assignment --- .../week-2/Function as a variable/index.html | 0 .../week-2/Function as a variable/script.js | 36 ++++++ .../week-2/Functions!/index.html | 17 +++ .../week-2/Functions!/script.js | 114 ++++++++++++++++++ .../index.html | 36 ++++++ .../script.js | 81 +++++++++++++ .../style.css | 81 +++++++++++++ 7 files changed, 365 insertions(+) create mode 100644 courses/frontend/advanced-javascript/week-2/Function as a variable/index.html create mode 100644 courses/frontend/advanced-javascript/week-2/Function as a variable/script.js create mode 100644 courses/frontend/advanced-javascript/week-2/Functions!/index.html create mode 100644 courses/frontend/advanced-javascript/week-2/Functions!/script.js create mode 100644 courses/frontend/advanced-javascript/week-2/The fastest presser in this realm/index.html create mode 100644 courses/frontend/advanced-javascript/week-2/The fastest presser in this realm/script.js create mode 100644 courses/frontend/advanced-javascript/week-2/The fastest presser in this realm/style.css diff --git a/courses/frontend/advanced-javascript/week-2/Function as a variable/index.html b/courses/frontend/advanced-javascript/week-2/Function as a variable/index.html new file mode 100644 index 000000000..e69de29bb diff --git a/courses/frontend/advanced-javascript/week-2/Function as a variable/script.js b/courses/frontend/advanced-javascript/week-2/Function as a variable/script.js new file mode 100644 index 000000000..667fe9d15 --- /dev/null +++ b/courses/frontend/advanced-javascript/week-2/Function as a variable/script.js @@ -0,0 +1,36 @@ +//Array of functions +const myFunctions = [ + function () { + console.log("Hello!"); + }, + function () { + console.log(2 + 3); + }, + function () { + console.log("This is the third function!"); + }, +]; + +// Function declaration and a function expression +function sayHello() { + console.log("Hello from a normal function!"); +} + +sayHello(); + +const sayHi = function () { + console.log("Hello from a function expression!"); +}; + +sayHi(); + + +//Object with function +const myObject = { + greet: function() { + console.log("Hello I m here!"); + } +}; + + +myObject.greet(); diff --git a/courses/frontend/advanced-javascript/week-2/Functions!/index.html b/courses/frontend/advanced-javascript/week-2/Functions!/index.html new file mode 100644 index 000000000..7cc3d6eb5 --- /dev/null +++ b/courses/frontend/advanced-javascript/week-2/Functions!/index.html @@ -0,0 +1,17 @@ + + + + + + Functions! + + + + + +

        +

        +

        + + + diff --git a/courses/frontend/advanced-javascript/week-2/Functions!/script.js b/courses/frontend/advanced-javascript/week-2/Functions!/script.js new file mode 100644 index 000000000..d9785e3c6 --- /dev/null +++ b/courses/frontend/advanced-javascript/week-2/Functions!/script.js @@ -0,0 +1,114 @@ +paragraph = document.getElementById("paragraph"); +btn = document.getElementById("btn"); + +/* setTimeout(()=>{ + paragraph.textContent="Called after 2.5 seconds"; +},2500); */ + +function showStringAfterDelay(delay, stringToLog) { + setTimeout(() => { + paragraph.textContent = stringToLog; + }, delay); +} + +btn.addEventListener("click", () => showStringAfterDelay(3000, "Hi I'm here")); + +const earth = function () { + console.log("Earth"); +}; + +//Planet + +const saturn = () => { + console.log("Saturn"); +}; + +function planetLogFunction(planet) { + planet(); +} + +planetLogFunction(earth); +planetLogFunction(saturn); + +//Log location +btnLocation = document.getElementById("btnLocation"); +latitude = document.getElementById("latitude"); +longitude = document.getElementById("longitude"); + +function getLocation() { + if (navigator.geolocation) { + navigator.geolocation.getCurrentPosition( + (position) => { + latitude.textContent = "Latitude :" + position.coords.latitude; + longitude.textContent = "Longitude :" + position.coords.longitude; + }, + (error) => { + console.error("Error getting location:", error.message); + }, + ); + } else { + console.log("Geolocation is not supported by this browser."); + } +} + +btnLocation.addEventListener("click", getLocation); + +//runAfterDelay + +function runAfterDelay(delay, callback) { + setTimeout(callback, delay); +} + +runAfterDelay(4000, () => { + console.log("should be logged after 4 seconds"); +}); + +//Double click +function doubleClick() { + let clickCount = 0; + let timer = null; + + document.addEventListener("click", function () { + clickCount++; + + // If this is the first click, start a 0.5s timer + if (clickCount === 1) { + timer = setTimeout(() => { + // Reset after 0.5s if no double click happened + clickCount = 0; + }, 500); + } else if (clickCount === 2) { + // Second click happened within 0.5s double click + console.log("double click!"); + clearTimeout(timer); // stop the timer + clickCount = 0; // reset counter + } + }); +} + +doubleClick(); + +//Joke creator + +function logFunnyJoke() { + console.log( + "Why did the math book look sad? Because it had too many problems!", + ); +} + +function logBadJoke() { + console.log( + "Why don’t skeletons fight each other? They don’t have the guts!", + ); +} + +function jokeCreator(shouldTellFunnyJoke, logFunnyJoke, logBadJoke) { + if (shouldTellFunnyJoke) { + logFunnyJoke(); + } else { + logBadJoke(); + } +} + +jokeCreator(true, logFunnyJoke, logBadJoke); +jokeCreator(false, logFunnyJoke, logBadJoke); diff --git a/courses/frontend/advanced-javascript/week-2/The fastest presser in this realm/index.html b/courses/frontend/advanced-javascript/week-2/The fastest presser in this realm/index.html new file mode 100644 index 000000000..41d3c933d --- /dev/null +++ b/courses/frontend/advanced-javascript/week-2/The fastest presser in this realm/index.html @@ -0,0 +1,36 @@ + + + + + + Fastest Presser + + + + + + +
        +

        Fastest presser

        + + +
        + +
        +
        +

        Press S

        +

        0

        +
        + +
        +

        Press L

        +

        0

        +
        +
        + + + + diff --git a/courses/frontend/advanced-javascript/week-2/The fastest presser in this realm/script.js b/courses/frontend/advanced-javascript/week-2/The fastest presser in this realm/script.js new file mode 100644 index 000000000..a2978a7c9 --- /dev/null +++ b/courses/frontend/advanced-javascript/week-2/The fastest presser in this realm/script.js @@ -0,0 +1,81 @@ +const gameDuration = document.getElementById("gameDuration"); +const startGame = document.getElementById("startGame"); +const lCountDisplay = document.getElementById("lCount"); +const sCountDisplay = document.getElementById("sCount"); + +const leftPlayer = document.querySelector(".left"); +const rightPlayer = document.querySelector(".right"); + +let lCount = 0; +let sCount = 0; +let gameActive = false; + +function resetGame() { + lCount = 0; + sCount = 0; + lCountDisplay.textContent = 0; + sCountDisplay.textContent = 0; + + leftPlayer.classList.remove("winner", "loser"); + rightPlayer.classList.remove("winner", "loser"); +} + +function startTheGame() { + resetGame(); + + const duration = Number(gameDuration.value); + + if (!duration || duration <= 0) return; + + gameActive = true; + + setTimeout(endGame, duration * 1000); +} + +function endGame() { + gameActive = false; + + if (lCount > sCount) { + rightPlayer.classList.add("winner"); + leftPlayer.classList.add("loser"); + + confetti({ + particleCount: 150, + spread: 70, + origin: { x: 0.8, y: 0.6 }, + }); + } else if (sCount > lCount) { + leftPlayer.classList.add("winner"); + rightPlayer.classList.add("loser"); + + confetti({ + particleCount: 150, + spread: 70, + origin: { x: 0.2, y: 0.6 }, + }); + } else { + confetti({ + particleCount: 100, + spread: 100, + origin: { x: 0.5, y: 0.6 }, + }); + } +} + +// Key press listener +document.addEventListener("keydown", function (event) { + if (!gameActive) return; + + if (event.key === "l") { + lCount++; + lCountDisplay.textContent = lCount; + } + + if (event.key === "s") { + sCount++; + sCountDisplay.textContent = sCount; + } +}); + +// Start button +startGame.addEventListener("click", startTheGame); diff --git a/courses/frontend/advanced-javascript/week-2/The fastest presser in this realm/style.css b/courses/frontend/advanced-javascript/week-2/The fastest presser in this realm/style.css new file mode 100644 index 000000000..685081bb2 --- /dev/null +++ b/courses/frontend/advanced-javascript/week-2/The fastest presser in this realm/style.css @@ -0,0 +1,81 @@ +body { + margin: 0; + font-family: Arial, sans-serif; + background-color: #f2f2f2; +} + +/* Top section */ +.top-section { + text-align: center; + padding: 40px 20px; +} + +.top-section h1 { + font-family: "Pacifico", cursive; + font-size: 55px; + color: #555; + margin-bottom: 20px; + text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2); +} + +input { + padding: 12px; + width: 200px; + border: none; + border-radius: 5px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); + margin-bottom: 15px; + font-size: 16px; +} + +button { + display: block; + margin: 0 auto; + padding: 12px 25px; + background-color: #3ec28f; + color: white; + border: none; + border-radius: 6px; + font-size: 16px; + cursor: pointer; +} + +button:hover { + background-color: #2fa97a; +} + + +.game-area { + display: flex; + height: 50vh; +} + +.player { + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + font-size: 24px; + transition: all 0.3s ease; + margin-top: 2px solid #ccc; +} + +.left { + border-right: 2px solid #ccc; +} + +.player p { + font-size: 20px; + margin-top: 10px; +} + + +.winner { + background-color: #d4edda; + transform: scale(1.05); +} + +.loser { + opacity: 0.4; +} From 25d4dc05bf16c5952d4d30b4fa21449cdcd88918 Mon Sep 17 00:00:00 2001 From: Oumaima Sakka Date: Thu, 19 Mar 2026 11:23:56 +0100 Subject: [PATCH 62/62] Delete courses/frontend/advanced-javascript/week-1 directory --- .../week-1/Doubling of numbers/index.html | 24 --- .../week-1/Doubling of numbers/script.js | 16 -- .../week-1/Doubling of numbers/style.css | 26 --- .../week-1/Working with movies/index.html | 30 --- .../week-1/Working with movies/movies.js | 1 - .../week-1/Working with movies/script.js | 199 ------------------ .../week-1/Working with movies/style.css | 49 ----- 7 files changed, 345 deletions(-) delete mode 100644 courses/frontend/advanced-javascript/week-1/Doubling of numbers/index.html delete mode 100644 courses/frontend/advanced-javascript/week-1/Doubling of numbers/script.js delete mode 100644 courses/frontend/advanced-javascript/week-1/Doubling of numbers/style.css delete mode 100644 courses/frontend/advanced-javascript/week-1/Working with movies/index.html delete mode 100644 courses/frontend/advanced-javascript/week-1/Working with movies/movies.js delete mode 100644 courses/frontend/advanced-javascript/week-1/Working with movies/script.js delete mode 100644 courses/frontend/advanced-javascript/week-1/Working with movies/style.css diff --git a/courses/frontend/advanced-javascript/week-1/Doubling of numbers/index.html b/courses/frontend/advanced-javascript/week-1/Doubling of numbers/index.html deleted file mode 100644 index 1cb01641f..000000000 --- a/courses/frontend/advanced-javascript/week-1/Doubling of numbers/index.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - Double Odd Numbers - - - - -

        Double Odd Numbers

        - - - - -

        Original Numbers:

        -
        - -

        Doubled Odd Numbers:

        -
        - - - - \ No newline at end of file diff --git a/courses/frontend/advanced-javascript/week-1/Doubling of numbers/script.js b/courses/frontend/advanced-javascript/week-1/Doubling of numbers/script.js deleted file mode 100644 index 017e70b15..000000000 --- a/courses/frontend/advanced-javascript/week-1/Doubling of numbers/script.js +++ /dev/null @@ -1,16 +0,0 @@ - -let numbers = []; - -document.getElementById('processBtn').addEventListener('click', () => { - const input = document.getElementById('numInput').value; - numbers = input.split(',').map(n => parseInt(n.trim())).filter(n => !isNaN(n)); - - // Show original numbers - document.getElementById('original').textContent = numbers.join(', '); - - // Filter odd numbers and double them - const newNumbers = numbers.filter(n => n % 2 !== 0).map(n => n * 2); - - // Show doubled numbers - document.getElementById('doubled').textContent = newNumbers.join(', '); -}); \ No newline at end of file diff --git a/courses/frontend/advanced-javascript/week-1/Doubling of numbers/style.css b/courses/frontend/advanced-javascript/week-1/Doubling of numbers/style.css deleted file mode 100644 index 27f229017..000000000 --- a/courses/frontend/advanced-javascript/week-1/Doubling of numbers/style.css +++ /dev/null @@ -1,26 +0,0 @@ -body { - font-family: Arial, sans-serif; - padding: 20px; - background-color: rgb(228, 224, 225); -} - -h1, h2 { - color:rgb(206, 142, 153); -} - - button { - padding: 5px; - margin: 5px 0; - border-radius: 2rem; - background-color: rgb(206, 142, 153); - border: 1px solid white; - color: rgb(211, 208, 208); - margin-left: 3rem; -} - -input,.original, .doubled { - margin-top: 10px; - padding: 5px; - border: 1px solid #000000; - min-height: 20px; -} \ No newline at end of file diff --git a/courses/frontend/advanced-javascript/week-1/Working with movies/index.html b/courses/frontend/advanced-javascript/week-1/Working with movies/index.html deleted file mode 100644 index c5d4bf9a0..000000000 --- a/courses/frontend/advanced-javascript/week-1/Working with movies/index.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - -Movie Dashboard - - - - -

        Movie Dashboard

        - -
        - - - - - - - - - -
        - -
        - - - - - - \ No newline at end of file diff --git a/courses/frontend/advanced-javascript/week-1/Working with movies/movies.js b/courses/frontend/advanced-javascript/week-1/Working with movies/movies.js deleted file mode 100644 index a114dbe4b..000000000 --- a/courses/frontend/advanced-javascript/week-1/Working with movies/movies.js +++ /dev/null @@ -1 +0,0 @@ -const movies = [{"title": "'71","year": 2014,"rating": 7.2,"votes": 41702,"running_times": 5940},{"title": "'A' gai wak","year": 1983,"rating": 7.4,"votes": 11942,"running_times": 6300},{"title": "'Breaker' Morant","year": 1980,"rating": 7.9,"votes": 10702,"running_times": 6420},{"title": "'Crocodile' Dundee II","year": 1988,"rating": 5.5,"votes": 47180,"running_times": 6480},{"title": "(500) Days of Summer","year": 2009,"rating": 7.7,"votes": 412368,"running_times": 5700},{"title": "*batteries not included","year": 1987,"rating": 6.6,"votes": 25636,"running_times": 6360},{"title": "...E tu vivrai nel terrore! L'aldilà","year": 1981,"rating": 6.9,"votes": 16484,"running_times": 5220},{"title": "...and justice for all.","year": 1979,"rating": 7.4,"votes": 25408,"running_times": 7140},{"title": "10","year": 1979,"rating": 6,"votes": 13152,"running_times": 7320},{"title": "10 Cloverfield Lane","year": 2016,"rating": 7.2,"votes": 216151,"running_times": 6240},{"title": "10 Items or Less","year": 2006,"rating": 6.7,"votes": 13342,"running_times": 4920},{"title": "10 Things I Hate About You","year": 1999,"rating": 7.2,"votes": 247070,"running_times": 5820},{"title": "10 Years","year": 2011,"rating": 6.1,"votes": 20790,"running_times": 6000},{"title": "10,000 BC","year": 2008,"rating": 5.1,"votes": 114750,"running_times": 6540},{"title": "100 Feet","year": 2008,"rating": 5.5,"votes": 10979,"running_times": 6240},{"title": "100 Girls","year": 2000,"rating": 5.9,"votes": 19232,"running_times": 5640},{"title": "101 Dalmatians","year": 1996,"rating": 5.7,"votes": 83245,"running_times": 6180},{"title": "102 Dalmatians","year": 2000,"rating": 4.9,"votes": 28927,"running_times": 6000},{"title": "11-11-11","year": 2011,"rating": 4,"votes": 11425,"running_times": 5400},{"title": "11:14","year": 2003,"rating": 7.2,"votes": 40149,"running_times": 5700},{"title": "12 Angry Men","year": 1957,"rating": 8.9,"votes": 518449,"running_times": 5760},{"title": "12 Rounds","year": 2009,"rating": 5.6,"votes": 24457,"running_times": 6480},{"title": "12 Years a Slave","year": 2013,"rating": 8.1,"votes": 513047,"running_times": 8040},{"title": "127 Hours","year": 2010,"rating": 7.6,"votes": 302809,"running_times": 5640},{"title": "13","year": 2010,"rating": 6.1,"votes": 36623,"running_times": 5460},{"title": "13 Going on 30","year": 2004,"rating": 6.1,"votes": 134434,"running_times": 5880},{"title": "13 Hours","year": 2016,"rating": 7.3,"votes": 85771,"running_times": 8640},{"title": "13 Sins","year": 2014,"rating": 6.3,"votes": 26738,"running_times": 5580},{"title": "13th","year": 2016,"rating": 8.2,"votes": 15188,"running_times": 6000},{"title": "1408","year": 2007,"rating": 6.8,"votes": 228738,"running_times": 6840},{"title": "1492: Conquest of Paradise","year": 1992,"rating": 6.5,"votes": 24439,"running_times": 9240},{"title": "15 Minutes","year": 2001,"rating": 6.1,"votes": 44647,"running_times": 7200},{"title": "16 Blocks","year": 2006,"rating": 6.6,"votes": 117443,"running_times": 6600},{"title": "17 Again","year": 2009,"rating": 6.4,"votes": 156663,"running_times": 6120},{"title": "1922","year": 2017,"rating": 6.4,"votes": 15416,"running_times": 6120},{"title": "1941","year": 1979,"rating": 5.9,"votes": 27172,"running_times": 8760},{"title": "2 Days in New York","year": 2012,"rating": 6,"votes": 12766,"running_times": 5760},{"title": "2 Days in Paris","year": 2007,"rating": 6.8,"votes": 28106,"running_times": 5760},{"title": "2 Days in the Valley","year": 1996,"rating": 6.5,"votes": 16528,"running_times": 6240},{"title": "2 Fast 2 Furious","year": 2003,"rating": 5.9,"votes": 213674,"running_times": 6420},{"title": "2 Guns","year": 2013,"rating": 6.7,"votes": 170412,"running_times": 6540},{"title": "20,000 Leagues Under the Sea","year": 1954,"rating": 7.2,"votes": 24094,"running_times": 7620},{"title": "200 Cigarettes","year": 1999,"rating": 5.9,"votes": 13532,"running_times": 6060},{"title": "2001 Maniacs","year": 2005,"rating": 5.4,"votes": 10889,"running_times": 5220},{"title": "2001: A Space Odyssey","year": 1968,"rating": 8.3,"votes": 481800,"running_times": 9660},{"title": "2001: A Space Travesty","year": 2000,"rating": 3.4,"votes": 10094,"running_times": 5940},{"title": "2010","year": 1984,"rating": 6.8,"votes": 44155,"running_times": 6960},{"title": "2012","year": 2009,"rating": 5.8,"votes": 306797,"running_times": 9480},{"title": "20th Century Women","year": 2016,"rating": 7.4,"votes": 22965,"running_times": 7140},{"title": "21 & Over","year": 2013,"rating": 5.9,"votes": 65298,"running_times": 5580},{"title": "21","year": 2008,"rating": 6.8,"votes": 203251,"running_times": 7380},{"title": "21 Grams","year": 2003,"rating": 7.7,"votes": 202129,"running_times": 7440},{"title": "21 Jump Street","year": 2012,"rating": 7.2,"votes": 446476,"running_times": 6540},{"title": "22 Jump Street","year": 2014,"rating": 7.1,"votes": 292991,"running_times": 6720},{"title": "24 Hour Party People","year": 2002,"rating": 7.4,"votes": 28750,"running_times": 7020},{"title": "25th Hour","year": 2002,"rating": 7.7,"votes": 157063,"running_times": 8100},{"title": "27 Dresses","year": 2008,"rating": 6.1,"votes": 134861,"running_times": 6660},{"title": "28 Days","year": 2000,"rating": 6,"votes": 37395,"running_times": 6180},{"title": "28 Days Later...","year": 2002,"rating": 7.6,"votes": 323591,"running_times": 6780},{"title": "28 Weeks Later","year": 2007,"rating": 7,"votes": 228033,"running_times": 6000},{"title": "2:22","year": 2017,"rating": 5.7,"votes": 10266,"running_times": 5880},{"title": "3 Days to Kill","year": 2014,"rating": 6.2,"votes": 75906,"running_times": 7380},{"title": "3 Idiots","year": 2009,"rating": 8.4,"votes": 256619,"running_times": 10200},{"title": "3 Men and a Baby","year": 1987,"rating": 5.9,"votes": 39924,"running_times": 6120},{"title": "3 Men and a Little Lady","year": 1990,"rating": 5.3,"votes": 19005,"running_times": 6240},{"title": "3 Ninjas","year": 1992,"rating": 5.2,"votes": 17582,"running_times": 5880},{"title": "3 Women","year": 1977,"rating": 7.9,"votes": 10852,"running_times": 7440},{"title": "30 Days of Night","year": 2007,"rating": 6.6,"votes": 148004,"running_times": 6780},{"title": "30 Minutes or Less","year": 2011,"rating": 6.1,"votes": 83073,"running_times": 4980},{"title": "300","year": 2006,"rating": 7.7,"votes": 654380,"running_times": 7020},{"title": "3000 Miles to Graceland","year": 2001,"rating": 5.9,"votes": 39646,"running_times": 7500},{"title": "300: Rise of an Empire","year": 2014,"rating": 6.2,"votes": 245690,"running_times": 6120},{"title": "31","year": 2016,"rating": 5,"votes": 12536,"running_times": 6120},{"title": "360","year": 2011,"rating": 6.2,"votes": 14275,"running_times": 6600},{"title": "3:10 to Yuma","year": 1957,"rating": 7.6,"votes": 15498,"running_times": 5520},{"title": "3:10 to Yuma","year": 2007,"rating": 7.7,"votes": 254591,"running_times": 7320},{"title": "40 Days and 40 Nights","year": 2002,"rating": 5.6,"votes": 64777,"running_times": 5760},{"title": "42","year": 2013,"rating": 7.5,"votes": 71968,"running_times": 7680},{"title": "45 Years","year": 2015,"rating": 7.1,"votes": 24269,"running_times": 5460},{"title": "47 Meters Down","year": 2017,"rating": 5.7,"votes": 23125,"running_times": 5340},{"title": "47 Ronin","year": 2013,"rating": 6.3,"votes": 127026,"running_times": 7680},{"title": "48 Hrs.","year": 1982,"rating": 6.9,"votes": 58092,"running_times": 5760},{"title": "4: Rise of the Silver Surfer","year": 2007,"rating": 5.6,"votes": 225698,"running_times": 5520},{"title": "5 Days of War","year": 2011,"rating": 5.6,"votes": 12658,"running_times": 6780},{"title": "5 to 7","year": 2014,"rating": 7.1,"votes": 13647,"running_times": 6000},{"title": "50 First Dates","year": 2004,"rating": 6.8,"votes": 286325,"running_times": 5940},{"title": "50/50","year": 2011,"rating": 7.7,"votes": 287608,"running_times": 6000},{"title": "54","year": 1998,"rating": 5.8,"votes": 28964,"running_times": 7260},{"title": "6 Bullets","year": 2012,"rating": 6.1,"votes": 12351,"running_times": 6900},{"title": "6 Souls","year": 2010,"rating": 6.1,"votes": 27608,"running_times": 6720},{"title": "8 Mile","year": 2002,"rating": 7.1,"votes": 208201,"running_times": 6600},{"title": "8 femmes","year": 2002,"rating": 7.1,"votes": 25351,"running_times": 6660},{"title": "88 Minutes","year": 2007,"rating": 5.9,"votes": 69067,"running_times": 6480},{"title": "8MM","year": 1999,"rating": 6.5,"votes": 110165,"running_times": 7380},{"title": "8½","year": 1963,"rating": 8.1,"votes": 88077,"running_times": 8280},{"title": "9","year": 2009,"rating": 7.1,"votes": 118743,"running_times": 4740},{"title": "9 Songs","year": 2004,"rating": 4.9,"votes": 19175,"running_times": 4260},{"title": "99 Homes","year": 2014,"rating": 7.1,"votes": 23100,"running_times": 6720},{"title": "A Beautiful Mind","year": 2001,"rating": 8.2,"votes": 692444,"running_times": 8100},{"title": "A Better Life","year": 2011,"rating": 7.2,"votes": 13931,"running_times": 5880},{"title": "A Bigger Splash","year": 2015,"rating": 6.4,"votes": 17641,"running_times": 7500},{"title": "A Boy and His Dog","year": 1975,"rating": 6.6,"votes": 14010,"running_times": 5460},{"title": "A Bridge Too Far","year": 1977,"rating": 7.4,"votes": 43717,"running_times": 10500},{"title": "A Bronx Tale","year": 1993,"rating": 7.8,"votes": 107443,"running_times": 7260},{"title": "A Bug's Life","year": 1998,"rating": 7.2,"votes": 229465,"running_times": 5700},{"title": "A Christmas Carol","year": 2009,"rating": 6.8,"votes": 82681,"running_times": 5760},{"title": "A Christmas Story","year": 1983,"rating": 8,"votes": 113032,"running_times": 5640},{"title": "A Cinderella Story","year": 2004,"rating": 5.9,"votes": 69295,"running_times": 5700},{"title": "A Civil Action","year": 1998,"rating": 6.5,"votes": 24558,"running_times": 6900},{"title": "A Clockwork Orange","year": 1971,"rating": 8.3,"votes": 623645,"running_times": 8160},{"title": "A Close Shave","year": 1995,"rating": 8.2,"votes": 33053,"running_times": 1800},{"title": "A Cock and Bull Story","year": 2005,"rating": 6.8,"votes": 11624,"running_times": 5640},{"title": "A Cure for Wellness","year": 2016,"rating": 6.4,"votes": 50746,"running_times": 8760},{"title": "A Dangerous Method","year": 2011,"rating": 6.5,"votes": 87773,"running_times": 5940},{"title": "A Day at the Races","year": 1937,"rating": 7.7,"votes": 11369,"running_times": 6660},{"title": "A Dirty Shame","year": 2004,"rating": 5.1,"votes": 11191,"running_times": 5340},{"title": "A Dog's Purpose","year": 2017,"rating": 6.9,"votes": 38675,"running_times": 6000},{"title": "A Face in the Crowd","year": 1957,"rating": 8.2,"votes": 10910,"running_times": 7560},{"title": "A Fantastic Fear of Everything","year": 2012,"rating": 5.9,"votes": 12446,"running_times": 6000},{"title": "A Few Best Men","year": 2011,"rating": 5.7,"votes": 11321,"running_times": 5820},{"title": "A Few Good Men","year": 1992,"rating": 7.7,"votes": 198227,"running_times": 8280},{"title": "A Fish Called Wanda","year": 1988,"rating": 7.6,"votes": 115086,"running_times": 6480},{"title": "A Ghost Story","year": 2017,"rating": 6.9,"votes": 21003,"running_times": 5520},{"title": "A Good Day to Die Hard","year": 2013,"rating": 5.3,"votes": 177298,"running_times": 6060},{"title": "A Good Old Fashioned Orgy","year": 2011,"rating": 6.2,"votes": 18997,"running_times": 5700},{"title": "A Good Woman","year": 2004,"rating": 6.5,"votes": 10271,"running_times": 5580},{"title": "A Good Year","year": 2006,"rating": 6.9,"votes": 77087,"running_times": 7020},{"title": "A Goofy Movie","year": 1995,"rating": 6.8,"votes": 37406,"running_times": 4680},{"title": "A Grand Day Out","year": 1989,"rating": 7.8,"votes": 25751,"running_times": 1380},{"title": "A Guide to Recognizing Your Saints","year": 2006,"rating": 7,"votes": 23140,"running_times": 6000},{"title": "A Guy Thing","year": 2003,"rating": 5.6,"votes": 15052,"running_times": 6060},{"title": "A Hard Day's Night","year": 1964,"rating": 7.7,"votes": 34132,"running_times": 5220},{"title": "A Haunted House","year": 2013,"rating": 5.1,"votes": 37624,"running_times": 5160},{"title": "A Haunted House 2","year": 2014,"rating": 4.7,"votes": 16458,"running_times": 5160},{"title": "A History of Violence","year": 2005,"rating": 7.5,"votes": 200459,"running_times": 5760},{"title": "A Hologram for the King","year": 2016,"rating": 6.1,"votes": 30336,"running_times": 5880},{"title": "A Home at the End of the World","year": 2004,"rating": 6.8,"votes": 12481,"running_times": 5820},{"title": "A Knight's Tale","year": 2001,"rating": 6.9,"votes": 147493,"running_times": 8640},{"title": "A Late Quartet","year": 2012,"rating": 7.1,"votes": 12157,"running_times": 6300},{"title": "A League of Their Own","year": 1992,"rating": 7.2,"votes": 77777,"running_times": 7680},{"title": "A Life Less Ordinary","year": 1997,"rating": 6.4,"votes": 31642,"running_times": 6180},{"title": "A Little Bit of Heaven","year": 2011,"rating": 6.3,"votes": 25008,"running_times": 6360},{"title": "A Little Chaos","year": 2014,"rating": 6.5,"votes": 15692,"running_times": 6720},{"title": "A Little Princess","year": 1995,"rating": 7.7,"votes": 27204,"running_times": 5820},{"title": "A Lonely Place to Die","year": 2011,"rating": 6.3,"votes": 23882,"running_times": 5940},{"title": "A Long Way Down","year": 2014,"rating": 6.4,"votes": 27396,"running_times": 5760},{"title": "A Lot Like Love","year": 2005,"rating": 6.6,"votes": 61471,"running_times": 6420},{"title": "A Love Song for Bobby Long","year": 2004,"rating": 7.2,"votes": 23145,"running_times": 7140},{"title": "A Man Apart","year": 2003,"rating": 6.1,"votes": 40595,"running_times": 6540},{"title": "A Man for All Seasons","year": 1966,"rating": 7.9,"votes": 25716,"running_times": 7200},{"title": "A Matter of Life and Death","year": 1946,"rating": 8.1,"votes": 15190,"running_times": 6240},{"title": "A Matter of Loaf and Death","year": 2008,"rating": 7.6,"votes": 11464,"running_times": 1800},{"title": "A Midsummer Night's Dream","year": 1999,"rating": 6.5,"votes": 22260,"running_times": 6960},{"title": "A Midsummer Night's Sex Comedy","year": 1982,"rating": 6.7,"votes": 16072,"running_times": 5280},{"title": "A Mighty Heart","year": 2007,"rating": 6.7,"votes": 25029,"running_times": 6480},{"title": "A Mighty Wind","year": 2003,"rating": 7.3,"votes": 23379,"running_times": 5460},{"title": "A Million Ways to Die in the West","year": 2014,"rating": 6.1,"votes": 149454,"running_times": 8160},{"title": "A Monster Calls","year": 2016,"rating": 7.5,"votes": 54692,"running_times": 6480},{"title": "A Most Violent Year","year": 2014,"rating": 7,"votes": 53486,"running_times": 7500},{"title": "A Most Wanted Man","year": 2014,"rating": 6.8,"votes": 63277,"running_times": 7320},{"title": "A Night at the Opera","year": 1935,"rating": 8,"votes": 26694,"running_times": 5760},{"title": "A Night at the Roxbury","year": 1998,"rating": 6.2,"votes": 51079,"running_times": 4920},{"title": "A Night to Remember","year": 1958,"rating": 7.9,"votes": 11342,"running_times": 7380},{"title": "A Nightmare on Elm Street","year": 1984,"rating": 7.5,"votes": 168011,"running_times": 6060},{"title": "A Nightmare on Elm Street","year": 2010,"rating": 5.2,"votes": 80750,"running_times": 5700},{"title": "A Nightmare on Elm Street 3: Dream Warriors","year": 1987,"rating": 6.6,"votes": 56620,"running_times": 5760},{"title": "A Nightmare on Elm Street 4: The Dream Master","year": 1988,"rating": 5.7,"votes": 40437,"running_times": 5940},{"title": "A Nightmare on Elm Street Part 2: Freddy's Revenge","year": 1985,"rating": 5.4,"votes": 49036,"running_times": 5220},{"title": "A Nightmare on Elm Street: The Dream Child","year": 1989,"rating": 5.1,"votes": 33151,"running_times": 5340},{"title": "A Passage to India","year": 1984,"rating": 7.4,"votes": 14283,"running_times": 9840},{"title": "A Perfect Day","year": 2015,"rating": 6.8,"votes": 14727,"running_times": 6360},{"title": "A Perfect Getaway","year": 2009,"rating": 6.5,"votes": 60120,"running_times": 6480},{"title": "A Perfect Murder","year": 1998,"rating": 6.5,"votes": 68812,"running_times": 6420},{"title": "A Perfect World","year": 1993,"rating": 7.5,"votes": 62447,"running_times": 8280},{"title": "A Place in the Sun","year": 1951,"rating": 7.8,"votes": 16542,"running_times": 7320},{"title": "A Prairie Home Companion","year": 2006,"rating": 6.8,"votes": 20330,"running_times": 6300},{"title": "A River Runs Through It","year": 1992,"rating": 7.3,"votes": 45327,"running_times": 7380},{"title": "A Room with a View","year": 1985,"rating": 7.4,"votes": 32554,"running_times": 7020},{"title": "A Scanner Darkly","year": 2006,"rating": 7.1,"votes": 95310,"running_times": 6000},{"title": "A Series of Unfortunate Events","year": 2004,"rating": 6.8,"votes": 173998,"running_times": 6480},{"title": "A Serious Man","year": 2009,"rating": 7,"votes": 111295,"running_times": 6360},{"title": "A Shot in the Dark","year": 1964,"rating": 7.6,"votes": 21546,"running_times": 6120},{"title": "A Simple Plan","year": 1998,"rating": 7.5,"votes": 54525,"running_times": 7260},{"title": "A Single Man","year": 2009,"rating": 7.6,"votes": 93627,"running_times": 5940},{"title": "A Sound of Thunder","year": 2005,"rating": 4.2,"votes": 17277,"running_times": 6600},{"title": "A Star Is Born","year": 1954,"rating": 7.8,"votes": 11576,"running_times": 10860},{"title": "A Street Cat Named Bob","year": 2016,"rating": 7.4,"votes": 18086,"running_times": 6180},{"title": "A Streetcar Named Desire","year": 1951,"rating": 8,"votes": 84993,"running_times": 7500},{"title": "A Thousand Words","year": 2012,"rating": 5.9,"votes": 33739,"running_times": 5460},{"title": "A Time to Kill","year": 1996,"rating": 7.4,"votes": 110362,"running_times": 8940},{"title": "A Very Harold & Kumar 3D Christmas","year": 2011,"rating": 6.3,"votes": 58988,"running_times": 5760},{"title": "A View to a Kill","year": 1985,"rating": 6.3,"votes": 74476,"running_times": 7860},{"title": "A Walk Among the Tombstones","year": 2014,"rating": 6.5,"votes": 96762,"running_times": 6840},{"title": "A Walk in the Clouds","year": 1995,"rating": 6.7,"votes": 26854,"running_times": 6120},{"title": "A Walk in the Woods","year": 2015,"rating": 6.3,"votes": 19128,"running_times": 6240},{"title": "A Walk to Remember","year": 2002,"rating": 7.4,"votes": 176490,"running_times": 6060},{"title": "A Wednesday","year": 2008,"rating": 8.3,"votes": 56214,"running_times": 6240},{"title": "A Woman Under the Influence","year": 1974,"rating": 8.2,"votes": 16018,"running_times": 9300},{"title": "A.C.O.D.","year": 2013,"rating": 5.7,"votes": 11540,"running_times": 5280},{"title": "ARQ","year": 2016,"rating": 6.4,"votes": 22206,"running_times": 5280},{"title": "ATM","year": 2012,"rating": 4.7,"votes": 20365,"running_times": 5400},{"title": "AVP: Alien vs. Predator","year": 2004,"rating": 5.6,"votes": 159110,"running_times": 6540},{"title": "AVPR: Aliens vs Predator - Requiem","year": 2007,"rating": 4.7,"votes": 101047,"running_times": 6120},{"title": "Abduction","year": 2011,"rating": 5.1,"votes": 68802,"running_times": 6360},{"title": "About Last Night","year": 2014,"rating": 6.1,"votes": 18754,"running_times": 6000},{"title": "About Last Night...","year": 1986,"rating": 6.2,"votes": 12416,"running_times": 6780},{"title": "About Schmidt","year": 2002,"rating": 7.2,"votes": 112727,"running_times": 7500},{"title": "About Time","year": 2013,"rating": 7.8,"votes": 232322,"running_times": 7380},{"title": "About a Boy","year": 2002,"rating": 7.1,"votes": 152115,"running_times": 6060},{"title": "Above the Law","year": 1988,"rating": 6,"votes": 24301,"running_times": 5940},{"title": "Above the Rim","year": 1994,"rating": 6.6,"votes": 11650,"running_times": 5760},{"title": "Abraham Lincoln: Vampire Hunter","year": 2012,"rating": 5.9,"votes": 136196,"running_times": 6300},{"title": "Absentia","year": 2011,"rating": 5.8,"votes": 14480,"running_times": 5220},{"title": "Absolute Power","year": 1997,"rating": 6.7,"votes": 42869,"running_times": 7260},{"title": "Absolutely Anything","year": 2015,"rating": 6,"votes": 29541,"running_times": 5100},{"title": "Accepted","year": 2006,"rating": 6.5,"votes": 111434,"running_times": 5580},{"title": "Ace Ventura: Pet Detective","year": 1994,"rating": 6.9,"votes": 236240,"running_times": 5160},{"title": "Ace Ventura: When Nature Calls","year": 1995,"rating": 6.3,"votes": 174677,"running_times": 5400},{"title": "Ace in the Hole","year": 1951,"rating": 8.2,"votes": 21834,"running_times": 6660},{"title": "Across the Universe","year": 2007,"rating": 7.4,"votes": 97183,"running_times": 7980},{"title": "Act of Valor","year": 2012,"rating": 6.5,"votes": 61069,"running_times": 6600},{"title": "Adam","year": 2009,"rating": 7.2,"votes": 31090,"running_times": 5940},{"title": "Adam's Rib","year": 1949,"rating": 7.6,"votes": 16857,"running_times": 6060},{"title": "Adaptation.","year": 2002,"rating": 7.7,"votes": 155220,"running_times": 6840},{"title": "Addams Family Values","year": 1993,"rating": 6.6,"votes": 63626,"running_times": 5640},{"title": "Addicted to Love","year": 1997,"rating": 6.1,"votes": 20962,"running_times": 6000},{"title": "Admission","year": 2013,"rating": 5.7,"votes": 30216,"running_times": 6420},{"title": "Adoration","year": 2013,"rating": 6.2,"votes": 26611,"running_times": 6720},{"title": "Adult World","year": 2013,"rating": 6.2,"votes": 14875,"running_times": 5820},{"title": "Adulthood","year": 2008,"rating": 6.7,"votes": 10672,"running_times": 5940},{"title": "Adventureland","year": 2009,"rating": 6.8,"votes": 139933,"running_times": 6420},{"title": "Adventures in Babysitting","year": 1987,"rating": 6.9,"votes": 31300,"running_times": 6120},{"title": "Afflicted","year": 2013,"rating": 6.3,"votes": 18513,"running_times": 5100},{"title": "Affliction","year": 1997,"rating": 7,"votes": 12755,"running_times": 6840},{"title": "After Earth","year": 2013,"rating": 4.9,"votes": 170966,"running_times": 6000},{"title": "After Hours","year": 1985,"rating": 7.7,"votes": 44784,"running_times": 5820},{"title": "After the Dark","year": 2013,"rating": 5.7,"votes": 18607,"running_times": 6420},{"title": "After the Sunset","year": 2004,"rating": 6.3,"votes": 40364,"running_times": 5820},{"title": "After.Life","year": 2009,"rating": 5.9,"votes": 32865,"running_times": 6240},{"title": "Aftermath","year": 2017,"rating": 5.7,"votes": 12202,"running_times": 5640},{"title": "Agent Cody Banks","year": 2003,"rating": 5.1,"votes": 28946,"running_times": 6120},{"title": "Agent Cody Banks 2: Destination London","year": 2004,"rating": 4.5,"votes": 12154,"running_times": 6000},{"title": "Agneepath","year": 2012,"rating": 7,"votes": 19127,"running_times": 10440},{"title": "Agora","year": 2009,"rating": 7.2,"votes": 57484,"running_times": 8460},{"title": "Aguirre, der Zorn Gottes","year": 1972,"rating": 8,"votes": 42543,"running_times": 5700},{"title": "Ah fei zing zyun","year": 1990,"rating": 7.6,"votes": 13683,"running_times": 5640},{"title": "Ain't Them Bodies Saints","year": 2013,"rating": 6.4,"votes": 18005,"running_times": 5760},{"title": "Air","year": 2015,"rating": 5.1,"votes": 10524,"running_times": 5700},{"title": "Air America","year": 1990,"rating": 5.7,"votes": 23513,"running_times": 6780},{"title": "Air Bud","year": 1997,"rating": 5.1,"votes": 14077,"running_times": 5880},{"title": "Air Force One","year": 1997,"rating": 6.5,"votes": 157206,"running_times": 7440},{"title": "Airheads","year": 1994,"rating": 6.1,"votes": 40608,"running_times": 5520},{"title": "Airplane II: The Sequel","year": 1982,"rating": 6.1,"votes": 41313,"running_times": 5100},{"title": "Airplane!","year": 1980,"rating": 7.8,"votes": 176142,"running_times": 5280},{"title": "Airport","year": 1970,"rating": 6.6,"votes": 14456,"running_times": 8220},{"title": "Ajeossi","year": 2010,"rating": 7.8,"votes": 49601,"running_times": 7140},{"title": "Akeelah and the Bee","year": 2006,"rating": 7.5,"votes": 16346,"running_times": 6720},{"title": "Aladdin","year": 1992,"rating": 8,"votes": 291038,"running_times": 5400},{"title": "Alan Partridge: Alpha Papa","year": 2013,"rating": 7,"votes": 26193,"running_times": 5400},{"title": "Albert Nobbs","year": 2011,"rating": 6.7,"votes": 21042,"running_times": 6780},{"title": "Alex & Emma","year": 2003,"rating": 5.6,"votes": 12051,"running_times": 5760},{"title": "Alex Cross","year": 2012,"rating": 5.1,"votes": 29794,"running_times": 6060},{"title": "Alexander","year": 2004,"rating": 5.6,"votes": 147126,"running_times": 12840},{"title": "Alexander and the Terrible, Horrible, No Good, Very Bad Day","year": 2014,"rating": 6.2,"votes": 33699,"running_times": 4860},{"title": "Alexis Zorbas","year": 1964,"rating": 7.8,"votes": 16943,"running_times": 8520},{"title": "Alferd Packer: The Musical","year": 1993,"rating": 7.2,"votes": 10661,"running_times": 5820},{"title": "Alfie","year": 1966,"rating": 7.1,"votes": 11435,"running_times": 6840},{"title": "Alfie","year": 2004,"rating": 6.2,"votes": 46025,"running_times": 6180},{"title": "Ali","year": 2001,"rating": 6.8,"votes": 83884,"running_times": 9900},{"title": "Ali Baba ve 7 Cüceler","year": 2015,"rating": 6.1,"votes": 12986,"running_times": 6840},{"title": "Ali G Indahouse","year": 2002,"rating": 6.2,"votes": 73785,"running_times": 5100},{"title": "Alice","year": 1990,"rating": 6.6,"votes": 11437,"running_times": 6360},{"title": "Alice Doesn't Live Here Anymore","year": 1974,"rating": 7.4,"votes": 17090,"running_times": 6720},{"title": "Alice Through the Looking Glass","year": 2016,"rating": 6.2,"votes": 65458,"running_times": 6780},{"title": "Alice in Wonderland","year": 1951,"rating": 7.4,"votes": 106178,"running_times": 4500},{"title": "Alice in Wonderland","year": 2010,"rating": 6.5,"votes": 334849,"running_times": 6480},{"title": "Alien","year": 1979,"rating": 8.5,"votes": 643183,"running_times": 7020},{"title": "Alien Nation","year": 1988,"rating": 6.3,"votes": 12239,"running_times": 5460},{"title": "Alien: Covenant","year": 2017,"rating": 6.5,"votes": 176022,"running_times": 7320},{"title": "Alien: Resurrection","year": 1997,"rating": 6.2,"votes": 193440,"running_times": 6960},{"title": "Aliens","year": 1986,"rating": 8.4,"votes": 547487,"running_times": 9240},{"title": "Aliens in the Attic","year": 2009,"rating": 5.4,"votes": 18127,"running_times": 5160},{"title": "Alien³","year": 1992,"rating": 6.4,"votes": 234564,"running_times": 8700},{"title": "Alive","year": 1993,"rating": 7.1,"votes": 42628,"running_times": 7200},{"title": "All About Eve","year": 1950,"rating": 8.3,"votes": 93769,"running_times": 8280},{"title": "All About Steve","year": 2009,"rating": 4.8,"votes": 35167,"running_times": 5940},{"title": "All About the Benjamins","year": 2002,"rating": 5.8,"votes": 10378,"running_times": 5700},{"title": "All Dogs Go to Heaven","year": 1989,"rating": 6.7,"votes": 29536,"running_times": 5040},{"title": "All Eyez on Me","year": 2017,"rating": 5.8,"votes": 12426,"running_times": 8340},{"title": "All Good Things","year": 2010,"rating": 6.3,"votes": 45790,"running_times": 6060},{"title": "All Is Lost","year": 2013,"rating": 6.9,"votes": 65230,"running_times": 6360},{"title": "All Quiet on the Western Front","year": 1930,"rating": 8.1,"votes": 50226,"running_times": 8820},{"title": "All That Heaven Allows","year": 1955,"rating": 7.7,"votes": 10431,"running_times": 5340},{"title": "All That Jazz","year": 1979,"rating": 7.8,"votes": 21615,"running_times": 7380},{"title": "All of Me","year": 1984,"rating": 6.7,"votes": 14228,"running_times": 5580},{"title": "All the Boys Love Mandy Lane","year": 2006,"rating": 5.6,"votes": 27574,"running_times": 5400},{"title": "All the King's Men","year": 1949,"rating": 7.6,"votes": 10818,"running_times": 6600},{"title": "All the King's Men","year": 2006,"rating": 6.2,"votes": 21751,"running_times": 7680},{"title": "All the President's Men","year": 1976,"rating": 8,"votes": 82613,"running_times": 8280},{"title": "All the Pretty Horses","year": 2000,"rating": 5.8,"votes": 11937,"running_times": 13200},{"title": "All the Right Moves","year": 1983,"rating": 5.9,"votes": 13281,"running_times": 5460},{"title": "Allegiant","year": 2016,"rating": 5.7,"votes": 79153,"running_times": 7200},{"title": "Allied","year": 2016,"rating": 7.1,"votes": 101406,"running_times": 7440},{"title": "Almost Famous","year": 2000,"rating": 7.9,"votes": 222016,"running_times": 9720},{"title": "Almost Heroes","year": 1998,"rating": 5.8,"votes": 13847,"running_times": 5400},{"title": "Aloha","year": 2015,"rating": 5.4,"votes": 47563,"running_times": 6300},{"title": "Alone in the Dark","year": 2005,"rating": 2.3,"votes": 39084,"running_times": 5940},{"title": "Along Came Polly","year": 2004,"rating": 5.9,"votes": 112528,"running_times": 5400},{"title": "Along Came a Spider","year": 2001,"rating": 6.3,"votes": 63476,"running_times": 6240},{"title": "Alpha Dog","year": 2006,"rating": 6.9,"votes": 91925,"running_times": 7320},{"title": "Alpha and Omega","year": 2010,"rating": 5.3,"votes": 11716,"running_times": 5400},{"title": "Altered States","year": 1980,"rating": 6.9,"votes": 26407,"running_times": 6120},{"title": "Alvin and the Chipmunks","year": 2007,"rating": 5.2,"votes": 62965,"running_times": 5520},{"title": "Alvin and the Chipmunks: Chipwrecked","year": 2011,"rating": 4.4,"votes": 25279,"running_times": 5220},{"title": "Alvin and the Chipmunks: The Road Chip","year": 2015,"rating": 5.1,"votes": 12390,"running_times": 5520},{"title": "Alvin and the Chipmunks: The Squeakquel","year": 2009,"rating": 4.5,"votes": 35242,"running_times": 5340},{"title": "Always","year": 1989,"rating": 6.4,"votes": 24085,"running_times": 7320},{"title": "Amadeus","year": 1984,"rating": 8.3,"votes": 303203,"running_times": 10800},{"title": "Amanda Knox","year": 2016,"rating": 7,"votes": 12227,"running_times": 5520},{"title": "Amazing Grace","year": 2006,"rating": 7.5,"votes": 22038,"running_times": 7080},{"title": "Amelia","year": 2009,"rating": 5.8,"votes": 10698,"running_times": 6660},{"title": "Amen.","year": 2002,"rating": 7.3,"votes": 11925,"running_times": 7920},{"title": "America's Sweethearts","year": 2001,"rating": 5.7,"votes": 49926,"running_times": 6120},{"title": "American Assassin","year": 2017,"rating": 6.2,"votes": 28116,"running_times": 6720},{"title": "American Beauty","year": 1999,"rating": 8.4,"votes": 911446,"running_times": 7320},{"title": "American Dreamz","year": 2006,"rating": 5.5,"votes": 23250,"running_times": 6420},{"title": "American Gangster","year": 2007,"rating": 7.8,"votes": 345631,"running_times": 10560},{"title": "American Gigolo","year": 1980,"rating": 6.2,"votes": 17629,"running_times": 7020},{"title": "American Graffiti","year": 1973,"rating": 7.5,"votes": 68973,"running_times": 12600},{"title": "American Heist","year": 2014,"rating": 5.2,"votes": 14405,"running_times": 5640},{"title": "American History X","year": 1998,"rating": 8.5,"votes": 868976,"running_times": 7140},{"title": "American Honey","year": 2016,"rating": 7,"votes": 24638,"running_times": 9780},{"title": "American Hustle","year": 2013,"rating": 7.3,"votes": 390260,"running_times": 8280},{"title": "American Made","year": 2017,"rating": 7.2,"votes": 54330,"running_times": 6900},{"title": "American Mary","year": 2012,"rating": 6.3,"votes": 18886,"running_times": 6180},{"title": "American Movie","year": 1999,"rating": 7.9,"votes": 14634,"running_times": 6420},{"title": "American Ninja","year": 1985,"rating": 5.4,"votes": 11392,"running_times": 5700},{"title": "American Outlaws","year": 2001,"rating": 6,"votes": 12644,"running_times": 5640},{"title": "American Pie","year": 1999,"rating": 7,"votes": 334732,"running_times": 5700},{"title": "American Pie 2","year": 2001,"rating": 6.4,"votes": 213276,"running_times": 6480},{"title": "American Psycho","year": 2000,"rating": 7.6,"votes": 396021,"running_times": 6120},{"title": "American Reunion","year": 2012,"rating": 6.7,"votes": 182331,"running_times": 6780},{"title": "American Sniper","year": 2014,"rating": 7.3,"votes": 368132,"running_times": 7980},{"title": "American Splendor","year": 2003,"rating": 7.5,"votes": 43842,"running_times": 6060},{"title": "American Ultra","year": 2015,"rating": 6.1,"votes": 68944,"running_times": 5760},{"title": "American Wedding","year": 2003,"rating": 6.3,"votes": 172946,"running_times": 6180},{"title": "Amistad","year": 1997,"rating": 7.3,"votes": 61388,"running_times": 9300},{"title": "Amour","year": 2012,"rating": 7.9,"votes": 78257,"running_times": 7620},{"title": "Amy","year": 2015,"rating": 7.8,"votes": 38716,"running_times": 7680},{"title": "An Affair to Remember","year": 1957,"rating": 7.6,"votes": 23942,"running_times": 6900},{"title": "An American Crime","year": 2007,"rating": 7.4,"votes": 27534,"running_times": 5880},{"title": "An American Haunting","year": 2005,"rating": 5,"votes": 23087,"running_times": 5460},{"title": "An American Tail","year": 1986,"rating": 6.9,"votes": 41433,"running_times": 4800},{"title": "An American Tail: Fievel Goes West","year": 1991,"rating": 6.5,"votes": 19175,"running_times": 4500},{"title": "An American Werewolf in London","year": 1981,"rating": 7.6,"votes": 74437,"running_times": 5820},{"title": "An American Werewolf in Paris","year": 1997,"rating": 5.1,"votes": 20423,"running_times": 6300},{"title": "An American in Paris","year": 1951,"rating": 7.2,"votes": 24711,"running_times": 6840},{"title": "An Education","year": 2009,"rating": 7.3,"votes": 117913,"running_times": 6000},{"title": "An Ideal Husband","year": 1999,"rating": 6.9,"votes": 13647,"running_times": 5820},{"title": "An Inconvenient Truth","year": 2006,"rating": 7.5,"votes": 73591,"running_times": 5760},{"title": "An Officer and a Gentleman","year": 1982,"rating": 7,"votes": 41135,"running_times": 7440},{"title": "An Unfinished Life","year": 2005,"rating": 7,"votes": 25784,"running_times": 6480},{"title": "Anaconda","year": 1997,"rating": 4.7,"votes": 80526,"running_times": 5340},{"title": "Anacondas: The Hunt for the Blood Orchid","year": 2004,"rating": 4.6,"votes": 24190,"running_times": 5820},{"title": "Analyze That","year": 2002,"rating": 5.9,"votes": 74001,"running_times": 5760},{"title": "Analyze This","year": 1999,"rating": 6.7,"votes": 131399,"running_times": 6540},{"title": "Anastasia","year": 1997,"rating": 7.1,"votes": 95743,"running_times": 5640},{"title": "Anatomy of a Murder","year": 1959,"rating": 8.1,"votes": 50250,"running_times": 9600},{"title": "Anchorman 2: The Legend Continues","year": 2013,"rating": 6.3,"votes": 143995,"running_times": 8580},{"title": "Anchorman: The Legend of Ron Burgundy","year": 2004,"rating": 7.2,"votes": 288977,"running_times": 6240},{"title": "And Now for Something Completely Different","year": 1971,"rating": 7.6,"votes": 25816,"running_times": 5280},{"title": "And So It Goes","year": 2014,"rating": 5.8,"votes": 10471,"running_times": 5640},{"title": "And Soon the Darkness","year": 2010,"rating": 5.2,"votes": 14637,"running_times": 5460},{"title": "And Then There Were None","year": 1945,"rating": 7.6,"votes": 10271,"running_times": 5820},{"title": "Angel Eyes","year": 2001,"rating": 5.6,"votes": 20391,"running_times": 6120},{"title": "Angel Heart","year": 1987,"rating": 7.3,"votes": 68210,"running_times": 6780},{"title": "Angela's Ashes","year": 1999,"rating": 7.3,"votes": 18063,"running_times": 8700},{"title": "Angels & Demons","year": 2009,"rating": 6.7,"votes": 235481,"running_times": 8760},{"title": "Angels in the Outfield","year": 1994,"rating": 6.1,"votes": 24230,"running_times": 6120},{"title": "Angels with Dirty Faces","year": 1938,"rating": 8,"votes": 17119,"running_times": 5820},{"title": "Anger Management","year": 2003,"rating": 6.2,"votes": 181738,"running_times": 6360},{"title": "Angry Birds","year": 2016,"rating": 6.3,"votes": 61016,"running_times": 5820},{"title": "Angus, Thongs and Perfect Snogging","year": 2008,"rating": 6.4,"votes": 22067,"running_times": 6000},{"title": "Animal Crackers","year": 1930,"rating": 7.7,"votes": 11502,"running_times": 5880},{"title": "Animal Factory","year": 2000,"rating": 6.6,"votes": 11266,"running_times": 5640},{"title": "Animal Farm","year": 1954,"rating": 7.2,"votes": 11658,"running_times": 4320},{"title": "Animal House","year": 1978,"rating": 7.6,"votes": 97022,"running_times": 6540},{"title": "Animal Kingdom","year": 2010,"rating": 7.3,"votes": 48897,"running_times": 6780},{"title": "Anna","year": 2013,"rating": 6.5,"votes": 17073,"running_times": 5940},{"title": "Anna Karenina","year": 2012,"rating": 6.6,"votes": 78137,"running_times": 7740},{"title": "Anna and the King","year": 1999,"rating": 6.7,"votes": 32703,"running_times": 8880},{"title": "Annabelle","year": 2014,"rating": 5.4,"votes": 103295,"running_times": 5940},{"title": "Annabelle: Creation","year": 2017,"rating": 6.6,"votes": 58319,"running_times": 6540},{"title": "Annapolis","year": 2006,"rating": 5.8,"votes": 18758,"running_times": 6480},{"title": "Annie","year": 1982,"rating": 6.5,"votes": 33623,"running_times": 7620},{"title": "Annie","year": 2014,"rating": 5.3,"votes": 28526,"running_times": 7080},{"title": "Annie Hall","year": 1977,"rating": 8.1,"votes": 217245,"running_times": 5580},{"title": "Anomalisa","year": 2015,"rating": 7.2,"votes": 49074,"running_times": 5400},{"title": "Anonymous","year": 2011,"rating": 6.9,"votes": 36351,"running_times": 7800},{"title": "Another 48 Hrs.","year": 1990,"rating": 5.8,"votes": 32415,"running_times": 5580},{"title": "Another Earth","year": 2011,"rating": 7,"votes": 80028,"running_times": 5520},{"title": "Another Stakeout","year": 1993,"rating": 5.5,"votes": 11646,"running_times": 6480},{"title": "Another Woman","year": 1988,"rating": 7.4,"votes": 10953,"running_times": 4860},{"title": "Another Year","year": 2010,"rating": 7.3,"votes": 25033,"running_times": 7740},{"title": "Ant-Man","year": 2015,"rating": 7.3,"votes": 399388,"running_times": 7020},{"title": "Anthropoid","year": 2016,"rating": 7.2,"votes": 30614,"running_times": 7200},{"title": "Antichrist","year": 2009,"rating": 6.6,"votes": 97620,"running_times": 6480},{"title": "Antitrust","year": 2001,"rating": 6.1,"votes": 26509,"running_times": 6300},{"title": "Antiviral","year": 2012,"rating": 5.7,"votes": 10297,"running_times": 6480},{"title": "Antwone Fisher","year": 2002,"rating": 7.3,"votes": 28617,"running_times": 7200},{"title": "Antz","year": 1998,"rating": 6.6,"votes": 132303,"running_times": 4980},{"title": "Anvil: The Story of Anvil","year": 2008,"rating": 8,"votes": 14104,"running_times": 4800},{"title": "Any Given Sunday","year": 1999,"rating": 6.8,"votes": 102436,"running_times": 9720},{"title": "Any Which Way You Can","year": 1980,"rating": 6,"votes": 14435,"running_times": 6960},{"title": "Anything Else","year": 2003,"rating": 6.4,"votes": 26831,"running_times": 6480},{"title": "Anywhere But Here","year": 1999,"rating": 6.2,"votes": 15513,"running_times": 6840},{"title": "Apocalypse Now","year": 1979,"rating": 8.5,"votes": 497723,"running_times": 19800},{"title": "Apollo 13","year": 1995,"rating": 7.6,"votes": 227008,"running_times": 8400},{"title": "Apollo 18","year": 2011,"rating": 5.2,"votes": 49390,"running_times": 5160},{"title": "Appaloosa","year": 2008,"rating": 6.8,"votes": 53205,"running_times": 6900},{"title": "April Fool's Day","year": 1986,"rating": 6.2,"votes": 11611,"running_times": 5340},{"title": "Apt Pupil","year": 1998,"rating": 6.7,"votes": 31118,"running_times": 6720},{"title": "Aqua Teen Hunger Force Colon Movie Film for Theaters","year": 2007,"rating": 6.9,"votes": 12541,"running_times": 5160},{"title": "Aquamarine","year": 2006,"rating": 5.3,"votes": 33298,"running_times": 6240},{"title": "Arachnophobia","year": 1990,"rating": 6.4,"votes": 54159,"running_times": 6180},{"title": "Ararat","year": 2002,"rating": 6.6,"votes": 10789,"running_times": 6900},{"title": "Arbitrage","year": 2012,"rating": 6.6,"votes": 44620,"running_times": 6420},{"title": "Are We Done Yet?","year": 2007,"rating": 4.1,"votes": 16925,"running_times": 5520},{"title": "Are We There Yet?","year": 2005,"rating": 4.6,"votes": 24773,"running_times": 5700},{"title": "Are You Here","year": 2013,"rating": 5.3,"votes": 12834,"running_times": 6840},{"title": "Area 51","year": 2015,"rating": 4.2,"votes": 10299,"running_times": 5460},{"title": "Argo","year": 2012,"rating": 7.7,"votes": 497169,"running_times": 7800},{"title": "Arizona Dream","year": 1993,"rating": 7.4,"votes": 36586,"running_times": 8520},{"title": "Arlington Road","year": 1999,"rating": 7.2,"votes": 73649,"running_times": 7020},{"title": "Armageddon","year": 1998,"rating": 6.6,"votes": 347486,"running_times": 9180},{"title": "Armored","year": 2009,"rating": 5.7,"votes": 27421,"running_times": 5280},{"title": "Army of Darkness","year": 1992,"rating": 7.6,"votes": 140929,"running_times": 5760},{"title": "Arn: Tempelriddaren","year": 2007,"rating": 6.6,"votes": 19100,"running_times": 16200},{"title": "Around the World in 80 Days","year": 1956,"rating": 6.8,"votes": 20004,"running_times": 10980},{"title": "Around the World in 80 Days","year": 2004,"rating": 5.8,"votes": 74283,"running_times": 7200},{"title": "Arrival","year": 2016,"rating": 8,"votes": 414134,"running_times": 6960},{"title": "Arsenic and Old Lace","year": 1944,"rating": 8,"votes": 58127,"running_times": 7080},{"title": "Art School Confidential","year": 2006,"rating": 6.3,"votes": 15550,"running_times": 6120},{"title": "Arthur","year": 1981,"rating": 6.9,"votes": 22746,"running_times": 5820},{"title": "Arthur","year": 2011,"rating": 5.7,"votes": 47295,"running_times": 6600},{"title": "Arthur Christmas","year": 2011,"rating": 7.1,"votes": 40559,"running_times": 5820},{"title": "Arthur et les Minimoys","year": 2006,"rating": 6,"votes": 28009,"running_times": 6240},{"title": "Artificial Intelligence: AI","year": 2001,"rating": 7.1,"votes": 258640,"running_times": 8760},{"title": "As Above, So Below","year": 2014,"rating": 6.2,"votes": 58359,"running_times": 5580},{"title": "As Good as It Gets","year": 1997,"rating": 7.7,"votes": 240006,"running_times": 8340},{"title": "Ashby","year": 2015,"rating": 6.4,"votes": 12069,"running_times": 6000},{"title": "Assassin's Creed","year": 2016,"rating": 5.8,"votes": 142293,"running_times": 6900},{"title": "Assassination Games","year": 2011,"rating": 6.2,"votes": 14739,"running_times": 6060},{"title": "Assassination of a High School President","year": 2008,"rating": 6.3,"votes": 14585,"running_times": 5580},{"title": "Assassins","year": 1995,"rating": 6.3,"votes": 68009,"running_times": 7920},{"title": "Assault on Precinct 13","year": 1976,"rating": 7.4,"votes": 35219,"running_times": 5460},{"title": "Assault on Precinct 13","year": 2005,"rating": 6.3,"votes": 68464,"running_times": 6540},{"title": "Astro Boy","year": 2009,"rating": 6.3,"votes": 28054,"running_times": 5640},{"title": "At Close Range","year": 1986,"rating": 7,"votes": 11734,"running_times": 6660},{"title": "At First Sight","year": 1999,"rating": 5.9,"votes": 11898,"running_times": 7680},{"title": "Atlantic City, USA","year": 1980,"rating": 7.4,"votes": 12335,"running_times": 6240},{"title": "Atlantis: The Lost Empire","year": 2001,"rating": 6.8,"votes": 82313,"running_times": 5700},{"title": "Atlas Shrugged: Part I","year": 2011,"rating": 5.7,"votes": 11880,"running_times": 5820},{"title": "Atomic Blonde","year": 2017,"rating": 6.8,"votes": 84987,"running_times": 6900},{"title": "Atonement","year": 2007,"rating": 7.8,"votes": 210033,"running_times": 7380},{"title": "Attack of the Killer Tomatoes!","year": 1978,"rating": 4.6,"votes": 10524,"running_times": 5400},{"title": "Attack the Block","year": 2011,"rating": 6.6,"votes": 88476,"running_times": 5280},{"title": "Au revoir les enfants","year": 1987,"rating": 8,"votes": 26271,"running_times": 6240},{"title": "Auf der anderen Seite","year": 2007,"rating": 7.9,"votes": 27515,"running_times": 7320},{"title": "August Rush","year": 2007,"rating": 7.5,"votes": 93885,"running_times": 6840},{"title": "August: Osage County","year": 2013,"rating": 7.2,"votes": 74140,"running_times": 7260},{"title": "Austenland","year": 2013,"rating": 6.3,"votes": 16601,"running_times": 5820},{"title": "Austin Powers in Goldmember","year": 2002,"rating": 6.2,"votes": 173560,"running_times": 5640},{"title": "Austin Powers: International Man of Mystery","year": 1997,"rating": 7,"votes": 195127,"running_times": 5640},{"title": "Austin Powers: The Spy Who Shagged Me","year": 1999,"rating": 6.6,"votes": 192813,"running_times": 5700},{"title": "Australia","year": 2008,"rating": 6.6,"votes": 108464,"running_times": 9900},{"title": "Auto Focus","year": 2002,"rating": 6.6,"votes": 11840,"running_times": 6300},{"title": "Autoreiji","year": 2010,"rating": 6.8,"votes": 10080,"running_times": 6540},{"title": "Autumn in New York","year": 2000,"rating": 5.5,"votes": 21753,"running_times": 6180},{"title": "Autómata","year": 2014,"rating": 6.1,"votes": 47310,"running_times": 6540},{"title": "Avatar","year": 2009,"rating": 7.8,"votes": 965391,"running_times": 10680},{"title": "Avengers: Age of Ultron","year": 2015,"rating": 7.4,"votes": 549839,"running_times": 8460},{"title": "Awake","year": 2007,"rating": 6.5,"votes": 66756,"running_times": 5040},{"title": "Awakenings","year": 1990,"rating": 7.8,"votes": 102781,"running_times": 7260},{"title": "Away We Go","year": 2009,"rating": 7.1,"votes": 47856,"running_times": 5880},{"title": "Away from Her","year": 2006,"rating": 7.6,"votes": 19754,"running_times": 6600},{"title": "Ayla: The Daughter of War","year": 2017,"rating": 9.1,"votes": 15688,"running_times": 7500},{"title": "BASEketball","year": 1998,"rating": 6.6,"votes": 51153,"running_times": 6180},{"title": "Babe","year": 1995,"rating": 6.8,"votes": 101472,"running_times": 5460},{"title": "Babe: Pig in the City","year": 1998,"rating": 5.8,"votes": 27221,"running_times": 5820},{"title": "Babel","year": 2006,"rating": 7.5,"votes": 259583,"running_times": 8580},{"title": "Baby Boom","year": 1987,"rating": 6.2,"votes": 11562,"running_times": 6600},{"title": "Baby Boy","year": 2001,"rating": 6.4,"votes": 10653,"running_times": 7800},{"title": "Baby Driver","year": 2017,"rating": 7.8,"votes": 228946,"running_times": 6720},{"title": "Baby Geniuses","year": 1999,"rating": 2.6,"votes": 21448,"running_times": 5820},{"title": "Baby Mama","year": 2008,"rating": 6,"votes": 36224,"running_times": 5940},{"title": "Baby's Day Out","year": 1994,"rating": 6,"votes": 37128,"running_times": 5940},{"title": "Babylon A.D.","year": 2008,"rating": 5.6,"votes": 86189,"running_times": 6060},{"title": "Bachelor Party","year": 1984,"rating": 6.3,"votes": 30852,"running_times": 6300},{"title": "Bachelorette","year": 2012,"rating": 5.3,"votes": 40392,"running_times": 5220},{"title": "Back to School","year": 1986,"rating": 6.6,"votes": 23321,"running_times": 5760},{"title": "Back to the Future","year": 1985,"rating": 8.5,"votes": 829676,"running_times": 6960},{"title": "Back to the Future Part II","year": 1989,"rating": 7.8,"votes": 382721,"running_times": 6480},{"title": "Back to the Future Part III","year": 1990,"rating": 7.4,"votes": 321449,"running_times": 7080},{"title": "Backcountry","year": 2014,"rating": 6,"votes": 13092,"running_times": 5520},{"title": "Backdraft","year": 1991,"rating": 6.7,"votes": 62230,"running_times": 8220},{"title": "Bad Ass","year": 2012,"rating": 5.5,"votes": 16900,"running_times": 5400},{"title": "Bad Boy Bubby","year": 1993,"rating": 7.4,"votes": 10399,"running_times": 6840},{"title": "Bad Boys","year": 1983,"rating": 7.2,"votes": 11737,"running_times": 7380},{"title": "Bad Boys","year": 1995,"rating": 6.8,"votes": 189209,"running_times": 7140},{"title": "Bad Boys II","year": 2003,"rating": 6.6,"votes": 192281,"running_times": 8820},{"title": "Bad Company","year": 2002,"rating": 5.6,"votes": 41533,"running_times": 7500},{"title": "Bad Day at Black Rock","year": 1955,"rating": 7.8,"votes": 15934,"running_times": 4860},{"title": "Bad Girls","year": 1994,"rating": 5.1,"votes": 10276,"running_times": 5940},{"title": "Bad Grandpa","year": 2013,"rating": 6.5,"votes": 82213,"running_times": 6120},{"title": "Bad Lieutenant","year": 1992,"rating": 7.1,"votes": 32064,"running_times": 5760},{"title": "Bad Moms","year": 2016,"rating": 6.2,"votes": 82020,"running_times": 6000},{"title": "Bad News Bears","year": 2005,"rating": 5.8,"votes": 18370,"running_times": 6780},{"title": "Bad Santa","year": 2003,"rating": 7.1,"votes": 119914,"running_times": 5940},{"title": "Bad Santa 2","year": 2016,"rating": 5.6,"votes": 14963,"running_times": 5520},{"title": "Bad Taste","year": 1987,"rating": 6.7,"votes": 38949,"running_times": 5880},{"title": "Bad Teacher","year": 2011,"rating": 5.7,"votes": 171167,"running_times": 5820},{"title": "Bad Words","year": 2013,"rating": 6.7,"votes": 41335,"running_times": 5340},{"title": "Badlands","year": 1973,"rating": 7.9,"votes": 53019,"running_times": 5640},{"title": "Bailout: The Age of Greed","year": 2013,"rating": 6.1,"votes": 18091,"running_times": 5940},{"title": "Baiohazâdo: Dijenerêshon","year": 2008,"rating": 6.6,"votes": 26286,"running_times": 5880},{"title": "Bait","year": 2012,"rating": 5.2,"votes": 13089,"running_times": 5580},{"title": "Bakjwi","year": 2009,"rating": 7.2,"votes": 34458,"running_times": 8880},{"title": "Ballerina","year": 2016,"rating": 6.8,"votes": 10767,"running_times": 5340},{"title": "Ballistic: Ecks vs. Sever","year": 2002,"rating": 3.6,"votes": 17379,"running_times": 5460},{"title": "Balls of Fury","year": 2007,"rating": 5.3,"votes": 37437,"running_times": 5400},{"title": "Balto","year": 1995,"rating": 7.1,"votes": 33431,"running_times": 4680},{"title": "Bambi","year": 1942,"rating": 7.3,"votes": 105971,"running_times": 4200},{"title": "Bana Masal Anlatma","year": 2015,"rating": 7.8,"votes": 11133,"running_times": 6180},{"title": "Bananas","year": 1971,"rating": 7.1,"votes": 29990,"running_times": 4920},{"title": "Band Baaja Baaraat","year": 2010,"rating": 7.3,"votes": 11333,"running_times": 8340},{"title": "Bande à part","year": 1964,"rating": 7.8,"votes": 18308,"running_times": 5700},{"title": "Bandidas","year": 2006,"rating": 5.7,"votes": 30735,"running_times": 5580},{"title": "Bandits","year": 2001,"rating": 6.5,"votes": 59840,"running_times": 7380},{"title": "Bandslam","year": 2009,"rating": 6.4,"votes": 12646,"running_times": 6660},{"title": "Bang Bang You're Dead","year": 2002,"rating": 7.9,"votes": 11636,"running_times": 5580},{"title": "Bangkok Dangerous","year": 2008,"rating": 5.4,"votes": 50670,"running_times": 5940},{"title": "Banlieue 13: Ultimatum","year": 2009,"rating": 6.5,"votes": 39420,"running_times": 6060},{"title": "Barb Wire","year": 1996,"rating": 3.2,"votes": 21839,"running_times": 6000},{"title": "Barbarella","year": 1968,"rating": 5.9,"votes": 26937,"running_times": 5880},{"title": "Barbershop","year": 2002,"rating": 6.3,"votes": 24682,"running_times": 6120},{"title": "Barbershop 2: Back in Business","year": 2004,"rating": 5.7,"votes": 11461,"running_times": 6360},{"title": "Barbershop: The Next Cut","year": 2016,"rating": 5.9,"votes": 11117,"running_times": 6660},{"title": "Barefoot","year": 2014,"rating": 6.6,"votes": 19458,"running_times": 5400},{"title": "Barefoot in the Park","year": 1967,"rating": 7,"votes": 13053,"running_times": 6360},{"title": "Barely Lethal","year": 2015,"rating": 5.4,"votes": 14428,"running_times": 5760},{"title": "Barfly","year": 1987,"rating": 7.3,"votes": 15840,"running_times": 6000},{"title": "Barney's Version","year": 2010,"rating": 7.3,"votes": 22142,"running_times": 8040},{"title": "Barnyard","year": 2006,"rating": 5.6,"votes": 22961,"running_times": 5400},{"title": "Barry Lyndon","year": 1975,"rating": 8.1,"votes": 114697,"running_times": 11100},{"title": "Barton Fink","year": 1991,"rating": 7.7,"votes": 97076,"running_times": 6960},{"title": "Basic","year": 2003,"rating": 6.5,"votes": 53220,"running_times": 5880},{"title": "Basic Instinct","year": 1992,"rating": 6.9,"votes": 145427,"running_times": 7680},{"title": "Basic Instinct 2","year": 2006,"rating": 4.3,"votes": 33147,"running_times": 6960},{"title": "Basket Case","year": 1982,"rating": 6.1,"votes": 12730,"running_times": 5460},{"title": "Basquiat","year": 1996,"rating": 6.9,"votes": 17003,"running_times": 6480},{"title": "Bastille Day","year": 2016,"rating": 6.3,"votes": 24569,"running_times": 5520},{"title": "Batman & Robin","year": 1997,"rating": 3.7,"votes": 204277,"running_times": 7500},{"title": "Batman","year": 1989,"rating": 7.6,"votes": 292105,"running_times": 7560},{"title": "Batman Begins","year": 2005,"rating": 8.3,"votes": 1089733,"running_times": 8400},{"title": "Batman Forever","year": 1995,"rating": 5.4,"votes": 206110,"running_times": 7260},{"title": "Batman Returns","year": 1992,"rating": 7,"votes": 234839,"running_times": 7560},{"title": "Batman v Superman: Dawn of Justice","year": 2016,"rating": 6.6,"votes": 512936,"running_times": 10980},{"title": "Batman: Mask of the Phantasm","year": 1993,"rating": 7.9,"votes": 34069,"running_times": 4560},{"title": "Batman: The Killing Joke","year": 2016,"rating": 6.5,"votes": 37257,"running_times": 5160},{"title": "Batman: The Movie","year": 1966,"rating": 6.5,"votes": 25655,"running_times": 6300},{"title": "Battle Los Angeles","year": 2011,"rating": 5.8,"votes": 161428,"running_times": 6960},{"title": "Battle for the Planet of the Apes","year": 1973,"rating": 5.5,"votes": 25097,"running_times": 5760},{"title": "Battle in Seattle","year": 2007,"rating": 6.7,"votes": 13340,"running_times": 5940},{"title": "Battle of Britain","year": 1969,"rating": 7,"votes": 17536,"running_times": 7920},{"title": "Battle of the Bulge","year": 1965,"rating": 6.8,"votes": 12257,"running_times": 10020},{"title": "Battlefield Earth","year": 2000,"rating": 2.4,"votes": 68599,"running_times": 7140},{"title": "Battleship","year": 2012,"rating": 5.8,"votes": 214998,"running_times": 7860},{"title": "Baywatch","year": 2017,"rating": 5.6,"votes": 82335,"running_times": 7260},{"title": "Be Cool","year": 2005,"rating": 5.7,"votes": 62138,"running_times": 7080},{"title": "Be Kind Rewind","year": 2008,"rating": 6.4,"votes": 83213,"running_times": 6120},{"title": "Beaches","year": 1988,"rating": 6.8,"votes": 19848,"running_times": 7380},{"title": "Bean","year": 1997,"rating": 6.4,"votes": 82345,"running_times": 5340},{"title": "Beastly","year": 2011,"rating": 5.6,"votes": 68792,"running_times": 5160},{"title": "Beasts of No Nation","year": 2015,"rating": 7.8,"votes": 54204,"running_times": 8220},{"title": "Beasts of the Southern Wild","year": 2012,"rating": 7.3,"votes": 74360,"running_times": 5580},{"title": "Beautiful Creatures","year": 2013,"rating": 6.2,"votes": 74302,"running_times": 7440},{"title": "Beautiful Girls","year": 1996,"rating": 7.2,"votes": 28097,"running_times": 6720},{"title": "Beautiful Thing","year": 1996,"rating": 7.7,"votes": 19989,"running_times": 5400},{"title": "Beauty Shop","year": 2005,"rating": 5.5,"votes": 14381,"running_times": 6300},{"title": "Beauty and the Beast","year": 1991,"rating": 8,"votes": 350813,"running_times": 5460},{"title": "Beauty and the Beast","year": 2017,"rating": 7.3,"votes": 184598,"running_times": 7740},{"title": "Beavis and Butt-Head Do America","year": 1996,"rating": 6.8,"votes": 45803,"running_times": 4860},{"title": "Because I Said So","year": 2007,"rating": 5.6,"votes": 34147,"running_times": 6120},{"title": "Becket","year": 1964,"rating": 8,"votes": 11879,"running_times": 9000},{"title": "Becoming Jane","year": 2007,"rating": 7.1,"votes": 50882,"running_times": 7200},{"title": "Bedazzled","year": 2000,"rating": 6,"votes": 86774,"running_times": 5580},{"title": "Bedknobs and Broomsticks","year": 1971,"rating": 7,"votes": 28432,"running_times": 8340},{"title": "Bedtime Stories","year": 2008,"rating": 6.1,"votes": 77344,"running_times": 5940},{"title": "Bee Movie","year": 2007,"rating": 6.1,"votes": 116761,"running_times": 5460},{"title": "Beerfest","year": 2006,"rating": 6.3,"votes": 57341,"running_times": 6600},{"title": "Beethoven","year": 1992,"rating": 5.6,"votes": 54880,"running_times": 5220},{"title": "Beethoven's 2nd","year": 1993,"rating": 4.8,"votes": 21277,"running_times": 5340},{"title": "Beetlejuice","year": 1988,"rating": 7.5,"votes": 210761,"running_times": 5520},{"title": "Before I Fall","year": 2017,"rating": 6.4,"votes": 25814,"running_times": 5880},{"title": "Before I Go to Sleep","year": 2014,"rating": 6.3,"votes": 57345,"running_times": 5520},{"title": "Before I Wake","year": 2016,"rating": 6.1,"votes": 21958,"running_times": 5820},{"title": "Before Midnight","year": 2013,"rating": 7.9,"votes": 110256,"running_times": 6540},{"title": "Before Night Falls","year": 2000,"rating": 7.3,"votes": 21900,"running_times": 7980},{"title": "Before Sunrise","year": 1995,"rating": 8.1,"votes": 210714,"running_times": 6060},{"title": "Before Sunset","year": 2004,"rating": 8,"votes": 185303,"running_times": 4800},{"title": "Before We Go","year": 2014,"rating": 6.9,"votes": 35613,"running_times": 5700},{"title": "Before the Devil Knows You're Dead","year": 2007,"rating": 7.3,"votes": 86289,"running_times": 7020},{"title": "Before the Flood","year": 2016,"rating": 8.3,"votes": 18725,"running_times": 5760},{"title": "Before the Rain","year": 1994,"rating": 8.1,"votes": 12111,"running_times": 6780},{"title": "Begin Again","year": 2013,"rating": 7.4,"votes": 118069,"running_times": 6240},{"title": "Beginners","year": 2010,"rating": 7.2,"votes": 79601,"running_times": 6300},{"title": "Behind Enemy Lines","year": 2001,"rating": 6.4,"votes": 91282,"running_times": 6360},{"title": "Behind the Mask: The Rise of Leslie Vernon","year": 2006,"rating": 6.8,"votes": 18319,"running_times": 5520},{"title": "Being Flynn","year": 2012,"rating": 6.4,"votes": 14976,"running_times": 6120},{"title": "Being John Malkovich","year": 1999,"rating": 7.8,"votes": 272442,"running_times": 6720},{"title": "Being Julia","year": 2004,"rating": 7,"votes": 11098,"running_times": 6240},{"title": "Being There","year": 1979,"rating": 8,"votes": 56236,"running_times": 7800},{"title": "Bel Ami","year": 2012,"rating": 5.4,"votes": 16345,"running_times": 6120},{"title": "Belle","year": 2013,"rating": 7.4,"votes": 23459,"running_times": 6000},{"title": "Below","year": 2002,"rating": 6.2,"votes": 18954,"running_times": 6300},{"title": "Ben-Hur","year": 1959,"rating": 8.1,"votes": 180774,"running_times": 13440},{"title": "Ben-Hur","year": 2016,"rating": 5.7,"votes": 33045,"running_times": 7380},{"title": "Bend It Like Beckham","year": 2002,"rating": 6.7,"votes": 95098,"running_times": 6900},{"title": "Beneath the Planet of the Apes","year": 1970,"rating": 6.1,"votes": 36158,"running_times": 5700},{"title": "Benny & Joon","year": 1993,"rating": 7.2,"votes": 49002,"running_times": 5880},{"title": "Benny's Video","year": 1992,"rating": 7.2,"votes": 10776,"running_times": 6300},{"title": "Beowulf & Grendel","year": 2005,"rating": 5.9,"votes": 16350,"running_times": 6180},{"title": "Beowulf","year": 1999,"rating": 4,"votes": 10148,"running_times": 5940},{"title": "Beowulf","year": 2007,"rating": 6.2,"votes": 149083,"running_times": 6900},{"title": "Berberian Sound Studio","year": 2012,"rating": 6.2,"votes": 11697,"running_times": 5520},{"title": "Berlin Syndrome","year": 2017,"rating": 6.3,"votes": 11929,"running_times": 6960},{"title": "Bernie","year": 2011,"rating": 6.8,"votes": 50518,"running_times": 6240},{"title": "Best in Show","year": 2000,"rating": 7.5,"votes": 48767,"running_times": 5400},{"title": "Best of the Best","year": 1989,"rating": 6.4,"votes": 10324,"running_times": 5820},{"title": "Better Living Through Chemistry","year": 2014,"rating": 6.3,"votes": 12403,"running_times": 5460},{"title": "Better Off Dead...","year": 1985,"rating": 7.2,"votes": 36214,"running_times": 5820},{"title": "Beverly Hills Chihuahua","year": 2008,"rating": 3.7,"votes": 18917,"running_times": 5460},{"title": "Beverly Hills Cop","year": 1984,"rating": 7.3,"votes": 138092,"running_times": 6300},{"title": "Beverly Hills Cop II","year": 1987,"rating": 6.5,"votes": 91948,"running_times": 6000},{"title": "Beverly Hills Cop III","year": 1994,"rating": 5.5,"votes": 65593,"running_times": 6240},{"title": "Beverly Hills Ninja","year": 1997,"rating": 5.5,"votes": 33242,"running_times": 5280},{"title": "Bewitched","year": 2005,"rating": 4.8,"votes": 61926,"running_times": 6120},{"title": "Beyond Borders","year": 2003,"rating": 6.5,"votes": 23974,"running_times": 7620},{"title": "Beyond a Reasonable Doubt","year": 2009,"rating": 5.9,"votes": 11253,"running_times": 6360},{"title": "Beyond the Lights","year": 2014,"rating": 6.9,"votes": 12882,"running_times": 6960},{"title": "Beyond the Sea","year": 2004,"rating": 6.7,"votes": 13535,"running_times": 7080},{"title": "Bicentennial Man","year": 1999,"rating": 6.8,"votes": 95874,"running_times": 7920},{"title": "Big","year": 1988,"rating": 7.3,"votes": 165755,"running_times": 7800},{"title": "Big Daddy","year": 1999,"rating": 6.4,"votes": 173724,"running_times": 5580},{"title": "Big Eyes","year": 2014,"rating": 7,"votes": 68354,"running_times": 6360},{"title": "Big Fat Liar","year": 2002,"rating": 5.4,"votes": 30820,"running_times": 5280},{"title": "Big Fish","year": 2003,"rating": 8,"votes": 372206,"running_times": 7500},{"title": "Big Game","year": 2014,"rating": 5.4,"votes": 25066,"running_times": 6600},{"title": "Big Hero 6","year": 2014,"rating": 7.8,"votes": 325944,"running_times": 6120},{"title": "Big Miracle","year": 2012,"rating": 6.5,"votes": 16311,"running_times": 6420},{"title": "Big Momma's House","year": 2000,"rating": 5.1,"votes": 71764,"running_times": 5940},{"title": "Big Momma's House 2","year": 2006,"rating": 4.6,"votes": 34990,"running_times": 5940},{"title": "Big Mommas: Like Father, Like Son","year": 2011,"rating": 4.4,"votes": 21699,"running_times": 6780},{"title": "Big Night","year": 1996,"rating": 7.3,"votes": 14157,"running_times": 6540},{"title": "Big Nothing","year": 2006,"rating": 6.8,"votes": 27146,"running_times": 5160},{"title": "Big Stan","year": 2007,"rating": 6.2,"votes": 36691,"running_times": 6300},{"title": "Big Trouble","year": 2002,"rating": 6.5,"votes": 18242,"running_times": 5100},{"title": "Big Trouble in Little China","year": 1986,"rating": 7.3,"votes": 103133,"running_times": 5940},{"title": "Bigger Stronger Faster*","year": 2008,"rating": 7.6,"votes": 12389,"running_times": 6300},{"title": "Biker Boyz","year": 2003,"rating": 4.6,"votes": 11604,"running_times": 6600},{"title": "Bikur Ha-Tizmoret","year": 2007,"rating": 7.6,"votes": 11513,"running_times": 5220},{"title": "Bill & Ted's Bogus Journey","year": 1991,"rating": 6.2,"votes": 53320,"running_times": 5580},{"title": "Bill & Ted's Excellent Adventure","year": 1989,"rating": 6.9,"votes": 91698,"running_times": 5400},{"title": "Bill","year": 2007,"rating": 6.3,"votes": 18340,"running_times": 5580},{"title": "Billy Bathgate","year": 1991,"rating": 5.9,"votes": 10143,"running_times": 6360},{"title": "Billy Elliot","year": 2000,"rating": 7.7,"votes": 105511,"running_times": 6600},{"title": "Billy Lynn's Long Halftime Walk","year": 2016,"rating": 6.3,"votes": 15639,"running_times": 6780},{"title": "Billy Madison","year": 1995,"rating": 6.4,"votes": 113436,"running_times": 5340},{"title": "Biloxi Blues","year": 1988,"rating": 6.6,"votes": 12664,"running_times": 6360},{"title": "Bio-Dome","year": 1996,"rating": 4.4,"votes": 22920,"running_times": 5700},{"title": "Bird on a Wire","year": 1990,"rating": 5.9,"votes": 33891,"running_times": 6600},{"title": "Birdemic: Shock and Terror","year": 2010,"rating": 1.8,"votes": 16894,"running_times": 6300},{"title": "Birdman of Alcatraz","year": 1962,"rating": 7.8,"votes": 13386,"running_times": 8820},{"title": "Birdman or (The Unexpected Virtue of Ignorance)","year": 2014,"rating": 7.8,"votes": 463395,"running_times": 7140},{"title": "Birdy","year": 1984,"rating": 7.3,"votes": 18621,"running_times": 7200},{"title": "Birth","year": 2004,"rating": 6.1,"votes": 31442,"running_times": 6000},{"title": "Birthday Girl","year": 2001,"rating": 6.1,"votes": 22488,"running_times": 5580},{"title": "Bitch Slap","year": 2009,"rating": 4.5,"votes": 12541,"running_times": 6540},{"title": "Bitter Moon","year": 1992,"rating": 7.2,"votes": 28437,"running_times": 8340},{"title": "Black","year": 2005,"rating": 8.2,"votes": 28133,"running_times": 7320},{"title": "Black Christmas","year": 1974,"rating": 7.2,"votes": 24393,"running_times": 5880},{"title": "Black Christmas","year": 2006,"rating": 4.6,"votes": 21469,"running_times": 5640},{"title": "Black Death","year": 2010,"rating": 6.4,"votes": 38775,"running_times": 6120},{"title": "Black Dynamite","year": 2009,"rating": 7.4,"votes": 38921,"running_times": 5040},{"title": "Black Hawk Down","year": 2001,"rating": 7.7,"votes": 317178,"running_times": 9120},{"title": "Black Knight","year": 2001,"rating": 4.8,"votes": 33164,"running_times": 5700},{"title": "Black Mass","year": 2015,"rating": 6.9,"votes": 142953,"running_times": 7380},{"title": "Black Narcissus","year": 1947,"rating": 8,"votes": 17316,"running_times": 6060},{"title": "Black Rain","year": 1989,"rating": 6.6,"votes": 42471,"running_times": 7500},{"title": "Black Sea","year": 2014,"rating": 6.4,"votes": 28893,"running_times": 6840},{"title": "Black Sheep","year": 1996,"rating": 6.2,"votes": 31823,"running_times": 5220},{"title": "Black Sheep","year": 2006,"rating": 5.8,"votes": 36324,"running_times": 5220},{"title": "Black Snake Moan","year": 2006,"rating": 7,"votes": 55960,"running_times": 6960},{"title": "Black Swan","year": 2010,"rating": 8,"votes": 601083,"running_times": 6480},{"title": "Black Water","year": 2007,"rating": 6,"votes": 10724,"running_times": 5400},{"title": "Blackadder Back & Forth","year": 1999,"rating": 7.7,"votes": 11766,"running_times": 1980},{"title": "Blackfish","year": 2013,"rating": 8.1,"votes": 51958,"running_times": 4980},{"title": "Blackhat","year": 2015,"rating": 5.4,"votes": 44981,"running_times": 7980},{"title": "Blade","year": 1998,"rating": 7.1,"votes": 209150,"running_times": 7200},{"title": "Blade II","year": 2002,"rating": 6.7,"votes": 173270,"running_times": 7020},{"title": "Blade Runner","year": 1982,"rating": 8.2,"votes": 549243,"running_times": 7020},{"title": "Blade Runner 2049","year": 2017,"rating": 8.4,"votes": 159689,"running_times": 9840},{"title": "Blade: Trinity","year": 2004,"rating": 5.9,"votes": 145063,"running_times": 7320},{"title": "Blades of Glory","year": 2007,"rating": 6.3,"votes": 138656,"running_times": 5580},{"title": "Blair Witch","year": 2016,"rating": 5,"votes": 31208,"running_times": 5340},{"title": "Blank Check","year": 1994,"rating": 5.2,"votes": 15623,"running_times": 5580},{"title": "Blast from the Past","year": 1999,"rating": 6.6,"votes": 52616,"running_times": 6720},{"title": "Blazing Saddles","year": 1974,"rating": 7.8,"votes": 106624,"running_times": 5580},{"title": "Bleed for This","year": 2016,"rating": 6.8,"votes": 16729,"running_times": 7020},{"title": "Blended","year": 2014,"rating": 6.5,"votes": 97403,"running_times": 7020},{"title": "Bless the Child","year": 2000,"rating": 5.1,"votes": 12753,"running_times": 6420},{"title": "Blind Date","year": 1987,"rating": 5.9,"votes": 18050,"running_times": 5700},{"title": "Blind Dating","year": 2006,"rating": 6.1,"votes": 10481,"running_times": 5700},{"title": "Blind Fury","year": 1989,"rating": 6.3,"votes": 11747,"running_times": 5160},{"title": "Blindness","year": 2008,"rating": 6.6,"votes": 62790,"running_times": 7260},{"title": "Blitz","year": 2011,"rating": 6.2,"votes": 73267,"running_times": 5820},{"title": "Blood Diamond","year": 2006,"rating": 8,"votes": 434531,"running_times": 8580},{"title": "Blood Father","year": 2016,"rating": 6.4,"votes": 45527,"running_times": 5280},{"title": "Blood Simple.","year": 1984,"rating": 7.7,"votes": 73424,"running_times": 5940},{"title": "Blood Ties","year": 2013,"rating": 6.5,"votes": 16346,"running_times": 8640},{"title": "Blood Work","year": 2002,"rating": 6.4,"votes": 36930,"running_times": 6600},{"title": "Blood and Bone","year": 2009,"rating": 6.7,"votes": 27624,"running_times": 5580},{"title": "Blood and Chocolate","year": 2007,"rating": 5.5,"votes": 16063,"running_times": 5880},{"title": "Blood: The Last Vampire","year": 2000,"rating": 6.7,"votes": 10762,"running_times": 2880},{"title": "Blood: The Last Vampire","year": 2009,"rating": 5.3,"votes": 13610,"running_times": 5460},{"title": "BloodRayne","year": 2005,"rating": 2.9,"votes": 31603,"running_times": 5700},{"title": "Bloodsport","year": 1988,"rating": 6.8,"votes": 64098,"running_times": 5520},{"title": "Bloody Sunday","year": 2002,"rating": 7.7,"votes": 21001,"running_times": 6420},{"title": "Blow","year": 2001,"rating": 7.6,"votes": 212868,"running_times": 7440},{"title": "Blow Out","year": 1981,"rating": 7.4,"votes": 32263,"running_times": 6420},{"title": "Blown Away","year": 1994,"rating": 6.2,"votes": 24653,"running_times": 7260},{"title": "Blowup","year": 1966,"rating": 7.6,"votes": 46137,"running_times": 6660},{"title": "Blue Chips","year": 1994,"rating": 6.1,"votes": 10259,"running_times": 6480},{"title": "Blue Crush","year": 2002,"rating": 5.6,"votes": 27345,"running_times": 6240},{"title": "Blue Jasmine","year": 2013,"rating": 7.3,"votes": 166439,"running_times": 5880},{"title": "Blue Mountain State: The Rise of Thadland","year": 2016,"rating": 5.9,"votes": 11882,"running_times": 5400},{"title": "Blue Ruin","year": 2013,"rating": 7.1,"votes": 52383,"running_times": 5400},{"title": "Blue Steel","year": 1989,"rating": 5.6,"votes": 10090,"running_times": 6120},{"title": "Blue Streak","year": 1999,"rating": 6.3,"votes": 64619,"running_times": 5580},{"title": "Blue Thunder","year": 1983,"rating": 6.4,"votes": 13524,"running_times": 6540},{"title": "Blue Valentine","year": 2010,"rating": 7.4,"votes": 156851,"running_times": 6720},{"title": "Blue Velvet","year": 1986,"rating": 7.8,"votes": 148871,"running_times": 10320},{"title": "Blues Brothers 2000","year": 1998,"rating": 4.8,"votes": 27755,"running_times": 7380},{"title": "Boat Trip","year": 2002,"rating": 4.9,"votes": 28039,"running_times": 5820},{"title": "Bob Roberts","year": 1992,"rating": 7,"votes": 12125,"running_times": 6120},{"title": "Bobby","year": 2006,"rating": 7,"votes": 39233,"running_times": 7020},{"title": "Body Double","year": 1984,"rating": 6.8,"votes": 22822,"running_times": 6840},{"title": "Body Heat","year": 1981,"rating": 7.4,"votes": 25400,"running_times": 6780},{"title": "Body Snatchers","year": 1993,"rating": 5.9,"votes": 14485,"running_times": 5220},{"title": "Body of Evidence","year": 1993,"rating": 4.4,"votes": 12109,"running_times": 6120},{"title": "Body of Lies","year": 2008,"rating": 7.1,"votes": 187229,"running_times": 7680},{"title": "Bodyguard","year": 2011,"rating": 4.6,"votes": 18446,"running_times": 7800},{"title": "Boiler Room","year": 2000,"rating": 7,"votes": 44177,"running_times": 7200},{"title": "Bolt","year": 2008,"rating": 6.9,"votes": 160434,"running_times": 5760},{"title": "Bon Cop, Bad Cop","year": 2006,"rating": 6.9,"votes": 10218,"running_times": 7200},{"title": "Bone Tomahawk","year": 2015,"rating": 7.1,"votes": 53235,"running_times": 7920},{"title": "Bonnie and Clyde","year": 1967,"rating": 7.9,"votes": 87339,"running_times": 6660},{"title": "Boogeyman","year": 2005,"rating": 4.1,"votes": 27541,"running_times": 5340},{"title": "Boogie Nights","year": 1997,"rating": 7.9,"votes": 204133,"running_times": 9300},{"title": "Book of Shadows: Blair Witch 2","year": 2000,"rating": 4,"votes": 31854,"running_times": 5400},{"title": "Boomerang","year": 1992,"rating": 5.4,"votes": 21930,"running_times": 7020},{"title": "Borat: Cultural Learnings of America for Make Benefit Glorious Nation of Kazakhstan","year": 2006,"rating": 7.3,"votes": 315298,"running_times": 5040},{"title": "Bordello of Blood","year": 1996,"rating": 5.3,"votes": 11395,"running_times": 5220},{"title": "Borgman","year": 2013,"rating": 6.8,"votes": 13256,"running_times": 6780},{"title": "Born Into Brothels: Calcutta's Red Light Kids","year": 2004,"rating": 7.4,"votes": 13355,"running_times": 5100},{"title": "Born on the Fourth of July","year": 1989,"rating": 7.2,"votes": 83568,"running_times": 8700},{"title": "Bottle Rocket","year": 1996,"rating": 7.1,"votes": 59209,"running_times": 5700},{"title": "Bottle Shock","year": 2008,"rating": 6.8,"votes": 13142,"running_times": 6600},{"title": "Bounce","year": 2000,"rating": 5.7,"votes": 18442,"running_times": 6360},{"title": "Bound","year": 1996,"rating": 7.4,"votes": 44030,"running_times": 6540},{"title": "Bound by Honor","year": 1993,"rating": 8,"votes": 24940,"running_times": 19800},{"title": "Boundin'","year": 2003,"rating": 7,"votes": 10569,"running_times": 300},{"title": "Bowfinger","year": 1999,"rating": 6.4,"votes": 59927,"running_times": 5820},{"title": "Bowling for Columbine","year": 2002,"rating": 8,"votes": 129424,"running_times": 7200},{"title": "Boxing Helena","year": 1993,"rating": 4.6,"votes": 10175,"running_times": 6420},{"title": "Boy","year": 2010,"rating": 7.5,"votes": 12607,"running_times": 5220},{"title": "Boy A","year": 2007,"rating": 7.7,"votes": 34618,"running_times": 6120},{"title": "Boyhood","year": 2014,"rating": 7.9,"votes": 296371,"running_times": 9900},{"title": "Boys Don't Cry","year": 1999,"rating": 7.6,"votes": 82611,"running_times": 7080},{"title": "Boys and Girls","year": 2000,"rating": 5.4,"votes": 14502,"running_times": 5640},{"title": "Boys on the Side","year": 1995,"rating": 6.4,"votes": 10282,"running_times": 6900},{"title": "Boyz n the Hood","year": 1991,"rating": 7.8,"votes": 103550,"running_times": 6720},{"title": "Braindead","year": 1992,"rating": 7.5,"votes": 82550,"running_times": 6240},{"title": "Brake","year": 2012,"rating": 6.1,"votes": 10558,"running_times": 5520},{"title": "Brassed Off","year": 1996,"rating": 7.1,"votes": 16742,"running_times": 6180},{"title": "Brat","year": 1997,"rating": 8,"votes": 12125,"running_times": 5940},{"title": "Bratz","year": 2007,"rating": 2.9,"votes": 15681,"running_times": 6600},{"title": "Brave","year": 2012,"rating": 7.2,"votes": 306335,"running_times": 5580},{"title": "Braveheart","year": 1995,"rating": 8.4,"votes": 817912,"running_times": 13500},{"title": "Brawl in Cell Block 99","year": 2017,"rating": 7.2,"votes": 11487,"running_times": 7920},{"title": "Brazil","year": 1985,"rating": 8,"votes": 164563,"running_times": 8520},{"title": "Breach","year": 2007,"rating": 7,"votes": 53971,"running_times": 6600},{"title": "Breakdown","year": 1997,"rating": 6.9,"votes": 41285,"running_times": 5580},{"title": "Breakfast at Tiffany's","year": 1961,"rating": 7.7,"votes": 137679,"running_times": 6900},{"title": "Breakfast on Pluto","year": 2005,"rating": 7.3,"votes": 18572,"running_times": 7680},{"title": "Breaking Away","year": 1979,"rating": 7.7,"votes": 18743,"running_times": 6060},{"title": "Breaking and Entering","year": 2006,"rating": 6.5,"votes": 20696,"running_times": 7200},{"title": "Breaking the Waves","year": 1996,"rating": 7.9,"votes": 52970,"running_times": 9540},{"title": "Breathe In","year": 2013,"rating": 6.4,"votes": 12109,"running_times": 5880},{"title": "Brewster's Millions","year": 1985,"rating": 6.5,"votes": 30512,"running_times": 6120},{"title": "Brick","year": 2005,"rating": 7.4,"votes": 90277,"running_times": 6600},{"title": "Brick Mansions","year": 2014,"rating": 5.7,"votes": 35186,"running_times": 6000},{"title": "Bride & Prejudice","year": 2004,"rating": 6.2,"votes": 18303,"running_times": 7320},{"title": "Bride Wars","year": 2009,"rating": 5.5,"votes": 87239,"running_times": 5340},{"title": "Bride of Chucky","year": 1998,"rating": 5.4,"votes": 43904,"running_times": 5340},{"title": "Bride of Frankenstein","year": 1935,"rating": 7.9,"votes": 35950,"running_times": 4500},{"title": "Bride of Re-Animator","year": 1989,"rating": 6.3,"votes": 10648,"running_times": 5760},{"title": "Brideshead Revisited","year": 2008,"rating": 6.7,"votes": 10686,"running_times": 7980},{"title": "Bridesmaids","year": 2011,"rating": 6.8,"votes": 234286,"running_times": 7800},{"title": "Bridge of Spies","year": 2015,"rating": 7.6,"votes": 232893,"running_times": 8520},{"title": "Bridge to Terabithia","year": 2007,"rating": 7.2,"votes": 121347,"running_times": 5760},{"title": "Bridget Jones's Baby","year": 2016,"rating": 6.6,"votes": 50177,"running_times": 7080},{"title": "Bridget Jones's Diary","year": 2001,"rating": 6.7,"votes": 191145,"running_times": 5820},{"title": "Bridget Jones: The Edge of Reason","year": 2004,"rating": 5.9,"votes": 87286,"running_times": 6480},{"title": "Brief Encounter","year": 1945,"rating": 8.1,"votes": 28907,"running_times": 5160},{"title": "Bright Star","year": 2009,"rating": 7,"votes": 22780,"running_times": 7140},{"title": "Brimstone","year": 2016,"rating": 7.1,"votes": 20832,"running_times": 8880},{"title": "Bring It On","year": 2000,"rating": 6,"votes": 75286,"running_times": 5880},{"title": "Bring Me the Head of Alfredo Garcia","year": 1974,"rating": 7.5,"votes": 15116,"running_times": 6720},{"title": "Bringing Down the House","year": 2003,"rating": 5.6,"votes": 31573,"running_times": 6300},{"title": "Bringing Out the Dead","year": 1999,"rating": 6.8,"votes": 56164,"running_times": 7260},{"title": "Bringing Up Baby","year": 1938,"rating": 8,"votes": 47943,"running_times": 6120},{"title": "Broadcast News","year": 1987,"rating": 7.2,"votes": 23019,"running_times": 7980},{"title": "Broadway Danny Rose","year": 1984,"rating": 7.5,"votes": 20316,"running_times": 5040},{"title": "Brokeback Mountain","year": 2005,"rating": 7.7,"votes": 279350,"running_times": 8040},{"title": "Brokedown Palace","year": 1999,"rating": 6.4,"votes": 19642,"running_times": 6000},{"title": "Broken","year": 2012,"rating": 7.3,"votes": 11713,"running_times": 5460},{"title": "Broken Arrow","year": 1996,"rating": 6,"votes": 81632,"running_times": 6480},{"title": "Broken City","year": 2013,"rating": 6.2,"votes": 68201,"running_times": 6540},{"title": "Broken Flowers","year": 2005,"rating": 7.2,"votes": 87301,"running_times": 6360},{"title": "Bronson","year": 2008,"rating": 7.1,"votes": 99451,"running_times": 5520},{"title": "Brooklyn","year": 2015,"rating": 7.5,"votes": 101435,"running_times": 7020},{"title": "Brooklyn's Finest","year": 2009,"rating": 6.7,"votes": 55474,"running_times": 7920},{"title": "Brother","year": 2000,"rating": 7.2,"votes": 19732,"running_times": 6840},{"title": "Brother Bear","year": 2003,"rating": 6.8,"votes": 78629,"running_times": 5100},{"title": "Brothers","year": 2009,"rating": 7.1,"votes": 95987,"running_times": 6300},{"title": "Brubaker","year": 1980,"rating": 7.1,"votes": 13091,"running_times": 7860},{"title": "Bruce Almighty","year": 2003,"rating": 6.7,"votes": 322967,"running_times": 6060},{"title": "Brüno","year": 2009,"rating": 5.8,"votes": 126745,"running_times": 4860},{"title": "Bubba Ho-Tep","year": 2002,"rating": 7.2,"votes": 40966,"running_times": 5520},{"title": "Bubble Boy","year": 2001,"rating": 5.6,"votes": 27195,"running_times": 5040},{"title": "Bucky Larson: Born to Be a Star","year": 2011,"rating": 3.3,"votes": 10028,"running_times": 5820},{"title": "Bud Abbott Lou Costello Meet Frankenstein","year": 1948,"rating": 7.6,"votes": 12025,"running_times": 5400},{"title": "Buena Vista Social Club","year": 1999,"rating": 7.6,"votes": 14396,"running_times": 6300},{"title": "Buffalo '66","year": 1998,"rating": 7.5,"votes": 39780,"running_times": 6600},{"title": "Buffalo Soldiers","year": 2001,"rating": 6.9,"votes": 21482,"running_times": 5880},{"title": "Buffy the Vampire Slayer","year": 1992,"rating": 5.6,"votes": 34513,"running_times": 5160},{"title": "Bug","year": 2006,"rating": 6.1,"votes": 29613,"running_times": 6120},{"title": "Bugsy","year": 1991,"rating": 6.8,"votes": 22391,"running_times": 8940},{"title": "Bugsy Malone","year": 1976,"rating": 6.8,"votes": 13397,"running_times": 5580},{"title": "Bull Durham","year": 1988,"rating": 7.1,"votes": 39732,"running_times": 6480},{"title": "Bullet to the Head","year": 2012,"rating": 5.7,"votes": 42174,"running_times": 5520},{"title": "Bulletproof","year": 1996,"rating": 5.8,"votes": 31443,"running_times": 5040},{"title": "Bulletproof Monk","year": 2003,"rating": 5.5,"votes": 44196,"running_times": 6240},{"title": "Bullets Over Broadway","year": 1994,"rating": 7.5,"votes": 31528,"running_times": 5880},{"title": "Bullitt","year": 1968,"rating": 7.5,"votes": 50729,"running_times": 6840},{"title": "Bully","year": 2001,"rating": 7,"votes": 30991,"running_times": 6780},{"title": "Bulworth","year": 1998,"rating": 6.8,"votes": 22996,"running_times": 6480},{"title": "Bunraku","year": 2010,"rating": 6.2,"votes": 17571,"running_times": 7440},{"title": "Buried","year": 2010,"rating": 7,"votes": 129590,"running_times": 5700},{"title": "Burke and Hare","year": 2010,"rating": 6.2,"votes": 17376,"running_times": 5460},{"title": "Burlesque","year": 2010,"rating": 6.4,"votes": 66239,"running_times": 7140},{"title": "Burn After Reading","year": 2008,"rating": 7,"votes": 267214,"running_times": 5760},{"title": "Burnt","year": 2015,"rating": 6.6,"votes": 82978,"running_times": 6060},{"title": "But I'm a Cheerleader","year": 1999,"rating": 6.6,"votes": 21535,"running_times": 5100},{"title": "Butch Cassidy and the Sundance Kid","year": 1969,"rating": 8.1,"votes": 168819,"running_times": 6600},{"title": "Butter","year": 2011,"rating": 6.2,"votes": 18455,"running_times": 5400},{"title": "Butterfly on a Wheel","year": 2007,"rating": 6.7,"votes": 27161,"running_times": 5880},{"title": "By the Sea","year": 2015,"rating": 5.2,"votes": 13448,"running_times": 7320},{"title": "Byzantium","year": 2012,"rating": 6.5,"votes": 35211,"running_times": 7080},{"title": "Byôsoku 5 senchimêtoru","year": 2007,"rating": 7.7,"votes": 35965,"running_times": 3780},{"title": "Bølgen","year": 2015,"rating": 6.7,"votes": 21289,"running_times": 6300},{"title": "C.R.A.Z.Y.","year": 2005,"rating": 8,"votes": 28956,"running_times": 7620},{"title": "CHIPS","year": 2017,"rating": 6,"votes": 24799,"running_times": 6060},{"title": "Cabaret","year": 1972,"rating": 7.8,"votes": 39966,"running_times": 7440},{"title": "Cabin Fever","year": 2002,"rating": 5.6,"votes": 66293,"running_times": 5880},{"title": "Cabin Fever 2: Spring Fever","year": 2009,"rating": 4.3,"votes": 11073,"running_times": 5160},{"title": "Caddyshack","year": 1980,"rating": 7.3,"votes": 88789,"running_times": 5880},{"title": "Caddyshack II","year": 1988,"rating": 3.7,"votes": 13034,"running_times": 5880},{"title": "Cadillac Man","year": 1990,"rating": 5.6,"votes": 11472,"running_times": 5820},{"title": "Cadillac Records","year": 2008,"rating": 7,"votes": 16892,"running_times": 6540},{"title": "Café Society","year": 2016,"rating": 6.6,"votes": 52800,"running_times": 5760},{"title": "Cake","year": 2014,"rating": 6.4,"votes": 30781,"running_times": 6120},{"title": "Calendar Girls","year": 2003,"rating": 6.9,"votes": 20684,"running_times": 6480},{"title": "Caligola","year": 1979,"rating": 5.3,"votes": 29361,"running_times": 9360},{"title": "Calvary","year": 2014,"rating": 7.4,"votes": 47886,"running_times": 6120},{"title": "Camp X-Ray","year": 2014,"rating": 7,"votes": 33991,"running_times": 7020},{"title": "Can't Buy Me Love","year": 1987,"rating": 6.7,"votes": 26695,"running_times": 5640},{"title": "Can't Hardly Wait","year": 1998,"rating": 6.5,"votes": 39898,"running_times": 6060},{"title": "Canadian Bacon","year": 1995,"rating": 5.9,"votes": 14379,"running_times": 5460},{"title": "Candy","year": 2006,"rating": 7.3,"votes": 38489,"running_times": 6960},{"title": "Candyman","year": 1992,"rating": 6.6,"votes": 54767,"running_times": 5940},{"title": "Cannibal Holocaust","year": 1980,"rating": 6,"votes": 42774,"running_times": 5700},{"title": "Cannonball Run II","year": 1984,"rating": 4.9,"votes": 12651,"running_times": 6480},{"title": "Cape Fear","year": 1962,"rating": 7.8,"votes": 22104,"running_times": 6360},{"title": "Cape Fear","year": 1991,"rating": 7.3,"votes": 140015,"running_times": 7680},{"title": "Capitalism: A Love Story","year": 2009,"rating": 7.4,"votes": 37838,"running_times": 7620},{"title": "Capote","year": 2005,"rating": 7.4,"votes": 109265,"running_times": 6840},{"title": "Capricorn One","year": 1977,"rating": 6.8,"votes": 17173,"running_times": 7800},{"title": "Captain America: Civil War","year": 2016,"rating": 7.9,"votes": 457587,"running_times": 8820},{"title": "Captain America: The First Avenger","year": 2011,"rating": 6.9,"votes": 572492,"running_times": 7440},{"title": "Captain America: The Winter Soldier","year": 2014,"rating": 7.8,"votes": 570329,"running_times": 8160},{"title": "Captain Blood","year": 1935,"rating": 7.8,"votes": 10708,"running_times": 7140},{"title": "Captain Corelli's Mandolin","year": 2001,"rating": 5.9,"votes": 29674,"running_times": 7860},{"title": "Captain Fantastic","year": 2016,"rating": 7.9,"votes": 127916,"running_times": 7080},{"title": "Captain Phillips","year": 2013,"rating": 7.8,"votes": 358882,"running_times": 8040},{"title": "Captain Ron","year": 1992,"rating": 5.7,"votes": 18068,"running_times": 5760},{"title": "Captain Underpants: The First Epic Movie","year": 2017,"rating": 6.2,"votes": 13648,"running_times": 5340},{"title": "Captivity","year": 2007,"rating": 4.7,"votes": 21294,"running_times": 5760},{"title": "Capturing the Friedmans","year": 2003,"rating": 7.8,"votes": 20887,"running_times": 6420},{"title": "Carlito's Way","year": 1993,"rating": 7.9,"votes": 174852,"running_times": 8640},{"title": "Carnage","year": 2011,"rating": 7.2,"votes": 104582,"running_times": 4800},{"title": "Carnival of Souls","year": 1962,"rating": 7.2,"votes": 15495,"running_times": 5460},{"title": "Carol","year": 2015,"rating": 7.2,"votes": 84444,"running_times": 7080},{"title": "Carrie","year": 1976,"rating": 7.4,"votes": 138986,"running_times": 5880},{"title": "Carrie","year": 2013,"rating": 5.9,"votes": 117179,"running_times": 6000},{"title": "Carriers","year": 2009,"rating": 6,"votes": 37502,"running_times": 5040},{"title": "Cars","year": 2006,"rating": 7.1,"votes": 295881,"running_times": 7020},{"title": "Cars 2","year": 2011,"rating": 6.2,"votes": 119432,"running_times": 6360},{"title": "Cars 3","year": 2017,"rating": 6.9,"votes": 32897,"running_times": 6120},{"title": "Cartel Land","year": 2015,"rating": 7.4,"votes": 14922,"running_times": 6000},{"title": "Casa de mi Padre","year": 2012,"rating": 5.5,"votes": 18263,"running_times": 5040},{"title": "Casablanca","year": 1942,"rating": 8.5,"votes": 430019,"running_times": 6120},{"title": "Casanova","year": 2005,"rating": 6.5,"votes": 47010,"running_times": 6720},{"title": "Case 39","year": 2009,"rating": 6.2,"votes": 66072,"running_times": 6540},{"title": "Cashback","year": 2006,"rating": 7.2,"votes": 76620,"running_times": 6120},{"title": "Casino","year": 1995,"rating": 8.2,"votes": 372920,"running_times": 10680},{"title": "Casino Jack","year": 2010,"rating": 6.2,"votes": 15537,"running_times": 6480},{"title": "Casino Royale","year": 1967,"rating": 5.2,"votes": 23463,"running_times": 7860},{"title": "Casino Royale","year": 2006,"rating": 8,"votes": 508304,"running_times": 8640},{"title": "Casper","year": 1995,"rating": 6.1,"votes": 96437,"running_times": 6000},{"title": "Cassandra's Dream","year": 2007,"rating": 6.7,"votes": 46383,"running_times": 6480},{"title": "Casse-tête chinois","year": 2013,"rating": 7,"votes": 11298,"running_times": 7020},{"title": "Cast Away","year": 2000,"rating": 7.8,"votes": 435433,"running_times": 8580},{"title": "Casualties of War","year": 1989,"rating": 7.1,"votes": 35750,"running_times": 7140},{"title": "Cat Ballou","year": 1965,"rating": 6.9,"votes": 11292,"running_times": 5820},{"title": "Cat People","year": 1942,"rating": 7.4,"votes": 15253,"running_times": 4380},{"title": "Cat People","year": 1982,"rating": 6.1,"votes": 15650,"running_times": 7080},{"title": "Cat on a Hot Tin Roof","year": 1958,"rating": 8.1,"votes": 37011,"running_times": 6480},{"title": "Cat's Eye","year": 1985,"rating": 6.3,"votes": 18823,"running_times": 5640},{"title": "Catch .44","year": 2011,"rating": 4.6,"votes": 15331,"running_times": 5640},{"title": "Catch Me If You Can","year": 2002,"rating": 8.1,"votes": 624495,"running_times": 8460},{"title": "Catch and Release","year": 2006,"rating": 6,"votes": 20037,"running_times": 7440},{"title": "Catch-22","year": 1970,"rating": 7.2,"votes": 18485,"running_times": 7320},{"title": "Catfish","year": 2010,"rating": 7.1,"votes": 37245,"running_times": 5220},{"title": "Cats & Dogs","year": 2001,"rating": 5.1,"votes": 49443,"running_times": 5220},{"title": "Cats & Dogs: The Revenge of Kitty Galore","year": 2010,"rating": 4.3,"votes": 11291,"running_times": 4920},{"title": "Catwoman","year": 2004,"rating": 3.3,"votes": 94234,"running_times": 6240},{"title": "Cave of Forgotten Dreams","year": 2010,"rating": 7.4,"votes": 12911,"running_times": 5700},{"title": "Cecil B. DeMented","year": 2000,"rating": 6.2,"votes": 12003,"running_times": 5220},{"title": "Cedar Rapids","year": 2011,"rating": 6.3,"votes": 33876,"running_times": 5220},{"title": "Celda 211","year": 2009,"rating": 7.7,"votes": 54977,"running_times": 6780},{"title": "Celebrity","year": 1998,"rating": 6.3,"votes": 21809,"running_times": 6780},{"title": "Celeste & Jesse Forever","year": 2012,"rating": 6.6,"votes": 26184,"running_times": 5520},{"title": "Cell","year": 2016,"rating": 4.3,"votes": 18673,"running_times": 5880},{"title": "Cellular","year": 2004,"rating": 6.5,"votes": 83353,"running_times": 5640},{"title": "Cemetery Junction","year": 2010,"rating": 6.9,"votes": 18430,"running_times": 5700},{"title": "Center Stage","year": 2000,"rating": 6.7,"votes": 16679,"running_times": 6900},{"title": "Central Intelligence","year": 2016,"rating": 6.3,"votes": 109993,"running_times": 6960},{"title": "Centurion","year": 2010,"rating": 6.4,"votes": 69872,"running_times": 5820},{"title": "Chain Reaction","year": 1996,"rating": 5.6,"votes": 42923,"running_times": 6420},{"title": "Chained","year": 2012,"rating": 6.4,"votes": 13885,"running_times": 5640},{"title": "Chakushin ari","year": 2003,"rating": 6.2,"votes": 15089,"running_times": 6720},{"title": "Chalet Girl","year": 2011,"rating": 6.3,"votes": 20636,"running_times": 5820},{"title": "Changeling","year": 2008,"rating": 7.8,"votes": 211563,"running_times": 8460},{"title": "Changing Lanes","year": 2002,"rating": 6.5,"votes": 60854,"running_times": 5880},{"title": "Chaos","year": 2005,"rating": 6.5,"votes": 46470,"running_times": 6360},{"title": "Chaos Theory","year": 2008,"rating": 6.7,"votes": 29293,"running_times": 5220},{"title": "Chaplin","year": 1992,"rating": 7.6,"votes": 46419,"running_times": 8580},{"title": "Chappie","year": 2015,"rating": 6.8,"votes": 197879,"running_times": 7200},{"title": "Charade","year": 1963,"rating": 8,"votes": 54637,"running_times": 6780},{"title": "Chariots of Fire","year": 1981,"rating": 7.2,"votes": 44814,"running_times": 7500},{"title": "Charlie Bartlett","year": 2007,"rating": 7,"votes": 58841,"running_times": 5820},{"title": "Charlie St. Cloud","year": 2010,"rating": 6.5,"votes": 51299,"running_times": 5940},{"title": "Charlie Wilson's War","year": 2007,"rating": 7.1,"votes": 94821,"running_times": 6120},{"title": "Charlie and the Chocolate Factory","year": 2005,"rating": 6.7,"votes": 355757,"running_times": 6900},{"title": "Charlie's Angels","year": 2000,"rating": 5.5,"votes": 154142,"running_times": 5880},{"title": "Charlie's Angels: Full Throttle","year": 2003,"rating": 4.8,"votes": 106759,"running_times": 6420},{"title": "Charlotte's Web","year": 1973,"rating": 6.9,"votes": 14527,"running_times": 5640},{"title": "Charlotte's Web","year": 2006,"rating": 6.3,"votes": 30791,"running_times": 5820},{"title": "Chasing Amy","year": 1997,"rating": 7.3,"votes": 120382,"running_times": 6780},{"title": "Chasing Liberty","year": 2004,"rating": 6.1,"votes": 32180,"running_times": 6660},{"title": "Chasing Mavericks","year": 2012,"rating": 7.2,"votes": 27345,"running_times": 6960},{"title": "Che: Part One","year": 2008,"rating": 7.2,"votes": 40419,"running_times": 8040},{"title": "Che: Part Two","year": 2008,"rating": 6.9,"votes": 29183,"running_times": 8100},{"title": "Cheap Thrills","year": 2013,"rating": 6.8,"votes": 14997,"running_times": 5280},{"title": "Cheaper by the Dozen","year": 2003,"rating": 5.8,"votes": 81367,"running_times": 5880},{"title": "Cheaper by the Dozen 2","year": 2005,"rating": 5.5,"votes": 46696,"running_times": 5640},{"title": "Chef","year": 2014,"rating": 7.3,"votes": 158787,"running_times": 6840},{"title": "Chennai Express","year": 2013,"rating": 6,"votes": 40979,"running_times": 8460},{"title": "Chernobyl Diaries","year": 2012,"rating": 5,"votes": 56089,"running_times": 5160},{"title": "Cherry Falls","year": 2000,"rating": 5.1,"votes": 10550,"running_times": 5520},{"title": "Chicago","year": 2002,"rating": 7.2,"votes": 186928,"running_times": 6780},{"title": "Chicken Little","year": 2005,"rating": 5.8,"votes": 71208,"running_times": 4860},{"title": "Chicken Run","year": 2000,"rating": 7,"votes": 152354,"running_times": 5040},{"title": "Child 44","year": 2015,"rating": 6.5,"votes": 51699,"running_times": 8220},{"title": "Child's Play","year": 1988,"rating": 6.6,"votes": 69387,"running_times": 5220},{"title": "Child's Play 2","year": 1990,"rating": 5.8,"votes": 35756,"running_times": 5400},{"title": "Child's Play 3","year": 1991,"rating": 5,"votes": 28492,"running_times": 5400},{"title": "Children of Men","year": 2006,"rating": 7.9,"votes": 396186,"running_times": 6540},{"title": "Children of a Lesser God","year": 1986,"rating": 7.2,"votes": 12664,"running_times": 7140},{"title": "Children of the Corn","year": 1984,"rating": 5.6,"votes": 39139,"running_times": 5520},{"title": "Chinatown","year": 1974,"rating": 8.2,"votes": 240563,"running_times": 7800},{"title": "Chinjeolhan geumjassi","year": 2005,"rating": 7.6,"votes": 59464,"running_times": 6900},{"title": "Chitty Chitty Bang Bang","year": 1968,"rating": 6.9,"votes": 33986,"running_times": 8640},{"title": "Chloe","year": 2009,"rating": 6.3,"votes": 61084,"running_times": 5760},{"title": "Chocolat","year": 2000,"rating": 7.3,"votes": 160087,"running_times": 7260},{"title": "Chocolate","year": 2008,"rating": 7,"votes": 15889,"running_times": 6600},{"title": "Choke","year": 2008,"rating": 6.5,"votes": 29570,"running_times": 5520},{"title": "Chopper","year": 2000,"rating": 7.2,"votes": 33112,"running_times": 5640},{"title": "Christine","year": 1983,"rating": 6.7,"votes": 56332,"running_times": 6600},{"title": "Christmas with the Kranks","year": 2004,"rating": 5.2,"votes": 32280,"running_times": 5940},{"title": "Chronicle","year": 2012,"rating": 7.1,"votes": 218220,"running_times": 5340},{"title": "Chung Hing sam lam","year": 1994,"rating": 8.1,"votes": 46274,"running_times": 6120},{"title": "Cinderella","year": 1950,"rating": 7.3,"votes": 118829,"running_times": 4440},{"title": "Cinderella","year": 2015,"rating": 7,"votes": 123774,"running_times": 6840},{"title": "Cinderella Man","year": 2005,"rating": 8,"votes": 158231,"running_times": 8640},{"title": "Circle","year": 2015,"rating": 6,"votes": 22091,"running_times": 5220},{"title": "Cirque du Freak: The Vampire's Assistant","year": 2009,"rating": 5.9,"votes": 38122,"running_times": 6540},{"title": "Citizen Kane","year": 1941,"rating": 8.4,"votes": 329256,"running_times": 7140},{"title": "Citizenfour","year": 2014,"rating": 8.1,"votes": 44407,"running_times": 6840},{"title": "City Hall","year": 1996,"rating": 6.2,"votes": 17638,"running_times": 6660},{"title": "City Island","year": 2009,"rating": 7.4,"votes": 28457,"running_times": 6240},{"title": "City Lights","year": 1931,"rating": 8.6,"votes": 125731,"running_times": 5220},{"title": "City Slickers","year": 1991,"rating": 6.7,"votes": 41722,"running_times": 6780},{"title": "City Slickers II: The Legend of Curly's Gold","year": 1994,"rating": 5.5,"votes": 16077,"running_times": 6960},{"title": "City by the Sea","year": 2002,"rating": 6.1,"votes": 22301,"running_times": 6480},{"title": "City of Angels","year": 1998,"rating": 6.7,"votes": 100989,"running_times": 6840},{"title": "City of Ember","year": 2008,"rating": 6.5,"votes": 56656,"running_times": 5400},{"title": "Clash of the Titans","year": 1981,"rating": 6.9,"votes": 35380,"running_times": 7080},{"title": "Clash of the Titans","year": 2010,"rating": 5.8,"votes": 243626,"running_times": 6360},{"title": "Cleaner","year": 2007,"rating": 6.1,"votes": 34279,"running_times": 5580},{"title": "Cleanskin","year": 2012,"rating": 6.3,"votes": 18425,"running_times": 6480},{"title": "Clear and Present Danger","year": 1994,"rating": 6.9,"votes": 75175,"running_times": 8460},{"title": "Cleopatra","year": 1963,"rating": 7,"votes": 24093,"running_times": 19200},{"title": "Clerks","year": 1994,"rating": 7.8,"votes": 191979,"running_times": 6120},{"title": "Clerks II","year": 2006,"rating": 7.4,"votes": 120022,"running_times": 5820},{"title": "Click","year": 2006,"rating": 6.4,"votes": 266298,"running_times": 6420},{"title": "Cliffhanger","year": 1993,"rating": 6.4,"votes": 103922,"running_times": 7440},{"title": "Clockers","year": 1995,"rating": 6.9,"votes": 17806,"running_times": 7740},{"title": "Clockstoppers","year": 2002,"rating": 5.2,"votes": 12024,"running_times": 5640},{"title": "Close Encounters of the Third Kind","year": 1977,"rating": 7.7,"votes": 154463,"running_times": 8280},{"title": "Closed Circuit","year": 2013,"rating": 6.2,"votes": 19118,"running_times": 5760},{"title": "Closer","year": 2004,"rating": 7.3,"votes": 179295,"running_times": 6240},{"title": "Cloud Atlas","year": 2012,"rating": 7.5,"votes": 307896,"running_times": 10320},{"title": "Clouds of Sils Maria","year": 2014,"rating": 6.7,"votes": 22177,"running_times": 7440},{"title": "Cloudy with a Chance of Meatballs","year": 2009,"rating": 7,"votes": 169393,"running_times": 5400},{"title": "Cloudy with a Chance of Meatballs 2","year": 2013,"rating": 6.4,"votes": 72622,"running_times": 5700},{"title": "Cloverfield","year": 2008,"rating": 7,"votes": 322764,"running_times": 5100},{"title": "Clown","year": 2014,"rating": 5.7,"votes": 16910,"running_times": 6000},{"title": "Club Dread","year": 2004,"rating": 5.7,"votes": 25170,"running_times": 7140},{"title": "Clue","year": 1985,"rating": 7.3,"votes": 63435,"running_times": 5820},{"title": "Clueless","year": 1995,"rating": 6.8,"votes": 139268,"running_times": 5820},{"title": "Coach Carter","year": 2005,"rating": 7.3,"votes": 101888,"running_times": 8160},{"title": "Coal Miner's Daughter","year": 1980,"rating": 7.5,"votes": 14038,"running_times": 7440},{"title": "Cobain: Montage of Heck","year": 2015,"rating": 7.6,"votes": 23885,"running_times": 8700},{"title": "Cobra","year": 1986,"rating": 5.7,"votes": 55581,"running_times": 5220},{"title": "Cocaine Cowboys","year": 2006,"rating": 7.9,"votes": 11305,"running_times": 9120},{"title": "Cockneys vs Zombies","year": 2012,"rating": 5.9,"votes": 16293,"running_times": 5280},{"title": "Cocktail","year": 1988,"rating": 5.8,"votes": 66672,"running_times": 6240},{"title": "Coco","year": 2017,"rating": 8.8,"votes": 38493,"running_times": 6300},{"title": "Coco avant Chanel","year": 2009,"rating": 6.7,"votes": 34380,"running_times": 6660},{"title": "Cocoon","year": 1985,"rating": 6.7,"votes": 48540,"running_times": 7020},{"title": "Cocoon: The Return","year": 1988,"rating": 5.3,"votes": 13077,"running_times": 6960},{"title": "Code 46","year": 2003,"rating": 6.2,"votes": 18825,"running_times": 5580},{"title": "Code Name: The Cleaner","year": 2007,"rating": 4.5,"votes": 10369,"running_times": 5460},{"title": "Coffee and Cigarettes","year": 2003,"rating": 7.1,"votes": 51479,"running_times": 5700},{"title": "Coherence","year": 2013,"rating": 7.2,"votes": 74162,"running_times": 5340},{"title": "Cold Creek Manor","year": 2003,"rating": 4.9,"votes": 19224,"running_times": 7080},{"title": "Cold Mountain","year": 2003,"rating": 7.2,"votes": 125299,"running_times": 9240},{"title": "Cold in July","year": 2014,"rating": 6.8,"votes": 29209,"running_times": 6540},{"title": "Collateral","year": 2004,"rating": 7.6,"votes": 314995,"running_times": 6900},{"title": "Collateral Beauty","year": 2016,"rating": 6.8,"votes": 61621,"running_times": 5820},{"title": "Collateral Damage","year": 2002,"rating": 5.5,"votes": 65175,"running_times": 6480},{"title": "College","year": 2008,"rating": 4.6,"votes": 11386,"running_times": 5640},{"title": "College Road Trip","year": 2008,"rating": 4.3,"votes": 13947,"running_times": 4980},{"title": "Collide","year": 2016,"rating": 5.7,"votes": 10342,"running_times": 5940},{"title": "Colombiana","year": 2011,"rating": 6.4,"votes": 81904,"running_times": 6720},{"title": "Colonia","year": 2015,"rating": 7.1,"votes": 34529,"running_times": 6360},{"title": "Color of Night","year": 1994,"rating": 5.1,"votes": 19983,"running_times": 8400},{"title": "Colors","year": 1988,"rating": 6.7,"votes": 20690,"running_times": 7620},{"title": "Colossal","year": 2016,"rating": 6.2,"votes": 34754,"running_times": 6540},{"title": "Coma","year": 1978,"rating": 6.9,"votes": 14481,"running_times": 6780},{"title": "Comet","year": 2014,"rating": 6.8,"votes": 14582,"running_times": 5460},{"title": "Coming Home","year": 1978,"rating": 7.3,"votes": 10277,"running_times": 7620},{"title": "Coming to America","year": 1988,"rating": 7,"votes": 132385,"running_times": 6960},{"title": "Commando","year": 1985,"rating": 6.7,"votes": 123223,"running_times": 5520},{"title": "Comme un chef","year": 2012,"rating": 6.7,"votes": 13946,"running_times": 5040},{"title": "Como agua para chocolate","year": 1992,"rating": 7.2,"votes": 14661,"running_times": 6780},{"title": "Compliance","year": 2012,"rating": 6.4,"votes": 26887,"running_times": 5400},{"title": "Con Air","year": 1997,"rating": 6.8,"votes": 241529,"running_times": 7380},{"title": "Conan the Barbarian","year": 1982,"rating": 6.9,"votes": 120899,"running_times": 7740},{"title": "Conan the Barbarian","year": 2011,"rating": 5.2,"votes": 86384,"running_times": 6780},{"title": "Conan the Destroyer","year": 1984,"rating": 5.9,"votes": 66764,"running_times": 6180},{"title": "Concussion","year": 2015,"rating": 7.1,"votes": 66336,"running_times": 7380},{"title": "Coneheads","year": 1993,"rating": 5.3,"votes": 44457,"running_times": 5280},{"title": "Confessions of a Dangerous Mind","year": 2002,"rating": 7.1,"votes": 75279,"running_times": 6780},{"title": "Confessions of a Shopaholic","year": 2009,"rating": 5.9,"votes": 67162,"running_times": 6240},{"title": "Confessions of a Teenage Drama Queen","year": 2004,"rating": 4.6,"votes": 24723,"running_times": 5340},{"title": "Confidence","year": 2003,"rating": 6.7,"votes": 31438,"running_times": 5820},{"title": "Congo","year": 1995,"rating": 5.1,"votes": 37007,"running_times": 6540},{"title": "Conquest of the Planet of the Apes","year": 1972,"rating": 6.1,"votes": 25995,"running_times": 5280},{"title": "Conspiracy Theory","year": 1997,"rating": 6.7,"votes": 82265,"running_times": 8100},{"title": "Constantine","year": 2005,"rating": 6.9,"votes": 256735,"running_times": 7260},{"title": "Contact","year": 1997,"rating": 7.4,"votes": 220252,"running_times": 9000},{"title": "Contagion","year": 2011,"rating": 6.6,"votes": 191199,"running_times": 6360},{"title": "Contraband","year": 2012,"rating": 6.5,"votes": 106830,"running_times": 6540},{"title": "Contracted","year": 2013,"rating": 5.3,"votes": 12077,"running_times": 5040},{"title": "Control","year": 2007,"rating": 7.7,"votes": 54840,"running_times": 7320},{"title": "Conversations with Other Women","year": 2005,"rating": 7.1,"votes": 10768,"running_times": 5040},{"title": "Conviction","year": 2010,"rating": 7.2,"votes": 37479,"running_times": 6420},{"title": "Convoy","year": 1978,"rating": 6.3,"votes": 12446,"running_times": 6600},{"title": "Coogan's Bluff","year": 1968,"rating": 6.5,"votes": 12776,"running_times": 5580},{"title": "Cookie's Fortune","year": 1999,"rating": 6.9,"votes": 11591,"running_times": 7080},{"title": "Cool Hand Luke","year": 1967,"rating": 8.2,"votes": 132362,"running_times": 7560},{"title": "Cool Runnings","year": 1993,"rating": 6.9,"votes": 76261,"running_times": 5880},{"title": "Cool World","year": 1992,"rating": 4.8,"votes": 17941,"running_times": 8820},{"title": "Cooties","year": 2014,"rating": 5.6,"votes": 18063,"running_times": 5280},{"title": "Cop Car","year": 2015,"rating": 6.3,"votes": 24603,"running_times": 5280},{"title": "Cop Land","year": 1997,"rating": 6.9,"votes": 74641,"running_times": 7200},{"title": "Cop Out","year": 2010,"rating": 5.6,"votes": 78523,"running_times": 6420},{"title": "Copenhagen","year": 2014,"rating": 7.2,"votes": 10195,"running_times": 5880},{"title": "Copie conforme","year": 2010,"rating": 7.3,"votes": 16521,"running_times": 6360},{"title": "Copycat","year": 1995,"rating": 6.6,"votes": 45500,"running_times": 7380},{"title": "Copying Beethoven","year": 2006,"rating": 6.8,"votes": 11733,"running_times": 6240},{"title": "Coraline","year": 2009,"rating": 7.7,"votes": 164057,"running_times": 6000},{"title": "Coriolanus","year": 2011,"rating": 6.2,"votes": 28410,"running_times": 7380},{"title": "Corky Romano","year": 2001,"rating": 4.6,"votes": 11368,"running_times": 5160},{"title": "Corpse Bride","year": 2005,"rating": 7.4,"votes": 208321,"running_times": 4620},{"title": "Corrina, Corrina","year": 1994,"rating": 6.5,"votes": 10767,"running_times": 6900},{"title": "Cosmopolis","year": 2012,"rating": 5,"votes": 39968,"running_times": 6540},{"title": "Country Strong","year": 2010,"rating": 6.3,"votes": 15545,"running_times": 7020},{"title": "Couples Retreat","year": 2009,"rating": 5.5,"votes": 88557,"running_times": 6780},{"title": "Courage Under Fire","year": 1996,"rating": 6.6,"votes": 43563,"running_times": 6960},{"title": "Courageous","year": 2011,"rating": 7,"votes": 16551,"running_times": 7740},{"title": "Cowboy Bebop: Tengoku no tobira","year": 2001,"rating": 7.9,"votes": 35543,"running_times": 6900},{"title": "Cowboys & Aliens","year": 2011,"rating": 6,"votes": 184726,"running_times": 8100},{"title": "Cowspiracy: The Sustainability Secret","year": 2014,"rating": 8.4,"votes": 14590,"running_times": 5100},{"title": "Coyote Ugly","year": 2000,"rating": 5.6,"votes": 95982,"running_times": 6420},{"title": "Cracks","year": 2009,"rating": 6.7,"votes": 16901,"running_times": 6240},{"title": "Cradle 2 the Grave","year": 2003,"rating": 5.8,"votes": 37167,"running_times": 6060},{"title": "Crank","year": 2006,"rating": 7,"votes": 210220,"running_times": 5580},{"title": "Crank: High Voltage","year": 2009,"rating": 6.2,"votes": 122969,"running_times": 5760},{"title": "Crash","year": 1996,"rating": 6.4,"votes": 45105,"running_times": 6000},{"title": "Crash","year": 2004,"rating": 7.8,"votes": 382043,"running_times": 6900},{"title": "Crazy Heart","year": 2009,"rating": 7.3,"votes": 73969,"running_times": 6720},{"title": "Crazy, Stupid, Love.","year": 2011,"rating": 7.4,"votes": 409038,"running_times": 7080},{"title": "Crazy/Beautiful","year": 2001,"rating": 6.5,"votes": 22330,"running_times": 8100},{"title": "Creation","year": 2009,"rating": 6.7,"votes": 12373,"running_times": 6480},{"title": "Creature from the Black Lagoon","year": 1954,"rating": 7,"votes": 20009,"running_times": 4740},{"title": "Creed","year": 2015,"rating": 7.6,"votes": 186555,"running_times": 7980},{"title": "Creep","year": 2004,"rating": 5.6,"votes": 24964,"running_times": 5100},{"title": "Creep","year": 2014,"rating": 6.2,"votes": 20497,"running_times": 4620},{"title": "Creepshow","year": 1982,"rating": 6.9,"votes": 33804,"running_times": 7800},{"title": "Creepshow 2","year": 1987,"rating": 6,"votes": 17797,"running_times": 5520},{"title": "Crimes and Misdemeanors","year": 1989,"rating": 8,"votes": 46799,"running_times": 6240},{"title": "Criminal","year": 2016,"rating": 6.3,"votes": 43955,"running_times": 6780},{"title": "Crimson Peak","year": 2015,"rating": 6.5,"votes": 105157,"running_times": 7140},{"title": "Crimson Tide","year": 1995,"rating": 7.3,"votes": 87400,"running_times": 7380},{"title": "Critters","year": 1986,"rating": 6,"votes": 25883,"running_times": 4920},{"title": "Critters 2","year": 1988,"rating": 5.4,"votes": 11269,"running_times": 5160},{"title": "Crocodile Dundee","year": 1986,"rating": 6.5,"votes": 80228,"running_times": 5820},{"title": "Crocodile Dundee in Los Angeles","year": 2001,"rating": 4.8,"votes": 20997,"running_times": 5520},{"title": "Cronos","year": 1993,"rating": 6.7,"votes": 22058,"running_times": 5640},{"title": "Cross of Iron","year": 1977,"rating": 7.5,"votes": 22038,"running_times": 7920},{"title": "Crossing Over","year": 2009,"rating": 6.8,"votes": 20695,"running_times": 8400},{"title": "Crossroads","year": 1986,"rating": 7.1,"votes": 11548,"running_times": 5940},{"title": "Crossroads","year": 2002,"rating": 3.4,"votes": 35455,"running_times": 5580},{"title": "Crouching Tiger, Hidden Dragon: Sword of Destiny","year": 2016,"rating": 6.1,"votes": 13783,"running_times": 6180},{"title": "Croupier","year": 1998,"rating": 7.2,"votes": 16685,"running_times": 5640},{"title": "Cruel Intentions","year": 1999,"rating": 6.8,"votes": 158764,"running_times": 5820},{"title": "Cruising","year": 1980,"rating": 6.4,"votes": 14634,"running_times": 6120},{"title": "Crumb","year": 1994,"rating": 8,"votes": 15416,"running_times": 7140},{"title": "Cry Freedom","year": 1987,"rating": 7.5,"votes": 10789,"running_times": 9420},{"title": "Cry Wolf","year": 2005,"rating": 5.9,"votes": 23969,"running_times": 5400},{"title": "Cry-Baby","year": 1990,"rating": 6.5,"votes": 47450,"running_times": 5460},{"title": "Crying Freeman","year": 1995,"rating": 6.5,"votes": 10059,"running_times": 6120},{"title": "Cuban Fury","year": 2014,"rating": 6.2,"votes": 16055,"running_times": 5880},{"title": "Cube","year": 1997,"rating": 7.3,"votes": 177332,"running_times": 5400},{"title": "Cube 2: Hypercube","year": 2002,"rating": 5.6,"votes": 54831,"running_times": 5640},{"title": "Cube Zero","year": 2004,"rating": 5.7,"votes": 31210,"running_times": 5820},{"title": "Cujo","year": 1983,"rating": 6,"votes": 30871,"running_times": 5580},{"title": "Cult of Chucky","year": 2017,"rating": 5.2,"votes": 11206,"running_times": 7140},{"title": "Curious George","year": 2006,"rating": 6.5,"votes": 13591,"running_times": 5220},{"title": "Curly Sue","year": 1991,"rating": 5.8,"votes": 17904,"running_times": 6060},{"title": "Curse of Chucky","year": 2013,"rating": 5.6,"votes": 27291,"running_times": 5820},{"title": "Cursed","year": 2005,"rating": 5,"votes": 27579,"running_times": 5940},{"title": "Cutthroat Island","year": 1995,"rating": 5.6,"votes": 22715,"running_times": 7440},{"title": "Cyborg","year": 1989,"rating": 5,"votes": 25164,"running_times": 5160},{"title": "Cypher","year": 2002,"rating": 6.8,"votes": 28151,"running_times": 5700},{"title": "Cyrus","year": 2010,"rating": 6.3,"votes": 31474,"running_times": 5460},{"title": "D-Tox","year": 2002,"rating": 5.3,"votes": 20961,"running_times": 5760},{"title": "D-War","year": 2007,"rating": 3.6,"votes": 22115,"running_times": 6420},{"title": "D.A.R.Y.L.","year": 1985,"rating": 6.2,"votes": 10271,"running_times": 5940},{"title": "D.E.B.S.","year": 2004,"rating": 5.3,"votes": 12982,"running_times": 5460},{"title": "D2: The Mighty Ducks","year": 1994,"rating": 6,"votes": 30535,"running_times": 6360},{"title": "D3: The Mighty Ducks","year": 1996,"rating": 5.3,"votes": 20741,"running_times": 6240},{"title": "DOA: Dead or Alive","year": 2006,"rating": 4.8,"votes": 40160,"running_times": 5220},{"title": "Dabba","year": 2013,"rating": 7.8,"votes": 37643,"running_times": 6240},{"title": "Daddy Day Camp","year": 2007,"rating": 3,"votes": 13152,"running_times": 5580},{"title": "Daddy Day Care","year": 2003,"rating": 5.5,"votes": 53857,"running_times": 5520},{"title": "Daddy's Home","year": 2015,"rating": 6.1,"votes": 77927,"running_times": 5760},{"title": "Dagon","year": 2001,"rating": 6.3,"votes": 13890,"running_times": 5880},{"title": "Dallas Buyers Club","year": 2013,"rating": 8,"votes": 367890,"running_times": 7020},{"title": "Damage","year": 1992,"rating": 6.9,"votes": 13462,"running_times": 6660},{"title": "Damien: Omen II","year": 1978,"rating": 6.3,"votes": 24472,"running_times": 6420},{"title": "Dan in Real Life","year": 2007,"rating": 6.8,"votes": 90389,"running_times": 5880},{"title": "Dance Flick","year": 2009,"rating": 3.5,"votes": 10591,"running_times": 5280},{"title": "Dance of the Dead","year": 2008,"rating": 5.8,"votes": 10563,"running_times": 5220},{"title": "Dance of the Vampires","year": 1967,"rating": 7.3,"votes": 24957,"running_times": 6480},{"title": "Dancer in the Dark","year": 2000,"rating": 8,"votes": 86306,"running_times": 8400},{"title": "Dances with Wolves","year": 1990,"rating": 8,"votes": 203335,"running_times": 14160},{"title": "Dangerous Beauty","year": 1998,"rating": 7.3,"votes": 13633,"running_times": 6660},{"title": "Dangerous Liaisons","year": 1988,"rating": 7.7,"votes": 56386,"running_times": 7140},{"title": "Dangerous Minds","year": 1995,"rating": 6.4,"votes": 41341,"running_times": 5940},{"title": "Danny Collins","year": 2015,"rating": 7,"votes": 25060,"running_times": 6360},{"title": "Dante's Peak","year": 1997,"rating": 5.9,"votes": 68066,"running_times": 6480},{"title": "Daredevil","year": 2003,"rating": 5.3,"votes": 187093,"running_times": 7980},{"title": "Dark Blue","year": 2002,"rating": 6.6,"votes": 18322,"running_times": 7080},{"title": "Dark City","year": 1998,"rating": 7.7,"votes": 168451,"running_times": 6660},{"title": "Dark Passage","year": 1947,"rating": 7.6,"votes": 14253,"running_times": 6360},{"title": "Dark Places","year": 2015,"rating": 6.2,"votes": 33917,"running_times": 6780},{"title": "Dark Shadows","year": 2012,"rating": 6.2,"votes": 215809,"running_times": 6780},{"title": "Dark Skies","year": 2013,"rating": 6.3,"votes": 62454,"running_times": 5820},{"title": "Dark Star","year": 1974,"rating": 6.5,"votes": 18630,"running_times": 4980},{"title": "Dark Water","year": 2005,"rating": 5.6,"votes": 53540,"running_times": 6300},{"title": "Darkman","year": 1990,"rating": 6.4,"votes": 51054,"running_times": 5760},{"title": "Darkness","year": 2002,"rating": 5.4,"votes": 17484,"running_times": 6180},{"title": "Darkness Falls","year": 2003,"rating": 5,"votes": 27450,"running_times": 5760},{"title": "Darr","year": 1993,"rating": 7.9,"votes": 18344,"running_times": 10680},{"title": "Das Boot","year": 1981,"rating": 8.4,"votes": 187200,"running_times": 17580},{"title": "Das Experiment","year": 2001,"rating": 7.8,"votes": 83528,"running_times": 7200},{"title": "Date Movie","year": 2006,"rating": 2.7,"votes": 52564,"running_times": 5100},{"title": "Date Night","year": 2010,"rating": 6.3,"votes": 136609,"running_times": 6060},{"title": "Dave","year": 1993,"rating": 6.8,"votes": 43104,"running_times": 6600},{"title": "Dawn of the Dead","year": 1978,"rating": 8,"votes": 97223,"running_times": 9360},{"title": "Dawn of the Dead","year": 2004,"rating": 7.3,"votes": 208261,"running_times": 6600},{"title": "Dawn of the Planet of the Apes","year": 2014,"rating": 7.6,"votes": 362251,"running_times": 7800},{"title": "Day & Night","year": 2010,"rating": 8.1,"votes": 13289,"running_times": 360},{"title": "Day of the Dead","year": 1985,"rating": 7.2,"votes": 54076,"running_times": 6060},{"title": "Day of the Woman","year": 1978,"rating": 5.7,"votes": 21922,"running_times": 6060},{"title": "Daybreakers","year": 2009,"rating": 6.5,"votes": 111322,"running_times": 5880},{"title": "Daydream Nation","year": 2010,"rating": 6.4,"votes": 11338,"running_times": 5880},{"title": "Daylight","year": 1996,"rating": 5.8,"votes": 57247,"running_times": 6840},{"title": "Days of Heaven","year": 1978,"rating": 7.9,"votes": 42093,"running_times": 5640},{"title": "Days of Thunder","year": 1990,"rating": 5.9,"votes": 65974,"running_times": 6420},{"title": "Dazed and Confused","year": 1993,"rating": 7.7,"votes": 135321,"running_times": 6120},{"title": "De battre mon coeur s'est arrêté","year": 2005,"rating": 7.3,"votes": 16729,"running_times": 6480},{"title": "De rouille et d'os","year": 2012,"rating": 7.5,"votes": 54550,"running_times": 7200},{"title": "De-Lovely","year": 2004,"rating": 6.6,"votes": 10074,"running_times": 7500},{"title": "Dead Again","year": 1991,"rating": 7,"votes": 22986,"running_times": 6420},{"title": "Dead Calm","year": 1989,"rating": 6.8,"votes": 31732,"running_times": 5760},{"title": "Dead End","year": 2003,"rating": 6.7,"votes": 21560,"running_times": 5100},{"title": "Dead Man","year": 1995,"rating": 7.7,"votes": 78292,"running_times": 7260},{"title": "Dead Man Down","year": 2013,"rating": 6.5,"votes": 58376,"running_times": 7080},{"title": "Dead Man Walking","year": 1995,"rating": 7.6,"votes": 77979,"running_times": 7320},{"title": "Dead Man on Campus","year": 1998,"rating": 6.1,"votes": 12326,"running_times": 5760},{"title": "Dead Man's Shoes","year": 2004,"rating": 7.7,"votes": 43049,"running_times": 5400},{"title": "Dead Men Don't Wear Plaid","year": 1982,"rating": 6.8,"votes": 17854,"running_times": 5280},{"title": "Dead Poets Society","year": 1989,"rating": 8,"votes": 310883,"running_times": 7680},{"title": "Dead Presidents","year": 1995,"rating": 6.9,"votes": 16576,"running_times": 7140},{"title": "Dead Ringers","year": 1988,"rating": 7.3,"votes": 32622,"running_times": 6960},{"title": "Dead Silence","year": 2007,"rating": 6.2,"votes": 74013,"running_times": 5520},{"title": "Deadfall","year": 2012,"rating": 6.3,"votes": 34661,"running_times": 5700},{"title": "Deadgirl","year": 2008,"rating": 5.7,"votes": 16648,"running_times": 6060},{"title": "Deadpool","year": 2016,"rating": 8,"votes": 686133,"running_times": 6480},{"title": "Dear Frankie","year": 2004,"rating": 7.8,"votes": 19677,"running_times": 6300},{"title": "Dear John","year": 2010,"rating": 6.3,"votes": 117324,"running_times": 6480},{"title": "Dear White People","year": 2014,"rating": 6.2,"votes": 22550,"running_times": 6480},{"title": "Dear Zachary: A Letter to a Son About His Father","year": 2008,"rating": 8.6,"votes": 25811,"running_times": 5700},{"title": "Death Becomes Her","year": 1992,"rating": 6.5,"votes": 86672,"running_times": 6240},{"title": "Death Note","year": 2017,"rating": 4.6,"votes": 51215,"running_times": 6060},{"title": "Death Proof","year": 2007,"rating": 7.1,"votes": 227440,"running_times": 7260},{"title": "Death Race","year": 2008,"rating": 6.4,"votes": 177881,"running_times": 6660},{"title": "Death Race 2000","year": 1975,"rating": 6.2,"votes": 21390,"running_times": 5040},{"title": "Death Sentence","year": 2007,"rating": 6.8,"votes": 63505,"running_times": 6660},{"title": "Death Warrant","year": 1990,"rating": 5.6,"votes": 13976,"running_times": 5340},{"title": "Death Wish","year": 1974,"rating": 7,"votes": 27842,"running_times": 5580},{"title": "Death Wish 3","year": 1985,"rating": 5.9,"votes": 11198,"running_times": 5520},{"title": "Death Wish II","year": 1982,"rating": 6,"votes": 11457,"running_times": 5700},{"title": "Death and the Maiden","year": 1994,"rating": 7.3,"votes": 19027,"running_times": 6180},{"title": "Death at a Funeral","year": 2007,"rating": 7.4,"votes": 96036,"running_times": 5220},{"title": "Death at a Funeral","year": 2010,"rating": 5.7,"votes": 38975,"running_times": 5520},{"title": "Death on the Nile","year": 1978,"rating": 7.3,"votes": 22145,"running_times": 8400},{"title": "Death to Smoochy","year": 2002,"rating": 6.4,"votes": 35983,"running_times": 6540},{"title": "Deathgasm","year": 2015,"rating": 6.3,"votes": 12177,"running_times": 5160},{"title": "December Boys","year": 2007,"rating": 6.6,"votes": 10972,"running_times": 6300},{"title": "Deception","year": 2008,"rating": 6.1,"votes": 34624,"running_times": 6420},{"title": "Deck the Halls","year": 2006,"rating": 4.9,"votes": 18286,"running_times": 5580},{"title": "Deconstructing Harry","year": 1997,"rating": 7.4,"votes": 38001,"running_times": 5760},{"title": "Deep Blue Sea","year": 1999,"rating": 5.8,"votes": 106958,"running_times": 6300},{"title": "Deep Impact","year": 1998,"rating": 6.1,"votes": 143093,"running_times": 7200},{"title": "Deep Rising","year": 1998,"rating": 6,"votes": 28323,"running_times": 6360},{"title": "Deepwater Horizon","year": 2016,"rating": 7.2,"votes": 110464,"running_times": 6420},{"title": "Defending Your Life","year": 1991,"rating": 7.3,"votes": 14660,"running_times": 6720},{"title": "Defendor","year": 2009,"rating": 6.8,"votes": 33008,"running_times": 6060},{"title": "Defiance","year": 2008,"rating": 7.2,"votes": 124297,"running_times": 9600},{"title": "Definitely, Maybe","year": 2008,"rating": 7.2,"votes": 136326,"running_times": 6720},{"title": "Deja Vu","year": 2006,"rating": 7,"votes": 260387,"running_times": 7560},{"title": "Delhi Belly","year": 2011,"rating": 7.6,"votes": 21588,"running_times": 6180},{"title": "Deliver Us from Evil","year": 2014,"rating": 6.2,"votes": 59445,"running_times": 7080},{"title": "Deliverance","year": 1972,"rating": 7.7,"votes": 84402,"running_times": 6540},{"title": "Delivery Man","year": 2013,"rating": 6.4,"votes": 65838,"running_times": 6300},{"title": "Dellamorte Dellamore","year": 1994,"rating": 7.3,"votes": 17402,"running_times": 6300},{"title": "Demain tout commence","year": 2016,"rating": 7.4,"votes": 10878,"running_times": 7080},{"title": "Demolition","year": 2015,"rating": 7,"votes": 66447,"running_times": 6060},{"title": "Demolition Man","year": 1993,"rating": 6.6,"votes": 135026,"running_times": 6900},{"title": "Demonic","year": 2015,"rating": 5.3,"votes": 10386,"running_times": 4980},{"title": "Den skaldede frisør","year": 2012,"rating": 6.6,"votes": 11148,"running_times": 6960},{"title": "Denial","year": 2016,"rating": 6.6,"votes": 11827,"running_times": 6540},{"title": "Dennis the Menace","year": 1993,"rating": 5.5,"votes": 47952,"running_times": 5640},{"title": "Der Baader Meinhof Komplex","year": 2008,"rating": 7.4,"votes": 31874,"running_times": 11040},{"title": "Der Himmel über Berlin","year": 1987,"rating": 8.1,"votes": 52212,"running_times": 7680},{"title": "Der Name der Rose","year": 1986,"rating": 7.8,"votes": 88129,"running_times": 7800},{"title": "Der amerikanische Freund","year": 1977,"rating": 7.4,"votes": 10256,"running_times": 7500},{"title": "Der blaue Engel","year": 1930,"rating": 7.8,"votes": 11350,"running_times": 6480},{"title": "Der rote Baron","year": 2008,"rating": 6.4,"votes": 10408,"running_times": 7740},{"title": "Derailed","year": 2005,"rating": 6.6,"votes": 65502,"running_times": 6720},{"title": "Desert Flower","year": 2009,"rating": 7.4,"votes": 10105,"running_times": 7200},{"title": "Desperado","year": 1995,"rating": 7.2,"votes": 149465,"running_times": 6240},{"title": "Desperate Measures","year": 1998,"rating": 6.1,"votes": 14560,"running_times": 6000},{"title": "Desperately Seeking Susan","year": 1985,"rating": 5.9,"votes": 17678,"running_times": 6240},{"title": "Despicable Me","year": 2010,"rating": 7.7,"votes": 427150,"running_times": 5700},{"title": "Despicable Me 2","year": 2013,"rating": 7.4,"votes": 317679,"running_times": 5880},{"title": "Despicable Me 3","year": 2017,"rating": 6.3,"votes": 58386,"running_times": 5400},{"title": "Detachment","year": 2011,"rating": 7.7,"votes": 63889,"running_times": 5880},{"title": "Detention","year": 2011,"rating": 5.8,"votes": 13464,"running_times": 5580},{"title": "Detour","year": 1945,"rating": 7.4,"votes": 11049,"running_times": 4080},{"title": "Detroit","year": 2017,"rating": 7.5,"votes": 16424,"running_times": 8580},{"title": "Detroit Rock City","year": 1999,"rating": 6.8,"votes": 31978,"running_times": 5700},{"title": "Deuce Bigalow: European Gigolo","year": 2005,"rating": 4.6,"votes": 43661,"running_times": 4980},{"title": "Deuce Bigalow: Male Gigolo","year": 1999,"rating": 5.7,"votes": 63262,"running_times": 5280},{"title": "Deux frères","year": 2004,"rating": 7.1,"votes": 12776,"running_times": 6540},{"title": "Deux jours, une nuit","year": 2014,"rating": 7.4,"votes": 37791,"running_times": 5700},{"title": "Dev.D","year": 2009,"rating": 8.1,"votes": 23620,"running_times": 8640},{"title": "Devil","year": 2010,"rating": 6.2,"votes": 113748,"running_times": 4800},{"title": "Devil in a Blue Dress","year": 1995,"rating": 6.7,"votes": 14584,"running_times": 6120},{"title": "Devil's Due","year": 2014,"rating": 4.1,"votes": 14846,"running_times": 5340},{"title": "Devil's Knot","year": 2013,"rating": 6.1,"votes": 16589,"running_times": 6840},{"title": "Dheepan","year": 2015,"rating": 7.2,"votes": 10267,"running_times": 6900},{"title": "Dhobi Ghat","year": 2010,"rating": 7.1,"votes": 10542,"running_times": 6000},{"title": "Dhoom:2","year": 2006,"rating": 6.4,"votes": 19515,"running_times": 9120},{"title": "Dhoom:3","year": 2013,"rating": 5.4,"votes": 37312,"running_times": 10320},{"title": "Diabolique","year": 1996,"rating": 5.3,"votes": 11767,"running_times": 6420},{"title": "Dial M for Murder","year": 1954,"rating": 8.2,"votes": 122214,"running_times": 6300},{"title": "Diamonds Are Forever","year": 1971,"rating": 6.7,"votes": 80479,"running_times": 7200},{"title": "Diana","year": 2013,"rating": 5.5,"votes": 16578,"running_times": 6780},{"title": "Diary of a Mad Black Woman","year": 2005,"rating": 5.7,"votes": 11236,"running_times": 6960},{"title": "Diary of a Wimpy Kid","year": 2010,"rating": 6.2,"votes": 35635,"running_times": 5640},{"title": "Diary of a Wimpy Kid: Dog Days","year": 2012,"rating": 6.3,"votes": 17804,"running_times": 5640},{"title": "Diary of a Wimpy Kid: Rodrick Rules","year": 2011,"rating": 6.6,"votes": 21150,"running_times": 5940},{"title": "Diary of the Dead","year": 2007,"rating": 5.7,"votes": 42623,"running_times": 5700},{"title": "Dick","year": 1999,"rating": 6.1,"votes": 16753,"running_times": 5640},{"title": "Dick Tracy","year": 1990,"rating": 6.1,"votes": 50794,"running_times": 6300},{"title": "Dickie Roberts: Former Child Star","year": 2003,"rating": 5.6,"votes": 12350,"running_times": 5880},{"title": "Did You Hear About the Morgans?","year": 2009,"rating": 4.8,"votes": 31932,"running_times": 6180},{"title": "Die Another Day","year": 2002,"rating": 6.1,"votes": 180923,"running_times": 7980},{"title": "Die Fälscher","year": 2007,"rating": 7.6,"votes": 38896,"running_times": 5880},{"title": "Die Hard","year": 1988,"rating": 8.2,"votes": 655576,"running_times": 7920},{"title": "Die Hard 2","year": 1990,"rating": 7.1,"votes": 291702,"running_times": 7440},{"title": "Die Hard with a Vengeance","year": 1995,"rating": 7.6,"votes": 320519,"running_times": 7680},{"title": "Die fetten Jahre sind vorbei","year": 2004,"rating": 7.5,"votes": 28388,"running_times": 7620},{"title": "Die unendliche Geschichte","year": 1984,"rating": 7.4,"votes": 109827,"running_times": 6120},{"title": "Dil Chahta Hai","year": 2001,"rating": 8.2,"votes": 55585,"running_times": 10980},{"title": "Dilwale Dulhania Le Jayenge","year": 1995,"rating": 8.2,"votes": 52081,"running_times": 11340},{"title": "Diner","year": 1982,"rating": 7.2,"votes": 16075,"running_times": 6600},{"title": "Dinner for Schmucks","year": 2010,"rating": 5.9,"votes": 85267,"running_times": 6840},{"title": "Dinosaur","year": 2000,"rating": 6.5,"votes": 42813,"running_times": 4920},{"title": "Dirty Dancing","year": 1987,"rating": 6.9,"votes": 158022,"running_times": 6000},{"title": "Dirty Dancing: Havana Nights","year": 2004,"rating": 6,"votes": 23751,"running_times": 5160},{"title": "Dirty Grandpa","year": 2016,"rating": 6,"votes": 85369,"running_times": 6540},{"title": "Dirty Harry","year": 1971,"rating": 7.8,"votes": 123351,"running_times": 6120},{"title": "Dirty Pretty Things","year": 2002,"rating": 7.4,"votes": 36840,"running_times": 5820},{"title": "Dirty Rotten Scoundrels","year": 1988,"rating": 7.3,"votes": 54644,"running_times": 6600},{"title": "Dirty Work","year": 1998,"rating": 6.4,"votes": 21069,"running_times": 4920},{"title": "Disaster Movie","year": 2008,"rating": 1.9,"votes": 78624,"running_times": 5280},{"title": "Disclosure","year": 1994,"rating": 6,"votes": 39560,"running_times": 7680},{"title": "Disconnect","year": 2012,"rating": 7.6,"votes": 66555,"running_times": 6900},{"title": "District 9","year": 2009,"rating": 8,"votes": 571695,"running_times": 6720},{"title": "Disturbia","year": 2007,"rating": 6.9,"votes": 197793,"running_times": 6300},{"title": "Disturbing Behavior","year": 1998,"rating": 5.5,"votes": 18430,"running_times": 5040},{"title": "Diva","year": 1981,"rating": 7.3,"votes": 10052,"running_times": 7020},{"title": "Divergent","year": 2014,"rating": 6.7,"votes": 374171,"running_times": 8340},{"title": "Divine Secrets of the Ya-Ya Sisterhood","year": 2002,"rating": 6,"votes": 16225,"running_times": 6960},{"title": "Django Unchained","year": 2012,"rating": 8.4,"votes": 1087375,"running_times": 9900},{"title": "Do the Right Thing","year": 1989,"rating": 7.9,"votes": 66608,"running_times": 7200},{"title": "Dobermann","year": 1997,"rating": 6.6,"votes": 15076,"running_times": 6180},{"title": "Doc Hollywood","year": 1991,"rating": 6.1,"votes": 27982,"running_times": 6240},{"title": "Doctor Dolittle","year": 1998,"rating": 5.3,"votes": 80924,"running_times": 5100},{"title": "Doctor Strange","year": 2016,"rating": 7.5,"votes": 369625,"running_times": 6900},{"title": "Doctor Zhivago","year": 1965,"rating": 8,"votes": 59974,"running_times": 12000},{"title": "Dodgeball: A True Underdog Story","year": 2004,"rating": 6.7,"votes": 200273,"running_times": 5520},{"title": "Dog Day Afternoon","year": 1975,"rating": 8,"votes": 201845,"running_times": 7860},{"title": "Dog Soldiers","year": 2002,"rating": 6.8,"votes": 48200,"running_times": 6300},{"title": "Doghouse","year": 2009,"rating": 6.1,"votes": 19400,"running_times": 5340},{"title": "Dogma","year": 1999,"rating": 7.3,"votes": 190705,"running_times": 7800},{"title": "Dogtown and Z-Boys","year": 2001,"rating": 7.7,"votes": 10986,"running_times": 5460},{"title": "Dogville","year": 2003,"rating": 8,"votes": 116919,"running_times": 10680},{"title": "Dolores Claiborne","year": 1995,"rating": 7.4,"votes": 31617,"running_times": 7920},{"title": "Dolphin Tale","year": 2011,"rating": 6.9,"votes": 19277,"running_times": 6780},{"title": "Dom Hemingway","year": 2013,"rating": 6.2,"votes": 23217,"running_times": 5580},{"title": "Dom za vesanje","year": 1988,"rating": 8.3,"votes": 20308,"running_times": 16200},{"title": "Domestic Disturbance","year": 2001,"rating": 5.5,"votes": 22329,"running_times": 5520},{"title": "Domino","year": 2005,"rating": 6,"votes": 60282,"running_times": 7620},{"title": "Don 2","year": 2011,"rating": 7.1,"votes": 43541,"running_times": 8880},{"title": "Don Jon","year": 2013,"rating": 6.6,"votes": 205177,"running_times": 5400},{"title": "Don Juan DeMarco","year": 1994,"rating": 6.7,"votes": 43768,"running_times": 5820},{"title": "Don't Be Afraid of the Dark","year": 2010,"rating": 5.6,"votes": 42818,"running_times": 5940},{"title": "Don't Be a Menace to South Central While Drinking Your Juice in the Hood","year": 1996,"rating": 6.6,"votes": 41316,"running_times": 5640},{"title": "Don't Breathe","year": 2016,"rating": 7.1,"votes": 147018,"running_times": 5280},{"title": "Don't Look Now","year": 1973,"rating": 7.3,"votes": 38356,"running_times": 6600},{"title": "Don't Say a Word","year": 2001,"rating": 6.3,"votes": 42979,"running_times": 6780},{"title": "Don't Tell Mom the Babysitter's Dead","year": 1991,"rating": 6.1,"votes": 23305,"running_times": 6120},{"title": "Don't Think Twice","year": 2016,"rating": 6.8,"votes": 12772,"running_times": 5520},{"title": "Donnie Brasco","year": 1997,"rating": 7.8,"votes": 241674,"running_times": 8820},{"title": "Donnie Darko","year": 2001,"rating": 8.1,"votes": 644118,"running_times": 7980},{"title": "Doodlebug","year": 1997,"rating": 7.1,"votes": 13264,"running_times": 180},{"title": "Doom","year": 2005,"rating": 5.2,"votes": 93106,"running_times": 6780},{"title": "Doomsday","year": 2008,"rating": 6,"votes": 65892,"running_times": 6780},{"title": "Dope","year": 2015,"rating": 7.2,"votes": 70696,"running_times": 6180},{"title": "Dorian Gray","year": 2009,"rating": 6.3,"votes": 55011,"running_times": 6720},{"title": "Dostana","year": 2008,"rating": 6.5,"votes": 11858,"running_times": 8700},{"title": "Dou fo sin","year": 2007,"rating": 6.8,"votes": 11247,"running_times": 5280},{"title": "Double Impact","year": 1991,"rating": 5.5,"votes": 31989,"running_times": 6600},{"title": "Double Indemnity","year": 1944,"rating": 8.3,"votes": 110821,"running_times": 6600},{"title": "Double Jeopardy","year": 1999,"rating": 6.4,"votes": 60879,"running_times": 6300},{"title": "Double Team","year": 1997,"rating": 4.7,"votes": 27220,"running_times": 5580},{"title": "Doubt","year": 2008,"rating": 7.5,"votes": 106866,"running_times": 6240},{"title": "Down Periscope","year": 1996,"rating": 6,"votes": 18230,"running_times": 5520},{"title": "Down and Out in Beverly Hills","year": 1986,"rating": 6.1,"votes": 13684,"running_times": 6180},{"title": "Down by Law","year": 1986,"rating": 7.8,"votes": 39932,"running_times": 6420},{"title": "Down in the Valley","year": 2005,"rating": 6.4,"votes": 17043,"running_times": 6840},{"title": "Down to Earth","year": 2001,"rating": 5.4,"votes": 19850,"running_times": 5220},{"title": "Down to You","year": 2000,"rating": 4.9,"votes": 12954,"running_times": 5460},{"title": "Down with Love","year": 2003,"rating": 6.3,"votes": 35365,"running_times": 6060},{"title": "Dr. Dolittle 2","year": 2001,"rating": 4.7,"votes": 36568,"running_times": 5220},{"title": "Dr. Jekyll and Mr. Hyde","year": 1931,"rating": 7.7,"votes": 10414,"running_times": 5880},{"title": "Dr. No","year": 1962,"rating": 7.3,"votes": 125450,"running_times": 6600},{"title": "Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb","year": 1964,"rating": 8.5,"votes": 379103,"running_times": 5700},{"title": "Dr. T & the Women","year": 2000,"rating": 4.6,"votes": 16257,"running_times": 7320},{"title": "Dracula","year": 1931,"rating": 7.6,"votes": 37354,"running_times": 4500},{"title": "Dracula","year": 1958,"rating": 7.4,"votes": 17052,"running_times": 4920},{"title": "Dracula","year": 1992,"rating": 7.5,"votes": 158038,"running_times": 9300},{"title": "Dracula 2000","year": 2000,"rating": 4.9,"votes": 28908,"running_times": 5940},{"title": "Dracula Untold","year": 2014,"rating": 6.3,"votes": 153899,"running_times": 5520},{"title": "Dracula: Dead and Loving It","year": 1995,"rating": 5.8,"votes": 33009,"running_times": 5280},{"title": "Draft Day","year": 2014,"rating": 6.8,"votes": 44200,"running_times": 6600},{"title": "Drag Me to Hell","year": 2009,"rating": 6.6,"votes": 168087,"running_times": 5940},{"title": "Dragnet","year": 1987,"rating": 5.9,"votes": 27668,"running_times": 6360},{"title": "Dragon: The Bruce Lee Story","year": 1993,"rating": 7,"votes": 23689,"running_times": 7200},{"title": "DragonHeart","year": 1996,"rating": 6.4,"votes": 82651,"running_times": 6180},{"title": "Dragonball Evolution","year": 2009,"rating": 2.6,"votes": 61559,"running_times": 6000},{"title": "Dragonfly","year": 2002,"rating": 6.1,"votes": 33351,"running_times": 6240},{"title": "Dragonslayer","year": 1981,"rating": 6.7,"votes": 11944,"running_times": 6540},{"title": "Dread","year": 2009,"rating": 5.7,"votes": 10792,"running_times": 6480},{"title": "Dream House","year": 2011,"rating": 6,"votes": 55422,"running_times": 5040},{"title": "Dreamcatcher","year": 2003,"rating": 5.5,"votes": 80773,"running_times": 8160},{"title": "Dreamer: Inspired by a True Story","year": 2005,"rating": 6.9,"votes": 10701,"running_times": 6360},{"title": "Dreamgirls","year": 2006,"rating": 6.5,"votes": 60700,"running_times": 8400},{"title": "Dreamscape","year": 1984,"rating": 6.3,"votes": 11483,"running_times": 5940},{"title": "Dredd","year": 2012,"rating": 7.1,"votes": 220351,"running_times": 5700},{"title": "Dressed to Kill","year": 1980,"rating": 7.1,"votes": 27122,"running_times": 6300},{"title": "Drillbit Taylor","year": 2008,"rating": 5.7,"votes": 52903,"running_times": 6600},{"title": "Drinking Buddies","year": 2013,"rating": 6.1,"votes": 50184,"running_times": 5400},{"title": "Drive","year": 2011,"rating": 7.8,"votes": 480193,"running_times": 6000},{"title": "Drive Angry","year": 2011,"rating": 5.4,"votes": 86046,"running_times": 6240},{"title": "Drive Me Crazy","year": 1999,"rating": 5.7,"votes": 15979,"running_times": 5460},{"title": "Driven","year": 2001,"rating": 4.5,"votes": 35985,"running_times": 6960},{"title": "Driving Miss Daisy","year": 1989,"rating": 7.4,"votes": 80605,"running_times": 5940},{"title": "Drop Dead Fred","year": 1991,"rating": 5.8,"votes": 23342,"running_times": 6180},{"title": "Drop Dead Gorgeous","year": 1999,"rating": 6.6,"votes": 28622,"running_times": 5820},{"title": "Drop Zone","year": 1994,"rating": 5.6,"votes": 16935,"running_times": 6060},{"title": "Drowning Mona","year": 2000,"rating": 5.6,"votes": 12216,"running_times": 5760},{"title": "Drugstore Cowboy","year": 1989,"rating": 7.4,"votes": 27237,"running_times": 6120},{"title": "Drumline","year": 2002,"rating": 5.7,"votes": 29808,"running_times": 7080},{"title": "Du rififi chez les hommes","year": 1955,"rating": 8.2,"votes": 20796,"running_times": 7080},{"title": "Duck Soup","year": 1933,"rating": 8,"votes": 49627,"running_times": 4080},{"title": "DuckTales the Movie: Treasure of the Lost Lamp","year": 1990,"rating": 6.9,"votes": 21820,"running_times": 4440},{"title": "Dude, Where's My Car?","year": 2000,"rating": 5.5,"votes": 122824,"running_times": 4980},{"title": "Due Date","year": 2010,"rating": 6.6,"votes": 288907,"running_times": 5700},{"title": "Dumb and Dumber","year": 1994,"rating": 7.3,"votes": 309873,"running_times": 6780},{"title": "Dumb and Dumber To","year": 2014,"rating": 5.6,"votes": 108504,"running_times": 6540},{"title": "Dumb and Dumberer: When Harry Met Lloyd","year": 2003,"rating": 3.4,"votes": 32270,"running_times": 5100},{"title": "Dumbo","year": 1941,"rating": 7.3,"votes": 96388,"running_times": 3840},{"title": "Dune","year": 1984,"rating": 6.6,"votes": 104438,"running_times": 11400},{"title": "Dungeons & Dragons","year": 2000,"rating": 3.7,"votes": 28833,"running_times": 6420},{"title": "Dunkirk","year": 2017,"rating": 8.2,"votes": 274342,"running_times": 6360},{"title": "Dunston Checks In","year": 1996,"rating": 5.3,"votes": 10452,"running_times": 5280},{"title": "Duplex","year": 2003,"rating": 5.9,"votes": 49293,"running_times": 5340},{"title": "Duplicity","year": 2009,"rating": 6.2,"votes": 43403,"running_times": 7500},{"title": "Dutch","year": 1991,"rating": 6.4,"votes": 10177,"running_times": 6420},{"title": "Dying Young","year": 1991,"rating": 5.9,"votes": 12716,"running_times": 6660},{"title": "Dylan Dog: Dead of Night","year": 2010,"rating": 5.1,"votes": 13629,"running_times": 6420},{"title": "Dèmoni","year": 1985,"rating": 6.7,"votes": 16120,"running_times": 5280},{"title": "Død snø 2","year": 2014,"rating": 6.9,"votes": 18637,"running_times": 6000},{"title": "E.T. the Extra-Terrestrial","year": 1982,"rating": 7.9,"votes": 309754,"running_times": 7200},{"title": "Eagle Eye","year": 2008,"rating": 6.6,"votes": 159498,"running_times": 7080},{"title": "Eagle vs Shark","year": 2007,"rating": 6.8,"votes": 18542,"running_times": 5580},{"title": "Earth","year": 2007,"rating": 8,"votes": 13297,"running_times": 5760},{"title": "Earth Girls Are Easy","year": 1988,"rating": 5.2,"votes": 17480,"running_times": 6000},{"title": "Earth to Echo","year": 2014,"rating": 5.8,"votes": 16868,"running_times": 5460},{"title": "Earthlings","year": 2005,"rating": 8.7,"votes": 14644,"running_times": 5700},{"title": "Earthquake","year": 1974,"rating": 5.8,"votes": 11463,"running_times": 9600},{"title": "East Is East","year": 1999,"rating": 6.9,"votes": 15380,"running_times": 5760},{"title": "East of Eden","year": 1955,"rating": 8,"votes": 33398,"running_times": 7080},{"title": "Eastern Promises","year": 2007,"rating": 7.7,"votes": 203215,"running_times": 6000},{"title": "Easy A","year": 2010,"rating": 7.1,"votes": 305254,"running_times": 5520},{"title": "Easy Rider","year": 1969,"rating": 7.4,"votes": 81753,"running_times": 5700},{"title": "Easy Virtue","year": 2008,"rating": 6.7,"votes": 17839,"running_times": 5820},{"title": "Eat Pray Love","year": 2010,"rating": 5.7,"votes": 70716,"running_times": 8400},{"title": "Echelon Conspiracy","year": 2009,"rating": 5.8,"votes": 17641,"running_times": 6300},{"title": "Ed Wood","year": 1994,"rating": 7.9,"votes": 150437,"running_times": 7620},{"title": "Eddie Murphy: Raw","year": 1987,"rating": 7.6,"votes": 16140,"running_times": 5580},{"title": "Eddie the Eagle","year": 2016,"rating": 7.4,"votes": 62469,"running_times": 6360},{"title": "Eden Lake","year": 2008,"rating": 6.8,"votes": 64341,"running_times": 5460},{"title": "Edge of Darkness","year": 2010,"rating": 6.6,"votes": 80466,"running_times": 7020},{"title": "Edge of Tomorrow","year": 2014,"rating": 7.9,"votes": 494688,"running_times": 6780},{"title": "Edison","year": 2005,"rating": 5.3,"votes": 13825,"running_times": 5940},{"title": "Edmond","year": 2005,"rating": 6.3,"votes": 10303,"running_times": 4920},{"title": "Edtv","year": 1999,"rating": 6.1,"votes": 37443,"running_times": 7320},{"title": "Educating Rita","year": 1983,"rating": 7.2,"votes": 10465,"running_times": 6600},{"title": "Edward Scissorhands","year": 1990,"rating": 7.9,"votes": 388885,"running_times": 6300},{"title": "Efter brylluppet","year": 2006,"rating": 7.8,"votes": 27865,"running_times": 7200},{"title": "Eight Below","year": 2006,"rating": 7.3,"votes": 52915,"running_times": 7200},{"title": "Eight Crazy Nights","year": 2002,"rating": 5.3,"votes": 19215,"running_times": 4560},{"title": "Eight Legged Freaks","year": 2002,"rating": 5.4,"votes": 46740,"running_times": 5940},{"title": "Eight Men Out","year": 1988,"rating": 7.3,"votes": 16091,"running_times": 7140},{"title": "Ek Tha Tiger","year": 2012,"rating": 5.4,"votes": 23349,"running_times": 7920},{"title": "El Cid","year": 1961,"rating": 7.3,"votes": 10715,"running_times": 10920},{"title": "El Dorado","year": 1967,"rating": 7.6,"votes": 19689,"running_times": 7560},{"title": "El abrazo de la serpiente","year": 2015,"rating": 7.9,"votes": 14165,"running_times": 7500},{"title": "Election","year": 1999,"rating": 7.3,"votes": 78350,"running_times": 6180},{"title": "Elegy","year": 2008,"rating": 6.8,"votes": 20349,"running_times": 6720},{"title": "Elektra","year": 2005,"rating": 4.8,"votes": 76634,"running_times": 6000},{"title": "Elephant","year": 2003,"rating": 7.2,"votes": 75743,"running_times": 4860},{"title": "Elf","year": 2003,"rating": 6.9,"votes": 166818,"running_times": 5820},{"title": "Eliza Graves","year": 2014,"rating": 6.8,"votes": 41308,"running_times": 6720},{"title": "Elizabeth","year": 1998,"rating": 7.5,"votes": 80820,"running_times": 7440},{"title": "Elizabeth: The Golden Age","year": 2007,"rating": 6.9,"votes": 58559,"running_times": 6840},{"title": "Elizabethtown","year": 2005,"rating": 6.4,"votes": 61503,"running_times": 7380},{"title": "Ella Enchanted","year": 2004,"rating": 6.3,"votes": 52416,"running_times": 5760},{"title": "Elle s'appelait Sarah","year": 2010,"rating": 7.5,"votes": 14100,"running_times": 6660},{"title": "Elvis & Nixon","year": 2016,"rating": 6.4,"votes": 10328,"running_times": 5160},{"title": "Elysium","year": 2013,"rating": 6.6,"votes": 370766,"running_times": 6540},{"title": "Emergo","year": 2011,"rating": 5.1,"votes": 10158,"running_times": 4800},{"title": "Emma","year": 1996,"rating": 6.7,"votes": 30394,"running_times": 7200},{"title": "Emperor","year": 2012,"rating": 6.5,"votes": 11452,"running_times": 6300},{"title": "Empire Records","year": 1995,"rating": 6.7,"votes": 41332,"running_times": 6420},{"title": "Empire State","year": 2013,"rating": 5.2,"votes": 16319,"running_times": 5640},{"title": "Empire of the Sun","year": 1987,"rating": 7.8,"votes": 97960,"running_times": 9180},{"title": "Employee of the Month","year": 2006,"rating": 5.5,"votes": 39579,"running_times": 6180},{"title": "En duva satt på en gren och funderade på tillvaron","year": 2014,"rating": 7,"votes": 12501,"running_times": 6060},{"title": "En kongelig affære","year": 2012,"rating": 7.6,"votes": 37904,"running_times": 8220},{"title": "Enchanted","year": 2007,"rating": 7.1,"votes": 154524,"running_times": 6420},{"title": "Encino Man","year": 1992,"rating": 5.7,"votes": 32299,"running_times": 5280},{"title": "Encounters at the End of the World","year": 2007,"rating": 7.8,"votes": 15121,"running_times": 5940},{"title": "End of Days","year": 1999,"rating": 5.7,"votes": 94909,"running_times": 7260},{"title": "End of Watch","year": 2012,"rating": 7.7,"votes": 198682,"running_times": 6540},{"title": "Ender's Game","year": 2013,"rating": 6.7,"votes": 199409,"running_times": 6840},{"title": "Endless Love","year": 2014,"rating": 6.3,"votes": 35053,"running_times": 6240},{"title": "Enemy","year": 2013,"rating": 6.9,"votes": 121880,"running_times": 5460},{"title": "Enemy Mine","year": 1985,"rating": 6.9,"votes": 37013,"running_times": 6480},{"title": "Enemy at the Gates","year": 2001,"rating": 7.6,"votes": 208107,"running_times": 7860},{"title": "Enemy of the State","year": 1998,"rating": 7.3,"votes": 201476,"running_times": 8400},{"title": "English Vinglish","year": 2012,"rating": 7.9,"votes": 26437,"running_times": 8040},{"title": "Enigma","year": 2001,"rating": 6.4,"votes": 18513,"running_times": 7140},{"title": "Enough","year": 2002,"rating": 5.7,"votes": 33306,"running_times": 6900},{"title": "Enough Said","year": 2013,"rating": 7.1,"votes": 52803,"running_times": 5580},{"title": "Enron: The Smartest Guys in the Room","year": 2005,"rating": 7.7,"votes": 13946,"running_times": 6600},{"title": "Enter the Dragon","year": 1973,"rating": 7.7,"votes": 83111,"running_times": 6120},{"title": "Enter the Void","year": 2009,"rating": 7.3,"votes": 52921,"running_times": 9660},{"title": "Entourage","year": 2015,"rating": 6.6,"votes": 67060,"running_times": 6240},{"title": "Entrapment","year": 1999,"rating": 6.3,"votes": 94568,"running_times": 6780},{"title": "Envy","year": 2004,"rating": 4.8,"votes": 27619,"running_times": 5940},{"title": "Epic","year": 2013,"rating": 6.7,"votes": 91102,"running_times": 6120},{"title": "Epic Movie","year": 2007,"rating": 2.3,"votes": 94044,"running_times": 5580},{"title": "Equals","year": 2015,"rating": 6,"votes": 19497,"running_times": 6060},{"title": "Equilibrium","year": 2002,"rating": 7.5,"votes": 280173,"running_times": 6420},{"title": "Eragon","year": 2006,"rating": 5.1,"votes": 112989,"running_times": 6240},{"title": "Erased","year": 2012,"rating": 6.1,"votes": 25184,"running_times": 6000},{"title": "Eraser","year": 1996,"rating": 6.1,"votes": 90788,"running_times": 6900},{"title": "Eraserhead","year": 1977,"rating": 7.4,"votes": 80638,"running_times": 5340},{"title": "Erik the Viking","year": 1989,"rating": 6.2,"votes": 11535,"running_times": 6420},{"title": "Erin Brockovich","year": 2000,"rating": 7.3,"votes": 147095,"running_times": 7860},{"title": "Escape Plan","year": 2013,"rating": 6.7,"votes": 194559,"running_times": 6900},{"title": "Escape from Alcatraz","year": 1979,"rating": 7.6,"votes": 95509,"running_times": 6720},{"title": "Escape from L.A.","year": 1996,"rating": 5.7,"votes": 59275,"running_times": 6060},{"title": "Escape from New York","year": 1981,"rating": 7.2,"votes": 101894,"running_times": 6360},{"title": "Escape from Planet Earth","year": 2013,"rating": 5.9,"votes": 22083,"running_times": 5340},{"title": "Escape from the Planet of the Apes","year": 1971,"rating": 6.3,"votes": 26898,"running_times": 5880},{"title": "Escobar: Paradise Lost","year": 2014,"rating": 6.5,"votes": 17217,"running_times": 7200},{"title": "Eternal Sunshine of the Spotless Mind","year": 2004,"rating": 8.3,"votes": 746335,"running_times": 6480},{"title": "EuroTrip","year": 2004,"rating": 6.6,"votes": 172986,"running_times": 5520},{"title": "Europa","year": 1991,"rating": 7.7,"votes": 17049,"running_times": 6720},{"title": "Europa Report","year": 2013,"rating": 6.5,"votes": 58836,"running_times": 5820},{"title": "Evan Almighty","year": 2007,"rating": 5.4,"votes": 122445,"running_times": 5760},{"title": "Evening","year": 2007,"rating": 6.6,"votes": 12168,"running_times": 7020},{"title": "Event Horizon","year": 1997,"rating": 6.7,"votes": 132242,"running_times": 7800},{"title": "EverAfter","year": 1998,"rating": 7,"votes": 61506,"running_times": 7260},{"title": "Everest","year": 2015,"rating": 7.1,"votes": 163956,"running_times": 7260},{"title": "Everly","year": 2014,"rating": 5.1,"votes": 14426,"running_times": 5520},{"title": "Every Which Way But Loose","year": 1978,"rating": 6.3,"votes": 19104,"running_times": 6840},{"title": "Everybody Wants Some!!","year": 2016,"rating": 7,"votes": 41481,"running_times": 7020},{"title": "Everybody's Fine","year": 2009,"rating": 7.1,"votes": 53263,"running_times": 5940},{"title": "Everyone Says I Love You","year": 1996,"rating": 6.8,"votes": 31978,"running_times": 6060},{"title": "Everything Is Illuminated","year": 2005,"rating": 7.5,"votes": 53082,"running_times": 6360},{"title": "Everything Must Go","year": 2010,"rating": 6.4,"votes": 43647,"running_times": 5820},{"title": "Everything You Always Wanted to Know About Sex * But Were Afraid to Ask","year": 1972,"rating": 6.8,"votes": 33803,"running_times": 5280},{"title": "Everything, Everything","year": 2017,"rating": 6.4,"votes": 14421,"running_times": 5760},{"title": "Evil Dead","year": 2013,"rating": 6.5,"votes": 137348,"running_times": 5820},{"title": "Evil Dead II","year": 1987,"rating": 7.8,"votes": 125028,"running_times": 5460},{"title": "Evil Under the Sun","year": 1982,"rating": 7,"votes": 10493,"running_times": 7020},{"title": "Evita","year": 1996,"rating": 6.3,"votes": 30668,"running_times": 8100},{"title": "Evolution","year": 2001,"rating": 6.1,"votes": 107448,"running_times": 6060},{"title": "Ex Machina","year": 2014,"rating": 7.7,"votes": 364240,"running_times": 6480},{"title": "Exam","year": 2009,"rating": 6.9,"votes": 84658,"running_times": 6060},{"title": "Excalibur","year": 1981,"rating": 7.4,"votes": 50072,"running_times": 8400},{"title": "Excess Baggage","year": 1997,"rating": 5.3,"votes": 11451,"running_times": 6060},{"title": "Excision","year": 2012,"rating": 6.1,"votes": 17447,"running_times": 4860},{"title": "Executive Decision","year": 1996,"rating": 6.4,"votes": 43820,"running_times": 7980},{"title": "Exit Through the Gift Shop","year": 2010,"rating": 8,"votes": 55428,"running_times": 5220},{"title": "Exit Wounds","year": 2001,"rating": 5.5,"votes": 28944,"running_times": 6060},{"title": "Exodus: Gods and Kings","year": 2014,"rating": 6,"votes": 141750,"running_times": 9000},{"title": "Exorcist II: The Heretic","year": 1977,"rating": 3.7,"votes": 17846,"running_times": 7080},{"title": "Exorcist: The Beginning","year": 2004,"rating": 5.1,"votes": 30144,"running_times": 7500},{"title": "Exotica","year": 1994,"rating": 7.1,"votes": 15581,"running_times": 6180},{"title": "Expelled: No Intelligence Allowed","year": 2008,"rating": 3.7,"votes": 11451,"running_times": 5820},{"title": "Experimenter","year": 2015,"rating": 6.6,"votes": 13685,"running_times": 5880},{"title": "Explorers","year": 1985,"rating": 6.6,"votes": 16258,"running_times": 6540},{"title": "Extinction","year": 2015,"rating": 5.8,"votes": 13381,"running_times": 6720},{"title": "Extract","year": 2009,"rating": 6.2,"votes": 39751,"running_times": 5520},{"title": "Extracted","year": 2012,"rating": 6.5,"votes": 10716,"running_times": 5100},{"title": "Extraordinary Measures","year": 2010,"rating": 6.5,"votes": 15069,"running_times": 6360},{"title": "Extraterrestrial","year": 2014,"rating": 5,"votes": 12754,"running_times": 6060},{"title": "Extreme Measures","year": 1996,"rating": 6.1,"votes": 14967,"running_times": 7080},{"title": "Extremely Loud & Incredibly Close","year": 2011,"rating": 6.9,"votes": 88270,"running_times": 7740},{"title": "Eye for an Eye","year": 1996,"rating": 6.1,"votes": 11091,"running_times": 6060},{"title": "Eye in the Sky","year": 2015,"rating": 7.3,"votes": 63254,"running_times": 6120},{"title": "Eye of the Beholder","year": 1999,"rating": 4.9,"votes": 13722,"running_times": 6540},{"title": "Eyes Wide Shut","year": 1999,"rating": 7.4,"votes": 249671,"running_times": 9540},{"title": "F for Fake","year": 1973,"rating": 7.8,"votes": 11788,"running_times": 5340},{"title": "F/X","year": 1986,"rating": 6.7,"votes": 14697,"running_times": 6540},{"title": "Face/Off","year": 1997,"rating": 7.3,"votes": 304712,"running_times": 8280},{"title": "Faces in the Crowd","year": 2011,"rating": 5.8,"votes": 16738,"running_times": 6180},{"title": "Facing the Giants","year": 2006,"rating": 6.7,"votes": 13404,"running_times": 6660},{"title": "Factory Girl","year": 2006,"rating": 6.4,"votes": 19330,"running_times": 5940},{"title": "Factotum","year": 2005,"rating": 6.6,"votes": 12632,"running_times": 5640},{"title": "Fading Gigolo","year": 2013,"rating": 6.2,"votes": 21136,"running_times": 5400},{"title": "Fahrenheit 451","year": 1966,"rating": 7.3,"votes": 35599,"running_times": 6720},{"title": "Fahrenheit 9/11","year": 2004,"rating": 7.5,"votes": 118010,"running_times": 7320},{"title": "Fail-Safe","year": 1964,"rating": 8,"votes": 16325,"running_times": 6720},{"title": "Failure to Launch","year": 2006,"rating": 5.6,"votes": 62881,"running_times": 5820},{"title": "Fair Game","year": 1995,"rating": 4.2,"votes": 10737,"running_times": 5460},{"title": "Fair Game","year": 2010,"rating": 6.8,"votes": 41205,"running_times": 6480},{"title": "Fallen","year": 1998,"rating": 7,"votes": 63656,"running_times": 7440},{"title": "Falling Down","year": 1993,"rating": 7.6,"votes": 145355,"running_times": 6780},{"title": "Falling in Love","year": 1984,"rating": 6.5,"votes": 10477,"running_times": 6360},{"title": "Fame","year": 1980,"rating": 6.6,"votes": 17572,"running_times": 8040},{"title": "Fame","year": 2009,"rating": 5,"votes": 14795,"running_times": 7380},{"title": "Family Business","year": 1989,"rating": 5.7,"votes": 10321,"running_times": 6600},{"title": "Family Plot","year": 1976,"rating": 6.8,"votes": 17005,"running_times": 7200},{"title": "Fanboys","year": 2009,"rating": 6.6,"votes": 52152,"running_times": 5400},{"title": "Fanny och Alexander","year": 1982,"rating": 8.1,"votes": 46972,"running_times": 18720},{"title": "Fantasia","year": 1940,"rating": 7.8,"votes": 77065,"running_times": 7500},{"title": "Fantasia 2000","year": 1999,"rating": 7.2,"votes": 29995,"running_times": 4500},{"title": "Fantastic Beasts and Where to Find Them","year": 2016,"rating": 7.4,"votes": 282792,"running_times": 7980},{"title": "Fantastic Four","year": 2005,"rating": 5.7,"votes": 282206,"running_times": 7500},{"title": "Fantastic Four","year": 2015,"rating": 4.3,"votes": 127702,"running_times": 6000},{"title": "Fantastic Mr. Fox","year": 2009,"rating": 7.8,"votes": 156778,"running_times": 5220},{"title": "Fantastic Voyage","year": 1966,"rating": 6.8,"votes": 14347,"running_times": 6000},{"title": "Far Cry","year": 2008,"rating": 3.1,"votes": 11917,"running_times": 5700},{"title": "Far and Away","year": 1992,"rating": 6.5,"votes": 51351,"running_times": 8400},{"title": "Far from Heaven","year": 2002,"rating": 7.4,"votes": 38810,"running_times": 6420},{"title": "Far from the Madding Crowd","year": 2015,"rating": 7.1,"votes": 36905,"running_times": 7140},{"title": "Fargo","year": 1996,"rating": 8.1,"votes": 507798,"running_times": 5880},{"title": "Fasandræberne","year": 2014,"rating": 7.1,"votes": 12548,"running_times": 7140},{"title": "Fast & Furious","year": 2009,"rating": 6.6,"votes": 225507,"running_times": 6420},{"title": "Fast Five","year": 2011,"rating": 7.3,"votes": 310070,"running_times": 7920},{"title": "Fast Food Nation","year": 2006,"rating": 6.3,"votes": 21840,"running_times": 6960},{"title": "Fast Times at Ridgemont High","year": 1982,"rating": 7.2,"votes": 78461,"running_times": 5400},{"title": "Fast Track","year": 2006,"rating": 5.5,"votes": 15704,"running_times": 5700},{"title": "Faster","year": 2010,"rating": 6.5,"votes": 86086,"running_times": 5880},{"title": "Faster, Pussycat! Kill! Kill!","year": 1965,"rating": 6.8,"votes": 11707,"running_times": 4980},{"title": "Fatal Attraction","year": 1987,"rating": 6.9,"votes": 61185,"running_times": 7140},{"title": "Father of the Bride","year": 1991,"rating": 6.5,"votes": 59093,"running_times": 6300},{"title": "Father of the Bride Part II","year": 1995,"rating": 5.9,"votes": 28927,"running_times": 6360},{"title": "Fathers & Daughters","year": 2015,"rating": 7.1,"votes": 17840,"running_times": 6960},{"title": "Fathers' Day","year": 1997,"rating": 5.1,"votes": 12966,"running_times": 5880},{"title": "Fear","year": 1996,"rating": 6.2,"votes": 34409,"running_times": 5820},{"title": "Fear and Loathing in Las Vegas","year": 1998,"rating": 7.7,"votes": 228574,"running_times": 7080},{"title": "Feardotcom","year": 2002,"rating": 3.3,"votes": 17929,"running_times": 6060},{"title": "Fearless","year": 1993,"rating": 7.1,"votes": 18784,"running_times": 7320},{"title": "Feast","year": 2005,"rating": 6.4,"votes": 26881,"running_times": 5700},{"title": "Feast","year": 2014,"rating": 8.3,"votes": 20154,"running_times": 360},{"title": "Feast of Love","year": 2007,"rating": 6.7,"votes": 14876,"running_times": 5820},{"title": "Fehér isten","year": 2014,"rating": 6.9,"votes": 12224,"running_times": 7260},{"title": "Felon","year": 2008,"rating": 7.5,"votes": 69677,"running_times": 6240},{"title": "Femme Fatale","year": 2002,"rating": 6.3,"votes": 30192,"running_times": 6840},{"title": "Fences","year": 2016,"rating": 7.2,"votes": 67254,"running_times": 8340},{"title": "FernGully: The Last Rainforest","year": 1992,"rating": 6.5,"votes": 22799,"running_times": 4560},{"title": "Ferris Bueller's Day Off","year": 1986,"rating": 7.8,"votes": 267726,"running_times": 6180},{"title": "Festen","year": 1998,"rating": 8.1,"votes": 69948,"running_times": 6300},{"title": "Fever Pitch","year": 2005,"rating": 6.2,"votes": 38133,"running_times": 6240},{"title": "Fiddler on the Roof","year": 1971,"rating": 8,"votes": 32288,"running_times": 10860},{"title": "Fido","year": 2006,"rating": 6.7,"votes": 26218,"running_times": 5580},{"title": "Field of Dreams","year": 1989,"rating": 7.5,"votes": 92902,"running_times": 6420},{"title": "Fierce Creatures","year": 1997,"rating": 6.4,"votes": 20671,"running_times": 5580},{"title": "Fifty Dead Men Walking","year": 2008,"rating": 6.9,"votes": 10022,"running_times": 7020},{"title": "Fifty Shades Darker","year": 2017,"rating": 4.6,"votes": 60766,"running_times": 7860},{"title": "Fifty Shades of Black","year": 2016,"rating": 3.5,"votes": 14489,"running_times": 5520},{"title": "Fifty Shades of Grey","year": 2015,"rating": 4.1,"votes": 253284,"running_times": 7740},{"title": "Fight Club","year": 1999,"rating": 8.8,"votes": 1513600,"running_times": 9060},{"title": "Fighting","year": 2009,"rating": 5.6,"votes": 29246,"running_times": 6300},{"title": "Filth","year": 2013,"rating": 7.1,"votes": 85698,"running_times": 5820},{"title": "Final Analysis","year": 1992,"rating": 5.8,"votes": 11587,"running_times": 7440},{"title": "Final Destination","year": 2000,"rating": 6.7,"votes": 196574,"running_times": 5880},{"title": "Final Destination 2","year": 2003,"rating": 6.2,"votes": 130693,"running_times": 5400},{"title": "Final Destination 3","year": 2006,"rating": 5.8,"votes": 111829,"running_times": 5580},{"title": "Final Destination 5","year": 2011,"rating": 5.9,"votes": 90949,"running_times": 5520},{"title": "Final Fantasy: The Spirits Within","year": 2001,"rating": 6.4,"votes": 75791,"running_times": 6360},{"title": "Final Girl","year": 2015,"rating": 4.7,"votes": 10302,"running_times": 5400},{"title": "Find Me Guilty","year": 2006,"rating": 7.1,"votes": 29806,"running_times": 7500},{"title": "Finding Dory","year": 2016,"rating": 7.4,"votes": 179302,"running_times": 5820},{"title": "Finding Forrester","year": 2000,"rating": 7.3,"votes": 76078,"running_times": 8160},{"title": "Finding Nemo","year": 2003,"rating": 8.1,"votes": 782783,"running_times": 6000},{"title": "Finding Neverland","year": 2004,"rating": 7.7,"votes": 183400,"running_times": 6360},{"title": "Finding Vivian Maier","year": 2013,"rating": 7.7,"votes": 10672,"running_times": 4980},{"title": "Fire Down Below","year": 1997,"rating": 5,"votes": 14680,"running_times": 6300},{"title": "Fire in the Sky","year": 1993,"rating": 6.5,"votes": 17724,"running_times": 6540},{"title": "Fire with Fire","year": 2012,"rating": 5.7,"votes": 22378,"running_times": 5820},{"title": "Fired Up!","year": 2009,"rating": 6.2,"votes": 39156,"running_times": 5460},{"title": "Fireflies in the Garden","year": 2008,"rating": 6.5,"votes": 11372,"running_times": 7200},{"title": "Firefox","year": 1982,"rating": 5.9,"votes": 21537,"running_times": 8160},{"title": "Fireproof","year": 2008,"rating": 6.6,"votes": 18427,"running_times": 7320},{"title": "Firestarter","year": 1984,"rating": 6,"votes": 24912,"running_times": 6840},{"title": "Firewall","year": 2006,"rating": 5.8,"votes": 52024,"running_times": 6300},{"title": "First Blood","year": 1982,"rating": 7.7,"votes": 187564,"running_times": 5580},{"title": "First Daughter","year": 2004,"rating": 5,"votes": 18521,"running_times": 6360},{"title": "First Knight","year": 1995,"rating": 5.9,"votes": 59640,"running_times": 8040},{"title": "Fish Tank","year": 2009,"rating": 7.3,"votes": 51982,"running_times": 7380},{"title": "Fist Fight","year": 2017,"rating": 5.6,"votes": 25330,"running_times": 5460},{"title": "Five Easy Pieces","year": 1970,"rating": 7.5,"votes": 27948,"running_times": 5880},{"title": "Five Minarets in New York","year": 2010,"rating": 5.9,"votes": 12857,"running_times": 7140},{"title": "Five Minutes of Heaven","year": 2009,"rating": 6.7,"votes": 11230,"running_times": 5340},{"title": "Flags of Our Fathers","year": 2006,"rating": 7.1,"votes": 107000,"running_times": 8100},{"title": "Flash Gordon","year": 1980,"rating": 6.5,"votes": 41587,"running_times": 6660},{"title": "Flash of Genius","year": 2008,"rating": 7,"votes": 15199,"running_times": 7140},{"title": "Flashbacks of a Fool","year": 2008,"rating": 6.8,"votes": 10970,"running_times": 6540},{"title": "Flashdance","year": 1983,"rating": 6.1,"votes": 39098,"running_times": 5700},{"title": "Flatliners","year": 1990,"rating": 6.6,"votes": 68965,"running_times": 6900},{"title": "Flawless","year": 1999,"rating": 6.4,"votes": 15528,"running_times": 6720},{"title": "Flawless","year": 2007,"rating": 6.8,"votes": 20643,"running_times": 6480},{"title": "Flesh+Blood","year": 1985,"rating": 6.7,"votes": 13910,"running_times": 7680},{"title": "Fletch","year": 1985,"rating": 6.9,"votes": 40497,"running_times": 5880},{"title": "Fletch Lives","year": 1989,"rating": 6.1,"votes": 16589,"running_times": 5700},{"title": "Flickan som lekte med elden","year": 2009,"rating": 7.2,"votes": 79566,"running_times": 10980},{"title": "Flight","year": 2012,"rating": 7.3,"votes": 283505,"running_times": 8280},{"title": "Flight 7500","year": 2014,"rating": 4.8,"votes": 12670,"running_times": 5820},{"title": "Flight of the Navigator","year": 1986,"rating": 6.9,"votes": 37089,"running_times": 5400},{"title": "Flight of the Phoenix","year": 2004,"rating": 6.1,"votes": 47745,"running_times": 6780},{"title": "Flightplan","year": 2005,"rating": 6.3,"votes": 135399,"running_times": 5880},{"title": "Flipped","year": 2010,"rating": 7.7,"votes": 68344,"running_times": 5400},{"title": "Flirting with Disaster","year": 1996,"rating": 6.8,"votes": 15896,"running_times": 5520},{"title": "Florence Foster Jenkins","year": 2016,"rating": 6.9,"votes": 37157,"running_times": 6660},{"title": "Flubber","year": 1997,"rating": 5.2,"votes": 70930,"running_times": 5580},{"title": "Flushed Away","year": 2006,"rating": 6.6,"votes": 93636,"running_times": 5100},{"title": "Fly Away Home","year": 1996,"rating": 6.8,"votes": 20944,"running_times": 6420},{"title": "Flyboys","year": 2006,"rating": 6.5,"votes": 37640,"running_times": 8400},{"title": "Flypaper","year": 2011,"rating": 6.4,"votes": 28968,"running_times": 5220},{"title": "Focus","year": 2015,"rating": 6.6,"votes": 174745,"running_times": 6300},{"title": "Following","year": 1998,"rating": 7.6,"votes": 72994,"running_times": 4140},{"title": "Food, Inc.","year": 2008,"rating": 7.8,"votes": 45811,"running_times": 5640},{"title": "Fool's Gold","year": 2008,"rating": 5.7,"votes": 64621,"running_times": 6720},{"title": "Fools Rush In","year": 1997,"rating": 6,"votes": 29168,"running_times": 6540},{"title": "Footloose","year": 1984,"rating": 6.5,"votes": 57957,"running_times": 6420},{"title": "Footloose","year": 2011,"rating": 5.9,"votes": 40438,"running_times": 6780},{"title": "For Love of the Game","year": 1999,"rating": 6.6,"votes": 27712,"running_times": 8220},{"title": "For Love or Money","year": 1993,"rating": 6.1,"votes": 10127,"running_times": 5760},{"title": "For Your Consideration","year": 2006,"rating": 6.3,"votes": 12713,"running_times": 5160},{"title": "For Your Eyes Only","year": 1981,"rating": 6.8,"votes": 77968,"running_times": 7620},{"title": "For a Good Time, Call...","year": 2012,"rating": 6,"votes": 14357,"running_times": 5280},{"title": "Forbidden Planet","year": 1956,"rating": 7.7,"votes": 37834,"running_times": 5880},{"title": "Force 10 from Navarone","year": 1978,"rating": 6.3,"votes": 14403,"running_times": 7560},{"title": "Forces of Nature","year": 1999,"rating": 5.4,"votes": 28462,"running_times": 6300},{"title": "Forces spéciales","year": 2011,"rating": 6.4,"votes": 16027,"running_times": 6540},{"title": "Foreign Correspondent","year": 1940,"rating": 7.6,"votes": 15032,"running_times": 7200},{"title": "Forever Young","year": 1992,"rating": 6.3,"votes": 39195,"running_times": 6120},{"title": "Forgetting Sarah Marshall","year": 2008,"rating": 7.2,"votes": 232023,"running_times": 7080},{"title": "Forrest Gump","year": 1994,"rating": 8.8,"votes": 1425423,"running_times": 8520},{"title": "Fort Apache","year": 1948,"rating": 7.6,"votes": 13695,"running_times": 7680},{"title": "Fortress","year": 1992,"rating": 5.9,"votes": 24762,"running_times": 5700},{"title": "Forushande","year": 2016,"rating": 7.9,"votes": 30515,"running_times": 7440},{"title": "Foul Play","year": 1978,"rating": 6.8,"votes": 11507,"running_times": 6960},{"title": "Four Brothers","year": 2005,"rating": 6.9,"votes": 118156,"running_times": 6540},{"title": "Four Christmases","year": 2008,"rating": 5.6,"votes": 53208,"running_times": 5280},{"title": "Four Lions","year": 2010,"rating": 7.3,"votes": 61920,"running_times": 5820},{"title": "Four Rooms","year": 1995,"rating": 6.7,"votes": 84665,"running_times": 6600},{"title": "Four Weddings and a Funeral","year": 1994,"rating": 7.1,"votes": 116667,"running_times": 7020},{"title": "Foxcatcher","year": 2014,"rating": 7,"votes": 118206,"running_times": 8040},{"title": "Fracture","year": 2007,"rating": 7.2,"votes": 155144,"running_times": 6780},{"title": "Frailty","year": 2001,"rating": 7.3,"votes": 66362,"running_times": 6000},{"title": "Frances Ha","year": 2012,"rating": 7.4,"votes": 51589,"running_times": 5160},{"title": "Frank","year": 2014,"rating": 7,"votes": 63921,"running_times": 5700},{"title": "Frankenstein","year": 1931,"rating": 7.9,"votes": 53795,"running_times": 4200},{"title": "Frankenweenie","year": 2012,"rating": 7,"votes": 82174,"running_times": 5220},{"title": "Frankie and Johnny","year": 1991,"rating": 6.7,"votes": 24600,"running_times": 7080},{"title": "Franklyn","year": 2008,"rating": 6.2,"votes": 15585,"running_times": 5880},{"title": "Frantic","year": 1988,"rating": 6.9,"votes": 42109,"running_times": 7200},{"title": "Freaks","year": 1932,"rating": 7.9,"votes": 35354,"running_times": 3840},{"title": "Freaky Friday","year": 2003,"rating": 6.2,"votes": 106102,"running_times": 5820},{"title": "Fred Claus","year": 2007,"rating": 5.6,"votes": 34482,"running_times": 6960},{"title": "Freddy Got Fingered","year": 2001,"rating": 4.5,"votes": 41471,"running_times": 5220},{"title": "Freddy vs. Jason","year": 2003,"rating": 5.8,"votes": 96473,"running_times": 5820},{"title": "Freddy's Dead: The Final Nightmare","year": 1991,"rating": 4.9,"votes": 34194,"running_times": 6300},{"title": "Free Birds","year": 2013,"rating": 5.9,"votes": 19574,"running_times": 5460},{"title": "Free Fire","year": 2016,"rating": 6.5,"votes": 25682,"running_times": 5460},{"title": "Free State of Jones","year": 2016,"rating": 6.9,"votes": 36148,"running_times": 8340},{"title": "Free Willy","year": 1993,"rating": 5.9,"votes": 56881,"running_times": 6720},{"title": "Free Willy 2: The Adventure Home","year": 1995,"rating": 4.9,"votes": 14085,"running_times": 5700},{"title": "Free to Play","year": 2014,"rating": 8,"votes": 12429,"running_times": 4500},{"title": "Freedom Writers","year": 2007,"rating": 7.5,"votes": 57530,"running_times": 7380},{"title": "Freedomland","year": 2006,"rating": 5.1,"votes": 14015,"running_times": 6780},{"title": "Freejack","year": 1992,"rating": 5.3,"votes": 12999,"running_times": 6600},{"title": "Freeway","year": 1996,"rating": 6.9,"votes": 23361,"running_times": 6240},{"title": "French Connection II","year": 1975,"rating": 6.8,"votes": 13988,"running_times": 7140},{"title": "French Kiss","year": 1995,"rating": 6.6,"votes": 41271,"running_times": 6660},{"title": "Frenzy","year": 1972,"rating": 7.5,"votes": 34045,"running_times": 6960},{"title": "Frequency","year": 2000,"rating": 7.4,"votes": 88661,"running_times": 7080},{"title": "Frequently Asked Questions About Time Travel","year": 2009,"rating": 7.1,"votes": 28572,"running_times": 4980},{"title": "Fresh","year": 1994,"rating": 7.6,"votes": 10428,"running_times": 6840},{"title": "Frida","year": 2002,"rating": 7.4,"votes": 67944,"running_times": 7380},{"title": "Friday","year": 1995,"rating": 7.3,"votes": 83187,"running_times": 5820},{"title": "Friday After Next","year": 2002,"rating": 5.8,"votes": 21533,"running_times": 5100},{"title": "Friday Night Lights","year": 2004,"rating": 7.3,"votes": 50876,"running_times": 7080},{"title": "Friday the 13th","year": 1980,"rating": 6.5,"votes": 94488,"running_times": 5700},{"title": "Friday the 13th","year": 2009,"rating": 5.6,"votes": 82090,"running_times": 6360},{"title": "Friday the 13th Part 2","year": 1981,"rating": 6.1,"votes": 45589,"running_times": 5220},{"title": "Friday the 13th Part III","year": 1982,"rating": 5.7,"votes": 36832,"running_times": 5700},{"title": "Friday the 13th Part VII: The New Blood","year": 1988,"rating": 5.3,"votes": 24702,"running_times": 5280},{"title": "Friday the 13th Part VIII: Jason Takes Manhattan","year": 1989,"rating": 4.6,"votes": 26121,"running_times": 6000},{"title": "Friday the 13th: A New Beginning","year": 1985,"rating": 4.8,"votes": 25750,"running_times": 5520},{"title": "Friday the 13th: The Final Chapter","year": 1984,"rating": 6,"votes": 34069,"running_times": 5820},{"title": "Fried Green Tomatoes","year": 1991,"rating": 7.7,"votes": 56574,"running_times": 8220},{"title": "Friend Request","year": 2016,"rating": 5.4,"votes": 16174,"running_times": 5520},{"title": "Friends with Benefits","year": 2011,"rating": 6.6,"votes": 295776,"running_times": 6540},{"title": "Friends with Kids","year": 2011,"rating": 6.2,"votes": 37913,"running_times": 6420},{"title": "Friends with Money","year": 2006,"rating": 5.8,"votes": 21365,"running_times": 5280},{"title": "Fright Night","year": 1985,"rating": 7.1,"votes": 48068,"running_times": 6360},{"title": "Fright Night","year": 2011,"rating": 6.4,"votes": 90148,"running_times": 6360},{"title": "From Beyond","year": 1986,"rating": 6.7,"votes": 17125,"running_times": 5160},{"title": "From Dusk Till Dawn","year": 1996,"rating": 7.3,"votes": 239943,"running_times": 6480},{"title": "From Hell","year": 2001,"rating": 6.8,"votes": 132974,"running_times": 7320},{"title": "From Here to Eternity","year": 1953,"rating": 7.7,"votes": 36695,"running_times": 7080},{"title": "From Justin to Kelly","year": 2003,"rating": 2.1,"votes": 24027,"running_times": 5400},{"title": "From Paris with Love","year": 2010,"rating": 6.5,"votes": 102829,"running_times": 5520},{"title": "From Prada to Nada","year": 2011,"rating": 5.5,"votes": 12822,"running_times": 6420},{"title": "From Russia with Love","year": 1963,"rating": 7.5,"votes": 97600,"running_times": 6900},{"title": "Frost/Nixon","year": 2008,"rating": 7.7,"votes": 92853,"running_times": 7320},{"title": "Frozen","year": 2010,"rating": 6.2,"votes": 57941,"running_times": 5580},{"title": "Frozen","year": 2013,"rating": 7.5,"votes": 470780,"running_times": 6120},{"title": "Frozen Fever","year": 2015,"rating": 7,"votes": 10101,"running_times": 480},{"title": "Frozen River","year": 2008,"rating": 7.2,"votes": 22666,"running_times": 5820},{"title": "Fruitvale Station","year": 2013,"rating": 7.5,"votes": 60680,"running_times": 5100},{"title": "Frágiles","year": 2005,"rating": 6.1,"votes": 13897,"running_times": 6060},{"title": "Full Metal Jacket","year": 1987,"rating": 8.3,"votes": 545907,"running_times": 6960},{"title": "Fun Size","year": 2012,"rating": 5.4,"votes": 12179,"running_times": 5160},{"title": "Fun with Dick and Jane","year": 2005,"rating": 6.1,"votes": 118363,"running_times": 5400},{"title": "Funny Face","year": 1957,"rating": 7.1,"votes": 21425,"running_times": 6180},{"title": "Funny Farm","year": 1988,"rating": 6.1,"votes": 16500,"running_times": 6060},{"title": "Funny Games","year": 2007,"rating": 6.5,"votes": 77100,"running_times": 6660},{"title": "Funny Girl","year": 1968,"rating": 7.6,"votes": 14783,"running_times": 9300},{"title": "Funny People","year": 2009,"rating": 6.3,"votes": 104820,"running_times": 9180},{"title": "Fur: An Imaginary Portrait of Diane Arbus","year": 2006,"rating": 6.5,"votes": 13935,"running_times": 7320},{"title": "Furious 6","year": 2013,"rating": 7.1,"votes": 327726,"running_times": 7860},{"title": "Furious Seven","year": 2015,"rating": 7.2,"votes": 313301,"running_times": 8400},{"title": "Furry Vengeance","year": 2010,"rating": 3.8,"votes": 13359,"running_times": 5520},{"title": "Fury","year": 2014,"rating": 7.6,"votes": 346870,"running_times": 8040},{"title": "G-Force","year": 2009,"rating": 5.1,"votes": 35892,"running_times": 5280},{"title": "G.I. Jane","year": 1997,"rating": 5.9,"votes": 64842,"running_times": 7500},{"title": "G.I. Joe: Retaliation","year": 2013,"rating": 5.8,"votes": 155817,"running_times": 7320},{"title": "G.I. Joe: The Rise of Cobra","year": 2009,"rating": 5.8,"votes": 183800,"running_times": 7080},{"title": "G.O.R.A.","year": 2004,"rating": 8,"votes": 41034,"running_times": 7620},{"title": "Gabriel","year": 2007,"rating": 5.7,"votes": 12850,"running_times": 6840},{"title": "Galaxy Quest","year": 1999,"rating": 7.3,"votes": 131167,"running_times": 6120},{"title": "Gallipoli","year": 1981,"rating": 7.5,"votes": 31959,"running_times": 6600},{"title": "Gambit","year": 2012,"rating": 5.7,"votes": 20482,"running_times": 6000},{"title": "Game of Death","year": 1978,"rating": 6.1,"votes": 13710,"running_times": 6180},{"title": "Gamer","year": 2009,"rating": 5.8,"votes": 119266,"running_times": 5700},{"title": "Gandhi","year": 1982,"rating": 8.1,"votes": 189632,"running_times": 11460},{"title": "Gangs of New York","year": 2002,"rating": 7.5,"votes": 344488,"running_times": 10020},{"title": "Gangster No. 1","year": 2000,"rating": 6.8,"votes": 11589,"running_times": 6180},{"title": "Gangster Squad","year": 2013,"rating": 6.7,"votes": 185855,"running_times": 6780},{"title": "Garden State","year": 2004,"rating": 7.5,"votes": 195068,"running_times": 6120},{"title": "Garfield","year": 2004,"rating": 5,"votes": 65785,"running_times": 4800},{"title": "Garfield: A Tail of Two Kitties","year": 2006,"rating": 5,"votes": 31226,"running_times": 5160},{"title": "Gaslight","year": 1944,"rating": 7.9,"votes": 18810,"running_times": 6840},{"title": "Gattaca","year": 1997,"rating": 7.8,"votes": 241382,"running_times": 6360},{"title": "Gegen die Wand","year": 2004,"rating": 8,"votes": 44019,"running_times": 7260},{"title": "Genius","year": 2016,"rating": 6.5,"votes": 12867,"running_times": 6240},{"title": "Gentleman's Agreement","year": 1947,"rating": 7.4,"votes": 12227,"running_times": 7080},{"title": "Gentlemen Prefer Blondes","year": 1953,"rating": 7.2,"votes": 25540,"running_times": 5460},{"title": "George of the Jungle","year": 1997,"rating": 5.4,"votes": 60896,"running_times": 5520},{"title": "Georgia Rule","year": 2007,"rating": 5.9,"votes": 21661,"running_times": 6780},{"title": "Geostorm","year": 2017,"rating": 5.5,"votes": 25413,"running_times": 6540},{"title": "Gerald's Game","year": 2017,"rating": 6.7,"votes": 31247,"running_times": 6180},{"title": "Gerry","year": 2002,"rating": 6.2,"votes": 16037,"running_times": 6180},{"title": "Get Carter","year": 1971,"rating": 7.5,"votes": 23892,"running_times": 6720},{"title": "Get Carter","year": 2000,"rating": 5.1,"votes": 29067,"running_times": 6120},{"title": "Get Hard","year": 2015,"rating": 6,"votes": 100323,"running_times": 6420},{"title": "Get Him to the Greek","year": 2010,"rating": 6.4,"votes": 154875,"running_times": 6840},{"title": "Get Low","year": 2009,"rating": 7.1,"votes": 20115,"running_times": 6180},{"title": "Get Out","year": 2017,"rating": 7.7,"votes": 210820,"running_times": 6240},{"title": "Get Over It","year": 2001,"rating": 5.8,"votes": 16318,"running_times": 5220},{"title": "Get Real","year": 1998,"rating": 7.6,"votes": 11209,"running_times": 6480},{"title": "Get Rich or Die Tryin'","year": 2005,"rating": 5.1,"votes": 39021,"running_times": 7020},{"title": "Get Shorty","year": 1995,"rating": 6.9,"votes": 66881,"running_times": 6300},{"title": "Get Smart","year": 2008,"rating": 6.5,"votes": 178169,"running_times": 6600},{"title": "Get a Job","year": 2016,"rating": 5.3,"votes": 17080,"running_times": 4980},{"title": "Get on Up","year": 2014,"rating": 6.9,"votes": 17525,"running_times": 8340},{"title": "Get the Gringo","year": 2012,"rating": 7,"votes": 93330,"running_times": 5760},{"title": "Getaway","year": 2013,"rating": 4.4,"votes": 20947,"running_times": 5400},{"title": "Gettysburg","year": 1993,"rating": 7.7,"votes": 23119,"running_times": 16260},{"title": "Ghost","year": 1990,"rating": 7,"votes": 166395,"running_times": 7620},{"title": "Ghost Dog: The Way of the Samurai","year": 1999,"rating": 7.5,"votes": 75463,"running_times": 6960},{"title": "Ghost Rider","year": 2007,"rating": 5.2,"votes": 196160,"running_times": 7380},{"title": "Ghost Rider: Spirit of Vengeance","year": 2011,"rating": 4.3,"votes": 95767,"running_times": 5760},{"title": "Ghost Ship","year": 2002,"rating": 5.5,"votes": 81267,"running_times": 5460},{"title": "Ghost Town","year": 2008,"rating": 6.7,"votes": 63420,"running_times": 6120},{"title": "Ghost World","year": 2001,"rating": 7.4,"votes": 102347,"running_times": 6660},{"title": "Ghost in the Shell","year": 2017,"rating": 6.4,"votes": 134199,"running_times": 6420},{"title": "Ghostbusters","year": 1984,"rating": 7.8,"votes": 299502,"running_times": 6300},{"title": "Ghostbusters","year": 2016,"rating": 5.3,"votes": 160952,"running_times": 8040},{"title": "Ghostbusters II","year": 1989,"rating": 6.5,"votes": 154653,"running_times": 6480},{"title": "Ghosts of Girlfriends Past","year": 2009,"rating": 5.8,"votes": 72653,"running_times": 6000},{"title": "Ghosts of Mars","year": 2001,"rating": 4.9,"votes": 45631,"running_times": 5880},{"title": "Giant","year": 1956,"rating": 7.7,"votes": 28660,"running_times": 12060},{"title": "Gifted","year": 2017,"rating": 7.6,"votes": 53458,"running_times": 6060},{"title": "Gigi","year": 1958,"rating": 6.8,"votes": 16227,"running_times": 6900},{"title": "Gigli","year": 2003,"rating": 2.4,"votes": 43066,"running_times": 7260},{"title": "Gilda","year": 1946,"rating": 7.8,"votes": 22667,"running_times": 6600},{"title": "Gin gwai","year": 2002,"rating": 6.7,"votes": 25927,"running_times": 6600},{"title": "Ging chaat goo si 4: Ji gaan daan yam mo","year": 1996,"rating": 6.6,"votes": 16216,"running_times": 6420},{"title": "Ging chaat goo si III: Chiu kup ging chaat","year": 1992,"rating": 6.9,"votes": 16239,"running_times": 5700},{"title": "Ginger Snaps","year": 2000,"rating": 6.8,"votes": 35786,"running_times": 6480},{"title": "Ginger Snaps 2: Unleashed","year": 2004,"rating": 6.5,"votes": 11059,"running_times": 5640},{"title": "Girl Most Likely","year": 2012,"rating": 5.8,"votes": 13274,"running_times": 6180},{"title": "Girl with a Pearl Earring","year": 2003,"rating": 7,"votes": 64538,"running_times": 6000},{"title": "Girl, Interrupted","year": 1999,"rating": 7.4,"votes": 137077,"running_times": 7620},{"title": "Girls Trip","year": 2017,"rating": 6.3,"votes": 14944,"running_times": 7320},{"title": "Gladiator","year": 2000,"rating": 8.5,"votes": 1095540,"running_times": 10260},{"title": "Glengarry Glen Ross","year": 1992,"rating": 7.8,"votes": 83225,"running_times": 6000},{"title": "Glitter","year": 2001,"rating": 2.2,"votes": 20105,"running_times": 6240},{"title": "Glory","year": 1989,"rating": 7.9,"votes": 108006,"running_times": 7320},{"title": "Glory Road","year": 2006,"rating": 7.2,"votes": 37469,"running_times": 7080},{"title": "Gnomeo & Juliet","year": 2011,"rating": 6,"votes": 45741,"running_times": 5040},{"title": "Go","year": 1999,"rating": 7.3,"votes": 61798,"running_times": 6120},{"title": "Goal II: Living the Dream","year": 2007,"rating": 5.9,"votes": 28017,"running_times": 6900},{"title": "Goal!","year": 2005,"rating": 6.7,"votes": 54338,"running_times": 7080},{"title": "God Bless America","year": 2011,"rating": 7.2,"votes": 63613,"running_times": 6300},{"title": "God's Not Dead","year": 2014,"rating": 4.8,"votes": 35130,"running_times": 6780},{"title": "Gods and Generals","year": 2003,"rating": 6.3,"votes": 13902,"running_times": 16800},{"title": "Gods and Monsters","year": 1998,"rating": 7.5,"votes": 26224,"running_times": 6300},{"title": "Gods of Egypt","year": 2016,"rating": 5.4,"votes": 80478,"running_times": 7620},{"title": "Godsend","year": 2004,"rating": 4.8,"votes": 23240,"running_times": 6120},{"title": "Godzilla","year": 1998,"rating": 5.3,"votes": 161405,"running_times": 8340},{"title": "Godzilla","year": 2014,"rating": 6.4,"votes": 326395,"running_times": 7380},{"title": "Going Clear: Scientology & the Prison of Belief","year": 2015,"rating": 8.1,"votes": 30417,"running_times": 7140},{"title": "Going Overboard","year": 1989,"rating": 1.9,"votes": 11122,"running_times": 5940},{"title": "Going in Style","year": 2017,"rating": 6.6,"votes": 46139,"running_times": 5760},{"title": "Going the Distance","year": 2010,"rating": 6.3,"votes": 52785,"running_times": 6120},{"title": "Gold","year": 2016,"rating": 6.7,"votes": 37148,"running_times": 7200},{"title": "GoldenEye","year": 1995,"rating": 7.2,"votes": 211375,"running_times": 7800},{"title": "Goldfinger","year": 1964,"rating": 7.8,"votes": 149047,"running_times": 6600},{"title": "Gone","year": 2012,"rating": 5.9,"votes": 37015,"running_times": 5640},{"title": "Gone Baby Gone","year": 2007,"rating": 7.7,"votes": 216054,"running_times": 6840},{"title": "Gone Girl","year": 2014,"rating": 8.1,"votes": 673078,"running_times": 8940},{"title": "Gone in Sixty Seconds","year": 2000,"rating": 6.5,"votes": 232755,"running_times": 7620},{"title": "Gone with the Wind","year": 1939,"rating": 8.2,"votes": 238572,"running_times": 14280},{"title": "Gongdong gyeongbi guyeok JSA","year": 2000,"rating": 7.9,"votes": 21127,"running_times": 6600},{"title": "Good Burger","year": 1997,"rating": 5.7,"votes": 22472,"running_times": 5700},{"title": "Good Bye Lenin!","year": 2003,"rating": 7.7,"votes": 122384,"running_times": 7260},{"title": "Good Kill","year": 2014,"rating": 6.4,"votes": 19133,"running_times": 6120},{"title": "Good Luck Chuck","year": 2007,"rating": 5.6,"votes": 78036,"running_times": 6060},{"title": "Good Morning, Vietnam","year": 1987,"rating": 7.3,"votes": 108279,"running_times": 7260},{"title": "Good Night, and Good Luck.","year": 2005,"rating": 7.5,"votes": 87338,"running_times": 5580},{"title": "Good People","year": 2014,"rating": 5.5,"votes": 13131,"running_times": 5400},{"title": "Good Time","year": 2017,"rating": 7.4,"votes": 17035,"running_times": 6060},{"title": "Good Will Hunting","year": 1997,"rating": 8.3,"votes": 686934,"running_times": 7560},{"title": "Goodbye Bafana","year": 2007,"rating": 7.1,"votes": 10712,"running_times": 7080},{"title": "Goodfellas","year": 1990,"rating": 8.7,"votes": 813765,"running_times": 8760},{"title": "Goon","year": 2011,"rating": 6.8,"votes": 76154,"running_times": 5520},{"title": "Goosebumps","year": 2015,"rating": 6.3,"votes": 61471,"running_times": 6180},{"title": "Gorillas in the Mist: The Story of Dian Fossey","year": 1988,"rating": 7,"votes": 20600,"running_times": 7740},{"title": "Gorky Park","year": 1983,"rating": 6.8,"votes": 10348,"running_times": 7680},{"title": "Gosford Park","year": 2001,"rating": 7.3,"votes": 69204,"running_times": 7860},{"title": "Gossip","year": 2000,"rating": 5.9,"votes": 13108,"running_times": 5400},{"title": "Gothika","year": 2003,"rating": 5.8,"votes": 95216,"running_times": 5880},{"title": "Goya's Ghosts","year": 2006,"rating": 6.9,"votes": 26554,"running_times": 6780},{"title": "Grabbers","year": 2012,"rating": 6.3,"votes": 14687,"running_times": 5640},{"title": "Grace of Monaco","year": 2014,"rating": 5.7,"votes": 14565,"running_times": 6180},{"title": "Gran Torino","year": 2008,"rating": 8.2,"votes": 617362,"running_times": 6960},{"title": "Grand Canyon","year": 1991,"rating": 6.9,"votes": 13347,"running_times": 8040},{"title": "Grand Hotel","year": 1932,"rating": 7.6,"votes": 14274,"running_times": 6720},{"title": "Grand Piano","year": 2013,"rating": 5.9,"votes": 14935,"running_times": 5400},{"title": "Grandma","year": 2015,"rating": 6.7,"votes": 12295,"running_times": 4740},{"title": "Grandma's Boy","year": 2006,"rating": 7,"votes": 71010,"running_times": 5640},{"title": "Grave Encounters","year": 2011,"rating": 6.1,"votes": 44630,"running_times": 5520},{"title": "Grave Encounters 2","year": 2012,"rating": 5.1,"votes": 19167,"running_times": 5700},{"title": "Gravity","year": 2013,"rating": 7.8,"votes": 646916,"running_times": 5460},{"title": "Grease","year": 1978,"rating": 7.2,"votes": 188022,"running_times": 6600},{"title": "Grease 2","year": 1982,"rating": 4.2,"votes": 28318,"running_times": 6900},{"title": "Great Balls of Fire!","year": 1989,"rating": 6.2,"votes": 13571,"running_times": 6480},{"title": "Great Expectations","year": 1946,"rating": 8,"votes": 18970,"running_times": 7080},{"title": "Great Expectations","year": 1998,"rating": 6.8,"votes": 45586,"running_times": 6660},{"title": "Great Expectations","year": 2012,"rating": 6.4,"votes": 10560,"running_times": 7680},{"title": "Greedy","year": 1994,"rating": 6.3,"votes": 11136,"running_times": 6780},{"title": "Green Card","year": 1990,"rating": 6.2,"votes": 19778,"running_times": 6420},{"title": "Green Lantern","year": 2011,"rating": 5.6,"votes": 237741,"running_times": 7380},{"title": "Green Room","year": 2015,"rating": 7,"votes": 72111,"running_times": 5700},{"title": "Green Zone","year": 2010,"rating": 6.8,"votes": 117010,"running_times": 6900},{"title": "Greenberg","year": 2010,"rating": 6.1,"votes": 32106,"running_times": 6420},{"title": "Gremlins","year": 1984,"rating": 7.2,"votes": 160563,"running_times": 6360},{"title": "Gremlins 2: The New Batch","year": 1990,"rating": 6.3,"votes": 76549,"running_times": 6360},{"title": "Greystoke: The Legend of Tarzan, Lord of the Apes","year": 1984,"rating": 6.4,"votes": 15791,"running_times": 8580},{"title": "Gridiron Gang","year": 2006,"rating": 6.9,"votes": 36158,"running_times": 7500},{"title": "Gridlock'd","year": 1997,"rating": 7,"votes": 12700,"running_times": 5460},{"title": "Grimsby","year": 2016,"rating": 6.2,"votes": 69187,"running_times": 4980},{"title": "Grind","year": 2003,"rating": 6,"votes": 10800,"running_times": 6300},{"title": "Grindhouse","year": 2007,"rating": 7.6,"votes": 163369,"running_times": 11460},{"title": "Grizzly Man","year": 2005,"rating": 7.8,"votes": 45276,"running_times": 6180},{"title": "Grosse Pointe Blank","year": 1997,"rating": 7.4,"votes": 78182,"running_times": 6420},{"title": "Groundhog Day","year": 1993,"rating": 8,"votes": 490746,"running_times": 6060},{"title": "Grown Ups","year": 2010,"rating": 6,"votes": 196291,"running_times": 6120},{"title": "Grown Ups 2","year": 2013,"rating": 5.4,"votes": 118711,"running_times": 6060},{"title": "Grudge Match","year": 2013,"rating": 6.4,"votes": 50640,"running_times": 6780},{"title": "Grumpier Old Men","year": 1995,"rating": 6.6,"votes": 20921,"running_times": 6060},{"title": "Grumpy Old Men","year": 1993,"rating": 7,"votes": 37362,"running_times": 6180},{"title": "Guardians of the Galaxy","year": 2014,"rating": 8.1,"votes": 804806,"running_times": 7260},{"title": "Guardians of the Galaxy Vol. 2","year": 2017,"rating": 7.8,"votes": 307773,"running_times": 8160},{"title": "Guarding Tess","year": 1994,"rating": 6.2,"votes": 13643,"running_times": 5760},{"title": "Guess Who","year": 2005,"rating": 5.9,"votes": 35779,"running_times": 6300},{"title": "Guess Who's Coming to Dinner","year": 1967,"rating": 7.8,"votes": 32153,"running_times": 6480},{"title": "Gulliver's Travels","year": 2010,"rating": 4.9,"votes": 56804,"running_times": 5100},{"title": "Gummo","year": 1997,"rating": 6.7,"votes": 26744,"running_times": 5340},{"title": "Gunfight at the O.K. Corral","year": 1957,"rating": 7.2,"votes": 11317,"running_times": 7320},{"title": "Gung Ho","year": 1986,"rating": 6.2,"votes": 10087,"running_times": 6720},{"title": "Guys and Dolls","year": 1955,"rating": 7.3,"votes": 12935,"running_times": 9120},{"title": "Guzaarish","year": 2010,"rating": 7.5,"votes": 13589,"running_times": 7560},{"title": "Gwoemul","year": 2006,"rating": 7,"votes": 77654,"running_times": 7200},{"title": "Habemus Papam","year": 2011,"rating": 6.7,"votes": 11615,"running_times": 6120},{"title": "Habitación en Roma","year": 2010,"rating": 6.2,"votes": 18445,"running_times": 6540},{"title": "Hachi: A Dog's Tale","year": 2009,"rating": 8.1,"votes": 190809,"running_times": 5580},{"title": "Hackers","year": 1995,"rating": 6.2,"votes": 58262,"running_times": 6420},{"title": "Hacksaw Ridge","year": 2016,"rating": 8.2,"votes": 282761,"running_times": 8340},{"title": "Hail, Caesar!","year": 2016,"rating": 6.3,"votes": 96939,"running_times": 6360},{"title": "Hair","year": 1979,"rating": 7.6,"votes": 29465,"running_times": 7260},{"title": "Hairspray","year": 1988,"rating": 7,"votes": 17296,"running_times": 5520},{"title": "Hairspray","year": 2007,"rating": 6.7,"votes": 105515,"running_times": 7020},{"title": "Half Baked","year": 1998,"rating": 6.7,"votes": 51176,"running_times": 4920},{"title": "Half Light","year": 2006,"rating": 6,"votes": 11903,"running_times": 6600},{"title": "Half Nelson","year": 2006,"rating": 7.2,"votes": 76232,"running_times": 6360},{"title": "Half Past Dead","year": 2002,"rating": 4.6,"votes": 12929,"running_times": 5880},{"title": "Hall Pass","year": 2011,"rating": 5.9,"votes": 108841,"running_times": 6660},{"title": "Hallam Foe","year": 2007,"rating": 7,"votes": 11427,"running_times": 5700},{"title": "Halloween","year": 1978,"rating": 7.8,"votes": 176749,"running_times": 6060},{"title": "Halloween","year": 2007,"rating": 6.1,"votes": 94747,"running_times": 7260},{"title": "Halloween 4: The Return of Michael Myers","year": 1988,"rating": 5.9,"votes": 33335,"running_times": 5280},{"title": "Halloween 5","year": 1989,"rating": 5.2,"votes": 26022,"running_times": 5760},{"title": "Halloween H20: 20 Years Later","year": 1998,"rating": 5.7,"votes": 53537,"running_times": 5160},{"title": "Halloween II","year": 1981,"rating": 6.6,"votes": 57321,"running_times": 5520},{"title": "Halloween II","year": 2009,"rating": 4.9,"votes": 39987,"running_times": 7140},{"title": "Halloween III: Season of the Witch","year": 1982,"rating": 4.7,"votes": 32487,"running_times": 5880},{"title": "Halloween: Resurrection","year": 2002,"rating": 4.1,"votes": 29692,"running_times": 5640},{"title": "Halloween: The Curse of Michael Myers","year": 1995,"rating": 5,"votes": 23489,"running_times": 5700},{"title": "Hamburger Hill","year": 1987,"rating": 6.7,"votes": 20324,"running_times": 6600},{"title": "Hamlet","year": 1948,"rating": 7.8,"votes": 12859,"running_times": 9240},{"title": "Hamlet","year": 1990,"rating": 6.8,"votes": 18948,"running_times": 8100},{"title": "Hamlet","year": 1996,"rating": 7.8,"votes": 32395,"running_times": 14520},{"title": "Hamlet 2","year": 2008,"rating": 6.4,"votes": 15690,"running_times": 5520},{"title": "Hancock","year": 2008,"rating": 6.4,"votes": 379865,"running_times": 6120},{"title": "Hands of Stone","year": 2016,"rating": 6.6,"votes": 10581,"running_times": 6660},{"title": "Hang 'Em High","year": 1968,"rating": 7,"votes": 28346,"running_times": 6840},{"title": "Hanging Up","year": 2000,"rating": 4.8,"votes": 10695,"running_times": 5640},{"title": "Hanna","year": 2011,"rating": 6.8,"votes": 167885,"running_times": 6660},{"title": "Hannah Montana: The Movie","year": 2009,"rating": 4.3,"votes": 34482,"running_times": 6120},{"title": "Hannah and Her Sisters","year": 1986,"rating": 8,"votes": 57685,"running_times": 6420},{"title": "Hannibal","year": 2001,"rating": 6.8,"votes": 223188,"running_times": 7860},{"title": "Hannibal Rising","year": 2007,"rating": 6.2,"votes": 92521,"running_times": 7860},{"title": "Hansel & Gretel: Witch Hunters","year": 2013,"rating": 6.1,"votes": 172538,"running_times": 5880},{"title": "Happiness","year": 1998,"rating": 7.8,"votes": 59093,"running_times": 8040},{"title": "Happy Death Day","year": 2017,"rating": 6.5,"votes": 26480,"running_times": 5760},{"title": "Happy Feet","year": 2006,"rating": 6.5,"votes": 145943,"running_times": 6480},{"title": "Happy Feet Two","year": 2011,"rating": 5.9,"votes": 35383,"running_times": 6000},{"title": "Happy Gilmore","year": 1996,"rating": 7,"votes": 168423,"running_times": 5520},{"title": "Happy-Go-Lucky","year": 2008,"rating": 7,"votes": 33856,"running_times": 7080},{"title": "Happythankyoumoreplease","year": 2010,"rating": 6.8,"votes": 27488,"running_times": 6000},{"title": "Hard Ball","year": 2001,"rating": 6.4,"votes": 24106,"running_times": 6540},{"title": "Hard Candy","year": 2005,"rating": 7.1,"votes": 140132,"running_times": 6240},{"title": "Hard Rain","year": 1998,"rating": 5.8,"votes": 28690,"running_times": 5820},{"title": "Hard Target","year": 1993,"rating": 6.1,"votes": 37873,"running_times": 7680},{"title": "Hard to Kill","year": 1990,"rating": 5.8,"votes": 23647,"running_times": 5760},{"title": "Hardcore Henry","year": 2015,"rating": 6.7,"votes": 66693,"running_times": 5760},{"title": "Hardware","year": 1990,"rating": 5.9,"votes": 10673,"running_times": 5640},{"title": "Harlem Nights","year": 1989,"rating": 6,"votes": 15812,"running_times": 6960},{"title": "Harley Davidson and the Marlboro Man","year": 1991,"rating": 6,"votes": 15709,"running_times": 5880},{"title": "Harold & Kumar Escape from Guantanamo Bay","year": 2008,"rating": 6.6,"votes": 119872,"running_times": 6420},{"title": "Harold & Kumar Go to White Castle","year": 2004,"rating": 7.1,"votes": 164461,"running_times": 5280},{"title": "Harold and Maude","year": 1971,"rating": 8,"votes": 61251,"running_times": 5460},{"title": "Harry Brown","year": 2009,"rating": 7.2,"votes": 77817,"running_times": 6180},{"title": "Harry Potter and the Chamber of Secrets","year": 2002,"rating": 7.4,"votes": 439161,"running_times": 10440},{"title": "Harry Potter and the Deathly Hallows: Part 1","year": 2010,"rating": 7.7,"votes": 374837,"running_times": 8760},{"title": "Harry Potter and the Deathly Hallows: Part 2","year": 2011,"rating": 8.1,"votes": 618562,"running_times": 7800},{"title": "Harry Potter and the Goblet of Fire","year": 2005,"rating": 7.7,"votes": 435781,"running_times": 9960},{"title": "Harry Potter and the Half-Blood Prince","year": 2009,"rating": 7.5,"votes": 368314,"running_times": 9180},{"title": "Harry Potter and the Order of the Phoenix","year": 2007,"rating": 7.5,"votes": 402883,"running_times": 8280},{"title": "Harry Potter and the Prisoner of Azkaban","year": 2004,"rating": 7.8,"votes": 434113,"running_times": 8520},{"title": "Harry Potter and the Sorcerer's Stone","year": 2001,"rating": 7.6,"votes": 506880,"running_times": 9540},{"title": "Harry and the Hendersons","year": 1987,"rating": 5.9,"votes": 26455,"running_times": 6600},{"title": "Harsh Times","year": 2005,"rating": 6.9,"votes": 57586,"running_times": 6960},{"title": "Hart's War","year": 2002,"rating": 6.3,"votes": 46235,"running_times": 7500},{"title": "Harvey","year": 1950,"rating": 8,"votes": 47393,"running_times": 6660},{"title": "Hasee Toh Phasee","year": 2014,"rating": 6.9,"votes": 11522,"running_times": 8460},{"title": "Hatchet","year": 2006,"rating": 5.7,"votes": 24930,"running_times": 5580},{"title": "Hatchet II","year": 2010,"rating": 5.5,"votes": 10247,"running_times": 5100},{"title": "Haunter","year": 2013,"rating": 5.9,"votes": 14290,"running_times": 5820},{"title": "Haute tension","year": 2003,"rating": 6.8,"votes": 59182,"running_times": 5460},{"title": "Havoc","year": 2005,"rating": 5.5,"votes": 16845,"running_times": 5580},{"title": "Haywire","year": 2011,"rating": 5.8,"votes": 75871,"running_times": 5580},{"title": "He Got Game","year": 1998,"rating": 6.9,"votes": 38768,"running_times": 8160},{"title": "He Never Died","year": 2015,"rating": 6.4,"votes": 12574,"running_times": 5940},{"title": "He Was a Quiet Man","year": 2007,"rating": 6.8,"votes": 20947,"running_times": 5700},{"title": "He's Just Not That Into You","year": 2009,"rating": 6.4,"votes": 141177,"running_times": 7740},{"title": "Head Over Heels","year": 2001,"rating": 5.4,"votes": 12415,"running_times": 5160},{"title": "Head in the Clouds","year": 2004,"rating": 6.6,"votes": 13236,"running_times": 7920},{"title": "Head of State","year": 2003,"rating": 5.4,"votes": 15818,"running_times": 5700},{"title": "Heart and Souls","year": 1993,"rating": 6.9,"votes": 13971,"running_times": 6240},{"title": "Heartbreak Ridge","year": 1986,"rating": 6.8,"votes": 33303,"running_times": 7800},{"title": "Heartbreakers","year": 2001,"rating": 6.2,"votes": 46577,"running_times": 7380},{"title": "Hearts in Atlantis","year": 2001,"rating": 6.9,"votes": 32398,"running_times": 6060},{"title": "Hearts of Darkness: A Filmmaker's Apocalypse","year": 1991,"rating": 8.2,"votes": 15340,"running_times": 5760},{"title": "Heat","year": 1995,"rating": 8.2,"votes": 476332,"running_times": 10200},{"title": "Heathers","year": 1988,"rating": 7.3,"votes": 68413,"running_times": 6180},{"title": "Heaven & Earth","year": 1993,"rating": 6.8,"votes": 11528,"running_times": 8400},{"title": "Heaven","year": 2002,"rating": 7.1,"votes": 21401,"running_times": 5820},{"title": "Heaven Can Wait","year": 1978,"rating": 6.9,"votes": 15486,"running_times": 6060},{"title": "Heaven Is for Real","year": 2014,"rating": 5.8,"votes": 22680,"running_times": 5940},{"title": "Heaven's Gate","year": 1980,"rating": 6.8,"votes": 11079,"running_times": 19500},{"title": "Heavenly Creatures","year": 1994,"rating": 7.4,"votes": 53288,"running_times": 6480},{"title": "Heavy Metal","year": 1981,"rating": 6.7,"votes": 25961,"running_times": 5400},{"title": "Heavy Weights","year": 1995,"rating": 6.7,"votes": 21356,"running_times": 6000},{"title": "Hector and the Search for Happiness","year": 2014,"rating": 7,"votes": 38151,"running_times": 7200},{"title": "Hedwig and the Angry Inch","year": 2001,"rating": 7.8,"votes": 27944,"running_times": 5700},{"title": "Heisei tanuki gassen ponpoko","year": 1994,"rating": 7.4,"votes": 16877,"running_times": 7140},{"title": "Heist","year": 2001,"rating": 6.6,"votes": 29396,"running_times": 6540},{"title": "Heist","year": 2015,"rating": 6.1,"votes": 21521,"running_times": 5580},{"title": "Hell Ride","year": 2008,"rating": 5.1,"votes": 14601,"running_times": 5040},{"title": "Hell or High Water","year": 2016,"rating": 7.6,"votes": 139821,"running_times": 6120},{"title": "Hellbound: Hellraiser II","year": 1988,"rating": 6.5,"votes": 33894,"running_times": 5940},{"title": "Hellboy","year": 2004,"rating": 6.8,"votes": 264309,"running_times": 7920},{"title": "Hellboy II: The Golden Army","year": 2008,"rating": 7,"votes": 223462,"running_times": 7200},{"title": "Hello, Dolly!","year": 1969,"rating": 7.2,"votes": 11068,"running_times": 8760},{"title": "Hello, My Name Is Doris","year": 2015,"rating": 6.7,"votes": 14600,"running_times": 5400},{"title": "Hellraiser","year": 1987,"rating": 7,"votes": 84790,"running_times": 5640},{"title": "Hellraiser III: Hell on Earth","year": 1992,"rating": 5.5,"votes": 22469,"running_times": 5820},{"title": "Hellraiser: Bloodline","year": 1996,"rating": 5.1,"votes": 15913,"running_times": 5100},{"title": "Help!","year": 1965,"rating": 7.3,"votes": 14710,"running_times": 5520},{"title": "Henry & June","year": 1990,"rating": 6.3,"votes": 10875,"running_times": 8160},{"title": "Henry Poole Is Here","year": 2008,"rating": 6.5,"votes": 11416,"running_times": 5940},{"title": "Henry V","year": 1989,"rating": 7.7,"votes": 25019,"running_times": 8220},{"title": "Henry's Crime","year": 2010,"rating": 6,"votes": 16652,"running_times": 6480},{"title": "Henry: Portrait of a Serial Killer","year": 1986,"rating": 7,"votes": 25794,"running_times": 4980},{"title": "Her","year": 2013,"rating": 8,"votes": 412823,"running_times": 7560},{"title": "Herbie Fully Loaded","year": 2005,"rating": 4.8,"votes": 39449,"running_times": 6060},{"title": "Hercules","year": 1997,"rating": 7.3,"votes": 162326,"running_times": 5580},{"title": "Hercules","year": 2014,"rating": 6,"votes": 126532,"running_times": 6060},{"title": "Hercules in New York","year": 1970,"rating": 3.2,"votes": 14990,"running_times": 5460},{"title": "Here Comes the Boom","year": 2012,"rating": 6.4,"votes": 78346,"running_times": 6300},{"title": "Hereafter","year": 2010,"rating": 6.5,"votes": 83811,"running_times": 7740},{"title": "Hero","year": 1992,"rating": 6.5,"votes": 18785,"running_times": 7140},{"title": "Hesher","year": 2010,"rating": 7.1,"votes": 46468,"running_times": 6360},{"title": "Hick","year": 2011,"rating": 5.7,"votes": 17000,"running_times": 5940},{"title": "Hidalgo","year": 2004,"rating": 6.7,"votes": 71055,"running_times": 8160},{"title": "Hidden","year": 2015,"rating": 6.4,"votes": 15457,"running_times": 5040},{"title": "Hidden Figures","year": 2016,"rating": 7.8,"votes": 130784,"running_times": 7620},{"title": "Hide and Seek","year": 2005,"rating": 5.9,"votes": 74510,"running_times": 6060},{"title": "High Anxiety","year": 1977,"rating": 6.7,"votes": 16701,"running_times": 5640},{"title": "High Crimes","year": 2002,"rating": 6.3,"votes": 33013,"running_times": 6900},{"title": "High Fidelity","year": 2000,"rating": 7.5,"votes": 151450,"running_times": 6780},{"title": "High Noon","year": 1952,"rating": 8,"votes": 85253,"running_times": 5100},{"title": "High Plains Drifter","year": 1973,"rating": 7.6,"votes": 40775,"running_times": 6300},{"title": "High School High","year": 1996,"rating": 5.5,"votes": 11436,"running_times": 5160},{"title": "High School Musical 3: Senior Year","year": 2008,"rating": 4.6,"votes": 48125,"running_times": 6720},{"title": "High Sierra","year": 1941,"rating": 7.6,"votes": 12432,"running_times": 6000},{"title": "High Society","year": 1956,"rating": 7,"votes": 11413,"running_times": 6660},{"title": "High-Rise","year": 2015,"rating": 5.7,"votes": 28955,"running_times": 7140},{"title": "Higher Learning","year": 1995,"rating": 6.5,"votes": 15725,"running_times": 7620},{"title": "Highlander","year": 1986,"rating": 7.2,"votes": 105854,"running_times": 6960},{"title": "Highlander II: The Quickening","year": 1991,"rating": 4.1,"votes": 38881,"running_times": 6540},{"title": "Highlander III: The Sorcerer","year": 1994,"rating": 4.4,"votes": 17489,"running_times": 5940},{"title": "Highlander: Endgame","year": 2000,"rating": 4.6,"votes": 17359,"running_times": 6060},{"title": "Highway","year": 2014,"rating": 7.6,"votes": 20548,"running_times": 7980},{"title": "Hiroshima mon amour","year": 1959,"rating": 8,"votes": 22156,"running_times": 5400},{"title": "His Girl Friday","year": 1940,"rating": 8,"votes": 44758,"running_times": 5520},{"title": "History of the World: Part I","year": 1981,"rating": 6.9,"votes": 39778,"running_times": 5820},{"title": "Hit and Run","year": 2012,"rating": 6.1,"votes": 31091,"running_times": 6000},{"title": "Hitch","year": 2005,"rating": 6.6,"votes": 262082,"running_times": 7080},{"title": "Hitchcock","year": 2012,"rating": 6.8,"votes": 64671,"running_times": 5880},{"title": "Hitman","year": 2007,"rating": 6.3,"votes": 147724,"running_times": 6000},{"title": "Hitman: Agent 47","year": 2015,"rating": 5.7,"votes": 74251,"running_times": 5760},{"title": "Hobo with a Shotgun","year": 2011,"rating": 6.1,"votes": 39715,"running_times": 5160},{"title": "Hocus Pocus","year": 1993,"rating": 6.8,"votes": 70603,"running_times": 5760},{"title": "Hodejegerne","year": 2011,"rating": 7.6,"votes": 86454,"running_times": 5760},{"title": "Hoffa","year": 1992,"rating": 6.6,"votes": 18392,"running_times": 8400},{"title": "Hokkabaz","year": 2006,"rating": 7.5,"votes": 22397,"running_times": 7320},{"title": "Holes","year": 2003,"rating": 7.1,"votes": 64114,"running_times": 7020},{"title": "Holiday","year": 1938,"rating": 7.9,"votes": 11757,"running_times": 5700},{"title": "Hollow Man","year": 2000,"rating": 5.7,"votes": 108608,"running_times": 7140},{"title": "Hollywood Ending","year": 2002,"rating": 6.6,"votes": 23284,"running_times": 6720},{"title": "Hollywood Homicide","year": 2003,"rating": 5.3,"votes": 32736,"running_times": 6960},{"title": "Hollywoodland","year": 2006,"rating": 6.5,"votes": 30461,"running_times": 7560},{"title": "Holy Man","year": 1998,"rating": 4.9,"votes": 17246,"running_times": 6840},{"title": "Holy Motors","year": 2012,"rating": 7.1,"votes": 33547,"running_times": 6900},{"title": "Holy Smoke","year": 1999,"rating": 5.9,"votes": 12767,"running_times": 6900},{"title": "Home","year": 2009,"rating": 8.6,"votes": 19620,"running_times": 7200},{"title": "Home","year": 2015,"rating": 6.7,"votes": 80214,"running_times": 5640},{"title": "Home Alone","year": 1990,"rating": 7.5,"votes": 358522,"running_times": 6180},{"title": "Home Alone 2: Lost in New York","year": 1992,"rating": 6.6,"votes": 231633,"running_times": 7200},{"title": "Home Alone 3","year": 1997,"rating": 4.3,"votes": 84915,"running_times": 6120},{"title": "Home Sweet Hell","year": 2015,"rating": 5.4,"votes": 11800,"running_times": 5880},{"title": "Home on the Range","year": 2004,"rating": 5.4,"votes": 15587,"running_times": 4560},{"title": "Homefront","year": 2013,"rating": 6.5,"votes": 91464,"running_times": 6000},{"title": "Homeward Bound II: Lost in San Francisco","year": 1996,"rating": 5.9,"votes": 11621,"running_times": 5340},{"title": "Homeward Bound: The Incredible Journey","year": 1993,"rating": 6.9,"votes": 36406,"running_times": 5040},{"title": "Honey","year": 2003,"rating": 5.3,"votes": 39141,"running_times": 5640},{"title": "Honey I Blew Up the Kid","year": 1992,"rating": 4.7,"votes": 34738,"running_times": 5340},{"title": "Honey, I Shrunk the Kids","year": 1989,"rating": 6.3,"votes": 118405,"running_times": 5580},{"title": "Honeymoon","year": 2014,"rating": 5.7,"votes": 20850,"running_times": 5220},{"title": "Honeymoon in Vegas","year": 1992,"rating": 5.8,"votes": 15156,"running_times": 5760},{"title": "Hoodwinked Too! Hood vs. Evil","year": 2011,"rating": 4.8,"votes": 10424,"running_times": 5160},{"title": "Hoodwinked!","year": 2005,"rating": 6.5,"votes": 49338,"running_times": 4800},{"title": "Hook","year": 1991,"rating": 6.7,"votes": 198650,"running_times": 8520},{"title": "Hooligans","year": 2005,"rating": 7.5,"votes": 127112,"running_times": 6540},{"title": "Hoop Dreams","year": 1994,"rating": 8.3,"votes": 20884,"running_times": 10200},{"title": "Hoosiers","year": 1986,"rating": 7.6,"votes": 36946,"running_times": 6840},{"title": "Hop","year": 2011,"rating": 5.5,"votes": 26311,"running_times": 5700},{"title": "Hope Floats","year": 1998,"rating": 5.9,"votes": 20949,"running_times": 6840},{"title": "Hope Springs","year": 2012,"rating": 6.3,"votes": 36803,"running_times": 6000},{"title": "Hope and Glory","year": 1987,"rating": 7.4,"votes": 10464,"running_times": 6780},{"title": "Horns","year": 2013,"rating": 6.5,"votes": 64239,"running_times": 7200},{"title": "Horrible Bosses","year": 2011,"rating": 6.9,"votes": 378107,"running_times": 6360},{"title": "Horrible Bosses 2","year": 2014,"rating": 6.3,"votes": 131371,"running_times": 6960},{"title": "Hors de prix","year": 2006,"rating": 7,"votes": 27628,"running_times": 6360},{"title": "Horse Feathers","year": 1932,"rating": 7.7,"votes": 10105,"running_times": 4080},{"title": "Horsemen","year": 2009,"rating": 5.6,"votes": 19785,"running_times": 5400},{"title": "Horton Hears a Who!","year": 2008,"rating": 6.8,"votes": 114271,"running_times": 5160},{"title": "Hostage","year": 2005,"rating": 6.6,"votes": 98148,"running_times": 6780},{"title": "Hostel","year": 2005,"rating": 5.9,"votes": 149732,"running_times": 5640},{"title": "Hostel: Part II","year": 2007,"rating": 5.5,"votes": 75544,"running_times": 5640},{"title": "Hot Fuzz","year": 2007,"rating": 7.9,"votes": 390102,"running_times": 7260},{"title": "Hot Girls Wanted","year": 2015,"rating": 6.1,"votes": 11368,"running_times": 5040},{"title": "Hot Pursuit","year": 2015,"rating": 5.1,"votes": 41002,"running_times": 5220},{"title": "Hot Rod","year": 2007,"rating": 6.7,"votes": 65211,"running_times": 5280},{"title": "Hot Shots!","year": 1991,"rating": 6.7,"votes": 86014,"running_times": 5040},{"title": "Hot Shots! Part Deux","year": 1993,"rating": 6.6,"votes": 72998,"running_times": 5160},{"title": "Hot Tub Time Machine","year": 2010,"rating": 6.4,"votes": 146646,"running_times": 6060},{"title": "Hot Tub Time Machine 2","year": 2015,"rating": 5.1,"votes": 32007,"running_times": 5940},{"title": "Hotel Chevalier","year": 2007,"rating": 7.3,"votes": 25983,"running_times": 780},{"title": "Hotel Rwanda","year": 2004,"rating": 8.1,"votes": 289707,"running_times": 7260},{"title": "Hotel Transylvania","year": 2012,"rating": 7.1,"votes": 183497,"running_times": 5460},{"title": "Hotel Transylvania 2","year": 2015,"rating": 6.7,"votes": 75463,"running_times": 5340},{"title": "Hotel for Dogs","year": 2009,"rating": 5.4,"votes": 18004,"running_times": 6000},{"title": "Hours","year": 2013,"rating": 6.5,"votes": 24595,"running_times": 5820},{"title": "House","year": 1985,"rating": 6.2,"votes": 18925,"running_times": 5580},{"title": "House at the End of the Street","year": 2012,"rating": 5.6,"votes": 62772,"running_times": 6060},{"title": "House of 1000 Corpses","year": 2003,"rating": 6,"votes": 65306,"running_times": 6300},{"title": "House of Games","year": 1987,"rating": 7.3,"votes": 17627,"running_times": 6120},{"title": "House of Sand and Fog","year": 2003,"rating": 7.6,"votes": 59246,"running_times": 7560},{"title": "House of Wax","year": 1953,"rating": 7.1,"votes": 13079,"running_times": 5280},{"title": "House of Wax","year": 2005,"rating": 5.3,"votes": 101370,"running_times": 6480},{"title": "House of the Dead","year": 2003,"rating": 2,"votes": 33466,"running_times": 5400},{"title": "House on Haunted Hill","year": 1959,"rating": 6.9,"votes": 18072,"running_times": 4500},{"title": "House on Haunted Hill","year": 1999,"rating": 5.6,"votes": 47824,"running_times": 5940},{"title": "HouseSitter","year": 1992,"rating": 6,"votes": 18605,"running_times": 6120},{"title": "Housebound","year": 2014,"rating": 6.8,"votes": 27690,"running_times": 6420},{"title": "How Do You Know","year": 2010,"rating": 5.4,"votes": 37932,"running_times": 7260},{"title": "How Green Was My Valley","year": 1941,"rating": 7.8,"votes": 17395,"running_times": 7080},{"title": "How High","year": 2001,"rating": 6.3,"votes": 46268,"running_times": 5700},{"title": "How I Live Now","year": 2013,"rating": 6.5,"votes": 24050,"running_times": 6060},{"title": "How the Grinch Stole Christmas","year": 2000,"rating": 6.1,"votes": 159672,"running_times": 6600},{"title": "How the West Was Won","year": 1962,"rating": 7.1,"votes": 15613,"running_times": 9840},{"title": "How to Be Single","year": 2016,"rating": 6.1,"votes": 64963,"running_times": 6600},{"title": "How to Lose Friends & Alienate People","year": 2008,"rating": 6.4,"votes": 63646,"running_times": 6600},{"title": "How to Lose a Guy in 10 Days","year": 2003,"rating": 6.4,"votes": 174435,"running_times": 6960},{"title": "How to Marry a Millionaire","year": 1953,"rating": 7,"votes": 17157,"running_times": 5700},{"title": "How to Steal a Million","year": 1966,"rating": 7.6,"votes": 19967,"running_times": 7380},{"title": "How to Train Your Dragon","year": 2010,"rating": 8.1,"votes": 546154,"running_times": 5880},{"title": "How to Train Your Dragon 2","year": 2014,"rating": 7.8,"votes": 246660,"running_times": 6120},{"title": "Howard the Duck","year": 1986,"rating": 4.6,"votes": 36526,"running_times": 6600},{"title": "Howards End","year": 1992,"rating": 7.5,"votes": 23352,"running_times": 8520},{"title": "Howl","year": 2010,"rating": 6.8,"votes": 11508,"running_times": 5040},{"title": "Hud","year": 1963,"rating": 7.9,"votes": 16445,"running_times": 6720},{"title": "Hudson Hawk","year": 1991,"rating": 5.8,"votes": 46017,"running_times": 6000},{"title": "Hugo","year": 2011,"rating": 7.5,"votes": 266903,"running_times": 7560},{"title": "Hulk","year": 2003,"rating": 5.7,"votes": 226165,"running_times": 8280},{"title": "Hum Dil De Chuke Sanam","year": 1999,"rating": 7.6,"votes": 13474,"running_times": 11280},{"title": "Hum Tum","year": 2004,"rating": 7.1,"votes": 11318,"running_times": 8520},{"title": "Human Nature","year": 2001,"rating": 6.4,"votes": 16165,"running_times": 5760},{"title": "Human Traffic","year": 1999,"rating": 7.1,"votes": 20483,"running_times": 5940},{"title": "Hummingbird","year": 2013,"rating": 6.2,"votes": 56975,"running_times": 6000},{"title": "Hundraåringen som klev ut genom fönstret och försvann","year": 2013,"rating": 7.1,"votes": 31798,"running_times": 6840},{"title": "Hung fan kui","year": 1995,"rating": 6.7,"votes": 32871,"running_times": 6240},{"title": "Hunger","year": 2008,"rating": 7.6,"votes": 56874,"running_times": 5760},{"title": "Hunt for the Wilderpeople","year": 2016,"rating": 7.9,"votes": 65738,"running_times": 6060},{"title": "Huo yuanjia","year": 2006,"rating": 7.7,"votes": 66069,"running_times": 8460},{"title": "Husbands and Wives","year": 1992,"rating": 7.6,"votes": 23348,"running_times": 6180},{"title": "Hush","year": 2016,"rating": 6.6,"votes": 56665,"running_times": 4860},{"title": "Hush...Hush, Sweet Charlotte","year": 1964,"rating": 7.7,"votes": 10077,"running_times": 7980},{"title": "Hustle & Flow","year": 2005,"rating": 7.4,"votes": 35128,"running_times": 6960},{"title": "Hyde Park on Hudson","year": 2012,"rating": 5.9,"votes": 10079,"running_times": 5640},{"title": "Hysteria","year": 2011,"rating": 6.7,"votes": 27483,"running_times": 6000},{"title": "Hævnen","year": 2010,"rating": 7.7,"votes": 34828,"running_times": 7140},{"title": "Höstsonaten","year": 1978,"rating": 8.3,"votes": 17643,"running_times": 5940},{"title": "I Am Legend","year": 2007,"rating": 7.2,"votes": 587088,"running_times": 6240},{"title": "I Am Number Four","year": 2011,"rating": 6.1,"votes": 207158,"running_times": 6540},{"title": "I Am Sam","year": 2001,"rating": 7.6,"votes": 129669,"running_times": 7920},{"title": "I Confess","year": 1953,"rating": 7.3,"votes": 15940,"running_times": 5700},{"title": "I Could Never Be Your Woman","year": 2007,"rating": 6,"votes": 15268,"running_times": 5820},{"title": "I Don't Feel at Home in This World Anymore.","year": 2017,"rating": 7,"votes": 21910,"running_times": 5580},{"title": "I Don't Know How She Does It","year": 2011,"rating": 4.9,"votes": 17591,"running_times": 5340},{"title": "I Give It a Year","year": 2013,"rating": 5.7,"votes": 32224,"running_times": 5820},{"title": "I Heart Huckabees","year": 2004,"rating": 6.7,"votes": 58804,"running_times": 6420},{"title": "I Kina spiser de hunde","year": 1999,"rating": 7.5,"votes": 17406,"running_times": 5460},{"title": "I Know What You Did Last Summer","year": 1997,"rating": 5.6,"votes": 114383,"running_times": 6060},{"title": "I Know Who Killed Me","year": 2007,"rating": 3.6,"votes": 23923,"running_times": 6300},{"title": "I Love Trouble","year": 1994,"rating": 5.2,"votes": 10211,"running_times": 7380},{"title": "I Love You Phillip Morris","year": 2009,"rating": 6.6,"votes": 83209,"running_times": 6120},{"title": "I Love You to Death","year": 1990,"rating": 6.4,"votes": 11731,"running_times": 5820},{"title": "I Love You, Beth Cooper","year": 2009,"rating": 5.3,"votes": 30092,"running_times": 6120},{"title": "I Love You, Man","year": 2009,"rating": 7,"votes": 176457,"running_times": 6300},{"title": "I Now Pronounce You Chuck & Larry","year": 2007,"rating": 6,"votes": 126959,"running_times": 6900},{"title": "I Origins","year": 2014,"rating": 7.3,"votes": 92619,"running_times": 6360},{"title": "I Spit on Your Grave","year": 2010,"rating": 6.3,"votes": 62588,"running_times": 6480},{"title": "I Spit on Your Grave 2","year": 2013,"rating": 5.7,"votes": 21431,"running_times": 6360},{"title": "I Spy","year": 2002,"rating": 5.4,"votes": 44160,"running_times": 5820},{"title": "I Still Know What You Did Last Summer","year": 1998,"rating": 4.6,"votes": 59565,"running_times": 6000},{"title": "I Think I Love My Wife","year": 2007,"rating": 5.5,"votes": 14333,"running_times": 5640},{"title": "I'm Gonna Git You Sucka","year": 1988,"rating": 6.6,"votes": 10536,"running_times": 5280},{"title": "I'm Not There.","year": 2007,"rating": 7,"votes": 50996,"running_times": 8100},{"title": "I'm Still Here","year": 2010,"rating": 6.2,"votes": 17253,"running_times": 6480},{"title": "I, Daniel Blake","year": 2016,"rating": 7.9,"votes": 33594,"running_times": 6000},{"title": "I, Frankenstein","year": 2014,"rating": 5.1,"votes": 71379,"running_times": 5520},{"title": "I, Robot","year": 2004,"rating": 7.1,"votes": 428767,"running_times": 6900},{"title": "I.Q.","year": 1994,"rating": 6.2,"votes": 21084,"running_times": 6000},{"title": "I.T.","year": 2016,"rating": 5.4,"votes": 10972,"running_times": 5700},{"title": "Ice Age","year": 2002,"rating": 7.6,"votes": 362481,"running_times": 6180},{"title": "Ice Age: Collision Course","year": 2016,"rating": 5.7,"votes": 39957,"running_times": 5640},{"title": "Ice Age: Continental Drift","year": 2012,"rating": 6.6,"votes": 160411,"running_times": 5280},{"title": "Ice Age: Dawn of the Dinosaurs","year": 2009,"rating": 7,"votes": 184847,"running_times": 7320},{"title": "Ice Age: The Meltdown","year": 2006,"rating": 6.8,"votes": 214495,"running_times": 6900},{"title": "Ice Princess","year": 2005,"rating": 6,"votes": 21459,"running_times": 5880},{"title": "Identity","year": 2003,"rating": 7.3,"votes": 194439,"running_times": 5460},{"title": "Identity Thief","year": 2013,"rating": 5.7,"votes": 106125,"running_times": 7260},{"title": "Idiocracy","year": 2006,"rating": 6.6,"votes": 119657,"running_times": 5040},{"title": "Idle Hands","year": 1999,"rating": 6.2,"votes": 35508,"running_times": 5520},{"title": "If I Stay","year": 2014,"rating": 6.8,"votes": 97119,"running_times": 6420},{"title": "If Only","year": 2004,"rating": 7.2,"votes": 28528,"running_times": 5580},{"title": "If....","year": 1968,"rating": 7.7,"votes": 18590,"running_times": 6660},{"title": "Igby Goes Down","year": 2002,"rating": 7,"votes": 30041,"running_times": 5940},{"title": "Igor","year": 2008,"rating": 6,"votes": 20624,"running_times": 5220},{"title": "Il conformista","year": 1970,"rating": 8.1,"votes": 20440,"running_times": 6780},{"title": "Il divo - La spettacolare vita di Giulio Andreotti","year": 2008,"rating": 7.3,"votes": 13070,"running_times": 6600},{"title": "Il grande silenzio","year": 1968,"rating": 7.8,"votes": 10696,"running_times": 6300},{"title": "Il racconto dei racconti - Tale of Tales","year": 2015,"rating": 6.4,"votes": 19327,"running_times": 8040},{"title": "Il y a longtemps que je t'aime","year": 2008,"rating": 7.6,"votes": 18473,"running_times": 7020},{"title": "Im Juli","year": 2000,"rating": 7.8,"votes": 18049,"running_times": 5940},{"title": "Imagine Me & You","year": 2005,"rating": 6.8,"votes": 25393,"running_times": 5400},{"title": "Imagine That","year": 2009,"rating": 5.6,"votes": 11384,"running_times": 6420},{"title": "Imitation of Life","year": 1959,"rating": 7.9,"votes": 12112,"running_times": 7500},{"title": "Immortal Beloved","year": 1994,"rating": 7.5,"votes": 20290,"running_times": 7260},{"title": "Immortals","year": 2011,"rating": 6,"votes": 146055,"running_times": 6600},{"title": "Immortel (ad vitam)","year": 2004,"rating": 6,"votes": 19010,"running_times": 6180},{"title": "Imperium","year": 2016,"rating": 6.5,"votes": 31969,"running_times": 6540},{"title": "Impostor","year": 2001,"rating": 6.2,"votes": 20888,"running_times": 6120},{"title": "In & Out","year": 1997,"rating": 6.3,"votes": 34168,"running_times": 5400},{"title": "In America","year": 2002,"rating": 7.8,"votes": 37906,"running_times": 6300},{"title": "In Bruges","year": 2008,"rating": 7.9,"votes": 332444,"running_times": 6420},{"title": "In Cold Blood","year": 1967,"rating": 8,"votes": 20567,"running_times": 8040},{"title": "In Dreams","year": 1999,"rating": 5.5,"votes": 11367,"running_times": 6000},{"title": "In Good Company","year": 2004,"rating": 6.5,"votes": 50486,"running_times": 6540},{"title": "In Hell","year": 2003,"rating": 6.3,"votes": 16438,"running_times": 5880},{"title": "In Her Shoes","year": 2005,"rating": 6.5,"votes": 54532,"running_times": 7800},{"title": "In Time","year": 2011,"rating": 6.7,"votes": 327425,"running_times": 6540},{"title": "In Your Eyes","year": 2014,"rating": 7.1,"votes": 26765,"running_times": 6360},{"title": "In a Lonely Place","year": 1950,"rating": 8,"votes": 19749,"running_times": 5640},{"title": "In a World...","year": 2013,"rating": 6.7,"votes": 28040,"running_times": 5580},{"title": "In the Army Now","year": 1994,"rating": 4.8,"votes": 10741,"running_times": 5460},{"title": "In the Bedroom","year": 2001,"rating": 7.5,"votes": 33930,"running_times": 8280},{"title": "In the Company of Men","year": 1997,"rating": 7.3,"votes": 12049,"running_times": 5820},{"title": "In the Cut","year": 2003,"rating": 5.3,"votes": 19559,"running_times": 7140},{"title": "In the Electric Mist","year": 2009,"rating": 6.1,"votes": 14439,"running_times": 7020},{"title": "In the Heart of the Sea","year": 2015,"rating": 6.9,"votes": 96896,"running_times": 7320},{"title": "In the Heat of the Night","year": 1967,"rating": 8,"votes": 55172,"running_times": 6540},{"title": "In the Land of Blood and Honey","year": 2011,"rating": 4.4,"votes": 32191,"running_times": 7620},{"title": "In the Land of Women","year": 2007,"rating": 6.5,"votes": 28999,"running_times": 5820},{"title": "In the Line of Fire","year": 1993,"rating": 7.2,"votes": 79362,"running_times": 8280},{"title": "In the Loop","year": 2009,"rating": 7.5,"votes": 47572,"running_times": 6360},{"title": "In the Mouth of Madness","year": 1994,"rating": 7.2,"votes": 48288,"running_times": 5700},{"title": "In the Name of the Father","year": 1993,"rating": 8.1,"votes": 125082,"running_times": 7980},{"title": "In the Name of the King: A Dungeon Siege Tale","year": 2007,"rating": 3.8,"votes": 40212,"running_times": 9360},{"title": "In the Valley of Elah","year": 2007,"rating": 7.2,"votes": 63206,"running_times": 7260},{"title": "Incendies","year": 2010,"rating": 8.2,"votes": 101345,"running_times": 7860},{"title": "Inception","year": 2010,"rating": 8.8,"votes": 1653028,"running_times": 8880},{"title": "Indecent Proposal","year": 1993,"rating": 5.8,"votes": 52305,"running_times": 7020},{"title": "Independence Day","year": 1996,"rating": 7,"votes": 465279,"running_times": 9240},{"title": "Independence Day: Resurgence","year": 2016,"rating": 5.3,"votes": 139960,"running_times": 7200},{"title": "Indiana Jones and the Kingdom of the Crystal Skull","year": 2008,"rating": 6.2,"votes": 362353,"running_times": 7320},{"title": "Indiana Jones and the Last Crusade","year": 1989,"rating": 8.3,"votes": 574150,"running_times": 7620},{"title": "Indiana Jones and the Temple of Doom","year": 1984,"rating": 7.6,"votes": 367264,"running_times": 7080},{"title": "Indie Game: The Movie","year": 2012,"rating": 7.7,"votes": 18687,"running_times": 6180},{"title": "Infamous","year": 2006,"rating": 7.1,"votes": 14944,"running_times": 7080},{"title": "Inferno","year": 1980,"rating": 6.7,"votes": 13844,"running_times": 7200},{"title": "Inferno","year": 2016,"rating": 6.2,"votes": 115981,"running_times": 7260},{"title": "Infini","year": 2015,"rating": 5.4,"votes": 12268,"running_times": 6600},{"title": "Infinitely Polar Bear","year": 2014,"rating": 7,"votes": 12653,"running_times": 5400},{"title": "Inglourious Basterds","year": 2009,"rating": 8.3,"votes": 1004190,"running_times": 9180},{"title": "Ingrid Goes West","year": 2017,"rating": 6.7,"votes": 10144,"running_times": 5880},{"title": "Inherent Vice","year": 2014,"rating": 6.7,"votes": 73405,"running_times": 8880},{"title": "Inherit the Wind","year": 1960,"rating": 8.2,"votes": 22703,"running_times": 7680},{"title": "Ink","year": 2009,"rating": 7,"votes": 19498,"running_times": 6420},{"title": "Inkheart","year": 2008,"rating": 6.1,"votes": 65047,"running_times": 6360},{"title": "Inland Empire","year": 2006,"rating": 7,"votes": 46150,"running_times": 11820},{"title": "Innerspace","year": 1987,"rating": 6.8,"votes": 45776,"running_times": 7200},{"title": "Innocence","year": 2004,"rating": 7.6,"votes": 31374,"running_times": 6000},{"title": "Inside I'm Dancing","year": 2004,"rating": 7.9,"votes": 12600,"running_times": 6240},{"title": "Inside Job","year": 2010,"rating": 8.3,"votes": 61590,"running_times": 6300},{"title": "Inside Llewyn Davis","year": 2013,"rating": 7.5,"votes": 110845,"running_times": 6240},{"title": "Inside Man","year": 2006,"rating": 7.6,"votes": 293330,"running_times": 7740},{"title": "Inside Out","year": 2015,"rating": 8.2,"votes": 451282,"running_times": 5700},{"title": "Insidious","year": 2010,"rating": 6.8,"votes": 229734,"running_times": 6180},{"title": "Insidious: Chapter 2","year": 2013,"rating": 6.6,"votes": 125404,"running_times": 6360},{"title": "Insidious: Chapter 3","year": 2015,"rating": 6.1,"votes": 69063,"running_times": 5820},{"title": "Insomnia","year": 2002,"rating": 7.2,"votes": 238048,"running_times": 7080},{"title": "Inspector Gadget","year": 1999,"rating": 4.1,"votes": 39282,"running_times": 6600},{"title": "Instinct","year": 1999,"rating": 6.5,"votes": 28930,"running_times": 7560},{"title": "Insurgent","year": 2015,"rating": 6.3,"votes": 181020,"running_times": 7140},{"title": "Intacto","year": 2001,"rating": 6.9,"votes": 11851,"running_times": 6480},{"title": "Interiors","year": 1978,"rating": 7.5,"votes": 15486,"running_times": 5520},{"title": "Intermission","year": 2003,"rating": 6.9,"votes": 14149,"running_times": 6300},{"title": "Internal Affairs","year": 1990,"rating": 6.5,"votes": 14372,"running_times": 6900},{"title": "Interstate 60: Episodes of the Road","year": 2002,"rating": 7.7,"votes": 25480,"running_times": 6960},{"title": "Interstella 5555: The 5tory of the 5ecret 5tar 5ystem","year": 2003,"rating": 7.9,"votes": 11987,"running_times": 4080},{"title": "Interstellar","year": 2014,"rating": 8.6,"votes": 1119789,"running_times": 10140},{"title": "Interview","year": 2007,"rating": 6.8,"votes": 12610,"running_times": 5040},{"title": "Interview with the Vampire: The Vampire Chronicles","year": 1994,"rating": 7.6,"votes": 257571,"running_times": 7380},{"title": "Into the Abyss","year": 2011,"rating": 7.3,"votes": 13936,"running_times": 6420},{"title": "Into the Blue","year": 2005,"rating": 5.8,"votes": 66989,"running_times": 6600},{"title": "Into the Forest","year": 2015,"rating": 5.9,"votes": 12306,"running_times": 6060},{"title": "Into the Storm","year": 2014,"rating": 5.8,"votes": 57871,"running_times": 5340},{"title": "Into the White","year": 2012,"rating": 7.2,"votes": 16822,"running_times": 6240},{"title": "Into the Wild","year": 2007,"rating": 8.1,"votes": 478844,"running_times": 8880},{"title": "Into the Woods","year": 2014,"rating": 6,"votes": 113738,"running_times": 7500},{"title": "Intolerable Cruelty","year": 2003,"rating": 6.3,"votes": 81396,"running_times": 6000},{"title": "Intouchables","year": 2011,"rating": 8.6,"votes": 590763,"running_times": 6720},{"title": "Intruders","year": 2011,"rating": 5.4,"votes": 18646,"running_times": 6000},{"title": "Invasion of the Body Snatchers","year": 1956,"rating": 7.8,"votes": 37639,"running_times": 4800},{"title": "Invasion of the Body Snatchers","year": 1978,"rating": 7.4,"votes": 41739,"running_times": 6900},{"title": "Inventing the Abbotts","year": 1997,"rating": 6.4,"votes": 10116,"running_times": 6600},{"title": "Invictus","year": 2009,"rating": 7.4,"votes": 133507,"running_times": 8040},{"title": "Invincible","year": 2006,"rating": 7.1,"votes": 56381,"running_times": 6300},{"title": "Io sono l'amore","year": 2009,"rating": 7,"votes": 15807,"running_times": 7200},{"title": "Iris","year": 2001,"rating": 7.1,"votes": 15548,"running_times": 5460},{"title": "Irma la Douce","year": 1963,"rating": 7.4,"votes": 13869,"running_times": 8820},{"title": "Iron Eagle","year": 1986,"rating": 5.3,"votes": 11396,"running_times": 7020},{"title": "Iron Man","year": 2008,"rating": 7.9,"votes": 765492,"running_times": 7560},{"title": "Iron Man 2","year": 2010,"rating": 7,"votes": 579338,"running_times": 7440},{"title": "Iron Man Three","year": 2013,"rating": 7.2,"votes": 613287,"running_times": 11700},{"title": "Iron Sky","year": 2012,"rating": 5.9,"votes": 83589,"running_times": 6600},{"title": "Ironclad","year": 2011,"rating": 6.2,"votes": 36401,"running_times": 7260},{"title": "Irrational Man","year": 2015,"rating": 6.6,"votes": 44129,"running_times": 5700},{"title": "Irréversible","year": 2002,"rating": 7.4,"votes": 96418,"running_times": 5940},{"title": "It","year": 2017,"rating": 7.7,"votes": 193799,"running_times": 8100},{"title": "It Comes at Night","year": 2017,"rating": 6.2,"votes": 42069,"running_times": 5460},{"title": "It Could Happen to You","year": 1994,"rating": 6.3,"votes": 29833,"running_times": 6060},{"title": "It Follows","year": 2014,"rating": 6.9,"votes": 152676,"running_times": 6000},{"title": "It Happened One Night","year": 1934,"rating": 8.2,"votes": 73493,"running_times": 6300},{"title": "It Might Get Loud","year": 2008,"rating": 7.6,"votes": 11240,"running_times": 5880},{"title": "It Takes Two","year": 1995,"rating": 5.8,"votes": 16405,"running_times": 6060},{"title": "It's All Gone Pete Tong","year": 2004,"rating": 7.4,"votes": 17682,"running_times": 5400},{"title": "It's Complicated","year": 2009,"rating": 6.6,"votes": 74931,"running_times": 7200},{"title": "It's Kind of a Funny Story","year": 2010,"rating": 7.1,"votes": 116972,"running_times": 6060},{"title": "It's a Boy Girl Thing","year": 2006,"rating": 6.3,"votes": 34972,"running_times": 5700},{"title": "It's a Mad Mad Mad Mad World","year": 1963,"rating": 7.6,"votes": 31888,"running_times": 12300},{"title": "It's a Wonderful Life","year": 1946,"rating": 8.6,"votes": 312993,"running_times": 7800},{"title": "Italiensk for begyndere","year": 2000,"rating": 7.1,"votes": 11849,"running_times": 7080},{"title": "J. Edgar","year": 2011,"rating": 6.6,"votes": 109877,"running_times": 8220},{"title": "JCVD","year": 2008,"rating": 7.2,"votes": 34799,"running_times": 5820},{"title": "JFK","year": 1991,"rating": 8,"votes": 122897,"running_times": 12360},{"title": "Jab We Met","year": 2007,"rating": 8,"votes": 37148,"running_times": 8280},{"title": "Jabberwocky","year": 1977,"rating": 6.2,"votes": 10865,"running_times": 6300},{"title": "Jack","year": 1996,"rating": 5.8,"votes": 49751,"running_times": 6780},{"title": "Jack Frost","year": 1998,"rating": 5.3,"votes": 27169,"running_times": 6060},{"title": "Jack Reacher","year": 2012,"rating": 7,"votes": 260550,"running_times": 7800},{"title": "Jack Reacher: Never Go Back","year": 2016,"rating": 6.1,"votes": 96285,"running_times": 7080},{"title": "Jack Ryan: Shadow Recruit","year": 2014,"rating": 6.2,"votes": 106376,"running_times": 6300},{"title": "Jack and Jill","year": 2011,"rating": 3.4,"votes": 65679,"running_times": 5460},{"title": "Jack the Giant Slayer","year": 2013,"rating": 6.3,"votes": 115065,"running_times": 6840},{"title": "Jackass 3D","year": 2010,"rating": 7,"votes": 50664,"running_times": 6060},{"title": "Jackass Number Two","year": 2006,"rating": 7.1,"votes": 59800,"running_times": 5520},{"title": "Jackass: The Movie","year": 2002,"rating": 6.6,"votes": 72492,"running_times": 5220},{"title": "Jackie","year": 2016,"rating": 6.7,"votes": 54108,"running_times": 6000},{"title": "Jackie Brown","year": 1997,"rating": 7.5,"votes": 260746,"running_times": 9240},{"title": "Jacob's Ladder","year": 1990,"rating": 7.5,"votes": 83001,"running_times": 6780},{"title": "Jagged Edge","year": 1985,"rating": 6.5,"votes": 11243,"running_times": 6480},{"title": "Jagten","year": 2012,"rating": 8.3,"votes": 206070,"running_times": 6900},{"title": "Jakob the Liar","year": 1999,"rating": 6.5,"votes": 13452,"running_times": 7200},{"title": "James and the Giant Peach","year": 1996,"rating": 6.7,"votes": 53040,"running_times": 4740},{"title": "Jane Austen's Mafia!","year": 1998,"rating": 5.5,"votes": 13259,"running_times": 5220},{"title": "Jane Eyre","year": 2011,"rating": 7.4,"votes": 69801,"running_times": 7200},{"title": "Jane Got a Gun","year": 2015,"rating": 5.9,"votes": 16203,"running_times": 5880},{"title": "Jarhead","year": 2005,"rating": 7,"votes": 153689,"running_times": 7500},{"title": "Jason Bourne","year": 2016,"rating": 6.6,"votes": 168047,"running_times": 7380},{"title": "Jason Goes to Hell: The Final Friday","year": 1993,"rating": 4.3,"votes": 21936,"running_times": 5460},{"title": "Jason Lives: Friday the 13th Part VI","year": 1986,"rating": 5.9,"votes": 29197,"running_times": 5160},{"title": "Jason X","year": 2001,"rating": 4.4,"votes": 42714,"running_times": 5460},{"title": "Jason and the Argonauts","year": 1963,"rating": 7.4,"votes": 19059,"running_times": 6240},{"title": "Jawbreaker","year": 1999,"rating": 5.5,"votes": 20502,"running_times": 5760},{"title": "Jaws","year": 1975,"rating": 8,"votes": 461570,"running_times": 7800},{"title": "Jaws 2","year": 1978,"rating": 5.7,"votes": 57309,"running_times": 7860},{"title": "Jaws 3-D","year": 1983,"rating": 3.6,"votes": 31520,"running_times": 5940},{"title": "Jaws: The Revenge","year": 1987,"rating": 2.9,"votes": 33783,"running_times": 5520},{"title": "Jay and Silent Bob Strike Back","year": 2001,"rating": 6.9,"votes": 135086,"running_times": 6240},{"title": "Jeepers Creepers","year": 2001,"rating": 6.1,"votes": 96505,"running_times": 5400},{"title": "Jeepers Creepers II","year": 2003,"rating": 5.6,"votes": 50446,"running_times": 6240},{"title": "Jeff, Who Lives at Home","year": 2011,"rating": 6.5,"votes": 58122,"running_times": 4980},{"title": "Jennifer Eight","year": 1992,"rating": 6.2,"votes": 13166,"running_times": 7500},{"title": "Jennifer's Body","year": 2009,"rating": 5.1,"votes": 99183,"running_times": 6420},{"title": "Jeremiah Johnson","year": 1972,"rating": 7.6,"votes": 23289,"running_times": 6960},{"title": "Jerry Maguire","year": 1996,"rating": 7.3,"votes": 206427,"running_times": 8340},{"title": "Jersey Boys","year": 2014,"rating": 6.8,"votes": 27880,"running_times": 8040},{"title": "Jersey Girl","year": 2004,"rating": 6.2,"votes": 57587,"running_times": 6120},{"title": "Jessabelle","year": 2014,"rating": 5.4,"votes": 18987,"running_times": 5400},{"title": "Jesus Camp","year": 2006,"rating": 7.5,"votes": 24239,"running_times": 5220},{"title": "Jesus Christ Superstar","year": 1973,"rating": 7.3,"votes": 21189,"running_times": 6480},{"title": "Jigsaw","year": 2017,"rating": 6.1,"votes": 16047,"running_times": 5520},{"title": "Jimmy Neutron: Boy Genius","year": 2001,"rating": 6,"votes": 26177,"running_times": 5040},{"title": "Jin ling shi san chai","year": 2011,"rating": 7.6,"votes": 42340,"running_times": 8760},{"title": "Jing wu men","year": 1972,"rating": 7.4,"votes": 20490,"running_times": 6480},{"title": "Jingle All the Way","year": 1996,"rating": 5.5,"votes": 76054,"running_times": 5640},{"title": "Joan of Arc","year": 1999,"rating": 6.4,"votes": 58830,"running_times": 9480},{"title": "Jobs","year": 2013,"rating": 5.9,"votes": 84088,"running_times": 7680},{"title": "Jodorowsky's Dune","year": 2013,"rating": 8.1,"votes": 16961,"running_times": 5400},{"title": "Joe","year": 2013,"rating": 6.9,"votes": 39777,"running_times": 7020},{"title": "Joe Dirt","year": 2001,"rating": 5.9,"votes": 44605,"running_times": 5460},{"title": "Joe Kidd","year": 1972,"rating": 6.5,"votes": 13727,"running_times": 5280},{"title": "Joe Versus the Volcano","year": 1990,"rating": 5.7,"votes": 30028,"running_times": 6120},{"title": "Joe's Apartment","year": 1996,"rating": 5.4,"votes": 11193,"running_times": 4800},{"title": "John Carter","year": 2012,"rating": 6.6,"votes": 226112,"running_times": 7920},{"title": "John Dies at the End","year": 2012,"rating": 6.4,"votes": 32588,"running_times": 5940},{"title": "John Q","year": 2002,"rating": 7.1,"votes": 107437,"running_times": 6960},{"title": "John Tucker Must Die","year": 2006,"rating": 5.8,"votes": 71843,"running_times": 5700},{"title": "John Wick","year": 2014,"rating": 7.3,"votes": 365044,"running_times": 6060},{"title": "John Wick: Chapter 2","year": 2017,"rating": 7.5,"votes": 201944,"running_times": 7320},{"title": "Johnny Dangerously","year": 1984,"rating": 6.4,"votes": 11727,"running_times": 5400},{"title": "Johnny English","year": 2003,"rating": 6.1,"votes": 122454,"running_times": 5280},{"title": "Johnny English Reborn","year": 2011,"rating": 6.3,"votes": 96666,"running_times": 6060},{"title": "Johnny Got His Gun","year": 1971,"rating": 7.9,"votes": 13068,"running_times": 6660},{"title": "Johnny Guitar","year": 1954,"rating": 7.7,"votes": 12458,"running_times": 6600},{"title": "Johnny Mnemonic","year": 1995,"rating": 5.6,"votes": 59292,"running_times": 6180},{"title": "Jonah Hex","year": 2010,"rating": 4.7,"votes": 48928,"running_times": 4860},{"title": "Jonas Brothers: The 3D Concert Experience","year": 2009,"rating": 2.1,"votes": 17138,"running_times": 5100},{"title": "Joshua","year": 2007,"rating": 5.9,"votes": 10668,"running_times": 6360},{"title": "Josie and the Pussycats","year": 2001,"rating": 5.4,"votes": 19739,"running_times": 5880},{"title": "Journey 2: The Mysterious Island","year": 2012,"rating": 5.8,"votes": 74661,"running_times": 5640},{"title": "Journey to the Center of the Earth","year": 1959,"rating": 7.1,"votes": 12773,"running_times": 7920},{"title": "Journey to the Center of the Earth","year": 2008,"rating": 5.8,"votes": 95171,"running_times": 5580},{"title": "Joy","year": 2015,"rating": 6.6,"votes": 104704,"running_times": 7440},{"title": "Joy Ride","year": 2001,"rating": 6.6,"votes": 56944,"running_times": 5820},{"title": "Joyeux Noël","year": 2005,"rating": 7.8,"votes": 23749,"running_times": 6960},{"title": "Judge Dredd","year": 1995,"rating": 5.5,"votes": 96037,"running_times": 5760},{"title": "Judgment Night","year": 1993,"rating": 6.6,"votes": 13094,"running_times": 6600},{"title": "Judgment at Nuremberg","year": 1961,"rating": 8.3,"votes": 51733,"running_times": 11160},{"title": "Jue di tao wang","year": 2016,"rating": 5.7,"votes": 14156,"running_times": 6420},{"title": "Juice","year": 1992,"rating": 7.1,"votes": 19092,"running_times": 5700},{"title": "Jules et Jim","year": 1962,"rating": 7.9,"votes": 30428,"running_times": 6300},{"title": "Julie & Julia","year": 2009,"rating": 7,"votes": 87286,"running_times": 7080},{"title": "Jumanji","year": 1995,"rating": 6.9,"votes": 236688,"running_times": 6240},{"title": "Jumper","year": 2008,"rating": 6.1,"votes": 258533,"running_times": 5280},{"title": "Jumpin' Jack Flash","year": 1986,"rating": 5.8,"votes": 15852,"running_times": 6300},{"title": "Junebug","year": 2005,"rating": 7,"votes": 19931,"running_times": 6360},{"title": "Jungle","year": 2017,"rating": 6.7,"votes": 16117,"running_times": 6900},{"title": "Jungle 2 Jungle","year": 1997,"rating": 5.1,"votes": 19645,"running_times": 6300},{"title": "Jungle Fever","year": 1991,"rating": 6.5,"votes": 14456,"running_times": 7920},{"title": "Junior","year": 1994,"rating": 4.6,"votes": 57432,"running_times": 6540},{"title": "Juno","year": 2007,"rating": 7.5,"votes": 442969,"running_times": 5760},{"title": "Jupiter Ascending","year": 2015,"rating": 5.3,"votes": 155246,"running_times": 7620},{"title": "Jurassic Park","year": 1993,"rating": 8.1,"votes": 695981,"running_times": 7620},{"title": "Jurassic Park III","year": 2001,"rating": 5.9,"votes": 242697,"running_times": 5520},{"title": "Jurassic World","year": 2015,"rating": 7,"votes": 476644,"running_times": 7440},{"title": "Just Before I Go","year": 2014,"rating": 6.4,"votes": 15316,"running_times": 5700},{"title": "Just Cause","year": 1995,"rating": 6.4,"votes": 21147,"running_times": 6120},{"title": "Just Friends","year": 2005,"rating": 6.2,"votes": 89395,"running_times": 5760},{"title": "Just Go with It","year": 2011,"rating": 6.4,"votes": 187549,"running_times": 7020},{"title": "Just Like Heaven","year": 2005,"rating": 6.7,"votes": 88168,"running_times": 5700},{"title": "Just Married","year": 2003,"rating": 5.5,"votes": 61009,"running_times": 5700},{"title": "Just My Luck","year": 2006,"rating": 5.4,"votes": 47721,"running_times": 6180},{"title": "Just One of the Guys","year": 1985,"rating": 6.5,"votes": 10976,"running_times": 6000},{"title": "Just Visiting","year": 2001,"rating": 5.8,"votes": 16255,"running_times": 5280},{"title": "Just Wright","year": 2010,"rating": 5.9,"votes": 11239,"running_times": 6000},{"title": "Justice League","year": 2017,"rating": 7.2,"votes": 141370,"running_times": 7200},{"title": "Justin Bieber: Never Say Never","year": 2011,"rating": 1.6,"votes": 74720,"running_times": 6900},{"title": "K-19: The Widowmaker","year": 2002,"rating": 6.7,"votes": 52505,"running_times": 8280},{"title": "K-9","year": 1989,"rating": 6,"votes": 27515,"running_times": 6060},{"title": "K-PAX","year": 2001,"rating": 7.4,"votes": 160033,"running_times": 7200},{"title": "Kabhi Alvida Naa Kehna","year": 2006,"rating": 6.1,"votes": 15518,"running_times": 11580},{"title": "Kabhi Haan Kabhi Naa","year": 1994,"rating": 8,"votes": 14320,"running_times": 9480},{"title": "Kabhi Khushi Kabhie Gham...","year": 2001,"rating": 7.5,"votes": 35341,"running_times": 12600},{"title": "Kaboom","year": 2010,"rating": 5.7,"votes": 11187,"running_times": 5160},{"title": "Kahaani","year": 2012,"rating": 8.2,"votes": 46148,"running_times": 7320},{"title": "Kaho Naa... Pyaar Hai","year": 2000,"rating": 6.9,"votes": 11078,"running_times": 10620},{"title": "Kalifornia","year": 1993,"rating": 6.7,"votes": 44968,"running_times": 7080},{"title": "Kaminey","year": 2009,"rating": 7.4,"votes": 14048,"running_times": 7800},{"title": "Kangaroo Jack","year": 2003,"rating": 4.4,"votes": 25282,"running_times": 5340},{"title": "Kapringen","year": 2012,"rating": 7.2,"votes": 13742,"running_times": 6180},{"title": "Kari-gurashi no Arietti","year": 2010,"rating": 7.6,"votes": 60734,"running_times": 5640},{"title": "Kate & Leopold","year": 2001,"rating": 6.4,"votes": 69690,"running_times": 7380},{"title": "Katy Perry: Part of Me","year": 2012,"rating": 5.9,"votes": 12764,"running_times": 5580},{"title": "Kazaam","year": 1996,"rating": 2.8,"votes": 20470,"running_times": 5580},{"title": "Kaze no tani no Naushika","year": 1984,"rating": 8.1,"votes": 111109,"running_times": 7020},{"title": "Keanu","year": 2016,"rating": 6.3,"votes": 35524,"running_times": 6000},{"title": "Keeping Mum","year": 2005,"rating": 6.8,"votes": 29947,"running_times": 5940},{"title": "Keeping Up with the Joneses","year": 2016,"rating": 5.9,"votes": 42363,"running_times": 6300},{"title": "Keeping the Faith","year": 2000,"rating": 6.4,"votes": 46463,"running_times": 7680},{"title": "Keith","year": 2008,"rating": 7.5,"votes": 32592,"running_times": 5580},{"title": "Kelly's Heroes","year": 1970,"rating": 7.7,"votes": 38115,"running_times": 8640},{"title": "Ken Park","year": 2002,"rating": 5.9,"votes": 26369,"running_times": 5880},{"title": "Kes","year": 1969,"rating": 7.9,"votes": 14791,"running_times": 6660},{"title": "Kevin & Perry Go Large","year": 2000,"rating": 5.4,"votes": 10780,"running_times": 4980},{"title": "Key Largo","year": 1948,"rating": 7.9,"votes": 31269,"running_times": 6000},{"title": "Kick-Ass","year": 2010,"rating": 7.7,"votes": 469966,"running_times": 7020},{"title": "Kick-Ass 2","year": 2013,"rating": 6.6,"votes": 222224,"running_times": 6180},{"title": "Kickboxer","year": 1989,"rating": 6.4,"votes": 40995,"running_times": 5820},{"title": "Kicking & Screaming","year": 2005,"rating": 5.6,"votes": 32051,"running_times": 5700},{"title": "Kidnap","year": 2017,"rating": 5.9,"votes": 19654,"running_times": 5700},{"title": "Kidnapping Mr. Heineken","year": 2015,"rating": 6.1,"votes": 15614,"running_times": 5700},{"title": "Kids","year": 1995,"rating": 7,"votes": 63667,"running_times": 5460},{"title": "Kidulthood","year": 2006,"rating": 6.8,"votes": 16066,"running_times": 5340},{"title": "Kill Bill: Vol. 1","year": 2003,"rating": 8.1,"votes": 818635,"running_times": 6720},{"title": "Kill Bill: Vol. 2","year": 2004,"rating": 8,"votes": 562155,"running_times": 8220},{"title": "Kill List","year": 2011,"rating": 6.4,"votes": 29640,"running_times": 5700},{"title": "Kill Me Three Times","year": 2014,"rating": 5.9,"votes": 16475,"running_times": 5400},{"title": "Kill Your Darlings","year": 2013,"rating": 6.5,"votes": 29764,"running_times": 6240},{"title": "Kill the Irishman","year": 2011,"rating": 7.1,"votes": 38020,"running_times": 6360},{"title": "Kill the Messenger","year": 2014,"rating": 7,"votes": 37172,"running_times": 6720},{"title": "Killer Elite","year": 2011,"rating": 6.5,"votes": 112178,"running_times": 6960},{"title": "Killer Joe","year": 2011,"rating": 6.7,"votes": 63883,"running_times": 6120},{"title": "Killer Klowns from Outer Space","year": 1988,"rating": 6.1,"votes": 25861,"running_times": 5400},{"title": "Killer's Kiss","year": 1955,"rating": 6.7,"votes": 17257,"running_times": 4020},{"title": "Killers","year": 2010,"rating": 5.4,"votes": 77516,"running_times": 6000},{"title": "Killing Me Softly","year": 2002,"rating": 5.5,"votes": 15313,"running_times": 6240},{"title": "Killing Season","year": 2013,"rating": 5.4,"votes": 31036,"running_times": 5460},{"title": "Killing Them Softly","year": 2012,"rating": 6.2,"votes": 118699,"running_times": 9000},{"title": "Killing Zoe","year": 1993,"rating": 6.5,"votes": 18088,"running_times": 5940},{"title": "Killshot","year": 2008,"rating": 6,"votes": 19189,"running_times": 5700},{"title": "Kimssi pyoryugi","year": 2009,"rating": 8.1,"votes": 12593,"running_times": 6960},{"title": "Kind Hearts and Coronets","year": 1949,"rating": 8.1,"votes": 29983,"running_times": 6360},{"title": "Kindergarten Cop","year": 1990,"rating": 6.1,"votes": 116526,"running_times": 6660},{"title": "King Arthur","year": 2004,"rating": 6.3,"votes": 145122,"running_times": 8520},{"title": "King Arthur: Legend of the Sword","year": 2017,"rating": 6.9,"votes": 126686,"running_times": 7560},{"title": "King Kong","year": 1933,"rating": 7.9,"votes": 69395,"running_times": 7500},{"title": "King Kong","year": 1976,"rating": 5.8,"votes": 25327,"running_times": 10920},{"title": "King Kong","year": 2005,"rating": 7.2,"votes": 343810,"running_times": 12000},{"title": "King Ralph","year": 1991,"rating": 5.2,"votes": 13406,"running_times": 5820},{"title": "King Solomon's Mines","year": 1985,"rating": 5.1,"votes": 10636,"running_times": 6000},{"title": "King of California","year": 2007,"rating": 6.7,"votes": 20594,"running_times": 5760},{"title": "King of New York","year": 1990,"rating": 7,"votes": 25783,"running_times": 6180},{"title": "Kingdom of Heaven","year": 2005,"rating": 7.2,"votes": 235089,"running_times": 11640},{"title": "Kingpin","year": 1996,"rating": 6.9,"votes": 67678,"running_times": 7020},{"title": "Kingsglaive: Final Fantasy XV","year": 2016,"rating": 6.9,"votes": 16107,"running_times": 6600},{"title": "Kingsman: The Golden Circle","year": 2017,"rating": 7,"votes": 110963,"running_times": 8460},{"title": "Kingsman: The Secret Service","year": 2014,"rating": 7.7,"votes": 484875,"running_times": 7740},{"title": "Kinky Boots","year": 2005,"rating": 7.1,"votes": 15459,"running_times": 6420},{"title": "Kinsey","year": 2004,"rating": 7.1,"votes": 44243,"running_times": 7080},{"title": "Kis Uykusu","year": 2014,"rating": 8.2,"votes": 30351,"running_times": 11760},{"title": "Kiss Kiss Bang Bang","year": 2005,"rating": 7.6,"votes": 190431,"running_times": 6180},{"title": "Kiss Me Deadly","year": 1955,"rating": 7.7,"votes": 15308,"running_times": 6360},{"title": "Kiss of Death","year": 1995,"rating": 5.9,"votes": 15074,"running_times": 6060},{"title": "Kiss of the Dragon","year": 2001,"rating": 6.6,"votes": 55800,"running_times": 5880},{"title": "Kiss of the Spider Woman","year": 1985,"rating": 7.4,"votes": 11944,"running_times": 7200},{"title": "Kiss the Girls","year": 1997,"rating": 6.6,"votes": 55048,"running_times": 6900},{"title": "Kissing Jessica Stein","year": 2001,"rating": 6.6,"votes": 14678,"running_times": 5820},{"title": "Kites","year": 2010,"rating": 6.1,"votes": 10633,"running_times": 7380},{"title": "Klute","year": 1971,"rating": 7.2,"votes": 17394,"running_times": 6840},{"title": "Knick Knack","year": 1989,"rating": 7.6,"votes": 10535,"running_times": 240},{"title": "Knight and Day","year": 2010,"rating": 6.3,"votes": 159127,"running_times": 7020},{"title": "Knight of Cups","year": 2015,"rating": 5.7,"votes": 19328,"running_times": 7080},{"title": "Knights of Badassdom","year": 2013,"rating": 5.7,"votes": 17324,"running_times": 5160},{"title": "Knock Knock","year": 2015,"rating": 4.9,"votes": 58848,"running_times": 5940},{"title": "Knock Off","year": 1998,"rating": 4.8,"votes": 12281,"running_times": 5460},{"title": "Knockaround Guys","year": 2001,"rating": 6.1,"votes": 20617,"running_times": 5520},{"title": "Knocked Up","year": 2007,"rating": 7,"votes": 315872,"running_times": 7980},{"title": "Knockin' on Heaven's Door","year": 1997,"rating": 8,"votes": 22709,"running_times": 5220},{"title": "Knowing","year": 2009,"rating": 6.2,"votes": 198560,"running_times": 7260},{"title": "Koi... Mil Gaya","year": 2003,"rating": 7.1,"votes": 16564,"running_times": 10260},{"title": "Kon-Tiki","year": 2012,"rating": 7.2,"votes": 38464,"running_times": 7080},{"title": "Kong: Skull Island","year": 2017,"rating": 6.7,"votes": 179436,"running_times": 7080},{"title": "Kopps","year": 2003,"rating": 6.8,"votes": 17114,"running_times": 5400},{"title": "Koroshiya 1","year": 2001,"rating": 7.1,"votes": 45555,"running_times": 7740},{"title": "Koto no ha no niwa","year": 2013,"rating": 7.6,"votes": 17489,"running_times": 2760},{"title": "Kraftidioten","year": 2014,"rating": 7.2,"votes": 15869,"running_times": 6960},{"title": "Kramer vs. Kramer","year": 1979,"rating": 7.8,"votes": 107796,"running_times": 6300},{"title": "Krampus","year": 2015,"rating": 6.2,"votes": 46500,"running_times": 5880},{"title": "Krrish","year": 2006,"rating": 6.3,"votes": 14376,"running_times": 11100},{"title": "Krull","year": 1983,"rating": 6.1,"votes": 25399,"running_times": 7260},{"title": "Kubo and the Two Strings","year": 2016,"rating": 7.8,"votes": 86088,"running_times": 6060},{"title": "Kuch Kuch Hota Hai","year": 1998,"rating": 7.7,"votes": 38584,"running_times": 10620},{"title": "Kumiko, the Treasure Hunter","year": 2014,"rating": 6.6,"votes": 10007,"running_times": 6300},{"title": "Kundun","year": 1997,"rating": 7,"votes": 23036,"running_times": 8040},{"title": "Kung Fu Panda","year": 2008,"rating": 7.6,"votes": 343919,"running_times": 5520},{"title": "Kung Fu Panda 2","year": 2011,"rating": 7.3,"votes": 205944,"running_times": 5400},{"title": "Kung Fu Panda 3","year": 2016,"rating": 7.1,"votes": 97816,"running_times": 5700},{"title": "Kung Fury","year": 2015,"rating": 8.1,"votes": 47091,"running_times": 1860},{"title": "Kung Pow: Enter the Fist","year": 2002,"rating": 6.2,"votes": 39822,"running_times": 5220},{"title": "Kurtlar Vadisi: Irak","year": 2006,"rating": 5.9,"votes": 15471,"running_times": 7320},{"title": "L'amant","year": 1992,"rating": 6.9,"votes": 16277,"running_times": 6960},{"title": "L'appartement","year": 1996,"rating": 7.5,"votes": 12177,"running_times": 6960},{"title": "L'armée des ombres","year": 1969,"rating": 8.2,"votes": 16310,"running_times": 8700},{"title": "L'arnacoeur","year": 2010,"rating": 6.8,"votes": 22667,"running_times": 6300},{"title": "L'auberge espagnole","year": 2002,"rating": 7.3,"votes": 36179,"running_times": 7320},{"title": "L'avventura","year": 1960,"rating": 7.9,"votes": 20494,"running_times": 8580},{"title": "L'eclisse","year": 1962,"rating": 7.9,"votes": 13282,"running_times": 7560},{"title": "L'ennemi public n°1","year": 2008,"rating": 7.5,"votes": 25292,"running_times": 7980},{"title": "L'illusionniste","year": 2010,"rating": 7.5,"votes": 30209,"running_times": 4800},{"title": "L'instinct de mort","year": 2008,"rating": 7.6,"votes": 28541,"running_times": 6780},{"title": "L'ours","year": 1988,"rating": 7.7,"votes": 14103,"running_times": 5760},{"title": "L'écume des jours","year": 2013,"rating": 6.5,"votes": 13056,"running_times": 7860},{"title": "L.A. Confidential","year": 1997,"rating": 8.3,"votes": 453989,"running_times": 8280},{"title": "L.A. Story","year": 1991,"rating": 6.7,"votes": 26514,"running_times": 5700},{"title": "LOL","year": 2012,"rating": 4.3,"votes": 48379,"running_times": 5820},{"title": "La Bamba","year": 1987,"rating": 6.8,"votes": 23070,"running_times": 6480},{"title": "La La Land","year": 2016,"rating": 8.1,"votes": 330222,"running_times": 7680},{"title": "La Luna","year": 2011,"rating": 8,"votes": 10173,"running_times": 420},{"title": "La battaglia di Algeri","year": 1966,"rating": 8.1,"votes": 42954,"running_times": 7260},{"title": "La belle et la bête","year": 2014,"rating": 6.4,"votes": 16164,"running_times": 6720},{"title": "La dolce vita","year": 1960,"rating": 8.1,"votes": 54029,"running_times": 10800},{"title": "La grande illusion","year": 1937,"rating": 8.1,"votes": 29036,"running_times": 6780},{"title": "La grande vadrouille","year": 1966,"rating": 8,"votes": 12617,"running_times": 7920},{"title": "La leggenda del pianista sull'oceano","year": 1998,"rating": 8.1,"votes": 45764,"running_times": 9900},{"title": "La marche de l'empereur","year": 2005,"rating": 7.6,"votes": 50416,"running_times": 4800},{"title": "La maschera del demonio","year": 1960,"rating": 7.3,"votes": 10828,"running_times": 5220},{"title": "La meglio gioventù","year": 2003,"rating": 8.5,"votes": 17794,"running_times": 21960},{"title": "La migliore offerta","year": 2013,"rating": 7.8,"votes": 83547,"running_times": 7860},{"title": "La montaña sagrada","year": 1973,"rating": 7.9,"votes": 27321,"running_times": 6840},{"title": "La môme","year": 2007,"rating": 7.6,"votes": 72235,"running_times": 8400},{"title": "La nuit américaine","year": 1973,"rating": 8.1,"votes": 16124,"running_times": 6900},{"title": "La règle du jeu","year": 1939,"rating": 8.1,"votes": 22461,"running_times": 6600},{"title": "La science des rêves","year": 2006,"rating": 7.3,"votes": 63946,"running_times": 6300},{"title": "La tigre e la neve","year": 2005,"rating": 7.2,"votes": 12250,"running_times": 6840},{"title": "La vie d'Adèle","year": 2013,"rating": 7.8,"votes": 109423,"running_times": 10800},{"title": "La vita è bella","year": 1997,"rating": 8.6,"votes": 484883,"running_times": 7320},{"title": "Labor Day","year": 2013,"rating": 6.9,"votes": 35525,"running_times": 6660},{"title": "Labyrinth","year": 1986,"rating": 7.4,"votes": 104063,"running_times": 6060},{"title": "Ladder 49","year": 2004,"rating": 6.5,"votes": 50649,"running_times": 6900},{"title": "Lady Bird","year": 2017,"rating": 8.4,"votes": 10997,"running_times": 5640},{"title": "Lady and the Tramp","year": 1955,"rating": 7.3,"votes": 96911,"running_times": 4560},{"title": "Lady in the Water","year": 2006,"rating": 5.6,"votes": 84760,"running_times": 6600},{"title": "Ladyhawke","year": 1985,"rating": 7,"votes": 36607,"running_times": 7260},{"title": "Lagaan: Once Upon a Time in India","year": 2001,"rating": 8.2,"votes": 83674,"running_times": 13440},{"title": "Laggies","year": 2014,"rating": 6.4,"votes": 35284,"running_times": 5940},{"title": "Lake Mungo","year": 2008,"rating": 6.1,"votes": 11249,"running_times": 5340},{"title": "Lake Placid","year": 1999,"rating": 5.6,"votes": 46572,"running_times": 4920},{"title": "Lakeview Terrace","year": 2008,"rating": 6.1,"votes": 43282,"running_times": 6600},{"title": "Lakposhtha parvaz mikonand","year": 2004,"rating": 8.1,"votes": 14924,"running_times": 5880},{"title": "Lakshya","year": 2004,"rating": 7.9,"votes": 15400,"running_times": 11160},{"title": "Land of the Dead","year": 2005,"rating": 6.2,"votes": 83236,"running_times": 5820},{"title": "Land of the Lost","year": 2009,"rating": 5.4,"votes": 55270,"running_times": 6120},{"title": "Lantana","year": 2001,"rating": 7.3,"votes": 17192,"running_times": 7260},{"title": "Lara Croft Tomb Raider: The Cradle of Life","year": 2003,"rating": 5.5,"votes": 111378,"running_times": 7020},{"title": "Lara Croft: Tomb Raider","year": 2001,"rating": 5.8,"votes": 169611,"running_times": 6000},{"title": "Largo Winch","year": 2008,"rating": 6.5,"votes": 12004,"running_times": 6480},{"title": "Larry Crowne","year": 2011,"rating": 6.1,"votes": 54197,"running_times": 5880},{"title": "Lars and the Real Girl","year": 2007,"rating": 7.4,"votes": 123925,"running_times": 6360},{"title": "Last Action Hero","year": 1993,"rating": 6.3,"votes": 115720,"running_times": 7800},{"title": "Last Chance Harvey","year": 2008,"rating": 6.7,"votes": 18870,"running_times": 5580},{"title": "Last Days","year": 2005,"rating": 5.8,"votes": 19794,"running_times": 5820},{"title": "Last Holiday","year": 2006,"rating": 6.4,"votes": 23312,"running_times": 6720},{"title": "Last Knights","year": 2015,"rating": 6.2,"votes": 32149,"running_times": 6900},{"title": "Last Man Standing","year": 1996,"rating": 6.4,"votes": 47431,"running_times": 6060},{"title": "Last Night","year": 2010,"rating": 6.6,"votes": 42441,"running_times": 5580},{"title": "Last Shift","year": 2014,"rating": 5.8,"votes": 12443,"running_times": 5400},{"title": "Last Vegas","year": 2013,"rating": 6.6,"votes": 115090,"running_times": 6300},{"title": "Lat sau san taam","year": 1992,"rating": 7.9,"votes": 41050,"running_times": 7860},{"title": "Latter Days","year": 2003,"rating": 7.1,"votes": 15357,"running_times": 6420},{"title": "Laura","year": 1944,"rating": 8.1,"votes": 35204,"running_times": 5280},{"title": "Laurel Canyon","year": 2002,"rating": 6.4,"votes": 13693,"running_times": 6180},{"title": "Laurence Anyways","year": 2012,"rating": 7.6,"votes": 13696,"running_times": 10080},{"title": "Lava","year": 2014,"rating": 7.2,"votes": 11034,"running_times": 420},{"title": "Law Abiding Citizen","year": 2009,"rating": 7.4,"votes": 234737,"running_times": 7080},{"title": "Lawless","year": 2012,"rating": 7.3,"votes": 201216,"running_times": 6960},{"title": "Lawrence of Arabia","year": 1962,"rating": 8.3,"votes": 215696,"running_times": 13680},{"title": "Laws of Attraction","year": 2004,"rating": 5.9,"votes": 19929,"running_times": 5400},{"title": "Layer Cake","year": 2004,"rating": 7.4,"votes": 143588,"running_times": 6300},{"title": "Le cinquième élément","year": 1997,"rating": 7.7,"votes": 374767,"running_times": 7560},{"title": "Le divorce","year": 2003,"rating": 4.9,"votes": 10178,"running_times": 7020},{"title": "Le fabuleux destin d'Amélie Poulain","year": 2001,"rating": 8.3,"votes": 594927,"running_times": 7320},{"title": "Le grand bleu","year": 1988,"rating": 7.6,"votes": 41252,"running_times": 10080},{"title": "Le locataire","year": 1976,"rating": 7.8,"votes": 30919,"running_times": 7560},{"title": "Le mépris","year": 1963,"rating": 7.7,"votes": 22380,"running_times": 6180},{"title": "Le procès","year": 1962,"rating": 7.8,"votes": 15401,"running_times": 7140},{"title": "Le salaire de la peur","year": 1953,"rating": 8.2,"votes": 40345,"running_times": 9360},{"title": "Le violon rouge","year": 1998,"rating": 7.7,"votes": 28394,"running_times": 8400},{"title": "Lean on Me","year": 1989,"rating": 7.4,"votes": 15573,"running_times": 6480},{"title": "Leap Year","year": 2010,"rating": 6.5,"votes": 78668,"running_times": 6000},{"title": "Leap of Faith","year": 1992,"rating": 6.1,"votes": 10526,"running_times": 6480},{"title": "Leatherface: Texas Chainsaw Massacre III","year": 1990,"rating": 5.2,"votes": 11025,"running_times": 5100},{"title": "Leatherheads","year": 2008,"rating": 6,"votes": 28907,"running_times": 6840},{"title": "Leaves of Grass","year": 2009,"rating": 6.5,"votes": 24966,"running_times": 6300},{"title": "Leaving Las Vegas","year": 1995,"rating": 7.6,"votes": 100091,"running_times": 6660},{"title": "Lebanon","year": 2009,"rating": 6.9,"votes": 10014,"running_times": 5580},{"title": "Left Behind","year": 2014,"rating": 3.1,"votes": 28793,"running_times": 6600},{"title": "Legally Blonde","year": 2001,"rating": 6.2,"votes": 147263,"running_times": 5760},{"title": "Legally Blonde 2: Red, White & Blonde","year": 2003,"rating": 4.7,"votes": 51197,"running_times": 5700},{"title": "Legend","year": 1985,"rating": 6.5,"votes": 50438,"running_times": 6840},{"title": "Legend","year": 2015,"rating": 7,"votes": 118845,"running_times": 7920},{"title": "Legend of the Guardians: The Owls of Ga'Hoole","year": 2010,"rating": 7,"votes": 70245,"running_times": 6060},{"title": "Legends of the Fall","year": 1994,"rating": 7.5,"votes": 122945,"running_times": 7980},{"title": "Legion","year": 2010,"rating": 5.2,"votes": 86405,"running_times": 6000},{"title": "Legionnaire","year": 1998,"rating": 5.4,"votes": 19924,"running_times": 5940},{"title": "Lenny","year": 1974,"rating": 7.6,"votes": 12098,"running_times": 6660},{"title": "Lepa sela lepo gore","year": 1996,"rating": 8.7,"votes": 12099,"running_times": 6900},{"title": "Leprechaun","year": 1993,"rating": 4.7,"votes": 18932,"running_times": 5520},{"title": "Les Misérables","year": 1998,"rating": 7.5,"votes": 34086,"running_times": 8040},{"title": "Les Misérables","year": 2012,"rating": 7.6,"votes": 264958,"running_times": 9480},{"title": "Les amours imaginaires","year": 2010,"rating": 7.2,"votes": 21824,"running_times": 6060},{"title": "Les aventures extraordinaires d'Adèle Blanc-Sec","year": 2010,"rating": 6.3,"votes": 17227,"running_times": 6420},{"title": "Les diaboliques","year": 1955,"rating": 8.1,"votes": 47931,"running_times": 7020},{"title": "Les invasions barbares","year": 2003,"rating": 7.7,"votes": 25965,"running_times": 6720},{"title": "Les parapluies de Cherbourg","year": 1964,"rating": 7.8,"votes": 17936,"running_times": 5460},{"title": "Les poupées russes","year": 2005,"rating": 7,"votes": 17598,"running_times": 7740},{"title": "Les quatre cents coups","year": 1959,"rating": 8.1,"votes": 79751,"running_times": 5940},{"title": "Les triplettes de Belleville","year": 2003,"rating": 7.8,"votes": 45275,"running_times": 4800},{"title": "Les vacances de Monsieur Hulot","year": 1953,"rating": 7.6,"votes": 13779,"running_times": 6840},{"title": "Les visiteurs","year": 1993,"rating": 7,"votes": 27169,"running_times": 6420},{"title": "Lesbian Vampire Killers","year": 2009,"rating": 5.2,"votes": 18201,"running_times": 5280},{"title": "Less Than Zero","year": 1987,"rating": 6.4,"votes": 15649,"running_times": 5880},{"title": "Let Me In","year": 2010,"rating": 7.2,"votes": 100116,"running_times": 6960},{"title": "Let's Be Cops","year": 2014,"rating": 6.5,"votes": 115774,"running_times": 6240},{"title": "Let's Go to Prison","year": 2006,"rating": 6,"votes": 20966,"running_times": 5400},{"title": "Lethal Weapon","year": 1987,"rating": 7.6,"votes": 206476,"running_times": 7020},{"title": "Lethal Weapon 2","year": 1989,"rating": 7.2,"votes": 139179,"running_times": 7080},{"title": "Lethal Weapon 3","year": 1992,"rating": 6.7,"votes": 137501,"running_times": 7260},{"title": "Lethal Weapon 4","year": 1998,"rating": 6.6,"votes": 136125,"running_times": 7620},{"title": "Letters from Iwo Jima","year": 2006,"rating": 7.9,"votes": 139966,"running_times": 8460},{"title": "Letters to Juliet","year": 2010,"rating": 6.6,"votes": 80645,"running_times": 6300},{"title": "Leviathan","year": 1989,"rating": 5.8,"votes": 14534,"running_times": 5880},{"title": "Liar Liar","year": 1997,"rating": 6.8,"votes": 240776,"running_times": 5160},{"title": "Liberal Arts","year": 2012,"rating": 6.7,"votes": 31904,"running_times": 5820},{"title": "Licence to Kill","year": 1989,"rating": 6.6,"votes": 79978,"running_times": 7980},{"title": "License to Drive","year": 1988,"rating": 6.3,"votes": 15196,"running_times": 5280},{"title": "License to Wed","year": 2007,"rating": 5.3,"votes": 34018,"running_times": 5460},{"title": "Lie with Me","year": 2005,"rating": 5.4,"votes": 12624,"running_times": 5580},{"title": "Life","year": 1999,"rating": 6.7,"votes": 36663,"running_times": 6480},{"title": "Life","year": 2017,"rating": 6.6,"votes": 137763,"running_times": 6240},{"title": "Life After Beth","year": 2014,"rating": 5.6,"votes": 15831,"running_times": 5340},{"title": "Life Itself","year": 2014,"rating": 7.8,"votes": 13010,"running_times": 7200},{"title": "Life as We Know It","year": 2010,"rating": 6.6,"votes": 104933,"running_times": 6840},{"title": "Life as a House","year": 2001,"rating": 7.5,"votes": 40518,"running_times": 7620},{"title": "Life in a Day","year": 2011,"rating": 7.7,"votes": 13937,"running_times": 5700},{"title": "Life of Brian","year": 1979,"rating": 8.1,"votes": 300297,"running_times": 5640},{"title": "Life of Crime","year": 2013,"rating": 5.8,"votes": 14325,"running_times": 5880},{"title": "Life of Pi","year": 2012,"rating": 7.9,"votes": 489527,"running_times": 7620},{"title": "Life or Something Like It","year": 2002,"rating": 5.8,"votes": 20754,"running_times": 6300},{"title": "Lifeboat","year": 1944,"rating": 7.8,"votes": 22355,"running_times": 5820},{"title": "Lifeforce","year": 1985,"rating": 6.1,"votes": 17593,"running_times": 6960},{"title": "Lights Out","year": 2016,"rating": 6.3,"votes": 84024,"running_times": 4860},{"title": "Like Crazy","year": 2011,"rating": 6.7,"votes": 52116,"running_times": 5160},{"title": "Like Mike","year": 2002,"rating": 5.2,"votes": 16319,"running_times": 5940},{"title": "Lilja 4-ever","year": 2002,"rating": 7.9,"votes": 37844,"running_times": 6540},{"title": "Lilo & Stitch","year": 2002,"rating": 7.2,"votes": 133382,"running_times": 5100},{"title": "Limelight","year": 1952,"rating": 8.1,"votes": 14677,"running_times": 8820},{"title": "Limitless","year": 2011,"rating": 7.4,"votes": 459364,"running_times": 6300},{"title": "Lincoln","year": 2012,"rating": 7.4,"votes": 213471,"running_times": 9000},{"title": "Lion","year": 2016,"rating": 8.1,"votes": 143387,"running_times": 7080},{"title": "Lion of the Desert","year": 1980,"rating": 8.4,"votes": 11257,"running_times": 10380},{"title": "Lionheart","year": 1990,"rating": 6.2,"votes": 27363,"running_times": 6480},{"title": "Lions for Lambs","year": 2007,"rating": 6.2,"votes": 43204,"running_times": 5520},{"title": "Little Big Man","year": 1970,"rating": 7.6,"votes": 28772,"running_times": 8820},{"title": "Little Black Book","year": 2004,"rating": 5.3,"votes": 15930,"running_times": 6660},{"title": "Little Boy","year": 2015,"rating": 7.4,"votes": 19507,"running_times": 6360},{"title": "Little Buddha","year": 1993,"rating": 6,"votes": 13350,"running_times": 8460},{"title": "Little Children","year": 2006,"rating": 7.6,"votes": 96874,"running_times": 8220},{"title": "Little Fockers","year": 2010,"rating": 5.5,"votes": 92568,"running_times": 5880},{"title": "Little Giants","year": 1994,"rating": 6.3,"votes": 21322,"running_times": 6420},{"title": "Little Man Tate","year": 1991,"rating": 6.7,"votes": 12292,"running_times": 5940},{"title": "Little Manhattan","year": 2005,"rating": 7.6,"votes": 20074,"running_times": 5400},{"title": "Little Miss Sunshine","year": 2006,"rating": 7.8,"votes": 384705,"running_times": 6060},{"title": "Little Nicky","year": 2000,"rating": 5.3,"votes": 86181,"running_times": 5400},{"title": "Little Shop of Horrors","year": 1986,"rating": 6.9,"votes": 54010,"running_times": 6120},{"title": "Little Voice","year": 1998,"rating": 7,"votes": 14546,"running_times": 5820},{"title": "Little Women","year": 1994,"rating": 7.3,"votes": 39880,"running_times": 6900},{"title": "Littleman","year": 2006,"rating": 4.3,"votes": 42807,"running_times": 5880},{"title": "Live Free or Die Hard","year": 2007,"rating": 7.2,"votes": 354620,"running_times": 7740},{"title": "Live and Let Die","year": 1973,"rating": 6.8,"votes": 81462,"running_times": 7260},{"title": "Live by Night","year": 2016,"rating": 6.4,"votes": 37860,"running_times": 7740},{"title": "Living in Oblivion","year": 1995,"rating": 7.5,"votes": 13790,"running_times": 5400},{"title": "Lo imposible","year": 2012,"rating": 7.6,"votes": 162773,"running_times": 6840},{"title": "Loaded Weapon 1","year": 1993,"rating": 6.1,"votes": 39692,"running_times": 5040},{"title": "Local Hero","year": 1983,"rating": 7.5,"votes": 17301,"running_times": 6660},{"title": "Lock Up","year": 1989,"rating": 6.4,"votes": 32444,"running_times": 6540},{"title": "Lock, Stock and Two Smoking Barrels","year": 1998,"rating": 8.2,"votes": 455613,"running_times": 7200},{"title": "Locke","year": 2013,"rating": 7.1,"votes": 106566,"running_times": 5100},{"title": "Lockout","year": 2012,"rating": 6.1,"votes": 86175,"running_times": 5700},{"title": "Logan","year": 2017,"rating": 8.2,"votes": 417826,"running_times": 8220},{"title": "Logan Lucky","year": 2017,"rating": 7.1,"votes": 44509,"running_times": 7080},{"title": "Logan's Run","year": 1976,"rating": 6.8,"votes": 43654,"running_times": 7140},{"title": "Lola rennt","year": 1998,"rating": 7.7,"votes": 170737,"running_times": 4860},{"title": "Lolita","year": 1962,"rating": 7.6,"votes": 75313,"running_times": 9180},{"title": "Lolita","year": 1997,"rating": 6.9,"votes": 42179,"running_times": 8220},{"title": "London","year": 2005,"rating": 6.6,"votes": 20332,"running_times": 5520},{"title": "London Boulevard","year": 2010,"rating": 6.2,"votes": 42810,"running_times": 6180},{"title": "London Has Fallen","year": 2016,"rating": 5.9,"votes": 108802,"running_times": 5940},{"title": "Lone Star","year": 1996,"rating": 7.5,"votes": 24721,"running_times": 8100},{"title": "Lone Survivor","year": 2013,"rating": 7.5,"votes": 227936,"running_times": 7260},{"title": "Lonely Hearts","year": 2006,"rating": 6.5,"votes": 18568,"running_times": 6480},{"title": "Look Who's Talking","year": 1989,"rating": 5.8,"votes": 68218,"running_times": 5580},{"title": "Look Who's Talking Now","year": 1993,"rating": 4.2,"votes": 23987,"running_times": 5760},{"title": "Look Who's Talking Too","year": 1990,"rating": 4.5,"votes": 39326,"running_times": 4860},{"title": "Looking for Eric","year": 2009,"rating": 7.2,"votes": 13977,"running_times": 6960},{"title": "Looney Tunes: Back in Action","year": 2003,"rating": 5.7,"votes": 27194,"running_times": 5460},{"title": "Looper","year": 2012,"rating": 7.4,"votes": 467183,"running_times": 7140},{"title": "Lord of Illusions","year": 1995,"rating": 6.1,"votes": 12128,"running_times": 7260},{"title": "Lord of War","year": 2005,"rating": 7.6,"votes": 263932,"running_times": 7320},{"title": "Lord of the Flies","year": 1963,"rating": 7,"votes": 14798,"running_times": 5520},{"title": "Lord of the Flies","year": 1990,"rating": 6.4,"votes": 24260,"running_times": 5400},{"title": "Lords of Dogtown","year": 2005,"rating": 7.1,"votes": 46833,"running_times": 6420},{"title": "Lore","year": 2012,"rating": 7.1,"votes": 12480,"running_times": 6540},{"title": "Lorenzo's Oil","year": 1992,"rating": 7.2,"votes": 17664,"running_times": 7740},{"title": "Los abrazos rotos","year": 2009,"rating": 7.2,"votes": 33706,"running_times": 7620},{"title": "Los amantes del Círculo Polar","year": 1998,"rating": 7.8,"votes": 16141,"running_times": 6720},{"title": "Loser","year": 2000,"rating": 5.3,"votes": 24126,"running_times": 5880},{"title": "Lost Highway","year": 1997,"rating": 7.6,"votes": 108996,"running_times": 8040},{"title": "Lost Horizon","year": 1937,"rating": 7.8,"votes": 10155,"running_times": 7920},{"title": "Lost River","year": 2014,"rating": 5.8,"votes": 13919,"running_times": 6720},{"title": "Lost and Delirious","year": 2001,"rating": 7,"votes": 18057,"running_times": 6180},{"title": "Lost in Space","year": 1998,"rating": 5.1,"votes": 61812,"running_times": 7800},{"title": "Lost in Translation","year": 2003,"rating": 7.8,"votes": 349205,"running_times": 6120},{"title": "Love & Basketball","year": 2000,"rating": 7.2,"votes": 15596,"running_times": 7440},{"title": "Love & Friendship","year": 2016,"rating": 6.5,"votes": 18384,"running_times": 5400},{"title": "Love & Mercy","year": 2014,"rating": 7.4,"votes": 29208,"running_times": 7260},{"title": "Love & Other Drugs","year": 2010,"rating": 6.7,"votes": 156299,"running_times": 6720},{"title": "Love","year": 2015,"rating": 6,"votes": 27109,"running_times": 8100},{"title": "Love Actually","year": 2003,"rating": 7.7,"votes": 351260,"running_times": 8100},{"title": "Love Happens","year": 2009,"rating": 5.6,"votes": 27218,"running_times": 6540},{"title": "Love Is Strange","year": 2014,"rating": 6.7,"votes": 10779,"running_times": 5640},{"title": "Love Potion No. 9","year": 1992,"rating": 5.6,"votes": 11182,"running_times": 5520},{"title": "Love Story","year": 1970,"rating": 6.9,"votes": 24825,"running_times": 5940},{"title": "Love Wrecked","year": 2005,"rating": 4.9,"votes": 12563,"running_times": 5220},{"title": "Love and Death","year": 1975,"rating": 7.8,"votes": 30482,"running_times": 5100},{"title": "Love and Other Disasters","year": 2006,"rating": 6.2,"votes": 12430,"running_times": 5400},{"title": "Love and Other Impossible Pursuits","year": 2009,"rating": 6.4,"votes": 16603,"running_times": 7140},{"title": "Love in the Afternoon","year": 1957,"rating": 7.3,"votes": 11220,"running_times": 7800},{"title": "Love in the Time of Cholera","year": 2007,"rating": 6.4,"votes": 20278,"running_times": 8340},{"title": "Love the Coopers","year": 2015,"rating": 5.7,"votes": 14440,"running_times": 6420},{"title": "Love, Rosie","year": 2014,"rating": 7.2,"votes": 87349,"running_times": 6120},{"title": "Lovelace","year": 2013,"rating": 6.2,"votes": 33759,"running_times": 5580},{"title": "Loving","year": 2016,"rating": 7,"votes": 22583,"running_times": 7380},{"title": "Loving Annabelle","year": 2006,"rating": 6.6,"votes": 10150,"running_times": 4560},{"title": "Lucas","year": 1986,"rating": 6.8,"votes": 12451,"running_times": 6000},{"title": "Lucky Number Slevin","year": 2006,"rating": 7.8,"votes": 277942,"running_times": 6600},{"title": "Lucky You","year": 2007,"rating": 5.9,"votes": 18963,"running_times": 7440},{"title": "Lucy","year": 2014,"rating": 6.4,"votes": 368660,"running_times": 5340},{"title": "Lucía y el sexo","year": 2001,"rating": 7.2,"votes": 31388,"running_times": 7680},{"title": "Lung hing foo dai","year": 1986,"rating": 7.1,"votes": 14172,"running_times": 5880},{"title": "Luther","year": 2003,"rating": 6.6,"votes": 13543,"running_times": 7380},{"title": "Lymelife","year": 2008,"rating": 7,"votes": 13184,"running_times": 5700},{"title": "Léon","year": 1994,"rating": 8.6,"votes": 819957,"running_times": 8160},{"title": "MASH","year": 1970,"rating": 7.6,"votes": 59702,"running_times": 6960},{"title": "MSG: The Messenger","year": 2015,"rating": 6.8,"votes": 10998,"running_times": 11820},{"title": "MacGruber","year": 2010,"rating": 5.5,"votes": 37968,"running_times": 5700},{"title": "Macbeth","year": 2015,"rating": 6.7,"votes": 44443,"running_times": 6780},{"title": "Machete","year": 2010,"rating": 6.6,"votes": 174552,"running_times": 6300},{"title": "Machete Kills","year": 2013,"rating": 5.6,"votes": 64908,"running_times": 6420},{"title": "Machine Gun Preacher","year": 2011,"rating": 6.8,"votes": 57085,"running_times": 7740},{"title": "Mad City","year": 1997,"rating": 6.2,"votes": 17393,"running_times": 6900},{"title": "Mad Dog and Glory","year": 1993,"rating": 6.2,"votes": 18261,"running_times": 5820},{"title": "Mad Max","year": 1979,"rating": 7,"votes": 165182,"running_times": 5580},{"title": "Mad Max 2","year": 1981,"rating": 7.6,"votes": 145142,"running_times": 5760},{"title": "Mad Max Beyond Thunderdome","year": 1985,"rating": 6.3,"votes": 110404,"running_times": 6420},{"title": "Mad Max: Fury Road","year": 2015,"rating": 8.1,"votes": 676904,"running_times": 7200},{"title": "Mad Money","year": 2008,"rating": 5.8,"votes": 17870,"running_times": 6240},{"title": "Madagascar","year": 2005,"rating": 6.9,"votes": 298407,"running_times": 5160},{"title": "Madagascar 3: Europe's Most Wanted","year": 2012,"rating": 6.9,"votes": 132064,"running_times": 5580},{"title": "Madagascar: Escape 2 Africa","year": 2008,"rating": 6.7,"votes": 164323,"running_times": 5340},{"title": "Made","year": 2001,"rating": 6.4,"votes": 15671,"running_times": 5700},{"title": "Made in America","year": 1993,"rating": 4.9,"votes": 12814,"running_times": 6660},{"title": "Made in Dagenham","year": 2010,"rating": 7.2,"votes": 12016,"running_times": 6780},{"title": "Made of Honor","year": 2008,"rating": 5.9,"votes": 59008,"running_times": 6060},{"title": "Madea Goes to Jail","year": 2009,"rating": 4.3,"votes": 10213,"running_times": 6180},{"title": "Maggie","year": 2015,"rating": 5.6,"votes": 35761,"running_times": 5700},{"title": "Maggie's Plan","year": 2015,"rating": 6.2,"votes": 11381,"running_times": 5880},{"title": "Magic Mike","year": 2012,"rating": 6.1,"votes": 116802,"running_times": 6600},{"title": "Magic Mike XXL","year": 2015,"rating": 5.6,"votes": 44596,"running_times": 6900},{"title": "Magic in the Moonlight","year": 2014,"rating": 6.6,"votes": 54096,"running_times": 5820},{"title": "Magnolia","year": 1999,"rating": 8,"votes": 255829,"running_times": 11280},{"title": "Magnum Force","year": 1973,"rating": 7.2,"votes": 47198,"running_times": 7440},{"title": "Maid in Manhattan","year": 2002,"rating": 5.1,"votes": 73669,"running_times": 6300},{"title": "Majo no takkyûbin","year": 1989,"rating": 7.9,"votes": 87286,"running_times": 6180},{"title": "Major League","year": 1989,"rating": 7.2,"votes": 52776,"running_times": 6420},{"title": "Major League II","year": 1994,"rating": 5.5,"votes": 21849,"running_times": 6300},{"title": "Major Payne","year": 1995,"rating": 6.2,"votes": 24817,"running_times": 5700},{"title": "Malcolm X","year": 1992,"rating": 7.7,"votes": 69810,"running_times": 12120},{"title": "Maleficent","year": 2014,"rating": 7,"votes": 278768,"running_times": 5820},{"title": "Malibu's Most Wanted","year": 2003,"rating": 5.1,"votes": 16870,"running_times": 5160},{"title": "Malice","year": 1993,"rating": 6.4,"votes": 19587,"running_times": 6420},{"title": "Mallrats","year": 1995,"rating": 7.2,"votes": 104168,"running_times": 7380},{"title": "Malèna","year": 2000,"rating": 7.5,"votes": 72681,"running_times": 6540},{"title": "Mama","year": 2013,"rating": 6.2,"votes": 148340,"running_times": 6000},{"title": "Mamma Mia!","year": 2008,"rating": 6.4,"votes": 159125,"running_times": 6480},{"title": "Man Up","year": 2015,"rating": 6.8,"votes": 39572,"running_times": 5280},{"title": "Man of Steel","year": 2013,"rating": 7.1,"votes": 600877,"running_times": 8580},{"title": "Man of Tai Chi","year": 2013,"rating": 6.1,"votes": 30729,"running_times": 6300},{"title": "Man of the House","year": 2005,"rating": 5.4,"votes": 20850,"running_times": 6000},{"title": "Man of the Year","year": 2006,"rating": 6.2,"votes": 29232,"running_times": 6900},{"title": "Man on Fire","year": 2004,"rating": 7.7,"votes": 287637,"running_times": 8760},{"title": "Man on Wire","year": 2008,"rating": 7.8,"votes": 45633,"running_times": 5640},{"title": "Man on a Ledge","year": 2012,"rating": 6.6,"votes": 131789,"running_times": 6120},{"title": "Man on the Moon","year": 1999,"rating": 7.4,"votes": 108535,"running_times": 7080},{"title": "Management","year": 2008,"rating": 5.9,"votes": 15648,"running_times": 5640},{"title": "Manchester by the Sea","year": 2016,"rating": 7.9,"votes": 169860,"running_times": 8220},{"title": "Mandela: Long Walk to Freedom","year": 2013,"rating": 7.1,"votes": 23331,"running_times": 8460},{"title": "Manderlay","year": 2005,"rating": 7.4,"votes": 19865,"running_times": 8340},{"title": "Manhattan","year": 1979,"rating": 8,"votes": 114313,"running_times": 5760},{"title": "Manhattan Murder Mystery","year": 1993,"rating": 7.4,"votes": 31311,"running_times": 6240},{"title": "Manhunter","year": 1986,"rating": 7.2,"votes": 54697,"running_times": 7440},{"title": "Maniac","year": 1980,"rating": 6.5,"votes": 11244,"running_times": 5220},{"title": "Maniac","year": 2012,"rating": 6.1,"votes": 30088,"running_times": 5340},{"title": "Maniac Cop","year": 1988,"rating": 6,"votes": 11047,"running_times": 5460},{"title": "Mannequin","year": 1987,"rating": 5.8,"votes": 24870,"running_times": 5400},{"title": "Manos: The Hands of Fate","year": 1966,"rating": 1.9,"votes": 32272,"running_times": 4200},{"title": "Mansfield Park","year": 1999,"rating": 7.1,"votes": 18343,"running_times": 6720},{"title": "Maps to the Stars","year": 2014,"rating": 6.2,"votes": 32048,"running_times": 6660},{"title": "Marathon Man","year": 1976,"rating": 7.5,"votes": 48758,"running_times": 7500},{"title": "Marauders","year": 2016,"rating": 5.5,"votes": 12275,"running_times": 6420},{"title": "Margaret","year": 2011,"rating": 6.5,"votes": 13896,"running_times": 11160},{"title": "Margin Call","year": 2011,"rating": 7.1,"votes": 100514,"running_times": 6420},{"title": "Margot at the Wedding","year": 2007,"rating": 6.1,"votes": 17187,"running_times": 5580},{"title": "Maria Full of Grace","year": 2004,"rating": 7.5,"votes": 31731,"running_times": 6060},{"title": "Marie Antoinette","year": 2006,"rating": 6.4,"votes": 86766,"running_times": 7380},{"title": "Marked for Death","year": 1990,"rating": 5.9,"votes": 16524,"running_times": 5580},{"title": "Marley & Me","year": 2008,"rating": 7.1,"votes": 127015,"running_times": 6900},{"title": "Marley","year": 2012,"rating": 8,"votes": 11860,"running_times": 8640},{"title": "Marmaduke","year": 2010,"rating": 4.2,"votes": 12249,"running_times": 5220},{"title": "Marnie","year": 1964,"rating": 7.2,"votes": 37177,"running_times": 7800},{"title": "Married to the Mob","year": 1988,"rating": 6.1,"votes": 13549,"running_times": 6240},{"title": "Mars Attacks!","year": 1996,"rating": 6.3,"votes": 185254,"running_times": 6360},{"title": "Mars Needs Moms","year": 2011,"rating": 5.4,"votes": 18755,"running_times": 5280},{"title": "Martha Marcy May Marlene","year": 2011,"rating": 6.9,"votes": 43275,"running_times": 6120},{"title": "Martian Child","year": 2007,"rating": 6.8,"votes": 18295,"running_times": 6360},{"title": "Marty","year": 1955,"rating": 7.7,"votes": 17265,"running_times": 5640},{"title": "Marvin's Room","year": 1996,"rating": 6.7,"votes": 21938,"running_times": 5880},{"title": "Mary Poppins","year": 1964,"rating": 7.8,"votes": 120704,"running_times": 8340},{"title": "Mary Reilly","year": 1996,"rating": 5.8,"votes": 12578,"running_times": 6480},{"title": "Mary Shelley's Frankenstein","year": 1994,"rating": 6.4,"votes": 45406,"running_times": 7380},{"title": "Mary and Max","year": 2009,"rating": 8.1,"votes": 134929,"running_times": 5520},{"title": "Mask","year": 1985,"rating": 7.2,"votes": 22226,"running_times": 7620},{"title": "Master and Commander: The Far Side of the World","year": 2003,"rating": 7.4,"votes": 179736,"running_times": 8280},{"title": "Masterminds","year": 2016,"rating": 5.8,"votes": 36500,"running_times": 5700},{"title": "Masters of the Universe","year": 1987,"rating": 5.4,"votes": 30771,"running_times": 8340},{"title": "Match Point","year": 2005,"rating": 7.7,"votes": 180746,"running_times": 7440},{"title": "Matchstick Men","year": 2003,"rating": 7.3,"votes": 112733,"running_times": 6960},{"title": "Material Girls","year": 2006,"rating": 3.9,"votes": 19988,"running_times": 5880},{"title": "Matilda","year": 1996,"rating": 6.8,"votes": 99960,"running_times": 6120},{"title": "Maurice","year": 1987,"rating": 7.7,"votes": 12111,"running_times": 8400},{"title": "Maverick","year": 1994,"rating": 7,"votes": 89064,"running_times": 7620},{"title": "Max","year": 2015,"rating": 6.8,"votes": 22467,"running_times": 6660},{"title": "Max Manus","year": 2008,"rating": 7.3,"votes": 23654,"running_times": 7080},{"title": "Max Payne","year": 2008,"rating": 5.4,"votes": 113037,"running_times": 6180},{"title": "Max Steel","year": 2016,"rating": 4.6,"votes": 14154,"running_times": 5520},{"title": "Maximum Overdrive","year": 1986,"rating": 5.4,"votes": 25300,"running_times": 5880},{"title": "Maximum Risk","year": 1996,"rating": 5.5,"votes": 17162,"running_times": 6060},{"title": "May","year": 2002,"rating": 6.7,"votes": 28776,"running_times": 5580},{"title": "Maze Runner: The Scorch Trials","year": 2015,"rating": 6.3,"votes": 170192,"running_times": 7860},{"title": "McCabe & Mrs. Miller","year": 1971,"rating": 7.7,"votes": 18101,"running_times": 7260},{"title": "McFarland, USA","year": 2015,"rating": 7.4,"votes": 28260,"running_times": 7740},{"title": "McLintock!","year": 1963,"rating": 7.3,"votes": 10231,"running_times": 7620},{"title": "Me Before You","year": 2016,"rating": 7.4,"votes": 133986,"running_times": 6360},{"title": "Me and Earl and the Dying Girl","year": 2015,"rating": 7.8,"votes": 99372,"running_times": 6300},{"title": "Me and You and Everyone We Know","year": 2005,"rating": 7.3,"votes": 32526,"running_times": 5460},{"title": "Me, Myself & Irene","year": 2000,"rating": 6.6,"votes": 198415,"running_times": 6960},{"title": "Mean Creek","year": 2004,"rating": 7.3,"votes": 28002,"running_times": 5400},{"title": "Mean Girls","year": 2004,"rating": 7,"votes": 274107,"running_times": 5820},{"title": "Mean Machine","year": 2001,"rating": 6.5,"votes": 31492,"running_times": 5940},{"title": "Mean Streets","year": 1973,"rating": 7.4,"votes": 76168,"running_times": 6720},{"title": "Meatballs","year": 1979,"rating": 6.2,"votes": 15923,"running_times": 5640},{"title": "Mechanic: Resurrection","year": 2016,"rating": 5.7,"votes": 55890,"running_times": 5880},{"title": "Medianeras","year": 2011,"rating": 7.6,"votes": 11721,"running_times": 5700},{"title": "Medicine Man","year": 1992,"rating": 6,"votes": 18595,"running_times": 6360},{"title": "Mediterraneo","year": 1991,"rating": 7.4,"votes": 11592,"running_times": 5760},{"title": "Meet Dave","year": 2008,"rating": 4.9,"votes": 33803,"running_times": 5400},{"title": "Meet Joe Black","year": 1998,"rating": 7.2,"votes": 182493,"running_times": 10680},{"title": "Meet John Doe","year": 1941,"rating": 7.7,"votes": 10038,"running_times": 7320},{"title": "Meet Me in St. Louis","year": 1944,"rating": 7.7,"votes": 16521,"running_times": 6780},{"title": "Meet the Blacks","year": 2016,"rating": 5.8,"votes": 19571,"running_times": 5640},{"title": "Meet the Feebles","year": 1989,"rating": 6.7,"votes": 16761,"running_times": 5820},{"title": "Meet the Fockers","year": 2004,"rating": 6.3,"votes": 225530,"running_times": 6900},{"title": "Meet the Parents","year": 2000,"rating": 7,"votes": 277578,"running_times": 6480},{"title": "Meet the Robinsons","year": 2007,"rating": 6.9,"votes": 74057,"running_times": 5700},{"title": "Meet the Spartans","year": 2008,"rating": 2.7,"votes": 93548,"running_times": 5160},{"title": "Meeting Evil","year": 2012,"rating": 5.3,"votes": 10575,"running_times": 5340},{"title": "Megamind","year": 2010,"rating": 7.3,"votes": 190379,"running_times": 5700},{"title": "Megan Leavey","year": 2017,"rating": 7.1,"votes": 11096,"running_times": 6960},{"title": "Melancholia","year": 2011,"rating": 7.1,"votes": 141879,"running_times": 8100},{"title": "Melinda and Melinda","year": 2004,"rating": 6.5,"votes": 28638,"running_times": 5940},{"title": "Memento","year": 2000,"rating": 8.5,"votes": 942167,"running_times": 6780},{"title": "Memoirs of a Geisha","year": 2005,"rating": 7.4,"votes": 125653,"running_times": 8700},{"title": "Memoirs of an Invisible Man","year": 1992,"rating": 5.9,"votes": 18853,"running_times": 5940},{"title": "Memorîzu","year": 1995,"rating": 7.6,"votes": 12744,"running_times": 6780},{"title": "Memphis Belle","year": 1990,"rating": 6.9,"votes": 24107,"running_times": 6420},{"title": "Men at Work","year": 1990,"rating": 5.9,"votes": 19577,"running_times": 5880},{"title": "Men in Black","year": 1997,"rating": 7.3,"votes": 443481,"running_times": 5880},{"title": "Men in Black 3","year": 2012,"rating": 6.8,"votes": 285598,"running_times": 6360},{"title": "Men in Black II","year": 2002,"rating": 6.1,"votes": 287094,"running_times": 5280},{"title": "Men of Honor","year": 2000,"rating": 7.2,"votes": 95757,"running_times": 7740},{"title": "Men, Women & Children","year": 2014,"rating": 6.7,"votes": 25774,"running_times": 7140},{"title": "Menace II Society","year": 1993,"rating": 7.5,"votes": 43249,"running_times": 5820},{"title": "Meng long guo jiang","year": 1972,"rating": 7.3,"votes": 25866,"running_times": 7980},{"title": "Mercury Rising","year": 1998,"rating": 6.1,"votes": 58173,"running_times": 6660},{"title": "Mermaids","year": 1990,"rating": 6.6,"votes": 24084,"running_times": 6600},{"title": "Merry Christmas Mr. Lawrence","year": 1983,"rating": 7.3,"votes": 11952,"running_times": 7380},{"title": "Message in a Bottle","year": 1999,"rating": 6.2,"votes": 31337,"running_times": 7560},{"title": "Metal: A Headbanger's Journey","year": 2005,"rating": 8.1,"votes": 10570,"running_times": 5880},{"title": "Metallica Through the Never","year": 2013,"rating": 7.2,"votes": 14579,"running_times": 5580},{"title": "Metallica: Some Kind of Monster","year": 2004,"rating": 7.5,"votes": 14893,"running_times": 8460},{"title": "Metoroporisu","year": 2001,"rating": 7.3,"votes": 18053,"running_times": 6780},{"title": "Metro","year": 1997,"rating": 5.5,"votes": 22659,"running_times": 7020},{"title": "Miami Vice","year": 2006,"rating": 6,"votes": 98088,"running_times": 8400},{"title": "Michael","year": 1996,"rating": 5.7,"votes": 36663,"running_times": 6300},{"title": "Michael Clayton","year": 2007,"rating": 7.3,"votes": 142224,"running_times": 7140},{"title": "Michael Collins","year": 1996,"rating": 7.1,"votes": 25953,"running_times": 7980},{"title": "Mickey Blue Eyes","year": 1999,"rating": 5.8,"votes": 31377,"running_times": 6120},{"title": "Middle Men","year": 2009,"rating": 6.6,"votes": 34183,"running_times": 6300},{"title": "Midnight Cowboy","year": 1969,"rating": 7.9,"votes": 83242,"running_times": 6780},{"title": "Midnight Express","year": 1978,"rating": 7.6,"votes": 59898,"running_times": 7260},{"title": "Midnight Run","year": 1988,"rating": 7.6,"votes": 59112,"running_times": 7560},{"title": "Midnight Special","year": 2016,"rating": 6.7,"votes": 60015,"running_times": 6720},{"title": "Midnight in Paris","year": 2011,"rating": 7.7,"votes": 331832,"running_times": 6000},{"title": "Midnight in the Garden of Good and Evil","year": 1997,"rating": 6.6,"votes": 33568,"running_times": 9300},{"title": "Midway","year": 1976,"rating": 6.8,"votes": 14666,"running_times": 7920},{"title": "Mighty Aphrodite","year": 1995,"rating": 7.1,"votes": 34007,"running_times": 5700},{"title": "Mighty Joe Young","year": 1998,"rating": 5.6,"votes": 24571,"running_times": 6840},{"title": "Mighty Morphin Power Rangers: The Movie","year": 1995,"rating": 5.1,"votes": 21853,"running_times": 5700},{"title": "Mike and Dave Need Wedding Dates","year": 2016,"rating": 6,"votes": 63508,"running_times": 5880},{"title": "Mildred Pierce","year": 1945,"rating": 8,"votes": 18004,"running_times": 6660},{"title": "Milk","year": 2008,"rating": 7.6,"votes": 146757,"running_times": 7680},{"title": "Miller's Crossing","year": 1990,"rating": 7.8,"votes": 111289,"running_times": 6900},{"title": "Million Dollar Arm","year": 2014,"rating": 7,"votes": 38810,"running_times": 7440},{"title": "Million Dollar Baby","year": 2004,"rating": 8.1,"votes": 535783,"running_times": 7920},{"title": "Millions","year": 2004,"rating": 6.9,"votes": 22849,"running_times": 5880},{"title": "Mimi wo sumaseba","year": 1995,"rating": 8,"votes": 35076,"running_times": 6660},{"title": "Mimic","year": 1997,"rating": 5.9,"votes": 39674,"running_times": 6720},{"title": "Mindhunters","year": 2004,"rating": 6.4,"votes": 52528,"running_times": 6360},{"title": "Minions","year": 2015,"rating": 6.4,"votes": 172484,"running_times": 5460},{"title": "Minority Report","year": 2002,"rating": 7.7,"votes": 435364,"running_times": 8700},{"title": "Miracle","year": 2004,"rating": 7.5,"votes": 39564,"running_times": 8100},{"title": "Miracle at St. Anna","year": 2008,"rating": 6,"votes": 16362,"running_times": 9600},{"title": "Miracle on 34th Street","year": 1947,"rating": 7.9,"votes": 33497,"running_times": 6060},{"title": "Miracle on 34th Street","year": 1994,"rating": 6.4,"votes": 25109,"running_times": 6840},{"title": "Miracles from Heaven","year": 2016,"rating": 7,"votes": 13888,"running_times": 6540},{"title": "Mirror Mirror","year": 2012,"rating": 5.6,"votes": 75292,"running_times": 6360},{"title": "Mirrormask","year": 2005,"rating": 6.9,"votes": 21061,"running_times": 6060},{"title": "Mirrors","year": 2008,"rating": 6.2,"votes": 92362,"running_times": 6720},{"title": "Misconduct","year": 2016,"rating": 5.3,"votes": 11364,"running_times": 6360},{"title": "Misery","year": 1990,"rating": 7.8,"votes": 149872,"running_times": 6420},{"title": "Miss Congeniality","year": 2000,"rating": 6.2,"votes": 152953,"running_times": 6540},{"title": "Miss Congeniality 2: Armed and Fabulous","year": 2005,"rating": 5,"votes": 57183,"running_times": 6900},{"title": "Miss March","year": 2009,"rating": 5,"votes": 19250,"running_times": 5400},{"title": "Miss Peregrine's Home for Peculiar Children","year": 2016,"rating": 6.7,"votes": 121273,"running_times": 7620},{"title": "Miss Pettigrew Lives for a Day","year": 2008,"rating": 7.1,"votes": 23635,"running_times": 5520},{"title": "Miss Potter","year": 2006,"rating": 7,"votes": 25274,"running_times": 5280},{"title": "Miss Sloane","year": 2016,"rating": 7.4,"votes": 32325,"running_times": 7920},{"title": "Miss You Already","year": 2015,"rating": 6.8,"votes": 13120,"running_times": 6720},{"title": "Missing","year": 1982,"rating": 7.8,"votes": 15297,"running_times": 7320},{"title": "Missing in Action","year": 1984,"rating": 5.3,"votes": 11580,"running_times": 6060},{"title": "Mission to Mars","year": 2000,"rating": 5.6,"votes": 64003,"running_times": 6840},{"title": "Mission: Impossible","year": 1996,"rating": 7.1,"votes": 326602,"running_times": 6600},{"title": "Mission: Impossible - Ghost Protocol","year": 2011,"rating": 7.4,"votes": 391959,"running_times": 7920},{"title": "Mission: Impossible - Rogue Nation","year": 2015,"rating": 7.4,"votes": 269296,"running_times": 7860},{"title": "Mission: Impossible II","year": 2000,"rating": 6.1,"votes": 263036,"running_times": 14400},{"title": "Mission: Impossible III","year": 2006,"rating": 6.9,"votes": 278264,"running_times": 7560},{"title": "Mississippi Burning","year": 1988,"rating": 7.8,"votes": 71359,"running_times": 7680},{"title": "Mississippi Grind","year": 2015,"rating": 6.3,"votes": 13547,"running_times": 6480},{"title": "Mister Roberts","year": 1955,"rating": 7.8,"votes": 13571,"running_times": 7380},{"title": "Mistress America","year": 2015,"rating": 6.7,"votes": 19864,"running_times": 5040},{"title": "Moana","year": 2016,"rating": 7.6,"votes": 169284,"running_times": 6420},{"title": "Moby Dick","year": 1956,"rating": 7.4,"votes": 14561,"running_times": 6960},{"title": "Modern Times","year": 1936,"rating": 8.5,"votes": 165123,"running_times": 5220},{"title": "Momentum","year": 2015,"rating": 5.5,"votes": 10775,"running_times": 5760},{"title": "Mommie Dearest","year": 1981,"rating": 6.7,"votes": 12068,"running_times": 7740},{"title": "Mommy","year": 2014,"rating": 8.1,"votes": 36886,"running_times": 8340},{"title": "Moms' Night Out","year": 2014,"rating": 5.5,"votes": 11563,"running_times": 5880},{"title": "Mona Lisa","year": 1986,"rating": 7.4,"votes": 10846,"running_times": 6240},{"title": "Mona Lisa Smile","year": 2003,"rating": 6.4,"votes": 66594,"running_times": 7020},{"title": "Money Monster","year": 2016,"rating": 6.5,"votes": 74698,"running_times": 5880},{"title": "Money Talks","year": 1997,"rating": 6.2,"votes": 23953,"running_times": 5820},{"title": "Money Train","year": 1995,"rating": 5.6,"votes": 34379,"running_times": 6600},{"title": "Moneyball","year": 2011,"rating": 7.6,"votes": 305109,"running_times": 7980},{"title": "Monkey Business","year": 1952,"rating": 7,"votes": 10755,"running_times": 5820},{"title": "Monkeybone","year": 2001,"rating": 4.7,"votes": 15142,"running_times": 5580},{"title": "Monsieur Lazhar","year": 2011,"rating": 7.5,"votes": 17159,"running_times": 5640},{"title": "Monsieur Verdoux","year": 1947,"rating": 8,"votes": 12827,"running_times": 7440},{"title": "Monsoon Wedding","year": 2001,"rating": 7.4,"votes": 21016,"running_times": 6840},{"title": "Monster","year": 2003,"rating": 7.3,"votes": 115609,"running_times": 6540},{"title": "Monster House","year": 2006,"rating": 6.6,"votes": 80929,"running_times": 5460},{"title": "Monster Trucks","year": 2016,"rating": 5.7,"votes": 10288,"running_times": 6240},{"title": "Monster's Ball","year": 2001,"rating": 7.1,"votes": 75193,"running_times": 6720},{"title": "Monster-in-Law","year": 2005,"rating": 5.5,"votes": 47838,"running_times": 6060},{"title": "Monsters","year": 2010,"rating": 6.4,"votes": 80963,"running_times": 5640},{"title": "Monsters University","year": 2013,"rating": 7.3,"votes": 263070,"running_times": 6240},{"title": "Monsters vs. Aliens","year": 2009,"rating": 6.5,"votes": 125293,"running_times": 5640},{"title": "Monsters, Inc.","year": 2001,"rating": 8.1,"votes": 661782,"running_times": 5520},{"title": "Monte Carlo","year": 2011,"rating": 5.8,"votes": 36047,"running_times": 6540},{"title": "Monty Python Live at the Hollywood Bowl","year": 1982,"rating": 7.9,"votes": 12068,"running_times": 4620},{"title": "Monty Python and the Holy Grail","year": 1975,"rating": 8.3,"votes": 419568,"running_times": 5460},{"title": "Moon","year": 2009,"rating": 7.9,"votes": 286855,"running_times": 5820},{"title": "Moonlight","year": 2016,"rating": 7.5,"votes": 171817,"running_times": 6660},{"title": "Moonlight Mile","year": 2002,"rating": 6.7,"votes": 12518,"running_times": 8760},{"title": "Moonraker","year": 1979,"rating": 6.3,"votes": 75827,"running_times": 7560},{"title": "Moonrise Kingdom","year": 2012,"rating": 7.8,"votes": 264990,"running_times": 5640},{"title": "Moonstruck","year": 1987,"rating": 7.1,"votes": 39131,"running_times": 6120},{"title": "Moonwalker","year": 1988,"rating": 6,"votes": 13485,"running_times": 5580},{"title": "Morgan","year": 2016,"rating": 5.8,"votes": 28784,"running_times": 5520},{"title": "Morning Glory","year": 2010,"rating": 6.5,"votes": 63060,"running_times": 6420},{"title": "Mortal Kombat","year": 1995,"rating": 5.8,"votes": 87746,"running_times": 6060},{"title": "Mortal Kombat: Annihilation","year": 1997,"rating": 3.7,"votes": 39249,"running_times": 5700},{"title": "Mortdecai","year": 2015,"rating": 5.5,"votes": 54994,"running_times": 6420},{"title": "Morte a Venezia","year": 1971,"rating": 7.5,"votes": 15085,"running_times": 7800},{"title": "Mother and Child","year": 2009,"rating": 7.2,"votes": 10396,"running_times": 7500},{"title": "Mother!","year": 2017,"rating": 6.9,"votes": 65060,"running_times": 7260},{"title": "Mother's Day","year": 2010,"rating": 6.3,"votes": 14047,"running_times": 6720},{"title": "Mother's Day","year": 2016,"rating": 5.6,"votes": 23336,"running_times": 7080},{"title": "Mou gaan dou","year": 2002,"rating": 8.1,"votes": 101710,"running_times": 6060},{"title": "Mou gaan dou II","year": 2003,"rating": 7.4,"votes": 14467,"running_times": 7140},{"title": "Moulin Rouge!","year": 2001,"rating": 7.6,"votes": 238849,"running_times": 7620},{"title": "Mousehunt","year": 1997,"rating": 6.4,"votes": 44738,"running_times": 5880},{"title": "Movie 43","year": 2013,"rating": 4.3,"votes": 86504,"running_times": 5640},{"title": "Mr 3000","year": 2004,"rating": 5.5,"votes": 12827,"running_times": 6240},{"title": "Mr. & Mrs. Smith","year": 2005,"rating": 6.5,"votes": 384128,"running_times": 7560},{"title": "Mr. Bean's Holiday","year": 2007,"rating": 6.3,"votes": 97284,"running_times": 5400},{"title": "Mr. Brooks","year": 2007,"rating": 7.3,"votes": 130745,"running_times": 7200},{"title": "Mr. Church","year": 2016,"rating": 7.6,"votes": 18951,"running_times": 6240},{"title": "Mr. Deeds","year": 2002,"rating": 5.8,"votes": 119207,"running_times": 5760},{"title": "Mr. Deeds Goes to Town","year": 1936,"rating": 8,"votes": 16367,"running_times": 6900},{"title": "Mr. Destiny","year": 1990,"rating": 6.3,"votes": 10098,"running_times": 6600},{"title": "Mr. Holland's Opus","year": 1995,"rating": 7.3,"votes": 31822,"running_times": 8580},{"title": "Mr. Holmes","year": 2015,"rating": 6.9,"votes": 52427,"running_times": 6240},{"title": "Mr. Magoo","year": 1997,"rating": 3.9,"votes": 12824,"running_times": 5220},{"title": "Mr. Magorium's Wonder Emporium","year": 2007,"rating": 6.2,"votes": 37848,"running_times": 5580},{"title": "Mr. Mom","year": 1983,"rating": 6.5,"votes": 17571,"running_times": 5460},{"title": "Mr. Morgan's Last Love","year": 2013,"rating": 6.8,"votes": 10599,"running_times": 6660},{"title": "Mr. Nobody","year": 2009,"rating": 7.9,"votes": 176739,"running_times": 9420},{"title": "Mr. Peabody & Sherman","year": 2014,"rating": 6.8,"votes": 53028,"running_times": 5520},{"title": "Mr. Popper's Penguins","year": 2011,"rating": 6,"votes": 73897,"running_times": 5640},{"title": "Mr. Right","year": 2015,"rating": 6.3,"votes": 34544,"running_times": 5700},{"title": "Mr. Smith Goes to Washington","year": 1939,"rating": 8.2,"votes": 85911,"running_times": 7740},{"title": "Mr. Turner","year": 2014,"rating": 6.8,"votes": 20793,"running_times": 9000},{"title": "Mr. Woodcock","year": 2007,"rating": 5.1,"votes": 32431,"running_times": 5220},{"title": "Mrs Brown","year": 1997,"rating": 7.3,"votes": 11844,"running_times": 6060},{"title": "Mrs Henderson Presents","year": 2005,"rating": 7.1,"votes": 14089,"running_times": 6180},{"title": "Mrs. Doubtfire","year": 1993,"rating": 6.9,"votes": 201287,"running_times": 7500},{"title": "Mrs. Miniver","year": 1942,"rating": 7.6,"votes": 12803,"running_times": 8040},{"title": "Much Ado About Nothing","year": 1993,"rating": 7.4,"votes": 39702,"running_times": 6660},{"title": "Much Ado About Nothing","year": 2012,"rating": 7.2,"votes": 14790,"running_times": 6540},{"title": "Mud","year": 2012,"rating": 7.4,"votes": 147427,"running_times": 7800},{"title": "Mulan","year": 1998,"rating": 7.6,"votes": 196734,"running_times": 5280},{"title": "Mulholland Dr.","year": 2001,"rating": 8,"votes": 267364,"running_times": 8820},{"title": "Mulholland Falls","year": 1996,"rating": 6.2,"votes": 13844,"running_times": 6420},{"title": "Multiplicity","year": 1996,"rating": 6,"votes": 26392,"running_times": 7020},{"title": "Munich","year": 2005,"rating": 7.6,"votes": 188027,"running_times": 9840},{"title": "Muppet Treasure Island","year": 1996,"rating": 6.9,"votes": 17495,"running_times": 5940},{"title": "Muppets Most Wanted","year": 2014,"rating": 6.4,"votes": 26686,"running_times": 7140},{"title": "Muppets from Space","year": 1999,"rating": 6.3,"votes": 15770,"running_times": 5280},{"title": "Murder at 1600","year": 1997,"rating": 6.1,"votes": 25149,"running_times": 6480},{"title": "Murder by Death","year": 1976,"rating": 7.4,"votes": 27268,"running_times": 5640},{"title": "Murder by Numbers","year": 2002,"rating": 6.1,"votes": 46580,"running_times": 6900},{"title": "Murder in the First","year": 1995,"rating": 7.3,"votes": 23309,"running_times": 7320},{"title": "Murder on the Orient Express","year": 1974,"rating": 7.3,"votes": 43168,"running_times": 7680},{"title": "Murder on the Orient Express","year": 2017,"rating": 6.8,"votes": 55516,"running_times": 6840},{"title": "Muriel's Wedding","year": 1994,"rating": 7.2,"votes": 30018,"running_times": 6360},{"title": "Music and Lyrics","year": 2007,"rating": 6.5,"votes": 86957,"running_times": 6360},{"title": "Music of the Heart","year": 1999,"rating": 6.8,"votes": 10711,"running_times": 7440},{"title": "Must Love Dogs","year": 2005,"rating": 5.9,"votes": 27642,"running_times": 5880},{"title": "Mutant Chronicles","year": 2008,"rating": 5.2,"votes": 24332,"running_times": 6660},{"title": "Mutiny on the Bounty","year": 1935,"rating": 7.8,"votes": 17571,"running_times": 7920},{"title": "Mutiny on the Bounty","year": 1962,"rating": 7.2,"votes": 12571,"running_times": 11100},{"title": "My Beautiful Laundrette","year": 1985,"rating": 6.9,"votes": 11620,"running_times": 5820},{"title": "My Best Friend's Girl","year": 2008,"rating": 5.9,"votes": 39104,"running_times": 6720},{"title": "My Best Friend's Wedding","year": 1997,"rating": 6.3,"votes": 107518,"running_times": 6300},{"title": "My Big Fat Greek Wedding","year": 2002,"rating": 6.6,"votes": 108638,"running_times": 5700},{"title": "My Big Fat Greek Wedding 2","year": 2016,"rating": 6,"votes": 22601,"running_times": 5640},{"title": "My Bloody Valentine","year": 1981,"rating": 6.2,"votes": 13928,"running_times": 5580},{"title": "My Bloody Valentine","year": 2009,"rating": 5.5,"votes": 48197,"running_times": 6060},{"title": "My Blue Heaven","year": 1990,"rating": 6.2,"votes": 16465,"running_times": 5820},{"title": "My Blueberry Nights","year": 2007,"rating": 6.7,"votes": 47098,"running_times": 5700},{"title": "My Boss's Daughter","year": 2003,"rating": 4.7,"votes": 25546,"running_times": 5400},{"title": "My Cousin Vinny","year": 1992,"rating": 7.5,"votes": 89632,"running_times": 7200},{"title": "My Darling Clementine","year": 1946,"rating": 7.8,"votes": 17919,"running_times": 6180},{"title": "My Dinner with Andre","year": 1981,"rating": 7.8,"votes": 13680,"running_times": 6600},{"title": "My Dog Skip","year": 2000,"rating": 7,"votes": 17536,"running_times": 5700},{"title": "My Fair Lady","year": 1964,"rating": 7.9,"votes": 73415,"running_times": 10200},{"title": "My Favorite Martian","year": 1999,"rating": 5,"votes": 11486,"running_times": 5640},{"title": "My Fellow Americans","year": 1996,"rating": 6.5,"votes": 12910,"running_times": 6060},{"title": "My Girl","year": 1991,"rating": 6.8,"votes": 61084,"running_times": 6120},{"title": "My Girl 2","year": 1994,"rating": 5.2,"votes": 16062,"running_times": 5940},{"title": "My Left Foot: The Story of Christy Brown","year": 1989,"rating": 7.9,"votes": 55465,"running_times": 6180},{"title": "My Life Without Me","year": 2003,"rating": 7.6,"votes": 22176,"running_times": 6420},{"title": "My Life in Ruins","year": 2009,"rating": 5.9,"votes": 16255,"running_times": 5880},{"title": "My Little Eye","year": 2002,"rating": 5.6,"votes": 10696,"running_times": 5700},{"title": "My Man Godfrey","year": 1936,"rating": 8.1,"votes": 16984,"running_times": 5640},{"title": "My Name Is Bruce","year": 2007,"rating": 6.3,"votes": 22187,"running_times": 5040},{"title": "My Name Is Khan","year": 2010,"rating": 8,"votes": 82373,"running_times": 9900},{"title": "My Own Private Idaho","year": 1991,"rating": 7.1,"votes": 40621,"running_times": 6240},{"title": "My Sassy Girl","year": 2008,"rating": 6.3,"votes": 18325,"running_times": 5520},{"title": "My Sister's Keeper","year": 2009,"rating": 7.4,"votes": 80671,"running_times": 6540},{"title": "My Soul to Take","year": 2010,"rating": 4.8,"votes": 17463,"running_times": 6420},{"title": "My Stepmother Is an Alien","year": 1988,"rating": 5.2,"votes": 22451,"running_times": 6300},{"title": "My Summer of Love","year": 2004,"rating": 6.8,"votes": 17370,"running_times": 5160},{"title": "My Super Ex-Girlfriend","year": 2006,"rating": 5.1,"votes": 56499,"running_times": 5760},{"title": "My Week with Marilyn","year": 2011,"rating": 7,"votes": 75892,"running_times": 5940},{"title": "Mysterious Skin","year": 2004,"rating": 7.7,"votes": 60112,"running_times": 6420},{"title": "Mystery Men","year": 1999,"rating": 6.1,"votes": 56460,"running_times": 7260},{"title": "Mystery Science Theater 3000: The Movie","year": 1996,"rating": 7.4,"votes": 16482,"running_times": 4380},{"title": "Mystery Train","year": 1989,"rating": 7.6,"votes": 20535,"running_times": 6600},{"title": "Mystery, Alaska","year": 1999,"rating": 6.7,"votes": 23221,"running_times": 7140},{"title": "Mystic Pizza","year": 1988,"rating": 6.2,"votes": 20318,"running_times": 6240},{"title": "Mystic River","year": 2003,"rating": 8,"votes": 365071,"running_times": 8280},{"title": "Män som hatar kvinnor","year": 2009,"rating": 7.8,"votes": 186700,"running_times": 11160},{"title": "Nacho Libre","year": 2006,"rating": 5.7,"votes": 70536,"running_times": 5520},{"title": "Naked","year": 1993,"rating": 7.9,"votes": 26891,"running_times": 7920},{"title": "Naked Gun 33 1/3: The Final Insult","year": 1994,"rating": 6.5,"votes": 83247,"running_times": 4980},{"title": "Naked Lunch","year": 1991,"rating": 7.1,"votes": 39652,"running_times": 6900},{"title": "Nancy Drew","year": 2007,"rating": 5.9,"votes": 17051,"running_times": 5940},{"title": "Nanny McPhee","year": 2005,"rating": 6.6,"votes": 55817,"running_times": 5880},{"title": "Nanny McPhee and the Big Bang","year": 2010,"rating": 6.1,"votes": 22057,"running_times": 6540},{"title": "Napoleon Dynamite","year": 2004,"rating": 6.9,"votes": 172599,"running_times": 5760},{"title": "Narc","year": 2002,"rating": 7.2,"votes": 35543,"running_times": 6300},{"title": "Nashville","year": 1975,"rating": 7.8,"votes": 19364,"running_times": 9600},{"title": "National Lampoon's Christmas Vacation","year": 1989,"rating": 7.6,"votes": 118874,"running_times": 5820},{"title": "National Lampoon's European Vacation","year": 1985,"rating": 6.1,"votes": 47396,"running_times": 5700},{"title": "National Lampoon's Vacation","year": 1983,"rating": 7.4,"votes": 78815,"running_times": 5880},{"title": "National Security","year": 2003,"rating": 5.6,"votes": 41680,"running_times": 5280},{"title": "National Treasure","year": 2004,"rating": 6.9,"votes": 270548,"running_times": 7860},{"title": "National Treasure: Book of Secrets","year": 2007,"rating": 6.5,"votes": 194576,"running_times": 7440},{"title": "Natural Born Killers","year": 1994,"rating": 7.3,"votes": 187627,"running_times": 7320},{"title": "Navy Seals","year": 1990,"rating": 5.5,"votes": 13865,"running_times": 6780},{"title": "Nayakan","year": 1987,"rating": 8.8,"votes": 10378,"running_times": 9360},{"title": "Near Dark","year": 1987,"rating": 7,"votes": 27846,"running_times": 5640},{"title": "Nebraska","year": 2013,"rating": 7.7,"votes": 98852,"running_times": 6900},{"title": "Ned Kelly","year": 2003,"rating": 6.5,"votes": 23002,"running_times": 6600},{"title": "Need for Speed","year": 2014,"rating": 6.5,"votes": 146918,"running_times": 7920},{"title": "Needful Things","year": 1993,"rating": 6.2,"votes": 18544,"running_times": 10980},{"title": "Neerja","year": 2016,"rating": 7.8,"votes": 15336,"running_times": 7320},{"title": "Neighbors","year": 2014,"rating": 6.3,"votes": 246015,"running_times": 5820},{"title": "Neighbors 2: Sorority Rising","year": 2016,"rating": 5.7,"votes": 85986,"running_times": 5520},{"title": "Neko no ongaeshi","year": 2002,"rating": 7.3,"votes": 35049,"running_times": 4500},{"title": "Nell","year": 1994,"rating": 6.5,"votes": 24192,"running_times": 6720},{"title": "Nerve","year": 2016,"rating": 6.6,"votes": 84651,"running_times": 5760},{"title": "Network","year": 1976,"rating": 8.1,"votes": 116290,"running_times": 7260},{"title": "Never Back Down","year": 2008,"rating": 6.6,"votes": 86232,"running_times": 6600},{"title": "Never Been Kissed","year": 1999,"rating": 6,"votes": 73008,"running_times": 6420},{"title": "Never Let Me Go","year": 2010,"rating": 7.2,"votes": 120871,"running_times": 6180},{"title": "Never Say Never Again","year": 1983,"rating": 6.2,"votes": 52439,"running_times": 8040},{"title": "New Jack City","year": 1991,"rating": 6.6,"votes": 26155,"running_times": 6060},{"title": "New Nightmare","year": 1994,"rating": 6.4,"votes": 42203,"running_times": 6720},{"title": "New Year's Eve","year": 2011,"rating": 5.7,"votes": 71453,"running_times": 6780},{"title": "New York Minute","year": 2004,"rating": 4.9,"votes": 18985,"running_times": 5460},{"title": "New York Stories","year": 1989,"rating": 6.4,"votes": 14779,"running_times": 7440},{"title": "New York, I Love You","year": 2008,"rating": 6.3,"votes": 41493,"running_times": 6180},{"title": "New York, New York","year": 1977,"rating": 6.7,"votes": 14965,"running_times": 9780},{"title": "New in Town","year": 2009,"rating": 5.6,"votes": 18943,"running_times": 5820},{"title": "Newsies","year": 1992,"rating": 7,"votes": 16512,"running_times": 7260},{"title": "Next","year": 2007,"rating": 6.2,"votes": 132917,"running_times": 5760},{"title": "Next Friday","year": 2000,"rating": 6.1,"votes": 30612,"running_times": 5880},{"title": "Ngo si seoi","year": 1998,"rating": 6.8,"votes": 30599,"running_times": 7200},{"title": "Niagara","year": 1953,"rating": 7.1,"votes": 12158,"running_times": 5520},{"title": "Nicholas Nickleby","year": 2002,"rating": 7.2,"votes": 10065,"running_times": 7920},{"title": "Nick and Norah's Infinite Playlist","year": 2008,"rating": 6.7,"votes": 79582,"running_times": 5400},{"title": "Nick of Time","year": 1995,"rating": 6.3,"votes": 34746,"running_times": 5400},{"title": "Night Moves","year": 2013,"rating": 6,"votes": 11460,"running_times": 6720},{"title": "Night Shift","year": 1982,"rating": 6.5,"votes": 11930,"running_times": 6360},{"title": "Night Train to Lisbon","year": 2013,"rating": 6.8,"votes": 14887,"running_times": 6660},{"title": "Night at the Museum","year": 2006,"rating": 6.4,"votes": 261448,"running_times": 6480},{"title": "Night at the Museum: Battle of the Smithsonian","year": 2009,"rating": 5.9,"votes": 145596,"running_times": 6300},{"title": "Night at the Museum: Secret of the Tomb","year": 2014,"rating": 6.2,"votes": 79834,"running_times": 5880},{"title": "Night of the Comet","year": 1984,"rating": 6.4,"votes": 14499,"running_times": 5700},{"title": "Night of the Creeps","year": 1986,"rating": 6.8,"votes": 16397,"running_times": 5280},{"title": "Night of the Demons","year": 1988,"rating": 6.3,"votes": 10119,"running_times": 5400},{"title": "Night of the Living Dead","year": 1968,"rating": 7.9,"votes": 96882,"running_times": 5760},{"title": "Night of the Living Dead","year": 1990,"rating": 6.9,"votes": 33568,"running_times": 5520},{"title": "Night on Earth","year": 1991,"rating": 7.8,"votes": 45481,"running_times": 7740},{"title": "Nightbreed","year": 1990,"rating": 6.6,"votes": 15960,"running_times": 8700},{"title": "Nightcrawler","year": 2014,"rating": 7.9,"votes": 354755,"running_times": 7080},{"title": "Nighthawks","year": 1981,"rating": 6.4,"votes": 13721,"running_times": 5940},{"title": "Nights in Rodanthe","year": 2008,"rating": 6,"votes": 19672,"running_times": 5820},{"title": "Nightwatch","year": 1997,"rating": 6.2,"votes": 17099,"running_times": 6060},{"title": "Nikita","year": 1990,"rating": 7.4,"votes": 59142,"running_times": 7020},{"title": "Nim's Island","year": 2008,"rating": 6,"votes": 29823,"running_times": 5760},{"title": "Nine","year": 2009,"rating": 5.8,"votes": 39270,"running_times": 7080},{"title": "Nine 1/2 Weeks","year": 1986,"rating": 5.9,"votes": 32143,"running_times": 7020},{"title": "Nine Dead","year": 2010,"rating": 5.5,"votes": 10493,"running_times": 5880},{"title": "Nine Lives","year": 2016,"rating": 5.3,"votes": 15077,"running_times": 5220},{"title": "Nine Months","year": 1995,"rating": 5.5,"votes": 31636,"running_times": 6180},{"title": "Nine to Five","year": 1980,"rating": 6.7,"votes": 22127,"running_times": 6540},{"title": "Nineteen Eighty-Four","year": 1984,"rating": 7.2,"votes": 54961,"running_times": 6780},{"title": "Ninja","year": 2009,"rating": 5.5,"votes": 10491,"running_times": 5160},{"title": "Ninja Assassin","year": 2009,"rating": 6.4,"votes": 61464,"running_times": 5940},{"title": "Ninotchka","year": 1939,"rating": 8,"votes": 15743,"running_times": 6600},{"title": "Nirgendwo in Afrika","year": 2001,"rating": 7.7,"votes": 11252,"running_times": 8460},{"title": "Nixon","year": 1995,"rating": 7.1,"votes": 25610,"running_times": 12720},{"title": "No Country for Old Men","year": 2007,"rating": 8.1,"votes": 689593,"running_times": 7320},{"title": "No Escape","year": 1994,"rating": 6.1,"votes": 16664,"running_times": 7080},{"title": "No Escape","year": 2015,"rating": 6.8,"votes": 62445,"running_times": 6180},{"title": "No Good Deed","year": 2014,"rating": 5.6,"votes": 14427,"running_times": 5040},{"title": "No Man's Land","year": 2001,"rating": 8,"votes": 39957,"running_times": 5880},{"title": "No One Lives","year": 2012,"rating": 6,"votes": 15163,"running_times": 5160},{"title": "No Reservations","year": 2007,"rating": 6.3,"votes": 62975,"running_times": 6240},{"title": "No Retreat, No Surrender","year": 1986,"rating": 5.6,"votes": 12983,"running_times": 5640},{"title": "No Strings Attached","year": 2011,"rating": 6.2,"votes": 183855,"running_times": 6480},{"title": "No Way Out","year": 1987,"rating": 7.1,"votes": 29075,"running_times": 6840},{"title": "No se aceptan devoluciones","year": 2013,"rating": 7.6,"votes": 24684,"running_times": 7320},{"title": "Noah","year": 2014,"rating": 5.8,"votes": 215683,"running_times": 8280},{"title": "Nobody's Fool","year": 1994,"rating": 7.4,"votes": 15887,"running_times": 6600},{"title": "Nocturnal Animals","year": 2016,"rating": 7.5,"votes": 162493,"running_times": 6960},{"title": "Non-Stop","year": 2014,"rating": 7,"votes": 218748,"running_times": 6360},{"title": "Norbit","year": 2007,"rating": 4,"votes": 57358,"running_times": 6180},{"title": "North","year": 1994,"rating": 4.4,"votes": 11933,"running_times": 5220},{"title": "North Country","year": 2005,"rating": 7.3,"votes": 34946,"running_times": 7560},{"title": "North by Northwest","year": 1959,"rating": 8.4,"votes": 243659,"running_times": 8160},{"title": "Nosferatu: Phantom der Nacht","year": 1979,"rating": 7.6,"votes": 26121,"running_times": 6420},{"title": "Not Another Teen Movie","year": 2001,"rating": 5.7,"votes": 85688,"running_times": 5940},{"title": "Not Without My Daughter","year": 1991,"rating": 6.2,"votes": 10448,"running_times": 6960},{"title": "Notes on a Scandal","year": 2006,"rating": 7.4,"votes": 67788,"running_times": 5520},{"title": "Nothing But Trouble","year": 1991,"rating": 4.9,"votes": 18965,"running_times": 5640},{"title": "Nothing But the Truth","year": 2008,"rating": 7.2,"votes": 32564,"running_times": 6480},{"title": "Nothing Is Private","year": 2007,"rating": 7,"votes": 10724,"running_times": 7440},{"title": "Nothing to Lose","year": 1997,"rating": 6.7,"votes": 38436,"running_times": 5880},{"title": "Notorious","year": 1946,"rating": 8,"votes": 79583,"running_times": 6060},{"title": "Notorious","year": 2009,"rating": 6.7,"votes": 35329,"running_times": 7680},{"title": "Notting Hill","year": 1999,"rating": 7.1,"votes": 223479,"running_times": 7440},{"title": "Now Is Good","year": 2012,"rating": 7.2,"votes": 29452,"running_times": 6180},{"title": "Now You See Me","year": 2013,"rating": 7.3,"votes": 511818,"running_times": 7500},{"title": "Now You See Me 2","year": 2016,"rating": 6.5,"votes": 178217,"running_times": 7740},{"title": "Now and Then","year": 1995,"rating": 6.8,"votes": 22910,"running_times": 6000},{"title": "Now, Voyager","year": 1942,"rating": 8,"votes": 12379,"running_times": 7020},{"title": "Nowhere Boy","year": 2009,"rating": 7.2,"votes": 30853,"running_times": 5880},{"title": "Nowhere to Run","year": 1993,"rating": 5.6,"votes": 18740,"running_times": 5640},{"title": "Nurse Betty","year": 2000,"rating": 6.2,"votes": 30959,"running_times": 6600},{"title": "Nutty Professor II: The Klumps","year": 2000,"rating": 4.3,"votes": 42268,"running_times": 6540},{"title": "Nymphomaniac: Vol. I","year": 2013,"rating": 7,"votes": 95493,"running_times": 8700},{"title": "Nymphomaniac: Vol. II","year": 2013,"rating": 6.7,"votes": 69731,"running_times": 10800},{"title": "O","year": 2001,"rating": 6.2,"votes": 17881,"running_times": 5700},{"title": "O Brother, Where Art Thou?","year": 2000,"rating": 7.8,"votes": 244698,"running_times": 6420},{"title": "O.J.: Made in America","year": 2016,"rating": 9,"votes": 12449,"running_times": 28020},{"title": "OMG: Oh My God!","year": 2012,"rating": 8.2,"votes": 37128,"running_times": 7500},{"title": "OSS 117: Rio ne répond plus","year": 2009,"rating": 6.9,"votes": 10637,"running_times": 6060},{"title": "OXV: The Manual","year": 2013,"rating": 6.8,"votes": 11970,"running_times": 6300},{"title": "Oblivion","year": 2013,"rating": 7,"votes": 423224,"running_times": 7440},{"title": "Observe and Report","year": 2009,"rating": 5.8,"votes": 54722,"running_times": 5160},{"title": "Obsessed","year": 2009,"rating": 4.9,"votes": 24823,"running_times": 6480},{"title": "Obvious Child","year": 2014,"rating": 6.8,"votes": 19332,"running_times": 5040},{"title": "Ocean's Eleven","year": 1960,"rating": 6.6,"votes": 16596,"running_times": 7620},{"title": "Ocean's Eleven","year": 2001,"rating": 7.8,"votes": 439145,"running_times": 6960},{"title": "Ocean's Thirteen","year": 2007,"rating": 6.9,"votes": 277326,"running_times": 7320},{"title": "Ocean's Twelve","year": 2004,"rating": 6.5,"votes": 308751,"running_times": 7500},{"title": "October Sky","year": 1999,"rating": 7.8,"votes": 70134,"running_times": 6480},{"title": "Octopussy","year": 1983,"rating": 6.6,"votes": 80552,"running_times": 7860},{"title": "Oculus","year": 2013,"rating": 6.5,"votes": 97266,"running_times": 6240},{"title": "Odd Thomas","year": 2013,"rating": 6.9,"votes": 40221,"running_times": 5820},{"title": "Of Mice and Men","year": 1992,"rating": 7.5,"votes": 34644,"running_times": 6900},{"title": "Office Christmas Party","year": 2016,"rating": 5.8,"votes": 42454,"running_times": 6660},{"title": "Office Space","year": 1999,"rating": 7.8,"votes": 214446,"running_times": 5340},{"title": "Offret","year": 1986,"rating": 8.1,"votes": 16928,"running_times": 8940},{"title": "Oh Boy","year": 2012,"rating": 7.4,"votes": 12277,"running_times": 5160},{"title": "Okja","year": 2017,"rating": 7.4,"votes": 49130,"running_times": 7200},{"title": "Old Boy","year": 2013,"rating": 5.8,"votes": 56956,"running_times": 6240},{"title": "Old Dogs","year": 2009,"rating": 5.4,"votes": 32907,"running_times": 5280},{"title": "Old School","year": 2003,"rating": 7.2,"votes": 195016,"running_times": 5280},{"title": "Oliver & Company","year": 1988,"rating": 6.7,"votes": 36062,"running_times": 4440},{"title": "Oliver Twist","year": 2005,"rating": 6.9,"votes": 27382,"running_times": 7800},{"title": "Oliver!","year": 1968,"rating": 7.5,"votes": 28194,"running_times": 9180},{"title": "Olympus Has Fallen","year": 2013,"rating": 6.5,"votes": 220967,"running_times": 7140},{"title": "On Deadly Ground","year": 1994,"rating": 4.4,"votes": 19370,"running_times": 6060},{"title": "On Golden Pond","year": 1981,"rating": 7.7,"votes": 23306,"running_times": 6540},{"title": "On Her Majesty's Secret Service","year": 1969,"rating": 6.8,"votes": 65821,"running_times": 8520},{"title": "On the Beach","year": 1959,"rating": 7.3,"votes": 10197,"running_times": 8040},{"title": "On the Road","year": 2012,"rating": 6.1,"votes": 35856,"running_times": 8220},{"title": "On the Town","year": 1949,"rating": 7.6,"votes": 13300,"running_times": 5880},{"title": "On the Waterfront","year": 1954,"rating": 8.2,"votes": 113409,"running_times": 6480},{"title": "Once","year": 2007,"rating": 7.9,"votes": 99752,"running_times": 5160},{"title": "Once Bitten","year": 1985,"rating": 5.5,"votes": 11056,"running_times": 5640},{"title": "Once Upon a Time in America","year": 1984,"rating": 8.4,"votes": 247434,"running_times": 16140},{"title": "Once Upon a Time in Mexico","year": 2003,"rating": 6.4,"votes": 138307,"running_times": 6120},{"title": "Once Were Warriors","year": 1994,"rating": 7.9,"votes": 27379,"running_times": 6120},{"title": "Ondine","year": 2009,"rating": 6.8,"votes": 18057,"running_times": 6660},{"title": "One Crazy Summer","year": 1986,"rating": 6.4,"votes": 11705,"running_times": 5580},{"title": "One Day","year": 2011,"rating": 7,"votes": 117869,"running_times": 6420},{"title": "One Direction: This Is Us","year": 2013,"rating": 4.1,"votes": 22601,"running_times": 6360},{"title": "One Eight Seven","year": 1997,"rating": 6.7,"votes": 19395,"running_times": 7140},{"title": "One Fine Day","year": 1996,"rating": 6.5,"votes": 38432,"running_times": 6480},{"title": "One Flew Over the Cuckoo's Nest","year": 1975,"rating": 8.7,"votes": 753853,"running_times": 7980},{"title": "One Hour Photo","year": 2002,"rating": 6.8,"votes": 103023,"running_times": 5760},{"title": "One Hundred and One Dalmatians","year": 1961,"rating": 7.2,"votes": 125012,"running_times": 4740},{"title": "One Man Band","year": 2005,"rating": 7.8,"votes": 12130,"running_times": 240},{"title": "One Missed Call","year": 2008,"rating": 4,"votes": 28125,"running_times": 5220},{"title": "One Night at McCool's","year": 2001,"rating": 6.1,"votes": 26629,"running_times": 5580},{"title": "One True Thing","year": 1998,"rating": 7,"votes": 10049,"running_times": 7620},{"title": "One Week","year": 2008,"rating": 7.1,"votes": 10363,"running_times": 5640},{"title": "One for the Money","year": 2012,"rating": 5.3,"votes": 36462,"running_times": 5460},{"title": "One, Two, Three","year": 1961,"rating": 8,"votes": 16319,"running_times": 6900},{"title": "Ong-bak","year": 2003,"rating": 7.2,"votes": 64314,"running_times": 6480},{"title": "Only God Forgives","year": 2013,"rating": 5.7,"votes": 93136,"running_times": 5400},{"title": "Only Lovers Left Alive","year": 2013,"rating": 7.3,"votes": 72348,"running_times": 7380},{"title": "Only You","year": 1994,"rating": 6.5,"votes": 16908,"running_times": 6900},{"title": "Oorlogswinter","year": 2008,"rating": 7,"votes": 10942,"running_times": 6180},{"title": "Open Grave","year": 2013,"rating": 6.3,"votes": 23858,"running_times": 6120},{"title": "Open Range","year": 2003,"rating": 7.5,"votes": 57963,"running_times": 8340},{"title": "Open Season","year": 2006,"rating": 6.2,"votes": 72098,"running_times": 5160},{"title": "Open Water","year": 2003,"rating": 5.7,"votes": 45441,"running_times": 4740},{"title": "Open Water 2: Adrift","year": 2006,"rating": 5.1,"votes": 14864,"running_times": 5700},{"title": "Open Windows","year": 2014,"rating": 5.2,"votes": 11765,"running_times": 6000},{"title": "Opera","year": 1987,"rating": 7.1,"votes": 10995,"running_times": 6420},{"title": "Operation Petticoat","year": 1959,"rating": 7.3,"votes": 10205,"running_times": 7440},{"title": "Orange County","year": 2002,"rating": 6.2,"votes": 43196,"running_times": 4920},{"title": "Ordinary Decent Criminal","year": 2000,"rating": 6.4,"votes": 12289,"running_times": 5580},{"title": "Ordinary People","year": 1980,"rating": 7.8,"votes": 38597,"running_times": 7440},{"title": "Orgazmo","year": 1997,"rating": 6.2,"votes": 31683,"running_times": 5640},{"title": "Original Sin","year": 2001,"rating": 6,"votes": 47818,"running_times": 7080},{"title": "Orlando","year": 1992,"rating": 7.2,"votes": 11064,"running_times": 5640},{"title": "Orphan","year": 2009,"rating": 7,"votes": 160192,"running_times": 7380},{"title": "Oscar","year": 1991,"rating": 6.4,"votes": 25381,"running_times": 6540},{"title": "Oslo, 31. august","year": 2011,"rating": 7.6,"votes": 15463,"running_times": 5700},{"title": "Osmosis Jones","year": 2001,"rating": 6.3,"votes": 27537,"running_times": 5700},{"title": "Ouija","year": 2014,"rating": 4.5,"votes": 39770,"running_times": 5340},{"title": "Ouija: Origin of Evil","year": 2016,"rating": 6.1,"votes": 37746,"running_times": 5940},{"title": "Our Brand Is Crisis","year": 2015,"rating": 6.1,"votes": 16624,"running_times": 6420},{"title": "Our Idiot Brother","year": 2011,"rating": 6.4,"votes": 78146,"running_times": 5400},{"title": "Our Kind of Traitor","year": 2016,"rating": 6.2,"votes": 14386,"running_times": 6480},{"title": "Out Cold","year": 2001,"rating": 6.3,"votes": 15223,"running_times": 5520},{"title": "Out for Justice","year": 1991,"rating": 6,"votes": 18349,"running_times": 5460},{"title": "Out of Africa","year": 1985,"rating": 7.2,"votes": 58200,"running_times": 9660},{"title": "Out of Rosenheim","year": 1987,"rating": 7.5,"votes": 10376,"running_times": 6480},{"title": "Out of Sight","year": 1998,"rating": 7,"votes": 75694,"running_times": 7380},{"title": "Out of Time","year": 2003,"rating": 6.5,"votes": 49592,"running_times": 6840},{"title": "Out of the Furnace","year": 2013,"rating": 6.8,"votes": 92039,"running_times": 6960},{"title": "Out of the Past","year": 1947,"rating": 8.1,"votes": 26203,"running_times": 5820},{"title": "Outbreak","year": 1995,"rating": 6.6,"votes": 96205,"running_times": 7620},{"title": "Outcast","year": 2014,"rating": 4.6,"votes": 10400,"running_times": 5940},{"title": "Outland","year": 1981,"rating": 6.6,"votes": 23324,"running_times": 6720},{"title": "Outlander","year": 2008,"rating": 6.3,"votes": 66588,"running_times": 6900},{"title": "Outlaw","year": 2007,"rating": 5.8,"votes": 11667,"running_times": 6180},{"title": "Outpost","year": 2008,"rating": 5.9,"votes": 14748,"running_times": 5400},{"title": "Outsourced","year": 2006,"rating": 7,"votes": 10317,"running_times": 6180},{"title": "Over Her Dead Body","year": 2008,"rating": 5.2,"votes": 22239,"running_times": 5700},{"title": "Over the Hedge","year": 2006,"rating": 6.7,"votes": 137721,"running_times": 4980},{"title": "Over the Top","year": 1987,"rating": 5.7,"votes": 41447,"running_times": 5580},{"title": "Overboard","year": 1987,"rating": 6.8,"votes": 41039,"running_times": 6720},{"title": "Owning Mahowny","year": 2003,"rating": 7.1,"votes": 11196,"running_times": 6240},{"title": "Oz the Great and Powerful","year": 2013,"rating": 6.3,"votes": 184733,"running_times": 7800},{"title": "P.S. I Love You","year": 2007,"rating": 7.1,"votes": 181630,"running_times": 7560},{"title": "P2","year": 2007,"rating": 5.9,"votes": 27730,"running_times": 5880},{"title": "PCU","year": 1994,"rating": 6.6,"votes": 11008,"running_times": 4740},{"title": "PK","year": 2014,"rating": 8.2,"votes": 114769,"running_times": 9180},{"title": "Pacific Heights","year": 1990,"rating": 6.4,"votes": 15273,"running_times": 6120},{"title": "Pacific Rim","year": 2013,"rating": 7,"votes": 411837,"running_times": 7860},{"title": "Paddington","year": 2014,"rating": 7.2,"votes": 59473,"running_times": 5700},{"title": "Pain & Gain","year": 2013,"rating": 6.4,"votes": 174254,"running_times": 7740},{"title": "Paint Your Wagon","year": 1969,"rating": 6.7,"votes": 10108,"running_times": 9480},{"title": "Pale Rider","year": 1985,"rating": 7.3,"votes": 43605,"running_times": 6900},{"title": "Palindromes","year": 2004,"rating": 6.8,"votes": 11200,"running_times": 6000},{"title": "Palo Alto","year": 2013,"rating": 6.3,"votes": 23349,"running_times": 6000},{"title": "Pan","year": 2015,"rating": 5.8,"votes": 50647,"running_times": 6660},{"title": "Pandorum","year": 2009,"rating": 6.8,"votes": 130076,"running_times": 6480},{"title": "Panic Room","year": 2002,"rating": 6.8,"votes": 222719,"running_times": 6780},{"title": "Paparazzi","year": 2004,"rating": 5.8,"votes": 13659,"running_times": 5040},{"title": "Paper Man","year": 2009,"rating": 6.6,"votes": 16527,"running_times": 6600},{"title": "Paper Moon","year": 1973,"rating": 8.2,"votes": 27816,"running_times": 6120},{"title": "Paper Towns","year": 2015,"rating": 6.3,"votes": 78166,"running_times": 6540},{"title": "Paperman","year": 2012,"rating": 8.3,"votes": 27834,"running_times": 420},{"title": "Papillon","year": 1973,"rating": 8,"votes": 103847,"running_times": 9060},{"title": "Papurika","year": 2006,"rating": 7.7,"votes": 52914,"running_times": 5400},{"title": "ParaNorman","year": 2012,"rating": 7,"votes": 80672,"running_times": 5520},{"title": "Paradise Lost: The Child Murders at Robin Hood Hills","year": 1996,"rating": 8.3,"votes": 12193,"running_times": 9000},{"title": "Paradise Now","year": 2005,"rating": 7.5,"votes": 20638,"running_times": 5400},{"title": "Parallels","year": 2015,"rating": 6.2,"votes": 11937,"running_times": 4980},{"title": "Paranoia","year": 2013,"rating": 5.7,"votes": 31219,"running_times": 6360},{"title": "Paranoid Park","year": 2007,"rating": 6.7,"votes": 26408,"running_times": 5100},{"title": "Paranormal Activity","year": 2007,"rating": 6.3,"votes": 197558,"running_times": 5820},{"title": "Paranormal Activity 2","year": 2010,"rating": 5.7,"votes": 88097,"running_times": 5880},{"title": "Paranormal Activity 3","year": 2011,"rating": 5.8,"votes": 81597,"running_times": 5640},{"title": "Paranormal Activity 4","year": 2012,"rating": 4.6,"votes": 54864,"running_times": 5760},{"title": "Paranormal Activity: The Ghost Dimension","year": 2015,"rating": 4.6,"votes": 19766,"running_times": 5820},{"title": "Paranormal Activity: The Marked Ones","year": 2014,"rating": 5,"votes": 34682,"running_times": 6060},{"title": "Parental Guidance","year": 2012,"rating": 6.1,"votes": 22572,"running_times": 6300},{"title": "Parenthood","year": 1989,"rating": 7,"votes": 38263,"running_times": 7440},{"title": "Paris, Texas","year": 1984,"rating": 8.1,"votes": 59559,"running_times": 8700},{"title": "Paris, je t'aime","year": 2006,"rating": 7.3,"votes": 65668,"running_times": 7200},{"title": "Parker","year": 2013,"rating": 6.2,"votes": 98698,"running_times": 7080},{"title": "Parkland","year": 2013,"rating": 6.4,"votes": 12999,"running_times": 5580},{"title": "Party Monster","year": 2003,"rating": 6.3,"votes": 13409,"running_times": 5880},{"title": "Passenger 57","year": 1992,"rating": 5.8,"votes": 39514,"running_times": 5040},{"title": "Passengers","year": 2008,"rating": 5.9,"votes": 30068,"running_times": 5580},{"title": "Passengers","year": 2016,"rating": 7,"votes": 252052,"running_times": 6960},{"title": "Passion","year": 2012,"rating": 5.3,"votes": 18568,"running_times": 6120},{"title": "Pat Garrett & Billy the Kid","year": 1973,"rating": 7.4,"votes": 14838,"running_times": 7320},{"title": "Patch Adams","year": 1998,"rating": 6.7,"votes": 87776,"running_times": 6900},{"title": "Paterson","year": 2016,"rating": 7.4,"votes": 40047,"running_times": 7080},{"title": "Pathfinder","year": 2007,"rating": 5.4,"votes": 39123,"running_times": 6420},{"title": "Pathology","year": 2008,"rating": 6,"votes": 28272,"running_times": 5700},{"title": "Paths of Glory","year": 1957,"rating": 8.4,"votes": 137012,"running_times": 5280},{"title": "Patriot Games","year": 1992,"rating": 6.9,"votes": 87400,"running_times": 7020},{"title": "Patriots Day","year": 2016,"rating": 7.4,"votes": 56247,"running_times": 7980},{"title": "Patton","year": 1970,"rating": 8,"votes": 82663,"running_times": 10320},{"title": "Paul","year": 2011,"rating": 7,"votes": 207118,"running_times": 6540},{"title": "Paul Blart: Mall Cop","year": 2009,"rating": 5.2,"votes": 90028,"running_times": 5460},{"title": "Paul Blart: Mall Cop 2","year": 2015,"rating": 4.4,"votes": 27660,"running_times": 5640},{"title": "Paulie","year": 1998,"rating": 6.5,"votes": 12631,"running_times": 5460},{"title": "Paura nella città dei morti viventi","year": 1980,"rating": 6.3,"votes": 12796,"running_times": 5580},{"title": "Pawn Sacrifice","year": 2014,"rating": 7,"votes": 30186,"running_times": 6900},{"title": "Pay It Forward","year": 2000,"rating": 7.2,"votes": 102406,"running_times": 7380},{"title": "Pay the Ghost","year": 2015,"rating": 5.2,"votes": 12141,"running_times": 5640},{"title": "Payback","year": 1999,"rating": 7.1,"votes": 118738,"running_times": 6000},{"title": "Paycheck","year": 2003,"rating": 6.3,"votes": 94288,"running_times": 7140},{"title": "Peaceful Warrior","year": 2006,"rating": 7.3,"votes": 22771,"running_times": 7200},{"title": "Pearl Harbor","year": 2001,"rating": 6.1,"votes": 275248,"running_times": 11040},{"title": "Pecker","year": 1998,"rating": 6.4,"votes": 12166,"running_times": 5220},{"title": "Pee-wee's Big Adventure","year": 1985,"rating": 7,"votes": 43899,"running_times": 5460},{"title": "Peeping Tom","year": 1960,"rating": 7.7,"votes": 24338,"running_times": 6060},{"title": "Peggy Sue Got Married","year": 1986,"rating": 6.3,"votes": 28771,"running_times": 6180},{"title": "Pelé: Birth of a Legend","year": 2016,"rating": 7.3,"votes": 10201,"running_times": 6420},{"title": "Penelope","year": 2006,"rating": 6.8,"votes": 54278,"running_times": 6240},{"title": "Penguins of Madagascar","year": 2014,"rating": 6.7,"votes": 67051,"running_times": 5520},{"title": "People I Know","year": 2002,"rating": 5.5,"votes": 10276,"running_times": 6000},{"title": "People Like Us","year": 2012,"rating": 7.1,"votes": 36939,"running_times": 6840},{"title": "Percy Jackson & the Olympians: The Lightning Thief","year": 2010,"rating": 5.9,"votes": 153720,"running_times": 7080},{"title": "Percy Jackson: Sea of Monsters","year": 2013,"rating": 5.9,"votes": 94873,"running_times": 6360},{"title": "Perfect Sense","year": 2011,"rating": 7.1,"votes": 47213,"running_times": 5520},{"title": "Perfect Stranger","year": 2007,"rating": 5.7,"votes": 39925,"running_times": 6540},{"title": "Perfume: The Story of a Murderer","year": 2006,"rating": 7.5,"votes": 205252,"running_times": 8820},{"title": "Persepolis","year": 2007,"rating": 8.1,"votes": 76676,"running_times": 5760},{"title": "Persona","year": 1966,"rating": 8.1,"votes": 72326,"running_times": 5100},{"title": "Personal Shopper","year": 2016,"rating": 6.2,"votes": 19478,"running_times": 6300},{"title": "Pet","year": 2016,"rating": 5.7,"votes": 11079,"running_times": 5640},{"title": "Pet Sematary","year": 1989,"rating": 6.6,"votes": 71858,"running_times": 6180},{"title": "Pet Sematary II","year": 1992,"rating": 4.8,"votes": 14806,"running_times": 6000},{"title": "Pete's Dragon","year": 1977,"rating": 6.4,"votes": 19167,"running_times": 7800},{"title": "Pete's Dragon","year": 2016,"rating": 6.7,"votes": 42488,"running_times": 6120},{"title": "Peter Pan","year": 1953,"rating": 7.3,"votes": 99989,"running_times": 4620},{"title": "Peter Pan","year": 2003,"rating": 6.9,"votes": 57870,"running_times": 6780},{"title": "Phantasm","year": 1979,"rating": 6.8,"votes": 25806,"running_times": 5280},{"title": "Phantasm II","year": 1988,"rating": 6.5,"votes": 10962,"running_times": 5820},{"title": "Phantom","year": 2013,"rating": 5.9,"votes": 12224,"running_times": 5880},{"title": "Phantom of the Paradise","year": 1974,"rating": 7.4,"votes": 12668,"running_times": 5520},{"title": "Phantoms","year": 1998,"rating": 5.4,"votes": 17351,"running_times": 5760},{"title": "Phenomena","year": 1985,"rating": 6.9,"votes": 18132,"running_times": 6960},{"title": "Phenomenon","year": 1996,"rating": 6.4,"votes": 67376,"running_times": 7380},{"title": "Philadelphia","year": 1993,"rating": 7.7,"votes": 193319,"running_times": 7500},{"title": "Philomena","year": 2013,"rating": 7.6,"votes": 83559,"running_times": 5880},{"title": "Phoenix","year": 2014,"rating": 7.3,"votes": 12924,"running_times": 5880},{"title": "Phone Booth","year": 2002,"rating": 7.1,"votes": 224082,"running_times": 4860},{"title": "Pi","year": 1998,"rating": 7.5,"votes": 153048,"running_times": 5040},{"title": "Pickup on South Street","year": 1953,"rating": 7.8,"votes": 10140,"running_times": 4800},{"title": "Picnic at Hanging Rock","year": 1975,"rating": 7.6,"votes": 27566,"running_times": 6900},{"title": "Picture Perfect","year": 1997,"rating": 5.5,"votes": 17051,"running_times": 6300},{"title": "Pieces of April","year": 2003,"rating": 7.1,"votes": 18663,"running_times": 4800},{"title": "Pierrot le fou","year": 1965,"rating": 7.7,"votes": 22303,"running_times": 6600},{"title": "Pillow Talk","year": 1959,"rating": 7.5,"votes": 12447,"running_times": 6120},{"title": "Pina","year": 2011,"rating": 7.7,"votes": 12632,"running_times": 6180},{"title": "Pineapple Express","year": 2008,"rating": 7,"votes": 275544,"running_times": 7020},{"title": "Pink","year": 2016,"rating": 8.2,"votes": 25888,"running_times": 8160},{"title": "Pink Flamingos","year": 1972,"rating": 6.1,"votes": 18394,"running_times": 6480},{"title": "Pink Floyd: The Wall","year": 1982,"rating": 8,"votes": 65194,"running_times": 5700},{"title": "Pinocchio","year": 1940,"rating": 7.5,"votes": 103226,"running_times": 5280},{"title": "Piper","year": 2016,"rating": 8.4,"votes": 18635,"running_times": 360},{"title": "Piranha","year": 1978,"rating": 5.9,"votes": 15470,"running_times": 6360},{"title": "Piranha 3D","year": 2010,"rating": 5.5,"votes": 77156,"running_times": 5280},{"title": "Piranha 3DD","year": 2012,"rating": 3.8,"votes": 34412,"running_times": 4980},{"title": "Pirates of the Caribbean: At World's End","year": 2007,"rating": 7.1,"votes": 519696,"running_times": 10140},{"title": "Pirates of the Caribbean: Dead Man's Chest","year": 2006,"rating": 7.3,"votes": 573617,"running_times": 9060},{"title": "Pirates of the Caribbean: Dead Men Tell No Tales","year": 2017,"rating": 6.7,"votes": 163797,"running_times": 7740},{"title": "Pirates of the Caribbean: On Stranger Tides","year": 2011,"rating": 6.6,"votes": 414326,"running_times": 8220},{"title": "Pirates of the Caribbean: The Curse of the Black Pearl","year": 2003,"rating": 8,"votes": 897059,"running_times": 8580},{"title": "Pit and the Pendulum","year": 1961,"rating": 7.1,"votes": 10125,"running_times": 4800},{"title": "Pitch Black","year": 2000,"rating": 7.1,"votes": 204768,"running_times": 6720},{"title": "Pitch Perfect","year": 2012,"rating": 7.2,"votes": 234523,"running_times": 6720},{"title": "Pitch Perfect 2","year": 2015,"rating": 6.4,"votes": 114324,"running_times": 6900},{"title": "Pixels","year": 2015,"rating": 5.6,"votes": 107829,"running_times": 6300},{"title": "Plan 9 from Outer Space","year": 1959,"rating": 4,"votes": 31677,"running_times": 4740},{"title": "Planes","year": 2013,"rating": 5.7,"votes": 37645,"running_times": 5460},{"title": "Planes, Trains & Automobiles","year": 1987,"rating": 7.6,"votes": 100740,"running_times": 5580},{"title": "Planes: Fire & Rescue","year": 2014,"rating": 6,"votes": 13931,"running_times": 4980},{"title": "Planet 51","year": 2009,"rating": 6.1,"votes": 44168,"running_times": 5460},{"title": "Planet Terror","year": 2007,"rating": 7.1,"votes": 178980,"running_times": 6300},{"title": "Planet of the Apes","year": 1968,"rating": 8,"votes": 147852,"running_times": 6900},{"title": "Planet of the Apes","year": 2001,"rating": 5.7,"votes": 192073,"running_times": 7140},{"title": "Platoon","year": 1986,"rating": 8.1,"votes": 321392,"running_times": 7200},{"title": "Play It Again, Sam","year": 1972,"rating": 7.7,"votes": 21490,"running_times": 5100},{"title": "Play It to the Bone","year": 1999,"rating": 5.4,"votes": 10608,"running_times": 7440},{"title": "Play Misty for Me","year": 1971,"rating": 7,"votes": 21050,"running_times": 6120},{"title": "Playing It Cool","year": 2014,"rating": 6,"votes": 19829,"running_times": 5640},{"title": "Playing by Heart","year": 1998,"rating": 7.2,"votes": 17228,"running_times": 7260},{"title": "Playing for Keeps","year": 2012,"rating": 5.7,"votes": 25958,"running_times": 6300},{"title": "Playtime","year": 1967,"rating": 8,"votes": 14743,"running_times": 9300},{"title": "Pleasantville","year": 1998,"rating": 7.5,"votes": 109185,"running_times": 7440},{"title": "Please Give","year": 2010,"rating": 6.6,"votes": 10282,"running_times": 5220},{"title": "Pledge This!","year": 2006,"rating": 1.9,"votes": 16019,"running_times": 5460},{"title": "Plein soleil","year": 1960,"rating": 7.8,"votes": 10567,"running_times": 7080},{"title": "Pocahontas","year": 1995,"rating": 6.7,"votes": 136066,"running_times": 5040},{"title": "Point Blank","year": 1967,"rating": 7.4,"votes": 15037,"running_times": 5520},{"title": "Point Break","year": 1991,"rating": 7.2,"votes": 125538,"running_times": 7320},{"title": "Point Break","year": 2015,"rating": 5.3,"votes": 47981,"running_times": 6840},{"title": "Point of No Return","year": 1993,"rating": 6,"votes": 21871,"running_times": 6540},{"title": "Poison Ivy","year": 1992,"rating": 5.4,"votes": 14868,"running_times": 5580},{"title": "Police Academy","year": 1984,"rating": 6.7,"votes": 96285,"running_times": 5760},{"title": "Police Academy 2: Their First Assignment","year": 1985,"rating": 5.7,"votes": 43178,"running_times": 5220},{"title": "Police Academy 3: Back in Training","year": 1986,"rating": 5.3,"votes": 35865,"running_times": 4980},{"title": "Police Academy 4: Citizens on Patrol","year": 1987,"rating": 4.8,"votes": 34317,"running_times": 5280},{"title": "Police Academy 5: Assignment: Miami Beach","year": 1988,"rating": 4.4,"votes": 27792,"running_times": 5400},{"title": "Police Academy 6: City Under Siege","year": 1989,"rating": 4.2,"votes": 23963,"running_times": 5040},{"title": "Police Academy: Mission to Moscow","year": 1994,"rating": 3.3,"votes": 26893,"running_times": 4980},{"title": "Politiki kouzina","year": 2003,"rating": 7.6,"votes": 11043,"running_times": 6480},{"title": "Pollock","year": 2000,"rating": 7,"votes": 24386,"running_times": 7920},{"title": "Poltergeist","year": 1982,"rating": 7.4,"votes": 118112,"running_times": 7200},{"title": "Poltergeist","year": 2015,"rating": 4.9,"votes": 48044,"running_times": 6060},{"title": "Poltergeist II: The Other Side","year": 1986,"rating": 5.7,"votes": 20967,"running_times": 7800},{"title": "Poltergeist III","year": 1988,"rating": 4.6,"votes": 14343,"running_times": 5880},{"title": "Pompeii","year": 2014,"rating": 5.5,"votes": 93779,"running_times": 6300},{"title": "Pontypool","year": 2008,"rating": 6.7,"votes": 24835,"running_times": 5700},{"title": "Pootie Tang","year": 2001,"rating": 5.2,"votes": 12089,"running_times": 4860},{"title": "Popeye","year": 1980,"rating": 5.2,"votes": 25242,"running_times": 6840},{"title": "Popstar: Never Stop Never Stopping","year": 2016,"rating": 6.7,"votes": 36918,"running_times": 5220},{"title": "Porky's","year": 1981,"rating": 6.2,"votes": 33257,"running_times": 5640},{"title": "Poseidon","year": 2006,"rating": 5.6,"votes": 87174,"running_times": 5880},{"title": "Possession","year": 1981,"rating": 7.4,"votes": 16899,"running_times": 7440},{"title": "Possession","year": 2002,"rating": 6.4,"votes": 12023,"running_times": 6120},{"title": "Post Grad","year": 2009,"rating": 5.3,"votes": 12427,"running_times": 5280},{"title": "Postal","year": 2007,"rating": 4.5,"votes": 20844,"running_times": 7620},{"title": "Postcards from the Edge","year": 1990,"rating": 6.7,"votes": 12982,"running_times": 6060},{"title": "Powder","year": 1995,"rating": 6.6,"votes": 25831,"running_times": 6660},{"title": "Powder Blue","year": 2009,"rating": 6.3,"votes": 12943,"running_times": 6900},{"title": "Power Rangers","year": 2017,"rating": 6.1,"votes": 72174,"running_times": 7440},{"title": "Practical Magic","year": 1998,"rating": 6.2,"votes": 61056,"running_times": 6240},{"title": "Precious","year": 2009,"rating": 7.3,"votes": 94382,"running_times": 6600},{"title": "Predator","year": 1987,"rating": 7.8,"votes": 316518,"running_times": 6420},{"title": "Predator 2","year": 1990,"rating": 6.2,"votes": 118584,"running_times": 6480},{"title": "Predators","year": 2010,"rating": 6.4,"votes": 184408,"running_times": 6420},{"title": "Predestination","year": 2014,"rating": 7.5,"votes": 201124,"running_times": 5820},{"title": "Prem Ratan Dhan Payo","year": 2015,"rating": 4.7,"votes": 13854,"running_times": 11040},{"title": "Premium Rush","year": 2012,"rating": 6.5,"votes": 100986,"running_times": 5460},{"title": "Premonition","year": 2007,"rating": 5.9,"votes": 65837,"running_times": 5760},{"title": "Presto","year": 2008,"rating": 8.4,"votes": 18991,"running_times": 300},{"title": "Presumed Innocent","year": 1990,"rating": 6.9,"votes": 31863,"running_times": 7620},{"title": "Pretty Woman","year": 1990,"rating": 7,"votes": 236465,"running_times": 7500},{"title": "Pretty in Pink","year": 1986,"rating": 6.8,"votes": 61371,"running_times": 5760},{"title": "Pride & Prejudice","year": 2005,"rating": 7.8,"votes": 211990,"running_times": 8100},{"title": "Pride","year": 2014,"rating": 7.8,"votes": 41996,"running_times": 7140},{"title": "Pride and Glory","year": 2008,"rating": 6.7,"votes": 55332,"running_times": 7800},{"title": "Pride and Prejudice and Zombies","year": 2016,"rating": 5.8,"votes": 38692,"running_times": 6480},{"title": "Priest","year": 2011,"rating": 5.7,"votes": 102900,"running_times": 5220},{"title": "Primal Fear","year": 1996,"rating": 7.7,"votes": 146913,"running_times": 7740},{"title": "Primary Colors","year": 1998,"rating": 6.7,"votes": 24922,"running_times": 8580},{"title": "Prime","year": 2005,"rating": 6.2,"votes": 36846,"running_times": 6300},{"title": "Primer","year": 2004,"rating": 6.9,"votes": 82678,"running_times": 4620},{"title": "Primeval","year": 2007,"rating": 4.7,"votes": 11690,"running_times": 5580},{"title": "Prince Avalanche","year": 2013,"rating": 6.4,"votes": 16895,"running_times": 5640},{"title": "Prince of Darkness","year": 1987,"rating": 6.7,"votes": 28609,"running_times": 6120},{"title": "Prince of Persia: The Sands of Time","year": 2010,"rating": 6.6,"votes": 239656,"running_times": 6960},{"title": "Prisoners","year": 2013,"rating": 8.1,"votes": 460550,"running_times": 9180},{"title": "Private Benjamin","year": 1980,"rating": 6.1,"votes": 19888,"running_times": 6540},{"title": "Private Parts","year": 1997,"rating": 6.8,"votes": 30894,"running_times": 6540},{"title": "Prizzi's Honor","year": 1985,"rating": 6.8,"votes": 19835,"running_times": 7800},{"title": "Problem Child","year": 1990,"rating": 5.3,"votes": 24246,"running_times": 5580},{"title": "Problem Child 2","year": 1991,"rating": 4.6,"votes": 18047,"running_times": 5580},{"title": "Professione: reporter","year": 1975,"rating": 7.6,"votes": 16673,"running_times": 7560},{"title": "Project Almanac","year": 2015,"rating": 6.4,"votes": 66044,"running_times": 6360},{"title": "Project X","year": 2012,"rating": 6.7,"votes": 168277,"running_times": 5580},{"title": "Prom","year": 2011,"rating": 5.4,"votes": 13556,"running_times": 6240},{"title": "Prom Night","year": 1980,"rating": 5.4,"votes": 11621,"running_times": 5520},{"title": "Prom Night","year": 2008,"rating": 3.9,"votes": 29693,"running_times": 5340},{"title": "Prometheus","year": 2012,"rating": 7,"votes": 508408,"running_times": 7440},{"title": "Promised Land","year": 2012,"rating": 6.6,"votes": 32498,"running_times": 6360},{"title": "Proof","year": 2005,"rating": 6.8,"votes": 38792,"running_times": 6000},{"title": "Proof of Life","year": 2000,"rating": 6.2,"votes": 51236,"running_times": 8100},{"title": "Prozac Nation","year": 2001,"rating": 6.3,"votes": 15523,"running_times": 5940},{"title": "Prêt-à-Porter","year": 1994,"rating": 5.1,"votes": 13074,"running_times": 7980},{"title": "Psycho","year": 1960,"rating": 8.5,"votes": 476643,"running_times": 6540},{"title": "Psycho","year": 1998,"rating": 4.6,"votes": 40252,"running_times": 6300},{"title": "Psycho II","year": 1983,"rating": 6.4,"votes": 18625,"running_times": 6780},{"title": "Psycho III","year": 1986,"rating": 5.3,"votes": 10195,"running_times": 5580},{"title": "Public Enemies","year": 2009,"rating": 7,"votes": 246492,"running_times": 8400},{"title": "Pulp Fiction","year": 1994,"rating": 8.9,"votes": 1477112,"running_times": 10680},{"title": "Pulse","year": 2006,"rating": 4.7,"votes": 26072,"running_times": 5400},{"title": "Pump Up the Volume","year": 1990,"rating": 7.2,"votes": 22894,"running_times": 6120},{"title": "Pumping Iron","year": 1977,"rating": 7.4,"votes": 18176,"running_times": 5100},{"title": "Pumpkinhead","year": 1988,"rating": 6.2,"votes": 16002,"running_times": 5160},{"title": "Punch-Drunk Love","year": 2002,"rating": 7.3,"votes": 120491,"running_times": 5700},{"title": "Puncture","year": 2011,"rating": 6.9,"votes": 20440,"running_times": 6000},{"title": "Punisher: War Zone","year": 2008,"rating": 6,"votes": 53355,"running_times": 6180},{"title": "Purple Rain","year": 1984,"rating": 6.5,"votes": 16275,"running_times": 6660},{"title": "Push","year": 2009,"rating": 6.1,"votes": 95978,"running_times": 6660},{"title": "Pushing Tin","year": 1999,"rating": 6,"votes": 25855,"running_times": 7440},{"title": "Puss in Boots","year": 2011,"rating": 6.7,"votes": 123808,"running_times": 5400},{"title": "Quadrophenia","year": 1979,"rating": 7.3,"votes": 14308,"running_times": 7200},{"title": "Quantum of Solace","year": 2008,"rating": 6.6,"votes": 356741,"running_times": 6360},{"title": "Quarantine","year": 2008,"rating": 6,"votes": 61636,"running_times": 5340},{"title": "Quarantine 2: Terminal","year": 2011,"rating": 5.2,"votes": 16236,"running_times": 5160},{"title": "Quartet","year": 2012,"rating": 6.8,"votes": 16936,"running_times": 5640},{"title": "Queen","year": 2013,"rating": 8.3,"votes": 49130,"running_times": 8760},{"title": "Queen of the Damned","year": 2002,"rating": 5.3,"votes": 46758,"running_times": 6240},{"title": "Quest for Camelot","year": 1998,"rating": 6.3,"votes": 12346,"running_times": 5160},{"title": "Quick Change","year": 1990,"rating": 6.8,"votes": 17040,"running_times": 5340},{"title": "Quigley Down Under","year": 1990,"rating": 6.8,"votes": 16366,"running_times": 7140},{"title": "Quills","year": 2000,"rating": 7.3,"votes": 47045,"running_times": 7440},{"title": "Quiz Show","year": 1994,"rating": 7.5,"votes": 57548,"running_times": 7980},{"title": "Quo Vadis","year": 1951,"rating": 7.2,"votes": 10998,"running_times": 10260},{"title": "R.I.P.D.","year": 2013,"rating": 5.6,"votes": 100458,"running_times": 5760},{"title": "RED","year": 2010,"rating": 7.1,"votes": 256610,"running_times": 6660},{"title": "RED 2","year": 2013,"rating": 6.7,"votes": 138032,"running_times": 6960},{"title": "RV","year": 2006,"rating": 5.5,"votes": 49630,"running_times": 5940},{"title": "Ra.One","year": 2011,"rating": 4.8,"votes": 33460,"running_times": 9360},{"title": "Raajneeti","year": 2010,"rating": 7.1,"votes": 13482,"running_times": 9780},{"title": "Rabbit Hole","year": 2010,"rating": 7,"votes": 43298,"running_times": 5460},{"title": "Rabbit-Proof Fence","year": 2002,"rating": 7.5,"votes": 24721,"running_times": 5640},{"title": "Rabid","year": 1977,"rating": 6.4,"votes": 11872,"running_times": 5460},{"title": "Race","year": 2016,"rating": 7.1,"votes": 26655,"running_times": 8040},{"title": "Race to Witch Mountain","year": 2009,"rating": 5.7,"votes": 47231,"running_times": 5880},{"title": "Rachel Getting Married","year": 2008,"rating": 6.7,"votes": 43171,"running_times": 6780},{"title": "Racing Stripes","year": 2005,"rating": 5.2,"votes": 13663,"running_times": 6120},{"title": "Radio","year": 2003,"rating": 6.9,"votes": 34113,"running_times": 6540},{"title": "Radio Days","year": 1987,"rating": 7.6,"votes": 26747,"running_times": 5280},{"title": "Radio Flyer","year": 1992,"rating": 6.9,"votes": 11027,"running_times": 6840},{"title": "Raging Bull","year": 1980,"rating": 8.2,"votes": 260123,"running_times": 7740},{"title": "Raiders of the Lost Ark","year": 1981,"rating": 8.5,"votes": 733003,"running_times": 6900},{"title": "Rain Man","year": 1988,"rating": 8,"votes": 412533,"running_times": 7980},{"title": "Raise Your Voice","year": 2004,"rating": 5.9,"votes": 24163,"running_times": 6180},{"title": "Raising Arizona","year": 1987,"rating": 7.4,"votes": 108635,"running_times": 5640},{"title": "Raising Cain","year": 1992,"rating": 6,"votes": 11138,"running_times": 5460},{"title": "Raising Helen","year": 2004,"rating": 6,"votes": 32625,"running_times": 7140},{"title": "Rambo","year": 2008,"rating": 7,"votes": 191441,"running_times": 5940},{"title": "Rambo III","year": 1988,"rating": 5.7,"votes": 100754,"running_times": 6120},{"title": "Rambo: First Blood Part II","year": 1985,"rating": 6.4,"votes": 127949,"running_times": 5760},{"title": "Ramona and Beezus","year": 2010,"rating": 6.6,"votes": 14941,"running_times": 6180},{"title": "Rampage","year": 2009,"rating": 6.3,"votes": 16303,"running_times": 5100},{"title": "Rampart","year": 2011,"rating": 5.8,"votes": 21024,"running_times": 6480},{"title": "Random Hearts","year": 1999,"rating": 5.1,"votes": 17900,"running_times": 7980},{"title": "Rang De Basanti","year": 2006,"rating": 8.3,"votes": 85999,"running_times": 9420},{"title": "Rango","year": 2011,"rating": 7.2,"votes": 200511,"running_times": 6420},{"title": "Ransom","year": 1996,"rating": 6.6,"votes": 105375,"running_times": 8340},{"title": "Rare Exports","year": 2010,"rating": 6.7,"votes": 21947,"running_times": 5040},{"title": "Rat Race","year": 2001,"rating": 6.4,"votes": 98259,"running_times": 6720},{"title": "Ratatouille","year": 2007,"rating": 8,"votes": 523106,"running_times": 6660},{"title": "Ravenous","year": 1999,"rating": 7,"votes": 32355,"running_times": 6060},{"title": "Raw Deal","year": 1986,"rating": 5.5,"votes": 25144,"running_times": 6360},{"title": "Ray","year": 2004,"rating": 7.7,"votes": 119531,"running_times": 10680},{"title": "Re-Animator","year": 1985,"rating": 7.2,"votes": 45022,"running_times": 6300},{"title": "Ready","year": 2011,"rating": 4.7,"votes": 12187,"running_times": 8700},{"title": "Ready to Rumble","year": 2000,"rating": 5.3,"votes": 12339,"running_times": 6420},{"title": "Real Genius","year": 1985,"rating": 7,"votes": 25660,"running_times": 6480},{"title": "Real Steel","year": 2011,"rating": 7.1,"votes": 270279,"running_times": 7620},{"title": "Reality Bites","year": 1994,"rating": 6.6,"votes": 39032,"running_times": 5940},{"title": "Rear Window","year": 1954,"rating": 8.5,"votes": 355438,"running_times": 6720},{"title": "Reasonable Doubt","year": 2014,"rating": 5.7,"votes": 16005,"running_times": 5460},{"title": "Rebecca","year": 1940,"rating": 8.2,"votes": 97897,"running_times": 7800},{"title": "Rebel Without a Cause","year": 1955,"rating": 7.8,"votes": 69975,"running_times": 6660},{"title": "Rebound","year": 2005,"rating": 5.1,"votes": 11179,"running_times": 5340},{"title": "Red Corner","year": 1997,"rating": 6.3,"votes": 14011,"running_times": 7320},{"title": "Red Dawn","year": 1984,"rating": 6.4,"votes": 44560,"running_times": 6840},{"title": "Red Dawn","year": 2012,"rating": 5.4,"votes": 65921,"running_times": 5580},{"title": "Red Dog","year": 2011,"rating": 7.5,"votes": 14257,"running_times": 5520},{"title": "Red Dragon","year": 2002,"rating": 7.2,"votes": 217740,"running_times": 7440},{"title": "Red Eye","year": 2005,"rating": 6.5,"votes": 99780,"running_times": 5100},{"title": "Red Heat","year": 1988,"rating": 6,"votes": 54349,"running_times": 6240},{"title": "Red Lights","year": 2012,"rating": 6.2,"votes": 52128,"running_times": 6840},{"title": "Red Planet","year": 2000,"rating": 5.7,"votes": 50272,"running_times": 6360},{"title": "Red Riding Hood","year": 2011,"rating": 5.4,"votes": 97160,"running_times": 6000},{"title": "Red River","year": 1948,"rating": 7.8,"votes": 23384,"running_times": 7980},{"title": "Red Road","year": 2006,"rating": 6.8,"votes": 10717,"running_times": 6780},{"title": "Red Rock West","year": 1993,"rating": 7,"votes": 17017,"running_times": 5880},{"title": "Red Sonja","year": 1985,"rating": 5,"votes": 33004,"running_times": 5340},{"title": "Red State","year": 2011,"rating": 6.2,"votes": 56761,"running_times": 5280},{"title": "Red Tails","year": 2012,"rating": 5.9,"votes": 30318,"running_times": 7500},{"title": "Redbelt","year": 2008,"rating": 6.8,"votes": 19251,"running_times": 5940},{"title": "Redirected","year": 2014,"rating": 6.7,"votes": 31764,"running_times": 5940},{"title": "Reds","year": 1981,"rating": 7.5,"votes": 17827,"running_times": 11700},{"title": "Regarding Henry","year": 1991,"rating": 6.7,"votes": 25315,"running_times": 6480},{"title": "Regression","year": 2015,"rating": 5.7,"votes": 28731,"running_times": 6360},{"title": "Reign Over Me","year": 2007,"rating": 7.5,"votes": 87332,"running_times": 7440},{"title": "Reign of Fire","year": 2002,"rating": 6.2,"votes": 114037,"running_times": 6060},{"title": "Reindeer Games","year": 2000,"rating": 5.7,"votes": 33382,"running_times": 7440},{"title": "Religulous","year": 2008,"rating": 7.7,"votes": 54600,"running_times": 6060},{"title": "Remember","year": 2015,"rating": 7.4,"votes": 14905,"running_times": 5640},{"title": "Remember Me","year": 2010,"rating": 7.2,"votes": 122498,"running_times": 6780},{"title": "Remember the Titans","year": 2000,"rating": 7.8,"votes": 173395,"running_times": 7200},{"title": "Renaissance","year": 2006,"rating": 6.7,"votes": 14769,"running_times": 6300},{"title": "Renaissance Man","year": 1994,"rating": 6.1,"votes": 14806,"running_times": 7680},{"title": "Rendition","year": 2007,"rating": 6.8,"votes": 49989,"running_times": 7320},{"title": "Reno 911!: Miami","year": 2007,"rating": 5.9,"votes": 24620,"running_times": 5040},{"title": "Rent","year": 2005,"rating": 7,"votes": 44039,"running_times": 8280},{"title": "Replicant","year": 2001,"rating": 5.4,"votes": 12077,"running_times": 6000},{"title": "Repo Man","year": 1984,"rating": 6.9,"votes": 28026,"running_times": 5520},{"title": "Repo Men","year": 2010,"rating": 6.3,"votes": 92099,"running_times": 7140},{"title": "Repo! The Genetic Opera","year": 2008,"rating": 6.7,"votes": 21463,"running_times": 9000},{"title": "Repulsion","year": 1965,"rating": 7.8,"votes": 39557,"running_times": 6300},{"title": "Requiem for a Dream","year": 2000,"rating": 8.3,"votes": 639501,"running_times": 6120},{"title": "Rescue Dawn","year": 2006,"rating": 7.3,"votes": 90216,"running_times": 7200},{"title": "Reservation Road","year": 2007,"rating": 6.7,"votes": 19843,"running_times": 6120},{"title": "Reservoir Dogs","year": 1992,"rating": 8.3,"votes": 745833,"running_times": 5940},{"title": "Resident Evil","year": 2002,"rating": 6.7,"votes": 218227,"running_times": 6000},{"title": "Resident Evil: Afterlife","year": 2010,"rating": 5.9,"votes": 144971,"running_times": 5760},{"title": "Resident Evil: Apocalypse","year": 2004,"rating": 6.2,"votes": 166319,"running_times": 5880},{"title": "Resident Evil: Extinction","year": 2007,"rating": 6.3,"votes": 164112,"running_times": 5640},{"title": "Resident Evil: Retribution","year": 2012,"rating": 5.4,"votes": 118015,"running_times": 5700},{"title": "Resident Evil: The Final Chapter","year": 2016,"rating": 5.6,"votes": 61809,"running_times": 6420},{"title": "Restless","year": 2011,"rating": 6.8,"votes": 15983,"running_times": 5460},{"title": "Restrepo","year": 2010,"rating": 7.6,"votes": 18615,"running_times": 5580},{"title": "Resurrecting the Champ","year": 2007,"rating": 6.7,"votes": 19090,"running_times": 6720},{"title": "Return of the Living Dead III","year": 1993,"rating": 5.9,"votes": 11289,"running_times": 5820},{"title": "Return of the Living Dead: Part II","year": 1988,"rating": 5.8,"votes": 15201,"running_times": 5340},{"title": "Return to Me","year": 2000,"rating": 6.9,"votes": 17309,"running_times": 6900},{"title": "Return to Never Land","year": 2002,"rating": 5.8,"votes": 14877,"running_times": 4320},{"title": "Return to Oz","year": 1985,"rating": 6.7,"votes": 20915,"running_times": 6780},{"title": "Return to Paradise","year": 1998,"rating": 6.9,"votes": 12207,"running_times": 6660},{"title": "Return to the Blue Lagoon","year": 1991,"rating": 5.1,"votes": 15423,"running_times": 6120},{"title": "Revenge","year": 1990,"rating": 6.2,"votes": 13676,"running_times": 7440},{"title": "Revenge of the Nerds","year": 1984,"rating": 6.6,"votes": 42777,"running_times": 5400},{"title": "Revenge of the Nerds II: Nerds in Paradise","year": 1987,"rating": 5,"votes": 11544,"running_times": 5280},{"title": "Revenge of the Pink Panther","year": 1978,"rating": 6.7,"votes": 17146,"running_times": 5940},{"title": "Reversal of Fortune","year": 1990,"rating": 7.3,"votes": 12249,"running_times": 6660},{"title": "Revolutionary Road","year": 2008,"rating": 7.3,"votes": 164174,"running_times": 7140},{"title": "Revolver","year": 2005,"rating": 6.5,"votes": 79694,"running_times": 6660},{"title": "Richard III","year": 1995,"rating": 7.5,"votes": 12308,"running_times": 6600},{"title": "Ricki and the Flash","year": 2015,"rating": 6,"votes": 18749,"running_times": 6060},{"title": "Ricochet","year": 1991,"rating": 6.1,"votes": 13653,"running_times": 6120},{"title": "Riddick","year": 2013,"rating": 6.4,"votes": 135943,"running_times": 7620},{"title": "Ride Along","year": 2014,"rating": 6.2,"votes": 86287,"running_times": 5940},{"title": "Ride Along 2","year": 2016,"rating": 5.9,"votes": 41634,"running_times": 6120},{"title": "Ride the High Country","year": 1962,"rating": 7.6,"votes": 10117,"running_times": 5640},{"title": "Ride with the Devil","year": 1999,"rating": 6.8,"votes": 11657,"running_times": 8880},{"title": "Riding in Cars with Boys","year": 2001,"rating": 6.5,"votes": 24075,"running_times": 7920},{"title": "Rien à déclarer","year": 2010,"rating": 6.3,"votes": 11017,"running_times": 6480},{"title": "Right at Your Door","year": 2006,"rating": 6.2,"votes": 11536,"running_times": 5760},{"title": "Righteous Kill","year": 2008,"rating": 6,"votes": 76972,"running_times": 6060},{"title": "Rings","year": 2017,"rating": 4.5,"votes": 27042,"running_times": 6120},{"title": "Rio","year": 2011,"rating": 6.9,"votes": 178784,"running_times": 5760},{"title": "Rio 2","year": 2014,"rating": 6.3,"votes": 65342,"running_times": 6060},{"title": "Rio Bravo","year": 1959,"rating": 8,"votes": 46875,"running_times": 8460},{"title": "Rio Grande","year": 1950,"rating": 7.2,"votes": 11457,"running_times": 6300},{"title": "Ripley's Game","year": 2002,"rating": 6.7,"votes": 15479,"running_times": 6720},{"title": "Rise","year": 2007,"rating": 4.9,"votes": 10667,"running_times": 7320},{"title": "Rise of the Footsoldier","year": 2007,"rating": 6.9,"votes": 17199,"running_times": 7140},{"title": "Rise of the Guardians","year": 2012,"rating": 7.3,"votes": 134813,"running_times": 5820},{"title": "Rise of the Planet of the Apes","year": 2011,"rating": 7.6,"votes": 445858,"running_times": 6300},{"title": "Risen","year": 2016,"rating": 6.3,"votes": 19540,"running_times": 6420},{"title": "Rising Sun","year": 1993,"rating": 6.2,"votes": 37411,"running_times": 7740},{"title": "Risky Business","year": 1983,"rating": 6.8,"votes": 67266,"running_times": 5940},{"title": "Ritânâ","year": 2002,"rating": 6.5,"votes": 10556,"running_times": 6960},{"title": "River's Edge","year": 1986,"rating": 7.1,"votes": 13038,"running_times": 5940},{"title": "Ri¢hie Ri¢h","year": 1994,"rating": 5.3,"votes": 54239,"running_times": 5700},{"title": "Road House","year": 1989,"rating": 6.5,"votes": 47980,"running_times": 6840},{"title": "Road Trip","year": 2000,"rating": 6.5,"votes": 141478,"running_times": 5640},{"title": "Road to Perdition","year": 2002,"rating": 7.7,"votes": 215795,"running_times": 7020},{"title": "Rob Roy","year": 1995,"rating": 6.9,"votes": 36497,"running_times": 8340},{"title": "Robin Hood","year": 1973,"rating": 7.6,"votes": 93873,"running_times": 4980},{"title": "Robin Hood","year": 2010,"rating": 6.7,"votes": 226558,"running_times": 9360},{"title": "Robin Hood: Men in Tights","year": 1993,"rating": 6.7,"votes": 99320,"running_times": 6240},{"title": "Robin Hood: Prince of Thieves","year": 1991,"rating": 6.9,"votes": 155703,"running_times": 9300},{"title": "Robinson Crusoe","year": 1997,"rating": 5.9,"votes": 10501,"running_times": 6300},{"title": "RoboCop","year": 1987,"rating": 7.5,"votes": 198737,"running_times": 6180},{"title": "RoboCop","year": 2014,"rating": 6.2,"votes": 195203,"running_times": 7020},{"title": "RoboCop 2","year": 1990,"rating": 5.8,"votes": 69631,"running_times": 7020},{"title": "RoboCop 3","year": 1993,"rating": 4,"votes": 38462,"running_times": 6240},{"title": "Robot & Frank","year": 2012,"rating": 7.1,"votes": 56154,"running_times": 5340},{"title": "Robots","year": 2005,"rating": 6.3,"votes": 112952,"running_times": 5460},{"title": "Rock On!!","year": 2008,"rating": 7.8,"votes": 17454,"running_times": 8700},{"title": "Rock Star","year": 2001,"rating": 6.2,"votes": 36621,"running_times": 6300},{"title": "Rock of Ages","year": 2012,"rating": 5.9,"votes": 65978,"running_times": 8160},{"title": "Rocket Science","year": 2007,"rating": 6.7,"votes": 12132,"running_times": 6060},{"title": "RocknRolla","year": 2008,"rating": 7.3,"votes": 209034,"running_times": 6840},{"title": "Rocky","year": 1976,"rating": 8.1,"votes": 424316,"running_times": 8700},{"title": "Rocky Balboa","year": 2006,"rating": 7.2,"votes": 176163,"running_times": 8340},{"title": "Rocky II","year": 1979,"rating": 7.2,"votes": 154543,"running_times": 8520},{"title": "Rocky III","year": 1982,"rating": 6.8,"votes": 139274,"running_times": 5940},{"title": "Rocky IV","year": 1985,"rating": 6.8,"votes": 150879,"running_times": 6420},{"title": "Rocky V","year": 1990,"rating": 5.2,"votes": 103747,"running_times": 8160},{"title": "Roger & Me","year": 1989,"rating": 7.5,"votes": 23911,"running_times": 5460},{"title": "Roger Dodger","year": 2002,"rating": 7,"votes": 15871,"running_times": 6360},{"title": "Rogue","year": 2007,"rating": 6.2,"votes": 23552,"running_times": 5940},{"title": "Rogue One","year": 2016,"rating": 7.8,"votes": 386122,"running_times": 7980},{"title": "Role Models","year": 2008,"rating": 6.9,"votes": 203170,"running_times": 6060},{"title": "Rollerball","year": 1975,"rating": 6.6,"votes": 18882,"running_times": 7500},{"title": "Rollerball","year": 2002,"rating": 3,"votes": 23117,"running_times": 5880},{"title": "Roman Holiday","year": 1953,"rating": 8.1,"votes": 110260,"running_times": 7080},{"title": "Romance & Cigarettes","year": 2005,"rating": 6.3,"votes": 10506,"running_times": 6300},{"title": "Romancing the Stone","year": 1984,"rating": 6.9,"votes": 69846,"running_times": 6360},{"title": "Romeo + Juliet","year": 1996,"rating": 6.8,"votes": 182222,"running_times": 7200},{"title": "Romeo Is Bleeding","year": 1993,"rating": 6.6,"votes": 11503,"running_times": 6600},{"title": "Romeo Must Die","year": 2000,"rating": 6.1,"votes": 60228,"running_times": 6900},{"title": "Romeo and Juliet","year": 1968,"rating": 7.6,"votes": 25418,"running_times": 8940},{"title": "Romper Stomper","year": 1992,"rating": 6.8,"votes": 33659,"running_times": 5640},{"title": "Romy and Michele's High School Reunion","year": 1997,"rating": 6.2,"votes": 36333,"running_times": 5520},{"title": "Ronaldo","year": 2015,"rating": 6.4,"votes": 12330,"running_times": 6120},{"title": "Ronin","year": 1998,"rating": 7.3,"votes": 153925,"running_times": 7320},{"title": "Rookie of the Year","year": 1993,"rating": 5.9,"votes": 19871,"running_times": 6180},{"title": "Room","year": 2015,"rating": 8.2,"votes": 251090,"running_times": 7080},{"title": "Room 237","year": 2012,"rating": 6.2,"votes": 18379,"running_times": 6120},{"title": "Rope","year": 1948,"rating": 8,"votes": 105677,"running_times": 4800},{"title": "Rosemary's Baby","year": 1968,"rating": 8,"votes": 155168,"running_times": 8220},{"title": "Rosencrantz & Guildenstern Are Dead","year": 1990,"rating": 7.6,"votes": 18279,"running_times": 7020},{"title": "Rough Night","year": 2017,"rating": 5.2,"votes": 24406,"running_times": 6060},{"title": "Rounders","year": 1998,"rating": 7.3,"votes": 128998,"running_times": 7260},{"title": "Roxanne","year": 1987,"rating": 6.6,"votes": 35090,"running_times": 6420},{"title": "Ruang rak noi nid mahasan","year": 2003,"rating": 7.6,"votes": 10116,"running_times": 6720},{"title": "Rubber","year": 2010,"rating": 5.8,"votes": 28779,"running_times": 4920},{"title": "Ruby Sparks","year": 2012,"rating": 7.2,"votes": 86036,"running_times": 6240},{"title": "Rudderless","year": 2014,"rating": 7.5,"votes": 15129,"running_times": 6300},{"title": "Rudy","year": 1993,"rating": 7.5,"votes": 46289,"running_times": 6840},{"title": "Rules of Engagement","year": 2000,"rating": 6.4,"votes": 39708,"running_times": 7680},{"title": "Rumble Fish","year": 1983,"rating": 7.2,"votes": 26538,"running_times": 5640},{"title": "Rumor Has It...","year": 2005,"rating": 5.5,"votes": 44506,"running_times": 5820},{"title": "Run All Night","year": 2015,"rating": 6.6,"votes": 86466,"running_times": 6840},{"title": "Run Fatboy Run","year": 2007,"rating": 6.6,"votes": 61200,"running_times": 6000},{"title": "Runaway Bride","year": 1999,"rating": 5.5,"votes": 80848,"running_times": 6960},{"title": "Runaway Jury","year": 2003,"rating": 7.1,"votes": 81319,"running_times": 7620},{"title": "Runaway Train","year": 1985,"rating": 7.3,"votes": 22568,"running_times": 6660},{"title": "Runner Runner","year": 2013,"rating": 5.6,"votes": 55723,"running_times": 5280},{"title": "Running Scared","year": 2006,"rating": 7.4,"votes": 91408,"running_times": 7320},{"title": "Running on Empty","year": 1988,"rating": 7.7,"votes": 11450,"running_times": 6960},{"title": "Running with Scissors","year": 2006,"rating": 6.2,"votes": 20716,"running_times": 7320},{"title": "Rupan sansei: Kariosutoro no shiro","year": 1979,"rating": 7.8,"votes": 18456,"running_times": 6120},{"title": "Rush","year": 2013,"rating": 8.1,"votes": 355535,"running_times": 7380},{"title": "Rush Hour","year": 1998,"rating": 6.9,"votes": 204134,"running_times": 5880},{"title": "Rush Hour 2","year": 2001,"rating": 6.6,"votes": 173251,"running_times": 5640},{"title": "Rush Hour 3","year": 2007,"rating": 6.2,"votes": 131488,"running_times": 5460},{"title": "Rushmore","year": 1998,"rating": 7.7,"votes": 146456,"running_times": 5580},{"title": "Ruthless People","year": 1986,"rating": 6.9,"votes": 22745,"running_times": 5580},{"title": "S. Darko","year": 2009,"rating": 3.6,"votes": 11844,"running_times": 6180},{"title": "S.W.A.T.","year": 2003,"rating": 6,"votes": 126105,"running_times": 7020},{"title": "S1m0ne","year": 2002,"rating": 6.1,"votes": 54325,"running_times": 7020},{"title": "SLC Punk!","year": 1998,"rating": 7.5,"votes": 23433,"running_times": 5880},{"title": "Sabotage","year": 1936,"rating": 7.1,"votes": 12150,"running_times": 5400},{"title": "Sabotage","year": 2014,"rating": 5.7,"votes": 51832,"running_times": 6540},{"title": "Saboteur","year": 1942,"rating": 7.2,"votes": 19326,"running_times": 6540},{"title": "Sabrina","year": 1954,"rating": 7.7,"votes": 48886,"running_times": 6780},{"title": "Sabrina","year": 1995,"rating": 6.3,"votes": 31724,"running_times": 7620},{"title": "Safe","year": 2012,"rating": 6.5,"votes": 90797,"running_times": 5640},{"title": "Safe Haven","year": 2013,"rating": 6.7,"votes": 88397,"running_times": 6900},{"title": "Safe House","year": 2012,"rating": 6.8,"votes": 179229,"running_times": 6900},{"title": "Safety Last!","year": 1923,"rating": 8.2,"votes": 14595,"running_times": 4200},{"title": "Safety Not Guaranteed","year": 2012,"rating": 7,"votes": 107260,"running_times": 5160},{"title": "Sahara","year": 2005,"rating": 6,"votes": 82179,"running_times": 7440},{"title": "Saints and Soldiers","year": 2003,"rating": 6.8,"votes": 18629,"running_times": 5400},{"title": "Salinui chueok","year": 2003,"rating": 8.1,"votes": 82435,"running_times": 7920},{"title": "Salmon Fishing in the Yemen","year": 2011,"rating": 6.8,"votes": 55360,"running_times": 6420},{"title": "Salt","year": 2010,"rating": 6.4,"votes": 262295,"running_times": 6240},{"title": "Salvador","year": 1986,"rating": 7.5,"votes": 16538,"running_times": 7320},{"title": "Samba","year": 2014,"rating": 6.7,"votes": 12045,"running_times": 7080},{"title": "Samâ uôzu","year": 2009,"rating": 7.6,"votes": 19763,"running_times": 6840},{"title": "San Andreas","year": 2015,"rating": 6.1,"votes": 169965,"running_times": 6840},{"title": "San ging chaat goo si","year": 2004,"rating": 7,"votes": 21048,"running_times": 7380},{"title": "San wa","year": 2005,"rating": 6.2,"votes": 12519,"running_times": 7320},{"title": "Sanctum","year": 2011,"rating": 5.9,"votes": 49371,"running_times": 6480},{"title": "Sand Castle","year": 2017,"rating": 6.3,"votes": 10093,"running_times": 6780},{"title": "Santa sangre","year": 1989,"rating": 7.7,"votes": 15409,"running_times": 7380},{"title": "Sap ji sang ciu","year": 2012,"rating": 6.2,"votes": 17720,"running_times": 7380},{"title": "Saturday Night Fever","year": 1977,"rating": 6.8,"votes": 59027,"running_times": 7080},{"title": "Sausage Party","year": 2016,"rating": 6.2,"votes": 137395,"running_times": 5340},{"title": "Savages","year": 2012,"rating": 6.5,"votes": 110068,"running_times": 8460},{"title": "Save the Last Dance","year": 2001,"rating": 6.2,"votes": 51141,"running_times": 6720},{"title": "Saved!","year": 2004,"rating": 6.8,"votes": 41753,"running_times": 5520},{"title": "Saving Christmas","year": 2014,"rating": 1.5,"votes": 13258,"running_times": 4740},{"title": "Saving Grace","year": 2000,"rating": 6.9,"votes": 16103,"running_times": 5580},{"title": "Saving Mr. Banks","year": 2013,"rating": 7.5,"votes": 129499,"running_times": 7500},{"title": "Saving Private Ryan","year": 1998,"rating": 8.6,"votes": 993815,"running_times": 10140},{"title": "Saving Silverman","year": 2001,"rating": 5.9,"votes": 34937,"running_times": 5760},{"title": "Saw","year": 2004,"rating": 7.7,"votes": 328740,"running_times": 6180},{"title": "Saw 3D","year": 2010,"rating": 5.6,"votes": 76230,"running_times": 5400},{"title": "Saw II","year": 2005,"rating": 6.6,"votes": 204490,"running_times": 5700},{"title": "Saw III","year": 2006,"rating": 6.2,"votes": 155338,"running_times": 7260},{"title": "Saw IV","year": 2007,"rating": 5.9,"votes": 121889,"running_times": 5760},{"title": "Saw V","year": 2008,"rating": 5.8,"votes": 98150,"running_times": 5700},{"title": "Saw VI","year": 2009,"rating": 6,"votes": 85460,"running_times": 5520},{"title": "Say Anything...","year": 1989,"rating": 7.4,"votes": 71475,"running_times": 6000},{"title": "Say It Isn't So","year": 2001,"rating": 4.9,"votes": 11798,"running_times": 5700},{"title": "Scanners","year": 1981,"rating": 6.8,"votes": 39342,"running_times": 6180},{"title": "Scarecrow","year": 1973,"rating": 7.3,"votes": 12680,"running_times": 6720},{"title": "Scarface","year": 1932,"rating": 7.8,"votes": 21323,"running_times": 5580},{"title": "Scarface","year": 1983,"rating": 8.3,"votes": 599692,"running_times": 10200},{"title": "Scarlet Street","year": 1945,"rating": 7.9,"votes": 11212,"running_times": 6120},{"title": "Scary Movie","year": 2000,"rating": 6.2,"votes": 201518,"running_times": 5280},{"title": "Scary Movie 2","year": 2001,"rating": 5.3,"votes": 129387,"running_times": 4980},{"title": "Scary Movie 3","year": 2003,"rating": 5.5,"votes": 120113,"running_times": 5040},{"title": "Scary Movie 4","year": 2006,"rating": 5.1,"votes": 100457,"running_times": 5340},{"title": "Scary Movie 5","year": 2013,"rating": 3.5,"votes": 54977,"running_times": 5280},{"title": "Scent of a Woman","year": 1992,"rating": 8,"votes": 212640,"running_times": 9360},{"title": "Schindler's List","year": 1993,"rating": 8.9,"votes": 971107,"running_times": 11700},{"title": "School Ties","year": 1992,"rating": 6.9,"votes": 19369,"running_times": 6360},{"title": "School for Scoundrels","year": 2006,"rating": 5.9,"votes": 27341,"running_times": 6480},{"title": "Scooby-Doo","year": 2002,"rating": 5,"votes": 78942,"running_times": 5340},{"title": "Scooby-Doo 2: Monsters Unleashed","year": 2004,"rating": 5,"votes": 37459,"running_times": 5580},{"title": "Scoop","year": 2006,"rating": 6.7,"votes": 72462,"running_times": 5760},{"title": "Scott Pilgrim vs. the World","year": 2010,"rating": 7.5,"votes": 306142,"running_times": 6720},{"title": "Scouts Guide to the Zombie Apocalypse","year": 2015,"rating": 6.3,"votes": 35038,"running_times": 5580},{"title": "Scream","year": 1996,"rating": 7.2,"votes": 242085,"running_times": 6660},{"title": "Scream 2","year": 1997,"rating": 6.1,"votes": 134734,"running_times": 7200},{"title": "Scream 3","year": 2000,"rating": 5.5,"votes": 106429,"running_times": 6960},{"title": "Scream 4","year": 2011,"rating": 6.2,"votes": 111421,"running_times": 6660},{"title": "Screamers","year": 1995,"rating": 6.4,"votes": 21789,"running_times": 6480},{"title": "Scrooge","year": 1951,"rating": 8.1,"votes": 16428,"running_times": 5160},{"title": "Scrooged","year": 1988,"rating": 7,"votes": 69474,"running_times": 6060},{"title": "Se, jie","year": 2007,"rating": 7.6,"votes": 32595,"running_times": 9420},{"title": "Se7en","year": 1995,"rating": 8.6,"votes": 1151698,"running_times": 7620},{"title": "Sea of Love","year": 1989,"rating": 6.8,"votes": 32423,"running_times": 6780},{"title": "Seabiscuit","year": 2003,"rating": 7.3,"votes": 60328,"running_times": 8400},{"title": "Searching for Bobby Fischer","year": 1993,"rating": 7.5,"votes": 25503,"running_times": 6540},{"title": "Searching for Sugar Man","year": 2012,"rating": 8.2,"votes": 54182,"running_times": 5160},{"title": "Season of the Witch","year": 2011,"rating": 5.4,"votes": 80961,"running_times": 5700},{"title": "Secondhand Lions","year": 2003,"rating": 7.6,"votes": 46061,"running_times": 7200},{"title": "Seconds","year": 1966,"rating": 7.7,"votes": 12635,"running_times": 6420},{"title": "Secret Window","year": 2004,"rating": 6.6,"votes": 159468,"running_times": 5760},{"title": "Secret in Their Eyes","year": 2015,"rating": 6.2,"votes": 30327,"running_times": 6660},{"title": "Secretariat","year": 2010,"rating": 7.2,"votes": 22480,"running_times": 7380},{"title": "Secretary","year": 2002,"rating": 7,"votes": 72711,"running_times": 6420},{"title": "Secrets & Lies","year": 1996,"rating": 8,"votes": 31211,"running_times": 8160},{"title": "See No Evil","year": 2006,"rating": 5.1,"votes": 23294,"running_times": 5040},{"title": "See No Evil, Hear No Evil","year": 1989,"rating": 6.8,"votes": 40633,"running_times": 6180},{"title": "Seed of Chucky","year": 2004,"rating": 4.9,"votes": 31943,"running_times": 5280},{"title": "Seeking Justice","year": 2011,"rating": 6.2,"votes": 41086,"running_times": 6300},{"title": "Seeking a Friend for the End of the World","year": 2012,"rating": 6.7,"votes": 95893,"running_times": 6060},{"title": "Selena","year": 1997,"rating": 6.7,"votes": 20825,"running_times": 7620},{"title": "Self/less","year": 2015,"rating": 6.5,"votes": 71967,"running_times": 7020},{"title": "Selma","year": 2014,"rating": 7.5,"votes": 70669,"running_times": 7680},{"title": "Semi-Pro","year": 2008,"rating": 5.8,"votes": 70857,"running_times": 5940},{"title": "Sen to Chihiro no kamikakushi","year": 2001,"rating": 8.6,"votes": 485508,"running_times": 7500},{"title": "Senna","year": 2010,"rating": 8.6,"votes": 50116,"running_times": 9720},{"title": "Sennen joyû","year": 2001,"rating": 7.9,"votes": 17251,"running_times": 5220},{"title": "Sense and Sensibility","year": 1995,"rating": 7.7,"votes": 85268,"running_times": 8160},{"title": "Senseless","year": 1998,"rating": 6,"votes": 11518,"running_times": 6480},{"title": "Seraphim Falls","year": 2006,"rating": 6.7,"votes": 26207,"running_times": 6900},{"title": "Serena","year": 2014,"rating": 5.4,"votes": 21113,"running_times": 6540},{"title": "Serendipity","year": 2001,"rating": 6.9,"votes": 92682,"running_times": 5400},{"title": "Serenity","year": 2005,"rating": 7.9,"votes": 256866,"running_times": 7140},{"title": "Sergeant York","year": 1941,"rating": 7.8,"votes": 13214,"running_times": 8040},{"title": "Serial Mom","year": 1994,"rating": 6.7,"votes": 22738,"running_times": 5700},{"title": "Serpico","year": 1973,"rating": 7.8,"votes": 88491,"running_times": 7800},{"title": "Serving Sara","year": 2002,"rating": 5.3,"votes": 15137,"running_times": 6120},{"title": "Session 9","year": 2001,"rating": 6.5,"votes": 47139,"running_times": 6120},{"title": "Set It Off","year": 1996,"rating": 6.8,"votes": 11365,"running_times": 7380},{"title": "Setup","year": 2011,"rating": 4.4,"votes": 18941,"running_times": 5100},{"title": "Seven Brides for Seven Brothers","year": 1954,"rating": 7.4,"votes": 17609,"running_times": 6120},{"title": "Seven Days in May","year": 1964,"rating": 7.9,"votes": 10362,"running_times": 7080},{"title": "Seven Pounds","year": 2008,"rating": 7.7,"votes": 252535,"running_times": 7380},{"title": "Seven Psychopaths","year": 2012,"rating": 7.2,"votes": 203387,"running_times": 6600},{"title": "Seven Sisters","year": 2017,"rating": 6.9,"votes": 37842,"running_times": 7380},{"title": "Seven Years in Tibet","year": 1997,"rating": 7,"votes": 104958,"running_times": 8160},{"title": "Seventh Son","year": 2014,"rating": 5.5,"votes": 62169,"running_times": 6120},{"title": "Severance","year": 2006,"rating": 6.5,"votes": 33423,"running_times": 5760},{"title": "Sex Drive","year": 2008,"rating": 6.5,"votes": 76427,"running_times": 7740},{"title": "Sex Tape","year": 2014,"rating": 5.1,"votes": 93123,"running_times": 5640},{"title": "Sex and the City","year": 2008,"rating": 5.6,"votes": 104825,"running_times": 9060},{"title": "Sex and the City 2","year": 2010,"rating": 4.4,"votes": 64341,"running_times": 8760},{"title": "Sex, Lies, and Videotape","year": 1989,"rating": 7.2,"votes": 41140,"running_times": 6000},{"title": "Sexy Beast","year": 2000,"rating": 7.3,"votes": 46733,"running_times": 5340},{"title": "Sgt. Bilko","year": 1996,"rating": 5.7,"votes": 18882,"running_times": 5580},{"title": "Shade","year": 2003,"rating": 6.4,"votes": 11191,"running_times": 6060},{"title": "Shadow Dancer","year": 2012,"rating": 6.2,"votes": 10788,"running_times": 6060},{"title": "Shadow of a Doubt","year": 1943,"rating": 8,"votes": 49533,"running_times": 6480},{"title": "Shadow of the Vampire","year": 2000,"rating": 6.9,"votes": 35903,"running_times": 5520},{"title": "Shadowlands","year": 1993,"rating": 7.4,"votes": 14386,"running_times": 7860},{"title": "Shadows and Fog","year": 1991,"rating": 6.8,"votes": 14152,"running_times": 5100},{"title": "Shaft","year": 1971,"rating": 6.6,"votes": 13222,"running_times": 6000},{"title": "Shaft","year": 2000,"rating": 5.9,"votes": 62032,"running_times": 5940},{"title": "Shakespeare in Love","year": 1998,"rating": 7.2,"votes": 188788,"running_times": 7380},{"title": "Shall We Dance","year": 2004,"rating": 6.1,"votes": 38211,"running_times": 6360},{"title": "Shallow Grave","year": 1994,"rating": 7.3,"votes": 49609,"running_times": 5340},{"title": "Shallow Hal","year": 2001,"rating": 5.9,"votes": 115543,"running_times": 6840},{"title": "Shame","year": 2011,"rating": 7.2,"votes": 160333,"running_times": 6060},{"title": "Shane","year": 1953,"rating": 7.7,"votes": 30834,"running_times": 7080},{"title": "Shanghai Knights","year": 2003,"rating": 6.2,"votes": 88141,"running_times": 6840},{"title": "Shanghai Noon","year": 2000,"rating": 6.6,"votes": 104603,"running_times": 6600},{"title": "Shark Night 3D","year": 2011,"rating": 4,"votes": 22050,"running_times": 5400},{"title": "Shark Tale","year": 2004,"rating": 6,"votes": 143701,"running_times": 5400},{"title": "Shattered Glass","year": 2003,"rating": 7.2,"votes": 30336,"running_times": 5940},{"title": "Shaun of the Dead","year": 2004,"rating": 8,"votes": 433429,"running_times": 5940},{"title": "She Wore a Yellow Ribbon","year": 1949,"rating": 7.4,"votes": 13029,"running_times": 6180},{"title": "She's All That","year": 1999,"rating": 5.8,"votes": 72798,"running_times": 5700},{"title": "She's Funny That Way","year": 2014,"rating": 6.1,"votes": 20084,"running_times": 5580},{"title": "She's Out of My League","year": 2010,"rating": 6.4,"votes": 108427,"running_times": 6240},{"title": "She's the Man","year": 2006,"rating": 6.4,"votes": 127102,"running_times": 6300},{"title": "She's the One","year": 1996,"rating": 6,"votes": 14808,"running_times": 5760},{"title": "She-Devil","year": 1989,"rating": 5.5,"votes": 13645,"running_times": 5940},{"title": "Shelter","year": 2007,"rating": 7.8,"votes": 17698,"running_times": 5820},{"title": "Sherlock Holmes","year": 2009,"rating": 7.6,"votes": 516835,"running_times": 7680},{"title": "Sherlock Holmes: A Game of Shadows","year": 2011,"rating": 7.5,"votes": 368922,"running_times": 7740},{"title": "Sherlock Jr.","year": 1924,"rating": 8.3,"votes": 24468,"running_times": 2940},{"title": "Sherrybaby","year": 2006,"rating": 6.6,"votes": 10703,"running_times": 5760},{"title": "Shin Gojira","year": 2016,"rating": 6.7,"votes": 12838,"running_times": 7200},{"title": "Shine","year": 1996,"rating": 7.7,"votes": 45923,"running_times": 6300},{"title": "Shine a Light","year": 2008,"rating": 7.2,"votes": 10160,"running_times": 7320},{"title": "Shivers","year": 1975,"rating": 6.6,"votes": 13853,"running_times": 5220},{"title": "Shocker","year": 1989,"rating": 5.4,"votes": 12332,"running_times": 6540},{"title": "Shoot 'Em Up","year": 2007,"rating": 6.7,"votes": 135567,"running_times": 5160},{"title": "Shooter","year": 2007,"rating": 7.2,"votes": 275550,"running_times": 7440},{"title": "Shooting Dogs","year": 2005,"rating": 7.7,"votes": 10219,"running_times": 6900},{"title": "Shopgirl","year": 2005,"rating": 6.4,"votes": 21937,"running_times": 6360},{"title": "Short Circuit","year": 1986,"rating": 6.6,"votes": 47621,"running_times": 5880},{"title": "Short Circuit 2","year": 1988,"rating": 5.6,"votes": 20055,"running_times": 6600},{"title": "Short Cuts","year": 1993,"rating": 7.7,"votes": 37446,"running_times": 11400},{"title": "Short Term 12","year": 2013,"rating": 8,"votes": 65542,"running_times": 5760},{"title": "Shortbus","year": 2006,"rating": 6.5,"votes": 29029,"running_times": 6060},{"title": "Shot Caller","year": 2017,"rating": 7.4,"votes": 33834,"running_times": 7260},{"title": "Showdown in Little Tokyo","year": 1991,"rating": 6.1,"votes": 13607,"running_times": 4740},{"title": "Showgirls","year": 1995,"rating": 4.7,"votes": 53808,"running_times": 7860},{"title": "Showtime","year": 2002,"rating": 5.5,"votes": 55104,"running_times": 5760},{"title": "Shrek","year": 2001,"rating": 7.9,"votes": 512613,"running_times": 5400},{"title": "Shrek 2","year": 2004,"rating": 7.2,"votes": 346813,"running_times": 5580},{"title": "Shrek Forever After","year": 2010,"rating": 6.3,"votes": 152396,"running_times": 5580},{"title": "Shrek the Third","year": 2007,"rating": 6.1,"votes": 232828,"running_times": 5580},{"title": "Shrink","year": 2009,"rating": 6.7,"votes": 17142,"running_times": 6600},{"title": "Shrooms","year": 2007,"rating": 4.7,"votes": 14549,"running_times": 5160},{"title": "Shutter","year": 2008,"rating": 5.2,"votes": 28911,"running_times": 5400},{"title": "Shutter Island","year": 2010,"rating": 8.1,"votes": 898401,"running_times": 8280},{"title": "Sibirskiy tsiryulnik","year": 1998,"rating": 7.9,"votes": 10003,"running_times": 16500},{"title": "Sicario","year": 2015,"rating": 7.6,"votes": 266558,"running_times": 7260},{"title": "Sicko","year": 2007,"rating": 8,"votes": 69593,"running_times": 7380},{"title": "Sid and Nancy","year": 1986,"rating": 7.1,"votes": 25324,"running_times": 6720},{"title": "Side Effects","year": 2013,"rating": 7.1,"votes": 159048,"running_times": 6360},{"title": "Side by Side","year": 2012,"rating": 7.6,"votes": 11999,"running_times": 5940},{"title": "Sideways","year": 2004,"rating": 7.5,"votes": 159915,"running_times": 7560},{"title": "Sightseers","year": 2012,"rating": 6.5,"votes": 23052,"running_times": 5280},{"title": "Signs","year": 2002,"rating": 6.7,"votes": 294860,"running_times": 6360},{"title": "Silence","year": 2016,"rating": 7.2,"votes": 66803,"running_times": 9660},{"title": "Silent Hill","year": 2006,"rating": 6.6,"votes": 191211,"running_times": 7920},{"title": "Silent Hill: Revelation","year": 2012,"rating": 5,"votes": 53668,"running_times": 5700},{"title": "Silent House","year": 2011,"rating": 5.3,"votes": 19737,"running_times": 5160},{"title": "Silent Night, Deadly Night","year": 1984,"rating": 5.9,"votes": 10538,"running_times": 5760},{"title": "Silent Running","year": 1972,"rating": 6.7,"votes": 22780,"running_times": 5340},{"title": "Silk","year": 2007,"rating": 5.9,"votes": 10005,"running_times": 6720},{"title": "Silkwood","year": 1983,"rating": 7.2,"votes": 15363,"running_times": 7860},{"title": "Silver Bullet","year": 1985,"rating": 6.4,"votes": 18780,"running_times": 5700},{"title": "Silver Linings Playbook","year": 2012,"rating": 7.8,"votes": 581668,"running_times": 7320},{"title": "Silver Streak","year": 1976,"rating": 6.9,"votes": 15181,"running_times": 6840},{"title": "Silverado","year": 1985,"rating": 7.2,"votes": 30487,"running_times": 7980},{"title": "Simon Birch","year": 1998,"rating": 6.9,"votes": 19163,"running_times": 6840},{"title": "Simply Irresistible","year": 1999,"rating": 5.3,"votes": 12052,"running_times": 5760},{"title": "Sin City","year": 2005,"rating": 8,"votes": 693152,"running_times": 8820},{"title": "Sin City: A Dame to Kill For","year": 2014,"rating": 6.5,"votes": 127939,"running_times": 6120},{"title": "Sinbad: Legend of the Seven Seas","year": 2003,"rating": 6.7,"votes": 40341,"running_times": 5400},{"title": "Sing","year": 2016,"rating": 7.1,"votes": 88772,"running_times": 6840},{"title": "Sing Street","year": 2016,"rating": 8,"votes": 61913,"running_times": 6360},{"title": "Singham","year": 2011,"rating": 6.7,"votes": 11623,"running_times": 8580},{"title": "Singin' in the Rain","year": 1952,"rating": 8.3,"votes": 172852,"running_times": 6180},{"title": "Single White Female","year": 1992,"rating": 6.3,"votes": 26137,"running_times": 6420},{"title": "Singles","year": 1992,"rating": 6.7,"votes": 24370,"running_times": 5940},{"title": "Sinister","year": 2012,"rating": 6.8,"votes": 180429,"running_times": 6600},{"title": "Sinister 2","year": 2015,"rating": 5.3,"votes": 34973,"running_times": 5820},{"title": "Sister Act","year": 1992,"rating": 6.3,"votes": 71673,"running_times": 6000},{"title": "Sister Act 2: Back in the Habit","year": 1993,"rating": 5.4,"votes": 39947,"running_times": 6420},{"title": "Sisters","year": 1972,"rating": 7,"votes": 11910,"running_times": 5580},{"title": "Sisters","year": 2015,"rating": 6,"votes": 53056,"running_times": 7080},{"title": "Sivaji","year": 2007,"rating": 7.5,"votes": 13175,"running_times": 11280},{"title": "Six Days Seven Nights","year": 1998,"rating": 5.8,"votes": 64644,"running_times": 5880},{"title": "Six Degrees of Separation","year": 1993,"rating": 6.9,"votes": 17552,"running_times": 6720},{"title": "Sixteen Candles","year": 1984,"rating": 7.1,"votes": 83729,"running_times": 5580},{"title": "Skinwalkers","year": 2006,"rating": 4.6,"votes": 12097,"running_times": 6600},{"title": "Sky Captain and the World of Tomorrow","year": 2004,"rating": 6.1,"votes": 75817,"running_times": 6360},{"title": "Sky High","year": 2005,"rating": 6.2,"votes": 67093,"running_times": 6000},{"title": "Skyfall","year": 2012,"rating": 7.8,"votes": 560755,"running_times": 8580},{"title": "Skyline","year": 2010,"rating": 4.4,"votes": 79577,"running_times": 5820},{"title": "Slacker","year": 1991,"rating": 7.1,"votes": 16600,"running_times": 6000},{"title": "Slackers","year": 2002,"rating": 5.3,"votes": 12868,"running_times": 5160},{"title": "Slap Shot","year": 1977,"rating": 7.4,"votes": 30240,"running_times": 7380},{"title": "Slaughterhouse-Five","year": 1972,"rating": 7,"votes": 10444,"running_times": 6240},{"title": "Sleepaway Camp","year": 1983,"rating": 6.3,"votes": 18885,"running_times": 5040},{"title": "Sleeper","year": 1973,"rating": 7.3,"votes": 35717,"running_times": 5340},{"title": "Sleepers","year": 1996,"rating": 7.6,"votes": 165120,"running_times": 8820},{"title": "Sleeping Beauty","year": 1959,"rating": 7.3,"votes": 111600,"running_times": 4500},{"title": "Sleeping Beauty","year": 2011,"rating": 5.3,"votes": 27668,"running_times": 6060},{"title": "Sleeping with Other People","year": 2015,"rating": 6.5,"votes": 30768,"running_times": 6060},{"title": "Sleeping with the Enemy","year": 1991,"rating": 6.2,"votes": 41133,"running_times": 5940},{"title": "Sleepless","year": 2017,"rating": 5.6,"votes": 19069,"running_times": 5700},{"title": "Sleepless in Seattle","year": 1993,"rating": 6.8,"votes": 133798,"running_times": 6300},{"title": "Sleepover","year": 2004,"rating": 5.3,"votes": 13528,"running_times": 5340},{"title": "Sleepwalk with Me","year": 2012,"rating": 6.8,"votes": 10769,"running_times": 4860},{"title": "Sleepwalkers","year": 1992,"rating": 5.2,"votes": 16562,"running_times": 5460},{"title": "Sleepy Hollow","year": 1999,"rating": 7.4,"votes": 288484,"running_times": 6300},{"title": "Sleuth","year": 1972,"rating": 8.1,"votes": 39448,"running_times": 8280},{"title": "Sleuth","year": 2007,"rating": 6.5,"votes": 27574,"running_times": 5280},{"title": "Sliding Doors","year": 1998,"rating": 6.8,"votes": 55967,"running_times": 5940},{"title": "Sling Blade","year": 1996,"rating": 8,"votes": 77328,"running_times": 8880},{"title": "Slither","year": 2006,"rating": 6.5,"votes": 66043,"running_times": 5700},{"title": "Sliver","year": 1993,"rating": 4.9,"votes": 24667,"running_times": 6420},{"title": "Slow West","year": 2015,"rating": 6.9,"votes": 33707,"running_times": 5040},{"title": "Slumdog Millionaire","year": 2008,"rating": 8,"votes": 697092,"running_times": 7200},{"title": "Slums of Beverly Hills","year": 1998,"rating": 6.6,"votes": 10177,"running_times": 5520},{"title": "Small Soldiers","year": 1998,"rating": 6.1,"votes": 81823,"running_times": 6600},{"title": "Small Time Crooks","year": 2000,"rating": 6.7,"votes": 33129,"running_times": 5640},{"title": "Smart People","year": 2008,"rating": 6.2,"votes": 21359,"running_times": 5700},{"title": "Smashed","year": 2012,"rating": 6.8,"votes": 14793,"running_times": 4860},{"title": "Smiley Face","year": 2007,"rating": 5.8,"votes": 14734,"running_times": 5280},{"title": "Smilla's Sense of Snow","year": 1997,"rating": 6.4,"votes": 12278,"running_times": 7260},{"title": "Smoke","year": 1995,"rating": 7.4,"votes": 29719,"running_times": 6720},{"title": "Smokey and the Bandit","year": 1977,"rating": 6.9,"votes": 35477,"running_times": 5760},{"title": "Smokey and the Bandit II","year": 1980,"rating": 5.2,"votes": 12223,"running_times": 6000},{"title": "Smokin' Aces","year": 2006,"rating": 6.7,"votes": 126545,"running_times": 6540},{"title": "Smurfs: The Lost Village","year": 2017,"rating": 5.9,"votes": 11182,"running_times": 5400},{"title": "Snabba cash","year": 2010,"rating": 6.7,"votes": 14683,"running_times": 7440},{"title": "Snake Eyes","year": 1998,"rating": 6,"votes": 67876,"running_times": 5880},{"title": "Snakes on a Plane","year": 2006,"rating": 5.6,"votes": 120964,"running_times": 6300},{"title": "Snatch","year": 2000,"rating": 8.3,"votes": 662781,"running_times": 6240},{"title": "Snatched","year": 2017,"rating": 4.3,"votes": 20447,"running_times": 5400},{"title": "Sneakers","year": 1992,"rating": 7.1,"votes": 46445,"running_times": 7560},{"title": "Sniper","year": 1993,"rating": 6.1,"votes": 20484,"running_times": 5880},{"title": "Snitch","year": 2013,"rating": 6.5,"votes": 70259,"running_times": 6720},{"title": "Snow Angels","year": 2007,"rating": 6.9,"votes": 11437,"running_times": 6420},{"title": "Snow Cake","year": 2006,"rating": 7.6,"votes": 11373,"running_times": 6720},{"title": "Snow Day","year": 2000,"rating": 5,"votes": 10054,"running_times": 5340},{"title": "Snow Dogs","year": 2002,"rating": 5.1,"votes": 21931,"running_times": 5940},{"title": "Snow Falling on Cedars","year": 1999,"rating": 6.8,"votes": 12764,"running_times": 7620},{"title": "Snow White and the Huntsman","year": 2012,"rating": 6.1,"votes": 245114,"running_times": 7920},{"title": "Snow White and the Seven Dwarfs","year": 1937,"rating": 7.6,"votes": 149216,"running_times": 4980},{"title": "Snowden","year": 2016,"rating": 7.3,"votes": 97053,"running_times": 8040},{"title": "Snowpiercer","year": 2013,"rating": 7,"votes": 211297,"running_times": 7560},{"title": "Snowtown","year": 2011,"rating": 6.6,"votes": 14705,"running_times": 7140},{"title": "So I Married an Axe Murderer","year": 1993,"rating": 6.4,"votes": 29635,"running_times": 5580},{"title": "So Undercover","year": 2012,"rating": 5,"votes": 16254,"running_times": 5640},{"title": "Soaked in Bleach","year": 2015,"rating": 7.5,"votes": 11775,"running_times": 5400},{"title": "Soapdish","year": 1991,"rating": 6.5,"votes": 12426,"running_times": 5820},{"title": "Solace","year": 2015,"rating": 6.4,"votes": 40172,"running_times": 6060},{"title": "Solaris","year": 2002,"rating": 6.2,"votes": 71407,"running_times": 5940},{"title": "Soldier","year": 1998,"rating": 6,"votes": 46574,"running_times": 5940},{"title": "Solitary Man","year": 2009,"rating": 6.4,"votes": 14234,"running_times": 5400},{"title": "Solomon Kane","year": 2009,"rating": 6.1,"votes": 62676,"running_times": 6240},{"title": "Some Kind of Wonderful","year": 1987,"rating": 7.1,"votes": 22260,"running_times": 5700},{"title": "Some Like It Hot","year": 1959,"rating": 8.3,"votes": 196104,"running_times": 7260},{"title": "Someone Like You...","year": 2001,"rating": 6.1,"votes": 21215,"running_times": 5820},{"title": "Something Borrowed","year": 2011,"rating": 5.9,"votes": 51403,"running_times": 6720},{"title": "Something New","year": 2006,"rating": 6.8,"votes": 11183,"running_times": 5940},{"title": "Something Wild","year": 1986,"rating": 6.9,"votes": 13322,"running_times": 6840},{"title": "Something to Talk About","year": 1995,"rating": 5.7,"votes": 11196,"running_times": 6360},{"title": "Something's Gotta Give","year": 2003,"rating": 6.7,"votes": 97460,"running_times": 7680},{"title": "Somewhere","year": 2010,"rating": 6.3,"votes": 38373,"running_times": 5820},{"title": "Somewhere in Time","year": 1980,"rating": 7.3,"votes": 22652,"running_times": 6180},{"title": "Sommersby","year": 1993,"rating": 6.1,"votes": 16639,"running_times": 6840},{"title": "Son in Law","year": 1993,"rating": 5.7,"votes": 14621,"running_times": 5700},{"title": "Son of God","year": 2014,"rating": 5.7,"votes": 16625,"running_times": 10200},{"title": "Son of Rambow","year": 2007,"rating": 7,"votes": 28460,"running_times": 5760},{"title": "Son of a Gun","year": 2014,"rating": 6.5,"votes": 21903,"running_times": 6480},{"title": "Son of the Mask","year": 2005,"rating": 2.2,"votes": 44987,"running_times": 5640},{"title": "Song of the Sea","year": 2014,"rating": 8.1,"votes": 36215,"running_times": 5580},{"title": "Song to Song","year": 2017,"rating": 5.8,"votes": 10321,"running_times": 7740},{"title": "Sophie's Choice","year": 1982,"rating": 7.7,"votes": 32806,"running_times": 9420},{"title": "Sorcerer","year": 1977,"rating": 7.8,"votes": 11937,"running_times": 7260},{"title": "Sorority Boys","year": 2002,"rating": 5.4,"votes": 12562,"running_times": 5580},{"title": "Sorority Row","year": 2009,"rating": 5.1,"votes": 25521,"running_times": 6060},{"title": "Soul Kitchen","year": 2009,"rating": 7.3,"votes": 31562,"running_times": 5940},{"title": "Soul Plane","year": 2004,"rating": 4.4,"votes": 19355,"running_times": 5520},{"title": "Soul Surfer","year": 2011,"rating": 7.1,"votes": 38676,"running_times": 6720},{"title": "Sound of My Voice","year": 2011,"rating": 6.6,"votes": 18046,"running_times": 5100},{"title": "Source Code","year": 2011,"rating": 7.5,"votes": 420082,"running_times": 5580},{"title": "South Park: Bigger, Longer & Uncut","year": 1999,"rating": 7.8,"votes": 173169,"running_times": 4860},{"title": "Southbound","year": 2015,"rating": 5.9,"votes": 11805,"running_times": 5340},{"title": "Southern Comfort","year": 1981,"rating": 7.2,"votes": 13134,"running_times": 6360},{"title": "Southland Tales","year": 2006,"rating": 5.5,"votes": 33843,"running_times": 9600},{"title": "Southpaw","year": 2015,"rating": 7.4,"votes": 180071,"running_times": 7440},{"title": "Soylent Green","year": 1973,"rating": 7.1,"votes": 48661,"running_times": 5820},{"title": "Space Cowboys","year": 2000,"rating": 6.4,"votes": 64257,"running_times": 7800},{"title": "Space Jam","year": 1996,"rating": 6.3,"votes": 126652,"running_times": 5280},{"title": "SpaceCamp","year": 1986,"rating": 5.6,"votes": 11589,"running_times": 6420},{"title": "Spaceballs","year": 1987,"rating": 7.1,"votes": 148313,"running_times": 5760},{"title": "Spanglish","year": 2004,"rating": 6.4,"votes": 69742,"running_times": 7860},{"title": "Sparks","year": 2013,"rating": 5.9,"votes": 10225,"running_times": 5820},{"title": "Spartacus","year": 1960,"rating": 7.9,"votes": 105800,"running_times": 11820},{"title": "Spartan","year": 2004,"rating": 6.6,"votes": 27486,"running_times": 6360},{"title": "Spawn","year": 1997,"rating": 5.2,"votes": 56746,"running_times": 5880},{"title": "Speak","year": 2004,"rating": 7.4,"votes": 22204,"running_times": 5340},{"title": "Special Correspondents","year": 2016,"rating": 5.8,"votes": 13704,"running_times": 6060},{"title": "Species","year": 1995,"rating": 5.8,"votes": 65194,"running_times": 6480},{"title": "Species II","year": 1998,"rating": 4.3,"votes": 24126,"running_times": 5580},{"title": "Spectral","year": 2016,"rating": 6.3,"votes": 32422,"running_times": 6420},{"title": "Spectre","year": 2015,"rating": 6.8,"votes": 323174,"running_times": 8880},{"title": "Speed","year": 1994,"rating": 7.2,"votes": 282195,"running_times": 6960},{"title": "Speed 2: Cruise Control","year": 1997,"rating": 3.8,"votes": 64736,"running_times": 7260},{"title": "Speed Racer","year": 2008,"rating": 6,"votes": 61516,"running_times": 8100},{"title": "Spellbound","year": 1945,"rating": 7.6,"votes": 36085,"running_times": 7080},{"title": "Spellbound","year": 2002,"rating": 7.6,"votes": 11339,"running_times": 5820},{"title": "Sphere","year": 1998,"rating": 6.1,"votes": 88295,"running_times": 8040},{"title": "Spice World","year": 1997,"rating": 3.4,"votes": 29530,"running_times": 5580},{"title": "Spider","year": 2002,"rating": 6.8,"votes": 31954,"running_times": 5880},{"title": "Spider-Man","year": 2002,"rating": 7.3,"votes": 592886,"running_times": 7260},{"title": "Spider-Man 2","year": 2004,"rating": 7.3,"votes": 456912,"running_times": 8100},{"title": "Spider-Man 3","year": 2007,"rating": 6.2,"votes": 421570,"running_times": 8340},{"title": "Spider-Man: Homecoming","year": 2017,"rating": 7.6,"votes": 249739,"running_times": 7980},{"title": "Spies Like Us","year": 1985,"rating": 6.4,"votes": 37604,"running_times": 6120},{"title": "Spirit: Stallion of the Cimarron","year": 2002,"rating": 7.1,"votes": 51140,"running_times": 5160},{"title": "Splash","year": 1984,"rating": 6.2,"votes": 59128,"running_times": 6660},{"title": "Splendor in the Grass","year": 1961,"rating": 7.8,"votes": 14760,"running_times": 7440},{"title": "Splice","year": 2009,"rating": 5.8,"votes": 83775,"running_times": 6240},{"title": "Splinter","year": 2008,"rating": 6.1,"votes": 28948,"running_times": 4920},{"title": "Split","year": 2016,"rating": 7.3,"votes": 234221,"running_times": 7020},{"title": "Spooks: The Greater Good","year": 2015,"rating": 6.2,"votes": 16463,"running_times": 6240},{"title": "Spoorloos","year": 1988,"rating": 7.8,"votes": 27755,"running_times": 6420},{"title": "Spotlight","year": 2015,"rating": 8.1,"votes": 297395,"running_times": 7680},{"title": "Spread","year": 2009,"rating": 5.9,"votes": 34410,"running_times": 5820},{"title": "Spring","year": 2014,"rating": 6.7,"votes": 17755,"running_times": 6540},{"title": "Spring Breakers","year": 2012,"rating": 5.3,"votes": 117494,"running_times": 5640},{"title": "Spun","year": 2002,"rating": 6.8,"votes": 33594,"running_times": 6360},{"title": "Spy","year": 2015,"rating": 7,"votes": 196663,"running_times": 7800},{"title": "Spy Game","year": 2001,"rating": 7.1,"votes": 128296,"running_times": 7560},{"title": "Spy Hard","year": 1996,"rating": 5.3,"votes": 31921,"running_times": 4860},{"title": "Spy Kids","year": 2001,"rating": 5.4,"votes": 91900,"running_times": 5280},{"title": "Spy Kids 2: Island of Lost Dreams","year": 2002,"rating": 5.1,"votes": 49760,"running_times": 6000},{"title": "Spy Kids 3: Game Over","year": 2003,"rating": 4.2,"votes": 44716,"running_times": 5040},{"title": "Spy Kids: All the Time in the World in 4D","year": 2011,"rating": 3.6,"votes": 17547,"running_times": 5340},{"title": "Srpski film","year": 2010,"rating": 5.2,"votes": 45822,"running_times": 6240},{"title": "St. Elmo's Fire","year": 1985,"rating": 6.4,"votes": 30251,"running_times": 6600},{"title": "St. Trinian's","year": 2007,"rating": 5.8,"votes": 19445,"running_times": 6000},{"title": "St. Vincent","year": 2014,"rating": 7.3,"votes": 83606,"running_times": 6120},{"title": "Stage Fright","year": 1950,"rating": 7.1,"votes": 10406,"running_times": 6600},{"title": "Stagecoach","year": 1939,"rating": 7.9,"votes": 34419,"running_times": 5760},{"title": "Stake Land","year": 2010,"rating": 6.5,"votes": 37105,"running_times": 5880},{"title": "Stakeout","year": 1987,"rating": 6.6,"votes": 20222,"running_times": 7020},{"title": "Stalag 17","year": 1953,"rating": 8,"votes": 45605,"running_times": 7200},{"title": "Stan Helsing","year": 2009,"rating": 3.6,"votes": 10509,"running_times": 6480},{"title": "Stand Up Guys","year": 2012,"rating": 6.5,"votes": 48161,"running_times": 5700},{"title": "Stand and Deliver","year": 1988,"rating": 7.3,"votes": 13394,"running_times": 6180},{"title": "Stand by Me","year": 1986,"rating": 8.1,"votes": 303523,"running_times": 5340},{"title": "Star Trek","year": 2009,"rating": 8,"votes": 536248,"running_times": 7620},{"title": "Star Trek III: The Search for Spock","year": 1984,"rating": 6.7,"votes": 63865,"running_times": 6300},{"title": "Star Trek IV: The Voyage Home","year": 1986,"rating": 7.3,"votes": 67227,"running_times": 7140},{"title": "Star Trek V: The Final Frontier","year": 1989,"rating": 5.4,"votes": 47861,"running_times": 6420},{"title": "Star Trek VI: The Undiscovered Country","year": 1991,"rating": 7.2,"votes": 60259,"running_times": 6780},{"title": "Star Trek: Beyond","year": 2016,"rating": 7.1,"votes": 184977,"running_times": 7320},{"title": "Star Trek: First Contact","year": 1996,"rating": 7.6,"votes": 103993,"running_times": 6660},{"title": "Star Trek: Generations","year": 1994,"rating": 6.6,"votes": 65421,"running_times": 7080},{"title": "Star Trek: Insurrection","year": 1998,"rating": 6.4,"votes": 60876,"running_times": 6180},{"title": "Star Trek: Into Darkness","year": 2013,"rating": 7.8,"votes": 427145,"running_times": 7920},{"title": "Star Trek: Nemesis","year": 2002,"rating": 6.4,"votes": 63211,"running_times": 6960},{"title": "Star Trek: The Motion Picture","year": 1979,"rating": 6.4,"votes": 69315,"running_times": 8580},{"title": "Star Trek: The Wrath of Khan","year": 1982,"rating": 7.7,"votes": 98459,"running_times": 6960},{"title": "Star Wars","year": 1977,"rating": 8.7,"votes": 1017627,"running_times": 7500},{"title": "Star Wars: Episode I - The Phantom Menace","year": 1999,"rating": 6.5,"votes": 595846,"running_times": 8160},{"title": "Star Wars: Episode II - Attack of the Clones","year": 2002,"rating": 6.6,"votes": 521026,"running_times": 8520},{"title": "Star Wars: Episode III - Revenge of the Sith","year": 2005,"rating": 7.6,"votes": 581269,"running_times": 8400},{"title": "Star Wars: Episode V - The Empire Strikes Back","year": 1980,"rating": 8.8,"votes": 945421,"running_times": 7620},{"title": "Star Wars: Episode VI - Return of the Jedi","year": 1983,"rating": 8.4,"votes": 775825,"running_times": 8040},{"title": "Star Wars: Episode VII - The Force Awakens","year": 2015,"rating": 8.1,"votes": 707963,"running_times": 8160},{"title": "Star Wars: Episode VIII - The Last Jedi","year": 2017,"rating": 7.8,"votes": 151246,"running_times": 9120},{"title": "Star Wars: The Clone Wars","year": 2008,"rating": 5.9,"votes": 46331,"running_times": 5880},{"title": "Stardust","year": 2007,"rating": 7.7,"votes": 226118,"running_times": 7620},{"title": "Stardust Memories","year": 1980,"rating": 7.4,"votes": 18163,"running_times": 5340},{"title": "Stargate","year": 1994,"rating": 7.1,"votes": 157475,"running_times": 7800},{"title": "Starman","year": 1984,"rating": 7,"votes": 36137,"running_times": 6900},{"title": "Starred Up","year": 2013,"rating": 7.4,"votes": 36248,"running_times": 6360},{"title": "Starry Eyes","year": 2014,"rating": 6,"votes": 13931,"running_times": 5880},{"title": "Starship Troopers","year": 1997,"rating": 7.2,"votes": 237306,"running_times": 7740},{"title": "Starsky & Hutch","year": 2004,"rating": 6.1,"votes": 126352,"running_times": 6060},{"title": "Starter for 10","year": 2006,"rating": 6.7,"votes": 19276,"running_times": 5520},{"title": "State and Main","year": 2000,"rating": 6.8,"votes": 18956,"running_times": 6300},{"title": "State of Grace","year": 1990,"rating": 7.3,"votes": 17972,"running_times": 8040},{"title": "State of Play","year": 2009,"rating": 7.1,"votes": 119675,"running_times": 7620},{"title": "Stay","year": 2005,"rating": 6.9,"votes": 66125,"running_times": 5940},{"title": "Stay Alive","year": 2006,"rating": 5.1,"votes": 27146,"running_times": 6000},{"title": "Staying Alive","year": 1983,"rating": 4.5,"votes": 12227,"running_times": 5760},{"title": "Stealing Beauty","year": 1996,"rating": 6.6,"votes": 21983,"running_times": 7080},{"title": "Stealing Harvard","year": 2002,"rating": 5.1,"votes": 11543,"running_times": 5100},{"title": "Stealth","year": 2005,"rating": 5,"votes": 47402,"running_times": 7260},{"title": "Steamboat Bill, Jr.","year": 1928,"rating": 8,"votes": 10531,"running_times": 4200},{"title": "Steel Magnolias","year": 1989,"rating": 7.2,"votes": 37721,"running_times": 7140},{"title": "Step Brothers","year": 2008,"rating": 6.9,"votes": 229760,"running_times": 6360},{"title": "Step Up","year": 2006,"rating": 6.5,"votes": 98606,"running_times": 6240},{"title": "Step Up 2: The Streets","year": 2008,"rating": 6.2,"votes": 72340,"running_times": 5880},{"title": "Step Up 3D","year": 2010,"rating": 6.2,"votes": 50574,"running_times": 6420},{"title": "Step Up All In","year": 2014,"rating": 6,"votes": 28255,"running_times": 6720},{"title": "Step Up Revolution","year": 2012,"rating": 6.5,"votes": 48730,"running_times": 5940},{"title": "Stepmom","year": 1998,"rating": 6.7,"votes": 51070,"running_times": 7440},{"title": "Steve Jobs","year": 2015,"rating": 7.2,"votes": 124496,"running_times": 7320},{"title": "Stick It","year": 2006,"rating": 6.4,"votes": 24032,"running_times": 6180},{"title": "Stigmata","year": 1999,"rating": 6.2,"votes": 57586,"running_times": 6180},{"title": "Still Alice","year": 2014,"rating": 7.5,"votes": 104004,"running_times": 6060},{"title": "Stir Crazy","year": 1980,"rating": 6.8,"votes": 20418,"running_times": 6660},{"title": "Stir of Echoes","year": 1999,"rating": 7,"votes": 66144,"running_times": 5940},{"title": "Stoker","year": 2013,"rating": 6.8,"votes": 91869,"running_times": 5940},{"title": "Stolen","year": 2012,"rating": 5.5,"votes": 39431,"running_times": 5760},{"title": "Stomp the Yard","year": 2007,"rating": 5.3,"votes": 20324,"running_times": 6900},{"title": "Stone","year": 2010,"rating": 5.4,"votes": 36629,"running_times": 6300},{"title": "Stop! Or My Mom Will Shoot","year": 1992,"rating": 4.1,"votes": 33866,"running_times": 5220},{"title": "Stop-Loss","year": 2008,"rating": 6.5,"votes": 18497,"running_times": 6720},{"title": "Stories We Tell","year": 2012,"rating": 7.6,"votes": 10436,"running_times": 6480},{"title": "Storks","year": 2016,"rating": 6.8,"votes": 42746,"running_times": 5220},{"title": "Stormbreaker","year": 2006,"rating": 5.1,"votes": 21362,"running_times": 5580},{"title": "Storytelling","year": 2001,"rating": 6.9,"votes": 15914,"running_times": 5220},{"title": "Straight Outta Compton","year": 2015,"rating": 7.9,"votes": 149835,"running_times": 10020},{"title": "Strange Days","year": 1995,"rating": 7.2,"votes": 58409,"running_times": 8700},{"title": "Strange Wilderness","year": 2008,"rating": 5.3,"votes": 19489,"running_times": 5220},{"title": "Stranger Than Fiction","year": 2006,"rating": 7.6,"votes": 198359,"running_times": 6780},{"title": "Stranger Than Paradise","year": 1984,"rating": 7.6,"votes": 28124,"running_times": 5340},{"title": "Strangers on a Train","year": 1951,"rating": 8,"votes": 106706,"running_times": 6180},{"title": "Straw Dogs","year": 1971,"rating": 7.5,"votes": 48867,"running_times": 7080},{"title": "Straw Dogs","year": 2011,"rating": 5.8,"votes": 28934,"running_times": 6600},{"title": "Street Fighter","year": 1994,"rating": 3.8,"votes": 56501,"running_times": 6120},{"title": "Street Fighter: The Legend of Chun-Li","year": 2009,"rating": 3.7,"votes": 20710,"running_times": 5760},{"title": "Street Kings","year": 2008,"rating": 6.8,"votes": 99006,"running_times": 6540},{"title": "Streets of Fire","year": 1984,"rating": 6.7,"votes": 13960,"running_times": 5700},{"title": "Stretch","year": 2014,"rating": 6.5,"votes": 25506,"running_times": 5640},{"title": "Strictly Ballroom","year": 1992,"rating": 7.2,"votes": 21836,"running_times": 5640},{"title": "Striking Distance","year": 1993,"rating": 5.8,"votes": 35780,"running_times": 6120},{"title": "Stripes","year": 1981,"rating": 6.9,"votes": 53430,"running_times": 7320},{"title": "Striptease","year": 1996,"rating": 4.3,"votes": 37180,"running_times": 7020},{"title": "Stroszek","year": 1977,"rating": 8,"votes": 10592,"running_times": 6900},{"title": "Struck by Lightning","year": 2012,"rating": 6.3,"votes": 13599,"running_times": 5400},{"title": "Stuart Little","year": 1999,"rating": 5.9,"votes": 105005,"running_times": 5040},{"title": "Stuart Little 2","year": 2002,"rating": 5.4,"votes": 41063,"running_times": 4920},{"title": "Stuck in Love","year": 2012,"rating": 7.3,"votes": 73477,"running_times": 5820},{"title": "Stuck on You","year": 2003,"rating": 5.8,"votes": 46800,"running_times": 7080},{"title": "Submarine","year": 2010,"rating": 7.3,"votes": 74119,"running_times": 5820},{"title": "Suburra","year": 2015,"rating": 7.4,"votes": 11483,"running_times": 7800},{"title": "Suchîmubôi","year": 2004,"rating": 6.9,"votes": 14714,"running_times": 7620},{"title": "Sucker Punch","year": 2011,"rating": 6.1,"votes": 209381,"running_times": 7680},{"title": "Sudden Death","year": 1995,"rating": 5.7,"votes": 27751,"running_times": 6660},{"title": "Sudden Impact","year": 1983,"rating": 6.6,"votes": 34112,"running_times": 7020},{"title": "Suddenly, Last Summer","year": 1959,"rating": 7.6,"votes": 11425,"running_times": 6840},{"title": "Suffragette","year": 2015,"rating": 6.9,"votes": 28983,"running_times": 6360},{"title": "Sugar & Spice","year": 2001,"rating": 5.6,"votes": 12104,"running_times": 5040},{"title": "Suicide Kings","year": 1997,"rating": 7,"votes": 23626,"running_times": 6360},{"title": "Suicide Squad","year": 2016,"rating": 6.1,"votes": 453361,"running_times": 8040},{"title": "Suite Française","year": 2014,"rating": 6.9,"votes": 15697,"running_times": 6420},{"title": "Sukiyaki Western Django","year": 2007,"rating": 6.3,"votes": 13457,"running_times": 7260},{"title": "Sullivan's Travels","year": 1941,"rating": 8.1,"votes": 20038,"running_times": 5400},{"title": "Sully","year": 2016,"rating": 7.5,"votes": 165235,"running_times": 5760},{"title": "Summer Catch","year": 2001,"rating": 5,"votes": 13708,"running_times": 6480},{"title": "Summer Rental","year": 1985,"rating": 6.2,"votes": 11213,"running_times": 5280},{"title": "Summer School","year": 1987,"rating": 6.5,"votes": 14190,"running_times": 5820},{"title": "Summer of Sam","year": 1999,"rating": 6.6,"votes": 32643,"running_times": 8520},{"title": "Sunrise: A Song of Two Humans","year": 1927,"rating": 8.2,"votes": 34599,"running_times": 6360},{"title": "Sunset Blvd.","year": 1950,"rating": 8.5,"votes": 157474,"running_times": 6900},{"title": "Sunshine","year": 1999,"rating": 7.5,"votes": 11782,"running_times": 10860},{"title": "Sunshine","year": 2007,"rating": 7.3,"votes": 206210,"running_times": 6420},{"title": "Sunshine Cleaning","year": 2008,"rating": 6.9,"votes": 63947,"running_times": 5460},{"title": "Super","year": 2010,"rating": 6.8,"votes": 66282,"running_times": 5760},{"title": "Super 8","year": 2011,"rating": 7,"votes": 305903,"running_times": 6720},{"title": "Super High Me","year": 2007,"rating": 6.1,"votes": 12122,"running_times": 5640},{"title": "Super Mario Bros.","year": 1993,"rating": 4,"votes": 40962,"running_times": 6240},{"title": "Super Size Me","year": 2004,"rating": 7.2,"votes": 91271,"running_times": 6000},{"title": "Super Troopers","year": 2001,"rating": 7.1,"votes": 81588,"running_times": 6000},{"title": "Superbabies: Baby Geniuses 2","year": 2004,"rating": 2,"votes": 27008,"running_times": 5280},{"title": "Superbad","year": 2007,"rating": 7.6,"votes": 454499,"running_times": 7140},{"title": "Supergirl","year": 1984,"rating": 4.3,"votes": 15532,"running_times": 9000},{"title": "Superhero Movie","year": 2008,"rating": 4.5,"votes": 55895,"running_times": 4920},{"title": "Superman","year": 1978,"rating": 7.3,"votes": 137512,"running_times": 11280},{"title": "Superman II","year": 1980,"rating": 6.8,"votes": 83797,"running_times": 7620},{"title": "Superman III","year": 1983,"rating": 4.9,"votes": 54869,"running_times": 7500},{"title": "Superman IV: The Quest for Peace","year": 1987,"rating": 3.7,"votes": 36261,"running_times": 8040},{"title": "Superman Returns","year": 2006,"rating": 6.1,"votes": 251227,"running_times": 9240},{"title": "Supernova","year": 2000,"rating": 4.8,"votes": 15455,"running_times": 5460},{"title": "Superstar","year": 1999,"rating": 5,"votes": 15843,"running_times": 4860},{"title": "Surf's Up","year": 2007,"rating": 6.7,"votes": 58422,"running_times": 5100},{"title": "Surrogates","year": 2009,"rating": 6.3,"votes": 158065,"running_times": 5340},{"title": "Surveillance","year": 2008,"rating": 6.4,"votes": 15562,"running_times": 5820},{"title": "Survival of the Dead","year": 2009,"rating": 4.9,"votes": 18505,"running_times": 5400},{"title": "Surviving Christmas","year": 2004,"rating": 5.4,"votes": 19131,"running_times": 5460},{"title": "Survivor","year": 2015,"rating": 5.6,"votes": 25487,"running_times": 5760},{"title": "Suspect Zero","year": 2004,"rating": 5.9,"votes": 17272,"running_times": 5940},{"title": "Suspicion","year": 1941,"rating": 7.4,"votes": 26314,"running_times": 5940},{"title": "Suspiria","year": 1977,"rating": 7.5,"votes": 53227,"running_times": 5880},{"title": "Swades: We, the People","year": 2004,"rating": 8.3,"votes": 67127,"running_times": 12600},{"title": "Swamp Thing","year": 1982,"rating": 5.4,"votes": 10572,"running_times": 5580},{"title": "Sweeney Todd: The Demon Barber of Fleet Street","year": 2007,"rating": 7.4,"votes": 304578,"running_times": 6960},{"title": "Sweet Home Alabama","year": 2002,"rating": 6.2,"votes": 89850,"running_times": 6480},{"title": "Sweet November","year": 2001,"rating": 6.7,"votes": 75538,"running_times": 7140},{"title": "Sweet Sixteen","year": 2002,"rating": 7.5,"votes": 11509,"running_times": 6360},{"title": "Sweet Smell of Success","year": 1957,"rating": 8.2,"votes": 22137,"running_times": 5760},{"title": "Sweet and Lowdown","year": 1999,"rating": 7.3,"votes": 29295,"running_times": 5700},{"title": "Swept Away","year": 2002,"rating": 3.6,"votes": 13837,"running_times": 5340},{"title": "Swimfan","year": 2002,"rating": 5,"votes": 17194,"running_times": 5100},{"title": "Swimming Pool","year": 2003,"rating": 6.8,"votes": 37303,"running_times": 6120},{"title": "Swimming with Sharks","year": 1994,"rating": 7.1,"votes": 20150,"running_times": 5580},{"title": "Swing Kids","year": 1993,"rating": 6.8,"votes": 13991,"running_times": 6720},{"title": "Swing Vote","year": 2008,"rating": 6.1,"votes": 15920,"running_times": 7200},{"title": "Swingers","year": 1996,"rating": 7.3,"votes": 67695,"running_times": 5760},{"title": "Swiss Army Man","year": 2016,"rating": 7,"votes": 73349,"running_times": 5820},{"title": "Swiss Family Robinson","year": 1960,"rating": 7.2,"votes": 11259,"running_times": 7560},{"title": "Switchback","year": 1997,"rating": 6.4,"votes": 10691,"running_times": 7080},{"title": "Swordfish","year": 2001,"rating": 6.5,"votes": 162723,"running_times": 5940},{"title": "Sydney","year": 1996,"rating": 7.3,"votes": 31752,"running_times": 6120},{"title": "Sydney White","year": 2007,"rating": 6.3,"votes": 40517,"running_times": 6480},{"title": "Synecdoche, New York","year": 2008,"rating": 7.5,"votes": 64501,"running_times": 7440},{"title": "Syriana","year": 2005,"rating": 7,"votes": 115584,"running_times": 7680},{"title": "Så som i himmelen","year": 2004,"rating": 7.6,"votes": 14507,"running_times": 7980},{"title": "T2 Trainspotting","year": 2017,"rating": 7.3,"votes": 71133,"running_times": 7020},{"title": "THX 1138","year": 1971,"rating": 6.8,"votes": 42170,"running_times": 5280},{"title": "TMNT","year": 2007,"rating": 6.3,"votes": 56090,"running_times": 5220},{"title": "TRON","year": 1982,"rating": 6.8,"votes": 100273,"running_times": 5760},{"title": "Taare Zameen Par","year": 2007,"rating": 8.5,"votes": 113334,"running_times": 9900},{"title": "Table 19","year": 2017,"rating": 5.8,"votes": 13202,"running_times": 5220},{"title": "Take Me Home Tonight","year": 2011,"rating": 6.3,"votes": 46354,"running_times": 5820},{"title": "Take Shelter","year": 2011,"rating": 7.4,"votes": 77009,"running_times": 7260},{"title": "Take This Waltz","year": 2011,"rating": 6.6,"votes": 24404,"running_times": 6960},{"title": "Take the Lead","year": 2006,"rating": 6.7,"votes": 22877,"running_times": 7080},{"title": "Take the Money and Run","year": 1969,"rating": 7.3,"votes": 24562,"running_times": 5100},{"title": "Taken","year": 2008,"rating": 7.8,"votes": 513482,"running_times": 5580},{"title": "Taken 2","year": 2012,"rating": 6.3,"votes": 257220,"running_times": 5880},{"title": "Taken 3","year": 2014,"rating": 6,"votes": 151174,"running_times": 6900},{"title": "Takers","year": 2010,"rating": 6.2,"votes": 50191,"running_times": 6420},{"title": "Taking Lives","year": 2004,"rating": 6.2,"votes": 69873,"running_times": 6540},{"title": "Taking Woodstock","year": 2009,"rating": 6.7,"votes": 26011,"running_times": 7200},{"title": "Talaash","year": 2012,"rating": 7.3,"votes": 32847,"running_times": 8400},{"title": "Tales from the Crypt: Demon Knight","year": 1995,"rating": 6.7,"votes": 17987,"running_times": 5520},{"title": "Tales from the Darkside: The Movie","year": 1990,"rating": 6.2,"votes": 12283,"running_times": 5580},{"title": "Talk Radio","year": 1988,"rating": 7.3,"votes": 10822,"running_times": 6600},{"title": "Talladega Nights: The Ballad of Ricky Bobby","year": 2006,"rating": 6.6,"votes": 141841,"running_times": 7320},{"title": "Tallulah","year": 2016,"rating": 6.8,"votes": 11732,"running_times": 6660},{"title": "Tamara Drewe","year": 2010,"rating": 6.2,"votes": 18287,"running_times": 6540},{"title": "También la lluvia","year": 2010,"rating": 7.5,"votes": 10848,"running_times": 6180},{"title": "Tammy","year": 2014,"rating": 4.9,"votes": 40482,"running_times": 6000},{"title": "Tangerine","year": 2015,"rating": 7.1,"votes": 17459,"running_times": 5280},{"title": "Tangled","year": 2010,"rating": 7.8,"votes": 330137,"running_times": 6000},{"title": "Tangled Ever After","year": 2012,"rating": 7.7,"votes": 14090,"running_times": 360},{"title": "Tango & Cash","year": 1989,"rating": 6.3,"votes": 82157,"running_times": 6240},{"title": "Tank Girl","year": 1995,"rating": 5.3,"votes": 26488,"running_times": 6240},{"title": "Tape","year": 2001,"rating": 7.3,"votes": 16803,"running_times": 5160},{"title": "Taps","year": 1981,"rating": 6.7,"votes": 14164,"running_times": 7560},{"title": "Tarzan","year": 1999,"rating": 7.2,"votes": 163076,"running_times": 5280},{"title": "Tarzan","year": 2013,"rating": 4.8,"votes": 11169,"running_times": 5640},{"title": "Taxi","year": 2004,"rating": 4.4,"votes": 35435,"running_times": 6240},{"title": "Taxi Driver","year": 1976,"rating": 8.3,"votes": 571416,"running_times": 6780},{"title": "Taxi to the Dark Side","year": 2007,"rating": 7.6,"votes": 12445,"running_times": 6360},{"title": "Taxidermia","year": 2006,"rating": 7,"votes": 14280,"running_times": 5460},{"title": "Te wu mi cheng","year": 2001,"rating": 5.9,"votes": 13830,"running_times": 6480},{"title": "Teaching Mrs. Tingle","year": 1999,"rating": 5.2,"votes": 18065,"running_times": 5760},{"title": "Team America: World Police","year": 2004,"rating": 7.2,"votes": 143954,"running_times": 5880},{"title": "Tears of the Sun","year": 2003,"rating": 6.6,"votes": 100114,"running_times": 8520},{"title": "Ted","year": 2012,"rating": 7,"votes": 507957,"running_times": 6720},{"title": "Ted 2","year": 2015,"rating": 6.3,"votes": 146086,"running_times": 7500},{"title": "Teen Wolf","year": 1985,"rating": 6,"votes": 38362,"running_times": 5460},{"title": "Teenage Mutant Ninja Turtles","year": 1990,"rating": 6.7,"votes": 74041,"running_times": 5580},{"title": "Teenage Mutant Ninja Turtles","year": 2014,"rating": 5.8,"votes": 183023,"running_times": 6060},{"title": "Teenage Mutant Ninja Turtles II: The Secret of the Ooze","year": 1991,"rating": 6,"votes": 45238,"running_times": 5280},{"title": "Teenage Mutant Ninja Turtles III","year": 1993,"rating": 4.8,"votes": 26894,"running_times": 5760},{"title": "Teenage Mutant Ninja Turtles: Out of the Shadows","year": 2016,"rating": 6,"votes": 66805,"running_times": 6720},{"title": "Teeth","year": 2007,"rating": 5.4,"votes": 36765,"running_times": 5640},{"title": "Tekken","year": 2010,"rating": 4.8,"votes": 23706,"running_times": 5520},{"title": "Temptation: Confessions of a Marriage Counselor","year": 2013,"rating": 5,"votes": 10536,"running_times": 6660},{"title": "Ten Inch Hero","year": 2007,"rating": 7.5,"votes": 10805,"running_times": 6120},{"title": "Tenacious D in The Pick of Destiny","year": 2006,"rating": 6.8,"votes": 91597,"running_times": 5580},{"title": "Tenebre","year": 1982,"rating": 7.2,"votes": 16000,"running_times": 6060},{"title": "Tequila Sunrise","year": 1988,"rating": 6,"votes": 24950,"running_times": 6900},{"title": "Terminal Velocity","year": 1994,"rating": 5.4,"votes": 11461,"running_times": 6120},{"title": "Terminator 2: Judgment Day","year": 1991,"rating": 8.5,"votes": 824332,"running_times": 9360},{"title": "Terminator 3: Rise of the Machines","year": 2003,"rating": 6.3,"votes": 328905,"running_times": 6540},{"title": "Terminator Genisys","year": 2015,"rating": 6.5,"votes": 215687,"running_times": 7560},{"title": "Terminator Salvation","year": 2009,"rating": 6.6,"votes": 304237,"running_times": 7080},{"title": "Terms of Endearment","year": 1983,"rating": 7.4,"votes": 44741,"running_times": 7920},{"title": "Terra","year": 2007,"rating": 6.6,"votes": 10448,"running_times": 5100},{"title": "Tess","year": 1979,"rating": 7.3,"votes": 12322,"running_times": 11160},{"title": "Testament of Youth","year": 2014,"rating": 7.3,"votes": 19729,"running_times": 7800},{"title": "Tetro","year": 2009,"rating": 6.9,"votes": 11124,"running_times": 7620},{"title": "Texas Chainsaw 3D","year": 2013,"rating": 4.8,"votes": 38655,"running_times": 5520},{"title": "Texas Killing Fields","year": 2011,"rating": 5.7,"votes": 16211,"running_times": 6300},{"title": "Thank You for Smoking","year": 2005,"rating": 7.6,"votes": 199541,"running_times": 5520},{"title": "Thanks for Sharing","year": 2012,"rating": 6.4,"votes": 22550,"running_times": 6720},{"title": "That Awkward Moment","year": 2014,"rating": 6.2,"votes": 84885,"running_times": 5640},{"title": "That Thing You Do!","year": 1996,"rating": 6.9,"votes": 53878,"running_times": 8940},{"title": "That's My Boy","year": 2012,"rating": 5.6,"votes": 76768,"running_times": 6960},{"title": "The 'Burbs","year": 1989,"rating": 6.9,"votes": 56541,"running_times": 6060},{"title": "The 13th Warrior","year": 1999,"rating": 6.6,"votes": 106127,"running_times": 6120},{"title": "The 33","year": 2015,"rating": 6.9,"votes": 28594,"running_times": 7620},{"title": "The 39 Steps","year": 1935,"rating": 7.8,"votes": 43400,"running_times": 5160},{"title": "The 40 Year Old Virgin","year": 2005,"rating": 7.1,"votes": 337621,"running_times": 7980},{"title": "The 51st State","year": 2001,"rating": 6.3,"votes": 44500,"running_times": 5580},{"title": "The 5th Wave","year": 2016,"rating": 5.2,"votes": 78607,"running_times": 6720},{"title": "The 6th Day","year": 2000,"rating": 5.9,"votes": 105516,"running_times": 7380},{"title": "The A-Team","year": 2010,"rating": 6.8,"votes": 224171,"running_times": 7980},{"title": "The ABCs of Death","year": 2012,"rating": 4.7,"votes": 15744,"running_times": 7740},{"title": "The Abandoned","year": 2006,"rating": 5.6,"votes": 11545,"running_times": 5940},{"title": "The Abominable Dr. Phibes","year": 1971,"rating": 7.2,"votes": 11188,"running_times": 5640},{"title": "The Abyss","year": 1989,"rating": 7.6,"votes": 141969,"running_times": 10260},{"title": "The Accidental Husband","year": 2008,"rating": 5.6,"votes": 20747,"running_times": 5400},{"title": "The Accidental Tourist","year": 1988,"rating": 6.8,"votes": 13149,"running_times": 7260},{"title": "The Accountant","year": 2016,"rating": 7.4,"votes": 198484,"running_times": 7680},{"title": "The Accused","year": 1988,"rating": 7.1,"votes": 26442,"running_times": 6660},{"title": "The Act of Killing","year": 2012,"rating": 8.2,"votes": 28060,"running_times": 9600},{"title": "The Addams Family","year": 1991,"rating": 6.8,"votes": 106391,"running_times": 5940},{"title": "The Adjustment Bureau","year": 2011,"rating": 7.1,"votes": 213923,"running_times": 6360},{"title": "The Adventures of Baron Munchausen","year": 1988,"rating": 7.2,"votes": 44289,"running_times": 7560},{"title": "The Adventures of Bob & Doug McKenzie: Strange Brew","year": 1983,"rating": 6.8,"votes": 13716,"running_times": 5400},{"title": "The Adventures of Buckaroo Banzai Across the 8th Dimension","year": 1984,"rating": 6.4,"votes": 19401,"running_times": 6180},{"title": "The Adventures of Ford Fairlane","year": 1990,"rating": 6.3,"votes": 15293,"running_times": 6240},{"title": "The Adventures of Pluto Nash","year": 2002,"rating": 3.8,"votes": 21371,"running_times": 5700},{"title": "The Adventures of Priscilla, Queen of the Desert","year": 1994,"rating": 7.5,"votes": 39960,"running_times": 6240},{"title": "The Adventures of Robin Hood","year": 1938,"rating": 8,"votes": 41275,"running_times": 6120},{"title": "The Adventures of Rocky & Bullwinkle","year": 2000,"rating": 4.2,"votes": 17533,"running_times": 5520},{"title": "The Adventures of Sharkboy and Lavagirl 3-D","year": 2005,"rating": 3.5,"votes": 23046,"running_times": 5580},{"title": "The Adventures of Tintin","year": 2011,"rating": 7.4,"votes": 189928,"running_times": 6420},{"title": "The African Queen","year": 1951,"rating": 7.9,"votes": 62420,"running_times": 6300},{"title": "The Age of Adaline","year": 2015,"rating": 7.2,"votes": 121718,"running_times": 6720},{"title": "The Age of Innocence","year": 1993,"rating": 7.2,"votes": 39664,"running_times": 8340},{"title": "The Air I Breathe","year": 2007,"rating": 6.9,"votes": 32248,"running_times": 5700},{"title": "The Alamo","year": 1960,"rating": 6.9,"votes": 11909,"running_times": 12180},{"title": "The Alamo","year": 2004,"rating": 6,"votes": 17754,"running_times": 8220},{"title": "The Amazing Spider-Man","year": 2012,"rating": 7,"votes": 489511,"running_times": 8160},{"title": "The Amazing Spider-Man 2","year": 2014,"rating": 6.7,"votes": 356578,"running_times": 8520},{"title": "The American","year": 2010,"rating": 6.3,"votes": 83595,"running_times": 6300},{"title": "The American President","year": 1995,"rating": 6.8,"votes": 45620,"running_times": 6840},{"title": "The Amityville Horror","year": 1979,"rating": 6.2,"votes": 30078,"running_times": 7020},{"title": "The Amityville Horror","year": 2005,"rating": 6,"votes": 92636,"running_times": 5400},{"title": "The Andromeda Strain","year": 1971,"rating": 7.2,"votes": 28205,"running_times": 7860},{"title": "The Angels' Share","year": 2012,"rating": 7,"votes": 20149,"running_times": 6060},{"title": "The Angriest Man in Brooklyn","year": 2014,"rating": 5.7,"votes": 18298,"running_times": 4980},{"title": "The Animal","year": 2001,"rating": 4.8,"votes": 50589,"running_times": 5040},{"title": "The Ant Bully","year": 2006,"rating": 5.9,"votes": 32279,"running_times": 5280},{"title": "The Apartment","year": 1960,"rating": 8.3,"votes": 124560,"running_times": 7500},{"title": "The Apostle","year": 1997,"rating": 7.2,"votes": 12080,"running_times": 8040},{"title": "The Apparition","year": 2012,"rating": 4.1,"votes": 17285,"running_times": 4980},{"title": "The AristoCats","year": 1970,"rating": 7.1,"votes": 73750,"running_times": 4680},{"title": "The Aristocrats","year": 2005,"rating": 6.4,"votes": 15362,"running_times": 5340},{"title": "The Arrival","year": 1996,"rating": 6.3,"votes": 27998,"running_times": 6900},{"title": "The Art of Getting By","year": 2011,"rating": 6.6,"votes": 50390,"running_times": 4980},{"title": "The Art of War","year": 2000,"rating": 5.7,"votes": 26345,"running_times": 7020},{"title": "The Art of the Steal","year": 2013,"rating": 6.3,"votes": 20660,"running_times": 5400},{"title": "The Artist","year": 2011,"rating": 7.9,"votes": 204685,"running_times": 6000},{"title": "The Asphalt Jungle","year": 1950,"rating": 7.9,"votes": 19607,"running_times": 6720},{"title": "The Assassination of Jesse James by the Coward Robert Ford","year": 2007,"rating": 7.5,"votes": 148086,"running_times": 9600},{"title": "The Assassination of Richard Nixon","year": 2004,"rating": 7,"votes": 24037,"running_times": 5700},{"title": "The Astronaut Farmer","year": 2006,"rating": 6.3,"votes": 20721,"running_times": 6240},{"title": "The Astronaut's Wife","year": 1999,"rating": 5.3,"votes": 48379,"running_times": 6540},{"title": "The Autopsy of Jane Doe","year": 2016,"rating": 6.8,"votes": 53254,"running_times": 5160},{"title": "The Avengers","year": 1998,"rating": 3.7,"votes": 36996,"running_times": 6900},{"title": "The Avengers","year": 2012,"rating": 8.1,"votes": 1076167,"running_times": 10380},{"title": "The Aviator","year": 2004,"rating": 7.5,"votes": 287186,"running_times": 10200},{"title": "The Awakening","year": 2011,"rating": 6.5,"votes": 56034,"running_times": 6120},{"title": "The Awful Truth","year": 1937,"rating": 7.9,"votes": 14615,"running_times": 5460},{"title": "The BFG","year": 2016,"rating": 6.4,"votes": 58384,"running_times": 7020},{"title": "The Babadook","year": 2014,"rating": 6.8,"votes": 145814,"running_times": 5580},{"title": "The Babysitter","year": 2017,"rating": 6.4,"votes": 23750,"running_times": 5100},{"title": "The Bachelor","year": 1999,"rating": 5,"votes": 15389,"running_times": 6060},{"title": "The Back-up Plan","year": 2010,"rating": 5.3,"votes": 43572,"running_times": 6240},{"title": "The Bad Batch","year": 2016,"rating": 5.3,"votes": 12315,"running_times": 7080},{"title": "The Bad Lieutenant: Port of Call - New Orleans","year": 2009,"rating": 6.7,"votes": 67911,"running_times": 7320},{"title": "The Bad News Bears","year": 1976,"rating": 7.3,"votes": 17548,"running_times": 6120},{"title": "The Bad Seed","year": 1956,"rating": 7.5,"votes": 10625,"running_times": 7740},{"title": "The Bad and the Beautiful","year": 1952,"rating": 7.9,"votes": 10767,"running_times": 7080},{"title": "The Bag Man","year": 2014,"rating": 5.3,"votes": 14481,"running_times": 6480},{"title": "The Banger Sisters","year": 2002,"rating": 5.6,"votes": 13118,"running_times": 5880},{"title": "The Bank Job","year": 2008,"rating": 7.3,"votes": 159896,"running_times": 6660},{"title": "The Basketball Diaries","year": 1995,"rating": 7.3,"votes": 87598,"running_times": 6120},{"title": "The Bay","year": 2012,"rating": 5.6,"votes": 21848,"running_times": 5040},{"title": "The Baytown Outlaws","year": 2012,"rating": 6.4,"votes": 12067,"running_times": 5880},{"title": "The Beach","year": 2000,"rating": 6.6,"votes": 193605,"running_times": 7140},{"title": "The Beastmaster","year": 1982,"rating": 6.2,"votes": 16843,"running_times": 7080},{"title": "The Beaver","year": 2011,"rating": 6.7,"votes": 42970,"running_times": 5460},{"title": "The Beguiled","year": 1971,"rating": 7.2,"votes": 12372,"running_times": 6300},{"title": "The Beguiled","year": 2017,"rating": 6.5,"votes": 25372,"running_times": 5580},{"title": "The Believer","year": 2001,"rating": 7.2,"votes": 32765,"running_times": 5880},{"title": "The Belko Experiment","year": 2016,"rating": 6.1,"votes": 26349,"running_times": 5340},{"title": "The Benchwarmers","year": 2006,"rating": 5.6,"votes": 43224,"running_times": 4800},{"title": "The Best Exotic Marigold Hotel","year": 2011,"rating": 7.3,"votes": 80701,"running_times": 7440},{"title": "The Best Man Holiday","year": 2013,"rating": 6.7,"votes": 12444,"running_times": 7380},{"title": "The Best Years of Our Lives","year": 1946,"rating": 8.1,"votes": 45211,"running_times": 10200},{"title": "The Best of Me","year": 2014,"rating": 6.7,"votes": 52301,"running_times": 7080},{"title": "The Beverly Hillbillies","year": 1993,"rating": 4.9,"votes": 15413,"running_times": 5520},{"title": "The Big Bounce","year": 2004,"rating": 4.9,"votes": 16572,"running_times": 5280},{"title": "The Big Chill","year": 1983,"rating": 7.2,"votes": 27814,"running_times": 6300},{"title": "The Big Country","year": 1958,"rating": 7.9,"votes": 12621,"running_times": 9960},{"title": "The Big Easy","year": 1986,"rating": 6.6,"votes": 10097,"running_times": 6120},{"title": "The Big Heat","year": 1953,"rating": 8,"votes": 18479,"running_times": 5400},{"title": "The Big Hit","year": 1998,"rating": 6.1,"votes": 25926,"running_times": 5460},{"title": "The Big Kahuna","year": 1999,"rating": 6.6,"votes": 12791,"running_times": 5400},{"title": "The Big Lebowski","year": 1998,"rating": 8.2,"votes": 601049,"running_times": 7020},{"title": "The Big Red One","year": 1980,"rating": 7.2,"votes": 16487,"running_times": 9720},{"title": "The Big Short","year": 2015,"rating": 7.8,"votes": 267728,"running_times": 7800},{"title": "The Big Sick","year": 2017,"rating": 7.7,"votes": 53386,"running_times": 7200},{"title": "The Big Sleep","year": 1946,"rating": 8,"votes": 69100,"running_times": 6960},{"title": "The Big Wedding","year": 2013,"rating": 5.6,"votes": 41213,"running_times": 5340},{"title": "The Big White","year": 2005,"rating": 6.4,"votes": 12913,"running_times": 6300},{"title": "The Big Year","year": 2011,"rating": 6.2,"votes": 37408,"running_times": 6000},{"title": "The Birdcage","year": 1996,"rating": 7,"votes": 67196,"running_times": 7020},{"title": "The Birds","year": 1963,"rating": 7.7,"votes": 142556,"running_times": 7140},{"title": "The Birth of a Nation","year": 2016,"rating": 6.3,"votes": 15740,"running_times": 7200},{"title": "The Bishop's Wife","year": 1947,"rating": 7.6,"votes": 11115,"running_times": 6540},{"title": "The Black Cauldron","year": 1985,"rating": 6.5,"votes": 24726,"running_times": 4800},{"title": "The Black Dahlia","year": 2006,"rating": 5.6,"votes": 65934,"running_times": 7260},{"title": "The Black Hole","year": 1979,"rating": 5.9,"votes": 19648,"running_times": 5880},{"title": "The Blair Witch Project","year": 1999,"rating": 6.4,"votes": 204574,"running_times": 5280},{"title": "The Blind Side","year": 2009,"rating": 7.7,"votes": 245570,"running_times": 7740},{"title": "The Bling Ring","year": 2013,"rating": 5.6,"votes": 73490,"running_times": 5400},{"title": "The Blob","year": 1958,"rating": 6.4,"votes": 18288,"running_times": 5160},{"title": "The Blob","year": 1988,"rating": 6.4,"votes": 25457,"running_times": 5700},{"title": "The Blue Lagoon","year": 1980,"rating": 5.7,"votes": 54458,"running_times": 6240},{"title": "The Blues Brothers","year": 1980,"rating": 7.9,"votes": 155256,"running_times": 8880},{"title": "The Boat That Rocked","year": 2009,"rating": 7.4,"votes": 96541,"running_times": 8100},{"title": "The Bodyguard","year": 1992,"rating": 6.2,"votes": 99144,"running_times": 7740},{"title": "The Bone Collector","year": 1999,"rating": 6.7,"votes": 131239,"running_times": 7080},{"title": "The Bonfire of the Vanities","year": 1990,"rating": 5.5,"votes": 19027,"running_times": 7500},{"title": "The Book Thief","year": 2013,"rating": 7.6,"votes": 110378,"running_times": 7860},{"title": "The Book of Eli","year": 2010,"rating": 6.9,"votes": 249346,"running_times": 7080},{"title": "The Book of Life","year": 2014,"rating": 7.3,"votes": 53590,"running_times": 5700},{"title": "The Boondock Saints","year": 1999,"rating": 7.9,"votes": 208050,"running_times": 6480},{"title": "The Boondock Saints II: All Saints Day","year": 2009,"rating": 6.3,"votes": 56167,"running_times": 8280},{"title": "The Borrowers","year": 1997,"rating": 5.8,"votes": 17522,"running_times": 5340},{"title": "The Boss","year": 2016,"rating": 5.4,"votes": 32380,"running_times": 6240},{"title": "The Boss Baby","year": 2017,"rating": 6.4,"votes": 63831,"running_times": 5820},{"title": "The Bounty","year": 1984,"rating": 7.1,"votes": 19851,"running_times": 7920},{"title": "The Bounty Hunter","year": 2010,"rating": 5.5,"votes": 104853,"running_times": 6600},{"title": "The Bourne Identity","year": 2002,"rating": 7.9,"votes": 446706,"running_times": 7140},{"title": "The Bourne Legacy","year": 2012,"rating": 6.7,"votes": 252525,"running_times": 8100},{"title": "The Bourne Supremacy","year": 2004,"rating": 7.8,"votes": 383149,"running_times": 6480},{"title": "The Bourne Ultimatum","year": 2007,"rating": 8.1,"votes": 543338,"running_times": 6900},{"title": "The Box","year": 2009,"rating": 5.6,"votes": 81032,"running_times": 6900},{"title": "The Boxer","year": 1997,"rating": 7.1,"votes": 15626,"running_times": 6780},{"title": "The Boxtrolls","year": 2014,"rating": 6.8,"votes": 47051,"running_times": 5760},{"title": "The Boy","year": 2016,"rating": 6,"votes": 57479,"running_times": 5820},{"title": "The Boy Next Door","year": 2015,"rating": 4.7,"votes": 31552,"running_times": 5460},{"title": "The Boy in the Striped Pyjamas","year": 2008,"rating": 7.8,"votes": 152019,"running_times": 5640},{"title": "The Boys from Brazil","year": 1978,"rating": 7,"votes": 22147,"running_times": 7500},{"title": "The Brady Bunch Movie","year": 1995,"rating": 5.9,"votes": 18341,"running_times": 5400},{"title": "The Brass Teapot","year": 2012,"rating": 6.4,"votes": 12898,"running_times": 6060},{"title": "The Brave Little Toaster","year": 1987,"rating": 7.3,"votes": 21079,"running_times": 5400},{"title": "The Brave One","year": 2007,"rating": 6.8,"votes": 53271,"running_times": 7320},{"title": "The Break-Up","year": 2006,"rating": 5.8,"votes": 109364,"running_times": 6360},{"title": "The Breakfast Club","year": 1985,"rating": 7.9,"votes": 288451,"running_times": 5820},{"title": "The Breed","year": 2006,"rating": 5.1,"votes": 10967,"running_times": 5460},{"title": "The Bridge","year": 2006,"rating": 7.3,"votes": 10012,"running_times": 5640},{"title": "The Bridge on the River Kwai","year": 1957,"rating": 8.2,"votes": 166597,"running_times": 9660},{"title": "The Bridges of Madison County","year": 1995,"rating": 7.6,"votes": 59681,"running_times": 8100},{"title": "The Broken Circle Breakdown","year": 2012,"rating": 7.8,"votes": 33487,"running_times": 6660},{"title": "The Brood","year": 1979,"rating": 6.9,"votes": 20386,"running_times": 5520},{"title": "The Brothers Bloom","year": 2008,"rating": 6.8,"votes": 44152,"running_times": 6840},{"title": "The Brothers Grimm","year": 2005,"rating": 5.9,"votes": 104533,"running_times": 7080},{"title": "The Brown Bunny","year": 2003,"rating": 5,"votes": 12246,"running_times": 5580},{"title": "The Bucket List","year": 2007,"rating": 7.4,"votes": 200761,"running_times": 5820},{"title": "The Burning","year": 1981,"rating": 6.5,"votes": 12063,"running_times": 5460},{"title": "The Burning Plain","year": 2008,"rating": 6.8,"votes": 16532,"running_times": 6660},{"title": "The Business","year": 2005,"rating": 6.7,"votes": 11837,"running_times": 5820},{"title": "The Butler","year": 2013,"rating": 7.2,"votes": 95749,"running_times": 7920},{"title": "The Butterfly Effect","year": 2004,"rating": 7.7,"votes": 391975,"running_times": 7200},{"title": "The Butterfly Effect 3: Revelations","year": 2009,"rating": 5.6,"votes": 16592,"running_times": 6300},{"title": "The Bye Bye Man","year": 2017,"rating": 4.3,"votes": 11949,"running_times": 6060},{"title": "The Cabin in the Woods","year": 2012,"rating": 7,"votes": 308636,"running_times": 5700},{"title": "The Cable Guy","year": 1996,"rating": 6.1,"votes": 132035,"running_times": 5760},{"title": "The Caine Mutiny","year": 1954,"rating": 7.9,"votes": 21348,"running_times": 7500},{"title": "The Call","year": 2013,"rating": 6.7,"votes": 96999,"running_times": 5640},{"title": "The Campaign","year": 2012,"rating": 6.1,"votes": 112910,"running_times": 5760},{"title": "The Canal","year": 2014,"rating": 5.9,"votes": 10928,"running_times": 5520},{"title": "The Cannonball Run","year": 1981,"rating": 6.2,"votes": 27997,"running_times": 5700},{"title": "The Captive","year": 2014,"rating": 5.9,"votes": 22667,"running_times": 6720},{"title": "The Castle","year": 1997,"rating": 7.7,"votes": 12869,"running_times": 5100},{"title": "The Cat in the Hat","year": 2003,"rating": 3.8,"votes": 40048,"running_times": 4920},{"title": "The Cave","year": 2005,"rating": 5.1,"votes": 30609,"running_times": 5820},{"title": "The Cell","year": 2000,"rating": 6.3,"votes": 84984,"running_times": 6540},{"title": "The Chamber","year": 1996,"rating": 6,"votes": 11124,"running_times": 6780},{"title": "The Change-Up","year": 2011,"rating": 6.3,"votes": 145281,"running_times": 7080},{"title": "The Changeling","year": 1980,"rating": 7.3,"votes": 23916,"running_times": 6420},{"title": "The Chase","year": 1994,"rating": 5.8,"votes": 15334,"running_times": 5640},{"title": "The Children","year": 2008,"rating": 6,"votes": 15438,"running_times": 5040},{"title": "The Children's Hour","year": 1961,"rating": 7.8,"votes": 11701,"running_times": 6480},{"title": "The China Syndrome","year": 1979,"rating": 7.4,"votes": 22339,"running_times": 7320},{"title": "The Choice","year": 2016,"rating": 6.6,"votes": 24018,"running_times": 6660},{"title": "The Chronicles of Narnia: Prince Caspian","year": 2008,"rating": 6.6,"votes": 164777,"running_times": 9000},{"title": "The Chronicles of Narnia: The Lion, the Witch and the Wardrobe","year": 2005,"rating": 6.9,"votes": 314354,"running_times": 9000},{"title": "The Chronicles of Narnia: The Voyage of the Dawn Treader","year": 2010,"rating": 6.3,"votes": 117763,"running_times": 6780},{"title": "The Chronicles of Riddick","year": 2004,"rating": 6.7,"votes": 195033,"running_times": 8040},{"title": "The Chumscrubber","year": 2005,"rating": 7,"votes": 16830,"running_times": 6480},{"title": "The Cider House Rules","year": 1999,"rating": 7.4,"votes": 83846,"running_times": 7560},{"title": "The Cincinnati Kid","year": 1965,"rating": 7.3,"votes": 12747,"running_times": 6120},{"title": "The Circle","year": 2017,"rating": 5.3,"votes": 49927,"running_times": 6600},{"title": "The Circus","year": 1928,"rating": 8.1,"votes": 20578,"running_times": 4320},{"title": "The Clearing","year": 2004,"rating": 5.9,"votes": 12264,"running_times": 5700},{"title": "The Client","year": 1994,"rating": 6.7,"votes": 50194,"running_times": 7140},{"title": "The Cobbler","year": 2014,"rating": 5.8,"votes": 42876,"running_times": 5940},{"title": "The Cold Light of Day","year": 2012,"rating": 4.9,"votes": 31139,"running_times": 5580},{"title": "The Collection","year": 2012,"rating": 6.1,"votes": 39094,"running_times": 4920},{"title": "The Collector","year": 2009,"rating": 6.4,"votes": 47976,"running_times": 5400},{"title": "The Colony","year": 2013,"rating": 5.3,"votes": 38078,"running_times": 5700},{"title": "The Color Purple","year": 1985,"rating": 7.8,"votes": 66127,"running_times": 9240},{"title": "The Color of Money","year": 1986,"rating": 7,"votes": 63117,"running_times": 7140},{"title": "The Comebacks","year": 2007,"rating": 4.2,"votes": 10359,"running_times": 6420},{"title": "The Commitments","year": 1991,"rating": 7.6,"votes": 28042,"running_times": 7080},{"title": "The Company Men","year": 2010,"rating": 6.8,"votes": 38949,"running_times": 6240},{"title": "The Company You Keep","year": 2012,"rating": 6.4,"votes": 28047,"running_times": 7500},{"title": "The Company of Wolves","year": 1984,"rating": 6.8,"votes": 12490,"running_times": 5700},{"title": "The Condemned","year": 2007,"rating": 6.1,"votes": 46846,"running_times": 6840},{"title": "The Congress","year": 2013,"rating": 6.5,"votes": 14545,"running_times": 7320},{"title": "The Conjuring","year": 2013,"rating": 7.5,"votes": 348698,"running_times": 6720},{"title": "The Conjuring 2","year": 2016,"rating": 7.4,"votes": 157206,"running_times": 8040},{"title": "The Conspirator","year": 2010,"rating": 6.9,"votes": 25221,"running_times": 7320},{"title": "The Constant Gardener","year": 2005,"rating": 7.5,"votes": 118632,"running_times": 7740},{"title": "The Contender","year": 2000,"rating": 7,"votes": 21284,"running_times": 7560},{"title": "The Contract","year": 2006,"rating": 5.7,"votes": 21488,"running_times": 5760},{"title": "The Conversation","year": 1974,"rating": 7.9,"votes": 81291,"running_times": 6780},{"title": "The Cook, the Thief, His Wife & Her Lover","year": 1989,"rating": 7.6,"votes": 29255,"running_times": 7440},{"title": "The Cooler","year": 2003,"rating": 7,"votes": 29684,"running_times": 6060},{"title": "The Core","year": 2003,"rating": 5.5,"votes": 81833,"running_times": 8100},{"title": "The Corporation","year": 2003,"rating": 8.1,"votes": 18984,"running_times": 9900},{"title": "The Corruptor","year": 1999,"rating": 6,"votes": 16047,"running_times": 6600},{"title": "The Cottage","year": 2008,"rating": 6.1,"votes": 10703,"running_times": 5520},{"title": "The Cotton Club","year": 1984,"rating": 6.5,"votes": 13741,"running_times": 7620},{"title": "The Counselor","year": 2013,"rating": 5.3,"votes": 87224,"running_times": 8280},{"title": "The Count of Monte Cristo","year": 2002,"rating": 7.8,"votes": 112596,"running_times": 8040},{"title": "The Cove","year": 2009,"rating": 8.5,"votes": 43055,"running_times": 5520},{"title": "The Covenant","year": 2006,"rating": 5.3,"votes": 41822,"running_times": 5820},{"title": "The Cowboys","year": 1972,"rating": 7.4,"votes": 11123,"running_times": 8040},{"title": "The Craft","year": 1996,"rating": 6.3,"votes": 63253,"running_times": 6060},{"title": "The Crazies","year": 2010,"rating": 6.5,"votes": 99111,"running_times": 6060},{"title": "The Croods","year": 2013,"rating": 7.2,"votes": 164945,"running_times": 5880},{"title": "The Crossing Guard","year": 1995,"rating": 6.3,"votes": 11372,"running_times": 6660},{"title": "The Crow","year": 1994,"rating": 7.6,"votes": 146355,"running_times": 6120},{"title": "The Crow: City of Angels","year": 1996,"rating": 4.6,"votes": 16864,"running_times": 5040},{"title": "The Crucible","year": 1996,"rating": 6.8,"votes": 31119,"running_times": 7440},{"title": "The Crush","year": 1993,"rating": 5.7,"votes": 13065,"running_times": 5340},{"title": "The Crying Game","year": 1992,"rating": 7.3,"votes": 44414,"running_times": 6720},{"title": "The Curious Case of Benjamin Button","year": 2008,"rating": 7.8,"votes": 501739,"running_times": 9960},{"title": "The Curse of the Jade Scorpion","year": 2001,"rating": 6.8,"votes": 34156,"running_times": 6180},{"title": "The Curse of the Were-Rabbit","year": 2005,"rating": 7.5,"votes": 106749,"running_times": 5100},{"title": "The Cutting Edge","year": 1992,"rating": 6.9,"votes": 16136,"running_times": 6060},{"title": "The DUFF","year": 2015,"rating": 6.5,"votes": 61918,"running_times": 6060},{"title": "The Da Vinci Code","year": 2006,"rating": 6.6,"votes": 348542,"running_times": 10440},{"title": "The Damned United","year": 2009,"rating": 7.6,"votes": 35342,"running_times": 5880},{"title": "The Dangerous Lives of Altar Boys","year": 2002,"rating": 7.1,"votes": 12389,"running_times": 6300},{"title": "The Danish Girl","year": 2015,"rating": 7.1,"votes": 121304,"running_times": 7140},{"title": "The Darjeeling Limited","year": 2007,"rating": 7.2,"votes": 151549,"running_times": 5460},{"title": "The Dark Crystal","year": 1982,"rating": 7.2,"votes": 45775,"running_times": 5580},{"title": "The Dark Half","year": 1993,"rating": 5.9,"votes": 13163,"running_times": 7320},{"title": "The Dark Knight","year": 2008,"rating": 9,"votes": 1864164,"running_times": 9120},{"title": "The Dark Knight Rises","year": 2012,"rating": 8.4,"votes": 1269255,"running_times": 9840},{"title": "The Dark Tower","year": 2017,"rating": 5.7,"votes": 69330,"running_times": 5700},{"title": "The Darkest Hour","year": 2011,"rating": 4.9,"votes": 52123,"running_times": 5340},{"title": "The Day","year": 2011,"rating": 5.2,"votes": 11245,"running_times": 5760},{"title": "The Day After Tomorrow","year": 2004,"rating": 6.4,"votes": 360260,"running_times": 7440},{"title": "The Day of the Jackal","year": 1973,"rating": 7.8,"votes": 31843,"running_times": 8580},{"title": "The Day the Earth Stood Still","year": 1951,"rating": 7.8,"votes": 68463,"running_times": 5520},{"title": "The Day the Earth Stood Still","year": 2008,"rating": 5.5,"votes": 147772,"running_times": 6240},{"title": "The Dead Girl","year": 2006,"rating": 6.7,"votes": 13077,"running_times": 6600},{"title": "The Dead Pool","year": 1988,"rating": 6.3,"votes": 33680,"running_times": 5460},{"title": "The Dead Zone","year": 1983,"rating": 7.2,"votes": 49908,"running_times": 6180},{"title": "The Death and Life of Bobby Z","year": 2007,"rating": 5.9,"votes": 12779,"running_times": 5820},{"title": "The Deaths of Ian Stone","year": 2007,"rating": 5.6,"votes": 11779,"running_times": 5220},{"title": "The Debt","year": 2010,"rating": 6.9,"votes": 58446,"running_times": 6780},{"title": "The Deep Blue Sea","year": 2011,"rating": 6.3,"votes": 12745,"running_times": 5880},{"title": "The Deep End","year": 2001,"rating": 6.7,"votes": 10170,"running_times": 6060},{"title": "The Deep End of the Ocean","year": 1999,"rating": 6.3,"votes": 11230,"running_times": 6360},{"title": "The Deer Hunter","year": 1978,"rating": 8.2,"votes": 257892,"running_times": 10980},{"title": "The Defiant Ones","year": 1958,"rating": 7.7,"votes": 10512,"running_times": 5760},{"title": "The Delta Force","year": 1986,"rating": 5.6,"votes": 16009,"running_times": 7740},{"title": "The Den","year": 2013,"rating": 6.1,"votes": 10840,"running_times": 4860},{"title": "The Departed","year": 2006,"rating": 8.5,"votes": 975301,"running_times": 9060},{"title": "The Descendants","year": 2011,"rating": 7.3,"votes": 215007,"running_times": 6900},{"title": "The Descent","year": 2005,"rating": 7.2,"votes": 170442,"running_times": 6000},{"title": "The Descent: Part 2","year": 2009,"rating": 5.8,"votes": 35987,"running_times": 5640},{"title": "The Devil Inside","year": 2012,"rating": 4.2,"votes": 32082,"running_times": 4980},{"title": "The Devil Wears Prada","year": 2006,"rating": 6.8,"votes": 311658,"running_times": 6540},{"title": "The Devil's Advocate","year": 1997,"rating": 7.5,"votes": 282173,"running_times": 8640},{"title": "The Devil's Double","year": 2011,"rating": 7.1,"votes": 56407,"running_times": 6540},{"title": "The Devil's Own","year": 1997,"rating": 6.1,"votes": 49873,"running_times": 6660},{"title": "The Devil's Rejects","year": 2005,"rating": 6.9,"votes": 81531,"running_times": 6540},{"title": "The Devils","year": 1971,"rating": 7.8,"votes": 10094,"running_times": 7020},{"title": "The Diary of Anne Frank","year": 1959,"rating": 7.4,"votes": 10181,"running_times": 10800},{"title": "The Diary of a Teenage Girl","year": 2015,"rating": 6.9,"votes": 23775,"running_times": 6120},{"title": "The Dictator","year": 2012,"rating": 6.4,"votes": 232383,"running_times": 5940},{"title": "The Dilemma","year": 2011,"rating": 5.3,"votes": 46181,"running_times": 6660},{"title": "The Dirty Dozen","year": 1967,"rating": 7.8,"votes": 57460,"running_times": 9000},{"title": "The Disappearance of Alice Creed","year": 2009,"rating": 6.8,"votes": 22306,"running_times": 6000},{"title": "The Disaster Artist","year": 2017,"rating": 8.1,"votes": 13911,"running_times": 6240},{"title": "The Discovery","year": 2017,"rating": 6.3,"votes": 18069,"running_times": 6120},{"title": "The Dish","year": 2000,"rating": 7.2,"votes": 13534,"running_times": 6060},{"title": "The Distinguished Gentleman","year": 1992,"rating": 5.9,"votes": 13275,"running_times": 6720},{"title": "The Divide","year": 2011,"rating": 5.8,"votes": 32184,"running_times": 7320},{"title": "The Do-Over","year": 2016,"rating": 5.7,"votes": 27382,"running_times": 6480},{"title": "The Doom Generation","year": 1995,"rating": 6,"votes": 12220,"running_times": 4980},{"title": "The Door in the Floor","year": 2004,"rating": 6.7,"votes": 14022,"running_times": 6660},{"title": "The Doors","year": 1991,"rating": 7.2,"votes": 73120,"running_times": 8400},{"title": "The Double","year": 2011,"rating": 5.9,"votes": 25630,"running_times": 5880},{"title": "The Double","year": 2013,"rating": 6.5,"votes": 40539,"running_times": 5580},{"title": "The Dream Team","year": 1989,"rating": 6.5,"votes": 10878,"running_times": 6780},{"title": "The Dreamers","year": 2003,"rating": 7.2,"votes": 91059,"running_times": 6900},{"title": "The Dressmaker","year": 2015,"rating": 7.1,"votes": 38252,"running_times": 7140},{"title": "The Driver","year": 1978,"rating": 7.2,"votes": 10892,"running_times": 7860},{"title": "The Drop","year": 2014,"rating": 7.1,"votes": 121549,"running_times": 6360},{"title": "The Duchess","year": 2008,"rating": 6.9,"votes": 67201,"running_times": 6600},{"title": "The Duellists","year": 1977,"rating": 7.5,"votes": 16242,"running_times": 6000},{"title": "The Dukes of Hazzard","year": 2005,"rating": 5.1,"votes": 69430,"running_times": 6420},{"title": "The Dyatlov Pass Incident","year": 2013,"rating": 5.7,"votes": 18197,"running_times": 6000},{"title": "The Eagle","year": 2011,"rating": 6.2,"votes": 57714,"running_times": 6840},{"title": "The Eagle Has Landed","year": 1976,"rating": 6.9,"votes": 15561,"running_times": 8700},{"title": "The East","year": 2013,"rating": 6.8,"votes": 44769,"running_times": 6960},{"title": "The Edge","year": 1997,"rating": 6.9,"votes": 60012,"running_times": 7020},{"title": "The Edge of Love","year": 2008,"rating": 6.3,"votes": 14525,"running_times": 6600},{"title": "The Edge of Seventeen","year": 2016,"rating": 7.4,"votes": 64320,"running_times": 6240},{"title": "The Eiger Sanction","year": 1975,"rating": 6.4,"votes": 14326,"running_times": 7740},{"title": "The Elephant Man","year": 1980,"rating": 8.2,"votes": 180762,"running_times": 7440},{"title": "The Emoji Movie","year": 2017,"rating": 2.9,"votes": 30594,"running_times": 5160},{"title": "The Emperor's Club","year": 2002,"rating": 6.9,"votes": 15186,"running_times": 6540},{"title": "The Emperor's New Groove","year": 2000,"rating": 7.3,"votes": 143961,"running_times": 4680},{"title": "The End of the Affair","year": 1999,"rating": 7.2,"votes": 18879,"running_times": 6120},{"title": "The End of the Tour","year": 2015,"rating": 7.3,"votes": 22666,"running_times": 6360},{"title": "The Enforcer","year": 1976,"rating": 6.8,"votes": 34977,"running_times": 5760},{"title": "The English Patient","year": 1996,"rating": 7.4,"votes": 154290,"running_times": 15000},{"title": "The English Teacher","year": 2013,"rating": 5.8,"votes": 10264,"running_times": 5580},{"title": "The Englishman Who Went Up a Hill But Came Down a Mountain","year": 1995,"rating": 6.6,"votes": 14515,"running_times": 5940},{"title": "The Entity","year": 1982,"rating": 6.6,"votes": 12185,"running_times": 7500},{"title": "The Equalizer","year": 2014,"rating": 7.2,"votes": 257869,"running_times": 7920},{"title": "The Escapist","year": 2008,"rating": 6.8,"votes": 15325,"running_times": 6120},{"title": "The Evil Dead","year": 1981,"rating": 7.5,"votes": 156301,"running_times": 5100},{"title": "The Exorcism of Emily Rose","year": 2005,"rating": 6.7,"votes": 104459,"running_times": 7320},{"title": "The Exorcist","year": 1973,"rating": 8,"votes": 308000,"running_times": 7920},{"title": "The Exorcist III","year": 1990,"rating": 6.3,"votes": 19690,"running_times": 6600},{"title": "The Expendables","year": 2010,"rating": 6.5,"votes": 291039,"running_times": 6780},{"title": "The Expendables 2","year": 2012,"rating": 6.6,"votes": 263602,"running_times": 6180},{"title": "The Expendables 3","year": 2014,"rating": 6.1,"votes": 143428,"running_times": 7860},{"title": "The Experiment","year": 2010,"rating": 6.4,"votes": 45286,"running_times": 5760},{"title": "The Express","year": 2008,"rating": 7.3,"votes": 17692,"running_times": 7800},{"title": "The Eye","year": 2008,"rating": 5.4,"votes": 46769,"running_times": 5880},{"title": "The F Word","year": 2013,"rating": 6.8,"votes": 58518,"running_times": 5880},{"title": "The Fabulous Baker Boys","year": 1989,"rating": 6.8,"votes": 18943,"running_times": 6840},{"title": "The Faculty","year": 1998,"rating": 6.5,"votes": 97855,"running_times": 6240},{"title": "The Fall","year": 2006,"rating": 7.9,"votes": 95904,"running_times": 7020},{"title": "The Family","year": 2013,"rating": 6.3,"votes": 96336,"running_times": 6660},{"title": "The Family Man","year": 2000,"rating": 6.7,"votes": 91526,"running_times": 7500},{"title": "The Family Stone","year": 2005,"rating": 6.3,"votes": 52823,"running_times": 6180},{"title": "The Fan","year": 1996,"rating": 5.8,"votes": 41100,"running_times": 6960},{"title": "The Fast and the Furious","year": 2001,"rating": 6.7,"votes": 298782,"running_times": 6360},{"title": "The Fast and the Furious: Tokyo Drift","year": 2006,"rating": 6,"votes": 201378,"running_times": 6240},{"title": "The Fate of the Furious","year": 2017,"rating": 6.8,"votes": 145524,"running_times": 8940},{"title": "The Fault in Our Stars","year": 2014,"rating": 7.8,"votes": 284557,"running_times": 7980},{"title": "The Fifth Estate","year": 2013,"rating": 6.2,"votes": 33032,"running_times": 7680},{"title": "The Fighter","year": 2010,"rating": 7.8,"votes": 297659,"running_times": 6960},{"title": "The Final Conflict","year": 1981,"rating": 5.6,"votes": 15344,"running_times": 6480},{"title": "The Final Countdown","year": 1980,"rating": 6.7,"votes": 17625,"running_times": 6180},{"title": "The Final Cut","year": 2004,"rating": 6.2,"votes": 28220,"running_times": 5700},{"title": "The Final Destination","year": 2009,"rating": 5.2,"votes": 82313,"running_times": 4920},{"title": "The Final Girls","year": 2015,"rating": 6.6,"votes": 25800,"running_times": 5280},{"title": "The Finest Hours","year": 2016,"rating": 6.8,"votes": 49089,"running_times": 7020},{"title": "The Firm","year": 1993,"rating": 6.8,"votes": 96653,"running_times": 9240},{"title": "The First Great Train Robbery","year": 1978,"rating": 7,"votes": 12833,"running_times": 6600},{"title": "The First Time","year": 2012,"rating": 6.9,"votes": 56573,"running_times": 5700},{"title": "The First Wives Club","year": 1996,"rating": 6.2,"votes": 35126,"running_times": 6180},{"title": "The Fisher King","year": 1991,"rating": 7.6,"votes": 68514,"running_times": 8220},{"title": "The Five-Year Engagement","year": 2012,"rating": 6.2,"votes": 83519,"running_times": 7860},{"title": "The Flight of the Phoenix","year": 1965,"rating": 7.6,"votes": 16592,"running_times": 8520},{"title": "The Flintstones","year": 1994,"rating": 4.8,"votes": 65040,"running_times": 5460},{"title": "The Flintstones in Viva Rock Vegas","year": 2000,"rating": 3.6,"votes": 17059,"running_times": 5400},{"title": "The Flock","year": 2007,"rating": 5.7,"votes": 10214,"running_times": 6300},{"title": "The Fly","year": 1958,"rating": 7.1,"votes": 17323,"running_times": 5640},{"title": "The Fly","year": 1986,"rating": 7.5,"votes": 131951,"running_times": 5760},{"title": "The Fly II","year": 1989,"rating": 4.9,"votes": 18231,"running_times": 6300},{"title": "The Fog","year": 1980,"rating": 6.8,"votes": 51466,"running_times": 5340},{"title": "The Fog","year": 2005,"rating": 3.6,"votes": 31194,"running_times": 6180},{"title": "The Fog of War: Eleven Lessons from the Life of Robert S. McNamara","year": 2003,"rating": 8.2,"votes": 20482,"running_times": 6420},{"title": "The Football Factory","year": 2004,"rating": 6.9,"votes": 25482,"running_times": 5460},{"title": "The Forbidden Kingdom","year": 2008,"rating": 6.6,"votes": 92869,"running_times": 6240},{"title": "The Foreigner","year": 2017,"rating": 7.2,"votes": 20056,"running_times": 6780},{"title": "The Forest","year": 2016,"rating": 4.8,"votes": 31517,"running_times": 5580},{"title": "The Forgotten","year": 2004,"rating": 5.8,"votes": 59837,"running_times": 5640},{"title": "The Fortune Cookie","year": 1966,"rating": 7.4,"votes": 10116,"running_times": 7500},{"title": "The Founder","year": 2016,"rating": 7.2,"votes": 69763,"running_times": 6900},{"title": "The Fountain","year": 2006,"rating": 7.3,"votes": 205452,"running_times": 5760},{"title": "The Four Feathers","year": 2002,"rating": 6.5,"votes": 29710,"running_times": 7920},{"title": "The Fourth Kind","year": 2009,"rating": 5.9,"votes": 66763,"running_times": 5880},{"title": "The Fox and the Hound","year": 1981,"rating": 7.3,"votes": 70116,"running_times": 4980},{"title": "The French Connection","year": 1971,"rating": 7.8,"votes": 91035,"running_times": 6240},{"title": "The Freshman","year": 1990,"rating": 6.5,"votes": 16664,"running_times": 6120},{"title": "The Frighteners","year": 1996,"rating": 7.1,"votes": 72402,"running_times": 7380},{"title": "The Front Page","year": 1974,"rating": 7.4,"votes": 10029,"running_times": 6300},{"title": "The Frozen Ground","year": 2013,"rating": 6.4,"votes": 47639,"running_times": 6300},{"title": "The Fugitive","year": 1993,"rating": 7.8,"votes": 229254,"running_times": 7800},{"title": "The Full Monty","year": 1997,"rating": 7.2,"votes": 87658,"running_times": 5460},{"title": "The Fundamentals of Caring","year": 2016,"rating": 7.3,"votes": 37504,"running_times": 5820},{"title": "The Fury","year": 1978,"rating": 6.4,"votes": 10870,"running_times": 7080},{"title": "The Gallows","year": 2015,"rating": 4.2,"votes": 16251,"running_times": 4860},{"title": "The Gambler","year": 2014,"rating": 6,"votes": 54739,"running_times": 6660},{"title": "The Game","year": 1997,"rating": 7.8,"votes": 289122,"running_times": 7740},{"title": "The Game Plan","year": 2007,"rating": 6.2,"votes": 48546,"running_times": 6600},{"title": "The Gate","year": 1987,"rating": 6,"votes": 11654,"running_times": 5100},{"title": "The Gauntlet","year": 1977,"rating": 6.4,"votes": 17358,"running_times": 6540},{"title": "The General","year": 1926,"rating": 8.2,"votes": 60825,"running_times": 6420},{"title": "The General's Daughter","year": 1999,"rating": 6.3,"votes": 45863,"running_times": 6960},{"title": "The Getaway","year": 1972,"rating": 7.5,"votes": 23131,"running_times": 7380},{"title": "The Getaway","year": 1994,"rating": 5.7,"votes": 15013,"running_times": 6960},{"title": "The Ghost Writer","year": 2010,"rating": 7.2,"votes": 141312,"running_times": 7680},{"title": "The Ghost and Mrs. Muir","year": 1947,"rating": 7.9,"votes": 12874,"running_times": 6240},{"title": "The Ghost and the Darkness","year": 1996,"rating": 6.8,"votes": 49449,"running_times": 6600},{"title": "The Gift","year": 2000,"rating": 6.7,"votes": 55680,"running_times": 6720},{"title": "The Gift","year": 2015,"rating": 7.1,"votes": 105875,"running_times": 6480},{"title": "The Girl Next Door","year": 2004,"rating": 6.8,"votes": 181517,"running_times": 6600},{"title": "The Girl Next Door","year": 2007,"rating": 6.7,"votes": 19959,"running_times": 5460},{"title": "The Girl on the Train","year": 2016,"rating": 6.5,"votes": 122564,"running_times": 6720},{"title": "The Girl with All the Gifts","year": 2016,"rating": 6.7,"votes": 35303,"running_times": 6660},{"title": "The Girl with the Dragon Tattoo","year": 2011,"rating": 7.8,"votes": 360665,"running_times": 9480},{"title": "The Girlfriend Experience","year": 2009,"rating": 5.5,"votes": 14540,"running_times": 4620},{"title": "The Giver","year": 2014,"rating": 6.5,"votes": 97577,"running_times": 5820},{"title": "The Glass House","year": 2001,"rating": 5.8,"votes": 27338,"running_times": 6360},{"title": "The Glimmer Man","year": 1996,"rating": 5.3,"votes": 16552,"running_times": 5460},{"title": "The Godfather","year": 1972,"rating": 9.2,"votes": 1289428,"running_times": 10500},{"title": "The Godfather: Part II","year": 1974,"rating": 9,"votes": 889607,"running_times": 13200},{"title": "The Godfather: Part III","year": 1990,"rating": 7.6,"votes": 299652,"running_times": 10200},{"title": "The Gods Must Be Crazy","year": 1980,"rating": 7.3,"votes": 46369,"running_times": 6540},{"title": "The Gods Must Be Crazy II","year": 1989,"rating": 6.8,"votes": 13913,"running_times": 5880},{"title": "The Gold Rush","year": 1925,"rating": 8.2,"votes": 77314,"running_times": 5700},{"title": "The Golden Child","year": 1986,"rating": 5.9,"votes": 43511,"running_times": 5640},{"title": "The Golden Compass","year": 2007,"rating": 6.1,"votes": 158622,"running_times": 6780},{"title": "The Good Dinosaur","year": 2015,"rating": 6.7,"votes": 82278,"running_times": 5580},{"title": "The Good German","year": 2006,"rating": 6.1,"votes": 22383,"running_times": 6300},{"title": "The Good Girl","year": 2002,"rating": 6.5,"votes": 39827,"running_times": 5580},{"title": "The Good Lie","year": 2014,"rating": 7.4,"votes": 23071,"running_times": 6600},{"title": "The Good Neighbor","year": 2016,"rating": 6.3,"votes": 10679,"running_times": 5880},{"title": "The Good Shepherd","year": 2006,"rating": 6.7,"votes": 90768,"running_times": 10020},{"title": "The Good Son","year": 1993,"rating": 6.4,"votes": 30990,"running_times": 5220},{"title": "The Goodbye Girl","year": 1977,"rating": 7.4,"votes": 10241,"running_times": 6660},{"title": "The Goods: Live Hard, Sell Hard","year": 2009,"rating": 5.8,"votes": 18442,"running_times": 5340},{"title": "The Goonies","year": 1985,"rating": 7.8,"votes": 197148,"running_times": 6840},{"title": "The Graduate","year": 1967,"rating": 8,"votes": 224868,"running_times": 6360},{"title": "The Grand Budapest Hotel","year": 2014,"rating": 8.1,"votes": 561138,"running_times": 5940},{"title": "The Grand Seduction","year": 2013,"rating": 7,"votes": 13205,"running_times": 6780},{"title": "The Grapes of Wrath","year": 1940,"rating": 8.1,"votes": 70651,"running_times": 7740},{"title": "The Great Buck Howard","year": 2008,"rating": 6.5,"votes": 12430,"running_times": 5400},{"title": "The Great Debaters","year": 2007,"rating": 7.6,"votes": 50698,"running_times": 7560},{"title": "The Great Dictator","year": 1940,"rating": 8.5,"votes": 157821,"running_times": 7500},{"title": "The Great Escape","year": 1963,"rating": 8.2,"votes": 184206,"running_times": 10320},{"title": "The Great Gatsby","year": 1974,"rating": 6.4,"votes": 20793,"running_times": 8640},{"title": "The Great Gatsby","year": 2013,"rating": 7.3,"votes": 399342,"running_times": 8580},{"title": "The Great Mouse Detective","year": 1986,"rating": 7.2,"votes": 37022,"running_times": 4440},{"title": "The Great Muppet Caper","year": 1981,"rating": 7.2,"votes": 11033,"running_times": 5820},{"title": "The Great Outdoors","year": 1988,"rating": 6.6,"votes": 31809,"running_times": 5460},{"title": "The Great Race","year": 1965,"rating": 7.3,"votes": 13583,"running_times": 9600},{"title": "The Great Raid","year": 2005,"rating": 6.7,"votes": 19473,"running_times": 7920},{"title": "The Great Train Robbery","year": 1903,"rating": 7.3,"votes": 13461,"running_times": 660},{"title": "The Great Wall","year": 2016,"rating": 6,"votes": 89046,"running_times": 6180},{"title": "The Greatest Game Ever Played","year": 2005,"rating": 7.5,"votes": 24027,"running_times": 7200},{"title": "The Greatest Movie Ever Sold","year": 2011,"rating": 6.6,"votes": 13836,"running_times": 5400},{"title": "The Greatest Show on Earth","year": 1952,"rating": 6.7,"votes": 10459,"running_times": 9120},{"title": "The Green Berets","year": 1968,"rating": 5.7,"votes": 10562,"running_times": 8520},{"title": "The Green Hornet","year": 2011,"rating": 5.8,"votes": 142985,"running_times": 7140},{"title": "The Green Inferno","year": 2013,"rating": 5.3,"votes": 29044,"running_times": 6000},{"title": "The Green Mile","year": 1999,"rating": 8.5,"votes": 894678,"running_times": 11340},{"title": "The Grey","year": 2011,"rating": 6.8,"votes": 216353,"running_times": 7020},{"title": "The Grifters","year": 1990,"rating": 7,"votes": 22164,"running_times": 6600},{"title": "The Grudge","year": 2004,"rating": 5.9,"votes": 124345,"running_times": 5880},{"title": "The Grudge 2","year": 2006,"rating": 5,"votes": 41766,"running_times": 8220},{"title": "The Grudge 3","year": 2009,"rating": 4.7,"votes": 14317,"running_times": 5400},{"title": "The Guard","year": 2011,"rating": 7.3,"votes": 70283,"running_times": 5760},{"title": "The Guardian","year": 2006,"rating": 6.9,"votes": 79495,"running_times": 8340},{"title": "The Guest","year": 2014,"rating": 6.7,"votes": 74941,"running_times": 6000},{"title": "The Guilt Trip","year": 2012,"rating": 5.8,"votes": 32258,"running_times": 5700},{"title": "The Gunman","year": 2015,"rating": 5.8,"votes": 32856,"running_times": 6900},{"title": "The Guns of Navarone","year": 1961,"rating": 7.6,"votes": 38967,"running_times": 9480},{"title": "The Guru","year": 2002,"rating": 5.4,"votes": 13997,"running_times": 5640},{"title": "The Hallow","year": 2015,"rating": 5.7,"votes": 11871,"running_times": 5820},{"title": "The Hand That Rocks the Cradle","year": 1992,"rating": 6.6,"votes": 32195,"running_times": 6600},{"title": "The Hangover","year": 2009,"rating": 7.7,"votes": 628581,"running_times": 6480},{"title": "The Hangover Part II","year": 2011,"rating": 6.5,"votes": 405784,"running_times": 6120},{"title": "The Hangover Part III","year": 2013,"rating": 5.9,"votes": 248444,"running_times": 6000},{"title": "The Happening","year": 2008,"rating": 5,"votes": 175416,"running_times": 5460},{"title": "The Hard Way","year": 1991,"rating": 6.3,"votes": 15713,"running_times": 6660},{"title": "The Hateful Eight","year": 2015,"rating": 7.8,"votes": 371314,"running_times": 11220},{"title": "The Haunted Mansion","year": 2003,"rating": 4.9,"votes": 35158,"running_times": 5280},{"title": "The Haunting","year": 1963,"rating": 7.6,"votes": 28813,"running_times": 6720},{"title": "The Haunting","year": 1999,"rating": 4.9,"votes": 62383,"running_times": 6780},{"title": "The Haunting in Connecticut","year": 2009,"rating": 5.9,"votes": 53737,"running_times": 6120},{"title": "The Haunting in Connecticut 2: Ghosts of Georgia","year": 2013,"rating": 5.3,"votes": 14226,"running_times": 6060},{"title": "The Heartbreak Kid","year": 2007,"rating": 5.8,"votes": 76510,"running_times": 6960},{"title": "The Heat","year": 2013,"rating": 6.6,"votes": 143870,"running_times": 7200},{"title": "The Heiress","year": 1949,"rating": 8.2,"votes": 10798,"running_times": 6900},{"title": "The Help","year": 2011,"rating": 8.1,"votes": 355833,"running_times": 8760},{"title": "The Hidden","year": 1987,"rating": 7,"votes": 14177,"running_times": 5760},{"title": "The Hill","year": 1965,"rating": 7.9,"votes": 10218,"running_times": 7380},{"title": "The Hills Have Eyes","year": 1977,"rating": 6.4,"votes": 24184,"running_times": 5340},{"title": "The Hills Have Eyes","year": 2006,"rating": 6.4,"votes": 140564,"running_times": 6480},{"title": "The Hills Have Eyes II","year": 2007,"rating": 5.1,"votes": 53674,"running_times": 5340},{"title": "The History Boys","year": 2006,"rating": 6.9,"votes": 18686,"running_times": 6540},{"title": "The Hit List","year": 2011,"rating": 5.4,"votes": 10708,"running_times": 5400},{"title": "The Hitcher","year": 1986,"rating": 7.3,"votes": 36646,"running_times": 5820},{"title": "The Hitcher","year": 2007,"rating": 5.6,"votes": 36919,"running_times": 5400},{"title": "The Hitchhiker's Guide to the Galaxy","year": 2005,"rating": 6.8,"votes": 166812,"running_times": 6540},{"title": "The Hitman's Bodyguard","year": 2017,"rating": 7,"votes": 96031,"running_times": 7080},{"title": "The Hoax","year": 2006,"rating": 6.7,"votes": 15075,"running_times": 6960},{"title": "The Hobbit: An Unexpected Journey","year": 2012,"rating": 7.9,"votes": 685564,"running_times": 10920},{"title": "The Hobbit: The Battle of the Five Armies","year": 2014,"rating": 7.4,"votes": 402317,"running_times": 9840},{"title": "The Hobbit: The Desolation of Smaug","year": 2013,"rating": 7.9,"votes": 530117,"running_times": 11160},{"title": "The Hole","year": 2001,"rating": 6.2,"votes": 40802,"running_times": 6120},{"title": "The Hole","year": 2009,"rating": 5.7,"votes": 20485,"running_times": 5520},{"title": "The Holiday","year": 2006,"rating": 6.9,"votes": 201183,"running_times": 8280},{"title": "The Homesman","year": 2014,"rating": 6.6,"votes": 25011,"running_times": 7320},{"title": "The Horse Whisperer","year": 1998,"rating": 6.6,"votes": 34548,"running_times": 10200},{"title": "The Host","year": 2013,"rating": 5.9,"votes": 99595,"running_times": 7500},{"title": "The Hot Chick","year": 2002,"rating": 5.5,"votes": 80111,"running_times": 6240},{"title": "The Hottie & the Nottie","year": 2008,"rating": 1.9,"votes": 34344,"running_times": 5460},{"title": "The Hours","year": 2002,"rating": 7.6,"votes": 109423,"running_times": 6600},{"title": "The House","year": 2017,"rating": 5.6,"votes": 16827,"running_times": 5280},{"title": "The House Bunny","year": 2008,"rating": 5.5,"votes": 69088,"running_times": 5820},{"title": "The House of the Devil","year": 2009,"rating": 6.4,"votes": 33789,"running_times": 5700},{"title": "The House of the Spirits","year": 1993,"rating": 6.9,"votes": 18218,"running_times": 8760},{"title": "The Howling","year": 1981,"rating": 6.6,"votes": 25122,"running_times": 5460},{"title": "The Hudsucker Proxy","year": 1994,"rating": 7.3,"votes": 69082,"running_times": 6660},{"title": "The Human Centipede (First Sequence)","year": 2009,"rating": 4.4,"votes": 62836,"running_times": 5520},{"title": "The Human Centipede II (Full Sequence)","year": 2011,"rating": 3.9,"votes": 29662,"running_times": 5460},{"title": "The Human Centipede III (Final Sequence)","year": 2015,"rating": 2.8,"votes": 10385,"running_times": 6120},{"title": "The Human Race","year": 2013,"rating": 5.3,"votes": 10292,"running_times": 5220},{"title": "The Human Stain","year": 2003,"rating": 6.3,"votes": 26760,"running_times": 6360},{"title": "The Hunchback of Notre Dame","year": 1996,"rating": 6.9,"votes": 115443,"running_times": 5460},{"title": "The Hundred-Foot Journey","year": 2014,"rating": 7.3,"votes": 62251,"running_times": 7320},{"title": "The Hunger","year": 1983,"rating": 6.7,"votes": 19245,"running_times": 5820},{"title": "The Hunger Games","year": 2012,"rating": 7.2,"votes": 754986,"running_times": 8520},{"title": "The Hunger Games: Catching Fire","year": 2013,"rating": 7.5,"votes": 541328,"running_times": 8760},{"title": "The Hunger Games: Mockingjay - Part 1","year": 2014,"rating": 6.7,"votes": 346570,"running_times": 7380},{"title": "The Hunger Games: Mockingjay - Part 2","year": 2015,"rating": 6.6,"votes": 218419,"running_times": 8220},{"title": "The Hunt for Red October","year": 1990,"rating": 7.6,"votes": 153965,"running_times": 8100},{"title": "The Hunted","year": 2003,"rating": 6,"votes": 38171,"running_times": 5640},{"title": "The Hunter","year": 2011,"rating": 6.8,"votes": 33016,"running_times": 6120},{"title": "The Hunting Party","year": 2007,"rating": 6.9,"votes": 22998,"running_times": 6060},{"title": "The Huntsman: Winter's War","year": 2016,"rating": 6.1,"votes": 73796,"running_times": 7200},{"title": "The Hurricane","year": 1999,"rating": 7.6,"votes": 81748,"running_times": 8760},{"title": "The Hurt Locker","year": 2008,"rating": 7.6,"votes": 363360,"running_times": 7860},{"title": "The Hustler","year": 1961,"rating": 8,"votes": 66871,"running_times": 8040},{"title": "The Ice Harvest","year": 2005,"rating": 6.3,"votes": 21621,"running_times": 5520},{"title": "The Ice Storm","year": 1997,"rating": 7.5,"votes": 48839,"running_times": 6720},{"title": "The Iceman","year": 2012,"rating": 6.9,"votes": 60972,"running_times": 6360},{"title": "The Ides of March","year": 2011,"rating": 7.1,"votes": 199959,"running_times": 6060},{"title": "The Illusionist","year": 2006,"rating": 7.6,"votes": 319514,"running_times": 6600},{"title": "The Imaginarium of Doctor Parnassus","year": 2009,"rating": 6.8,"votes": 132579,"running_times": 7380},{"title": "The Imitation Game","year": 2014,"rating": 8,"votes": 557214,"running_times": 6840},{"title": "The Immigrant","year": 2013,"rating": 6.6,"votes": 24241,"running_times": 7200},{"title": "The Importance of Being Earnest","year": 2002,"rating": 6.9,"votes": 20040,"running_times": 5820},{"title": "The Imposter","year": 2012,"rating": 7.5,"votes": 39049,"running_times": 5940},{"title": "The In-Laws","year": 2003,"rating": 5.7,"votes": 14691,"running_times": 5880},{"title": "The Inbetweeners Movie","year": 2011,"rating": 6.8,"votes": 68706,"running_times": 5820},{"title": "The Incredible Burt Wonderstone","year": 2013,"rating": 5.9,"votes": 64175,"running_times": 6000},{"title": "The Incredible Hulk","year": 2008,"rating": 6.8,"votes": 355393,"running_times": 8100},{"title": "The Incredible Shrinking Man","year": 1957,"rating": 7.7,"votes": 12983,"running_times": 4860},{"title": "The Incredibles","year": 2004,"rating": 8,"votes": 528232,"running_times": 6900},{"title": "The Indian in the Cupboard","year": 1995,"rating": 5.9,"votes": 22226,"running_times": 5760},{"title": "The Infiltrator","year": 2016,"rating": 7,"votes": 52466,"running_times": 7620},{"title": "The Informant!","year": 2009,"rating": 6.5,"votes": 55888,"running_times": 6480},{"title": "The Informers","year": 2008,"rating": 5,"votes": 14859,"running_times": 5880},{"title": "The Innkeepers","year": 2011,"rating": 5.5,"votes": 29339,"running_times": 6060},{"title": "The Innocents","year": 1961,"rating": 7.9,"votes": 21569,"running_times": 6000},{"title": "The Insider","year": 1999,"rating": 7.9,"votes": 142214,"running_times": 9420},{"title": "The Intern","year": 2015,"rating": 7.1,"votes": 170025,"running_times": 7260},{"title": "The International","year": 2009,"rating": 6.5,"votes": 83532,"running_times": 7080},{"title": "The Internet's Own Boy: The Story of Aaron Swartz","year": 2014,"rating": 8.1,"votes": 13666,"running_times": 6300},{"title": "The Internship","year": 2013,"rating": 6.3,"votes": 170490,"running_times": 7500},{"title": "The Interpreter","year": 2005,"rating": 6.4,"votes": 89818,"running_times": 7680},{"title": "The Interview","year": 2014,"rating": 6.6,"votes": 269477,"running_times": 6720},{"title": "The Invasion","year": 2007,"rating": 5.9,"votes": 68278,"running_times": 5940},{"title": "The Invention of Lying","year": 2009,"rating": 6.4,"votes": 100451,"running_times": 6000},{"title": "The Invisible","year": 2007,"rating": 6.3,"votes": 32411,"running_times": 6120},{"title": "The Invisible Man","year": 1933,"rating": 7.7,"votes": 23608,"running_times": 4260},{"title": "The Invitation","year": 2015,"rating": 6.7,"votes": 49850,"running_times": 6000},{"title": "The Ipcress File","year": 1965,"rating": 7.3,"votes": 11333,"running_times": 6540},{"title": "The Iron Giant","year": 1999,"rating": 8,"votes": 142069,"running_times": 5400},{"title": "The Iron Lady","year": 2011,"rating": 6.4,"votes": 89826,"running_times": 6300},{"title": "The Island","year": 2005,"rating": 6.9,"votes": 277513,"running_times": 8160},{"title": "The Island of Dr. Moreau","year": 1996,"rating": 4.4,"votes": 27744,"running_times": 5940},{"title": "The Italian Job","year": 1969,"rating": 7.4,"votes": 33958,"running_times": 5940},{"title": "The Italian Job","year": 2003,"rating": 7,"votes": 305232,"running_times": 6660},{"title": "The Jackal","year": 1997,"rating": 6.4,"votes": 93573,"running_times": 7440},{"title": "The Jacket","year": 2005,"rating": 7.1,"votes": 98859,"running_times": 6180},{"title": "The Jane Austen Book Club","year": 2007,"rating": 6.8,"votes": 22992,"running_times": 6360},{"title": "The Jerk","year": 1979,"rating": 7.2,"votes": 46074,"running_times": 5640},{"title": "The Jewel of the Nile","year": 1985,"rating": 6.1,"votes": 42960,"running_times": 6360},{"title": "The Joneses","year": 2009,"rating": 6.5,"votes": 35379,"running_times": 5760},{"title": "The Joy Luck Club","year": 1993,"rating": 7.6,"votes": 13162,"running_times": 8340},{"title": "The Judge","year": 2014,"rating": 7.4,"votes": 151986,"running_times": 8460},{"title": "The Jungle Book","year": 1967,"rating": 7.6,"votes": 137104,"running_times": 4680},{"title": "The Jungle Book","year": 1994,"rating": 6,"votes": 14136,"running_times": 6660},{"title": "The Jungle Book","year": 2016,"rating": 7.5,"votes": 214632,"running_times": 6360},{"title": "The Jungle Book 2","year": 2003,"rating": 5.4,"votes": 12654,"running_times": 4320},{"title": "The Juror","year": 1996,"rating": 5.6,"votes": 14913,"running_times": 7080},{"title": "The Karate Kid","year": 1984,"rating": 7.2,"votes": 143057,"running_times": 7560},{"title": "The Karate Kid","year": 2010,"rating": 6.2,"votes": 133659,"running_times": 8400},{"title": "The Karate Kid Part II","year": 1986,"rating": 5.9,"votes": 59233,"running_times": 6780},{"title": "The Karate Kid Part III","year": 1989,"rating": 5,"votes": 39191,"running_times": 6720},{"title": "The Kentucky Fried Movie","year": 1977,"rating": 6.5,"votes": 14750,"running_times": 4980},{"title": "The Kid","year": 1921,"rating": 8.3,"votes": 80699,"running_times": 4080},{"title": "The Kid","year": 2000,"rating": 6.1,"votes": 36333,"running_times": 6240},{"title": "The Kids Are All Right","year": 2010,"rating": 7.1,"votes": 116244,"running_times": 6360},{"title": "The Killer Inside Me","year": 2010,"rating": 6.1,"votes": 30253,"running_times": 6540},{"title": "The Killers","year": 1946,"rating": 7.8,"votes": 15492,"running_times": 6180},{"title": "The Killing","year": 1956,"rating": 8,"votes": 67769,"running_times": 5100},{"title": "The Killing Fields","year": 1984,"rating": 7.9,"votes": 44901,"running_times": 8460},{"title": "The Killing Room","year": 2009,"rating": 5.7,"votes": 12284,"running_times": 5580},{"title": "The Killing of a Sacred Deer","year": 2017,"rating": 7.5,"votes": 17681,"running_times": 7260},{"title": "The King and I","year": 1956,"rating": 7.5,"votes": 20645,"running_times": 7980},{"title": "The King of Comedy","year": 1982,"rating": 7.8,"votes": 60357,"running_times": 6540},{"title": "The King of Kong","year": 2007,"rating": 8.2,"votes": 32123,"running_times": 4740},{"title": "The King's Speech","year": 2010,"rating": 8,"votes": 550814,"running_times": 7080},{"title": "The Kingdom","year": 2007,"rating": 7.1,"votes": 107076,"running_times": 6600},{"title": "The Kings of Summer","year": 2013,"rating": 7.2,"votes": 68006,"running_times": 5700},{"title": "The Kite Runner","year": 2007,"rating": 7.6,"votes": 71569,"running_times": 7680},{"title": "The LEGO Batman Movie","year": 2017,"rating": 7.3,"votes": 87348,"running_times": 6240},{"title": "The LEGO Movie","year": 2014,"rating": 7.8,"votes": 277876,"running_times": 6000},{"title": "The Ladies Man","year": 2000,"rating": 5.1,"votes": 11284,"running_times": 5040},{"title": "The Lady Eve","year": 1941,"rating": 8,"votes": 16038,"running_times": 5640},{"title": "The Lady Vanishes","year": 1938,"rating": 7.9,"votes": 39168,"running_times": 5760},{"title": "The Lady from Shanghai","year": 1947,"rating": 7.7,"votes": 21256,"running_times": 5520},{"title": "The Lady in the Van","year": 2015,"rating": 6.7,"votes": 18691,"running_times": 6240},{"title": "The Ladykillers","year": 1955,"rating": 7.8,"votes": 22382,"running_times": 5460},{"title": "The Ladykillers","year": 2004,"rating": 6.2,"votes": 89327,"running_times": 6240},{"title": "The Lake House","year": 2006,"rating": 6.8,"votes": 122280,"running_times": 5940},{"title": "The Land Before Time","year": 1988,"rating": 7.4,"votes": 67462,"running_times": 4140},{"title": "The Last Airbender","year": 2010,"rating": 4.2,"votes": 128562,"running_times": 6180},{"title": "The Last Boy Scout","year": 1991,"rating": 6.9,"votes": 81045,"running_times": 6300},{"title": "The Last Castle","year": 2001,"rating": 6.9,"votes": 60790,"running_times": 7860},{"title": "The Last Days of Disco","year": 1998,"rating": 6.6,"votes": 10594,"running_times": 6780},{"title": "The Last Days on Mars","year": 2013,"rating": 5.5,"votes": 31366,"running_times": 5880},{"title": "The Last Detail","year": 1973,"rating": 7.6,"votes": 18086,"running_times": 6240},{"title": "The Last Dragon","year": 1985,"rating": 6.9,"votes": 10341,"running_times": 6540},{"title": "The Last Emperor","year": 1987,"rating": 7.8,"votes": 77398,"running_times": 13140},{"title": "The Last Exorcism","year": 2010,"rating": 5.6,"votes": 43905,"running_times": 5220},{"title": "The Last Exorcism Part II","year": 2013,"rating": 4,"votes": 14396,"running_times": 5580},{"title": "The Last House on the Left","year": 1972,"rating": 6,"votes": 27511,"running_times": 5460},{"title": "The Last House on the Left","year": 2009,"rating": 6.6,"votes": 73887,"running_times": 6840},{"title": "The Last King of Scotland","year": 2006,"rating": 7.7,"votes": 156424,"running_times": 7380},{"title": "The Last Kiss","year": 2006,"rating": 6.5,"votes": 39056,"running_times": 6900},{"title": "The Last Legion","year": 2007,"rating": 5.4,"votes": 31238,"running_times": 6120},{"title": "The Last Man on Earth","year": 1964,"rating": 6.9,"votes": 14115,"running_times": 5160},{"title": "The Last Mimzy","year": 2007,"rating": 6.3,"votes": 19614,"running_times": 5760},{"title": "The Last Picture Show","year": 1971,"rating": 8.1,"votes": 34547,"running_times": 7620},{"title": "The Last Samurai","year": 2003,"rating": 7.7,"votes": 343858,"running_times": 9240},{"title": "The Last Seduction","year": 1994,"rating": 7.1,"votes": 17490,"running_times": 7740},{"title": "The Last Song","year": 2010,"rating": 5.9,"votes": 67037,"running_times": 6420},{"title": "The Last Stand","year": 2013,"rating": 6.4,"votes": 121189,"running_times": 6420},{"title": "The Last Starfighter","year": 1984,"rating": 6.7,"votes": 31850,"running_times": 6060},{"title": "The Last Station","year": 2009,"rating": 7,"votes": 16168,"running_times": 6720},{"title": "The Last Supper","year": 1995,"rating": 6.8,"votes": 12803,"running_times": 5520},{"title": "The Last Temptation of Christ","year": 1988,"rating": 7.6,"votes": 43169,"running_times": 9840},{"title": "The Last Unicorn","year": 1982,"rating": 7.5,"votes": 20743,"running_times": 5520},{"title": "The Last Waltz","year": 1978,"rating": 8.2,"votes": 13674,"running_times": 7020},{"title": "The Last Witch Hunter","year": 2015,"rating": 6,"votes": 76521,"running_times": 6360},{"title": "The Last of the Mohicans","year": 1992,"rating": 7.8,"votes": 124618,"running_times": 7020},{"title": "The Lavender Hill Mob","year": 1951,"rating": 7.7,"votes": 10460,"running_times": 4860},{"title": "The Lawnmower Man","year": 1992,"rating": 5.4,"votes": 29850,"running_times": 8400},{"title": "The Lazarus Effect","year": 2015,"rating": 5.2,"votes": 33199,"running_times": 4980},{"title": "The Lazarus Project","year": 2008,"rating": 6.2,"votes": 15187,"running_times": 6000},{"title": "The League of Extraordinary Gentlemen","year": 2003,"rating": 5.8,"votes": 149821,"running_times": 6600},{"title": "The Ledge","year": 2011,"rating": 6.6,"votes": 16738,"running_times": 6060},{"title": "The Legend of Bagger Vance","year": 2000,"rating": 6.7,"votes": 48336,"running_times": 7560},{"title": "The Legend of Bhagat Singh","year": 2002,"rating": 8.1,"votes": 11090,"running_times": 9300},{"title": "The Legend of Hell House","year": 1973,"rating": 6.8,"votes": 10186,"running_times": 5700},{"title": "The Legend of Hercules","year": 2014,"rating": 4.2,"votes": 47928,"running_times": 5940},{"title": "The Legend of Tarzan","year": 2016,"rating": 6.3,"votes": 132022,"running_times": 6600},{"title": "The Legend of Zorro","year": 2005,"rating": 5.9,"votes": 78734,"running_times": 7740},{"title": "The Libertine","year": 2004,"rating": 6.4,"votes": 32595,"running_times": 6840},{"title": "The Life Aquatic with Steve Zissou","year": 2004,"rating": 7.3,"votes": 153261,"running_times": 7140},{"title": "The Life Before Her Eyes","year": 2007,"rating": 6.4,"votes": 12657,"running_times": 5400},{"title": "The Life and Death of Colonel Blimp","year": 1943,"rating": 8.2,"votes": 10828,"running_times": 9780},{"title": "The Life and Death of Peter Sellers","year": 2004,"rating": 6.9,"votes": 13563,"running_times": 7320},{"title": "The Life of David Gale","year": 2003,"rating": 7.6,"votes": 95802,"running_times": 7800},{"title": "The Lifeguard","year": 2013,"rating": 5.7,"votes": 12490,"running_times": 5880},{"title": "The Light Between Oceans","year": 2016,"rating": 7.2,"votes": 34727,"running_times": 7980},{"title": "The Limey","year": 1999,"rating": 7.1,"votes": 26116,"running_times": 5340},{"title": "The Limits of Control","year": 2009,"rating": 6.3,"votes": 17145,"running_times": 6960},{"title": "The Lincoln Lawyer","year": 2011,"rating": 7.3,"votes": 186192,"running_times": 7080},{"title": "The Lion King","year": 1994,"rating": 8.5,"votes": 735442,"running_times": 5280},{"title": "The Lion in Winter","year": 1968,"rating": 8.1,"votes": 24882,"running_times": 8220},{"title": "The Little Death","year": 2014,"rating": 7.1,"votes": 21713,"running_times": 5880},{"title": "The Little Girl Who Lives Down the Lane","year": 1976,"rating": 7.1,"votes": 10499,"running_times": 6000},{"title": "The Little Mermaid","year": 1989,"rating": 7.6,"votes": 191159,"running_times": 4980},{"title": "The Little Prince","year": 2015,"rating": 7.8,"votes": 42970,"running_times": 6480},{"title": "The Little Rascals","year": 1994,"rating": 6.3,"votes": 37088,"running_times": 4920},{"title": "The Little Shop of Horrors","year": 1960,"rating": 6.3,"votes": 13565,"running_times": 4320},{"title": "The Living Daylights","year": 1987,"rating": 6.7,"votes": 75085,"running_times": 7800},{"title": "The Lizzie McGuire Movie","year": 2003,"rating": 5.4,"votes": 30483,"running_times": 5640},{"title": "The Lobster","year": 2015,"rating": 7.1,"votes": 138204,"running_times": 7140},{"title": "The Loft","year": 2014,"rating": 6.3,"votes": 41266,"running_times": 6480},{"title": "The Lone Ranger","year": 2013,"rating": 6.5,"votes": 196792,"running_times": 9000},{"title": "The Long Good Friday","year": 1980,"rating": 7.7,"votes": 15439,"running_times": 6840},{"title": "The Long Goodbye","year": 1973,"rating": 7.7,"votes": 20432,"running_times": 6720},{"title": "The Long Kiss Goodnight","year": 1996,"rating": 6.7,"votes": 64190,"running_times": 7260},{"title": "The Longest Day","year": 1962,"rating": 7.8,"votes": 46242,"running_times": 10680},{"title": "The Longest Ride","year": 2015,"rating": 7.1,"votes": 62410,"running_times": 7380},{"title": "The Longest Yard","year": 1974,"rating": 7.1,"votes": 14139,"running_times": 7320},{"title": "The Longest Yard","year": 2005,"rating": 6.4,"votes": 141183,"running_times": 6780},{"title": "The Lookout","year": 2007,"rating": 7.1,"votes": 53036,"running_times": 5940},{"title": "The Lorax","year": 2012,"rating": 6.4,"votes": 83985,"running_times": 5160},{"title": "The Lord of the Rings","year": 1978,"rating": 6.2,"votes": 25910,"running_times": 7920},{"title": "The Lord of the Rings: The Fellowship of the Ring","year": 2001,"rating": 8.8,"votes": 1369632,"running_times": 13680},{"title": "The Lord of the Rings: The Return of the King","year": 2003,"rating": 8.9,"votes": 1349449,"running_times": 15780},{"title": "The Lord of the Rings: The Two Towers","year": 2002,"rating": 8.7,"votes": 1221456,"running_times": 14100},{"title": "The Lords of Salem","year": 2012,"rating": 5.1,"votes": 22967,"running_times": 6060},{"title": "The Losers","year": 2010,"rating": 6.4,"votes": 79049,"running_times": 5820},{"title": "The Lost Boys","year": 1987,"rating": 7.3,"votes": 102017,"running_times": 5820},{"title": "The Lost City of Z","year": 2016,"rating": 6.6,"votes": 45774,"running_times": 8460},{"title": "The Lost Weekend","year": 1945,"rating": 8,"votes": 27909,"running_times": 6060},{"title": "The Lost World: Jurassic Park","year": 1997,"rating": 6.5,"votes": 308796,"running_times": 7740},{"title": "The Love Bug","year": 1968,"rating": 6.5,"votes": 11610,"running_times": 6480},{"title": "The Love Guru","year": 2008,"rating": 3.8,"votes": 45254,"running_times": 5220},{"title": "The Love Punch","year": 2013,"rating": 5.7,"votes": 10551,"running_times": 5640},{"title": "The Loved Ones","year": 2009,"rating": 6.7,"votes": 31227,"running_times": 5040},{"title": "The Lovely Bones","year": 2009,"rating": 6.7,"votes": 134513,"running_times": 8100},{"title": "The Lucky One","year": 2012,"rating": 6.5,"votes": 86309,"running_times": 6060},{"title": "The Lucky Ones","year": 2008,"rating": 7,"votes": 12384,"running_times": 6900},{"title": "The Machine","year": 2013,"rating": 6.1,"votes": 27158,"running_times": 5460},{"title": "The Machinist","year": 2004,"rating": 7.7,"votes": 307967,"running_times": 6060},{"title": "The Madness of King George","year": 1994,"rating": 7.2,"votes": 13102,"running_times": 6240},{"title": "The Magdalene Sisters","year": 2002,"rating": 7.8,"votes": 23532,"running_times": 6840},{"title": "The Magic of Belle Isle","year": 2012,"rating": 7,"votes": 14905,"running_times": 6540},{"title": "The Magnificent Ambersons","year": 1942,"rating": 7.9,"votes": 18255,"running_times": 8880},{"title": "The Magnificent Seven","year": 1960,"rating": 7.8,"votes": 75093,"running_times": 7680},{"title": "The Magnificent Seven","year": 2016,"rating": 6.9,"votes": 144193,"running_times": 7920},{"title": "The Maiden Heist","year": 2009,"rating": 6.1,"votes": 13687,"running_times": 5400},{"title": "The Majestic","year": 2001,"rating": 6.9,"votes": 47475,"running_times": 9120},{"title": "The Maltese Falcon","year": 1941,"rating": 8.1,"votes": 125756,"running_times": 6000},{"title": "The Man","year": 2005,"rating": 5.5,"votes": 22837,"running_times": 4980},{"title": "The Man Who Cried","year": 2000,"rating": 6.2,"votes": 13144,"running_times": 6000},{"title": "The Man Who Fell to Earth","year": 1976,"rating": 6.7,"votes": 19563,"running_times": 8340},{"title": "The Man Who Knew Infinity","year": 2015,"rating": 7.2,"votes": 35156,"running_times": 6480},{"title": "The Man Who Knew Too Little","year": 1997,"rating": 6.6,"votes": 25635,"running_times": 5640},{"title": "The Man Who Knew Too Much","year": 1934,"rating": 6.9,"votes": 13970,"running_times": 4500},{"title": "The Man Who Knew Too Much","year": 1956,"rating": 7.5,"votes": 47038,"running_times": 7200},{"title": "The Man Who Shot Liberty Valance","year": 1962,"rating": 8.1,"votes": 58224,"running_times": 7440},{"title": "The Man Who Wasn't There","year": 2001,"rating": 7.6,"votes": 91464,"running_times": 7080},{"title": "The Man Who Would Be King","year": 1975,"rating": 7.9,"votes": 38413,"running_times": 7740},{"title": "The Man Without a Face","year": 1993,"rating": 6.7,"votes": 24519,"running_times": 6900},{"title": "The Man from Earth","year": 2007,"rating": 8,"votes": 146211,"running_times": 5220},{"title": "The Man from U.N.C.L.E.","year": 2015,"rating": 7.3,"votes": 216468,"running_times": 6960},{"title": "The Man in the Iron Mask","year": 1998,"rating": 6.5,"votes": 136416,"running_times": 7920},{"title": "The Man in the Moon","year": 1991,"rating": 7.4,"votes": 13109,"running_times": 5940},{"title": "The Man with One Red Shoe","year": 1985,"rating": 5.7,"votes": 12850,"running_times": 5520},{"title": "The Man with Two Brains","year": 1983,"rating": 6.4,"votes": 21124,"running_times": 5580},{"title": "The Man with the Golden Gun","year": 1974,"rating": 6.8,"votes": 80331,"running_times": 7500},{"title": "The Man with the Iron Fists","year": 2012,"rating": 5.4,"votes": 56139,"running_times": 6420},{"title": "The Manchurian Candidate","year": 1962,"rating": 8,"votes": 64529,"running_times": 7560},{"title": "The Manchurian Candidate","year": 2004,"rating": 6.6,"votes": 92180,"running_times": 7740},{"title": "The Many Adventures of Winnie the Pooh","year": 1977,"rating": 7.6,"votes": 27101,"running_times": 4440},{"title": "The Marine","year": 2006,"rating": 4.7,"votes": 29126,"running_times": 5520},{"title": "The Martian","year": 2015,"rating": 8,"votes": 592557,"running_times": 9060},{"title": "The Mask","year": 1994,"rating": 6.9,"votes": 290014,"running_times": 6840},{"title": "The Mask of Zorro","year": 1998,"rating": 6.7,"votes": 146223,"running_times": 8160},{"title": "The Master","year": 2012,"rating": 7.1,"votes": 117674,"running_times": 8280},{"title": "The Master of Disguise","year": 2002,"rating": 3.3,"votes": 19140,"running_times": 4800},{"title": "The Matador","year": 2005,"rating": 6.8,"votes": 41655,"running_times": 5760},{"title": "The Matrix","year": 1999,"rating": 8.7,"votes": 1358510,"running_times": 8160},{"title": "The Matrix Reloaded","year": 2003,"rating": 7.2,"votes": 450569,"running_times": 8280},{"title": "The Matrix Revolutions","year": 2003,"rating": 6.7,"votes": 390666,"running_times": 7740},{"title": "The Maze Runner","year": 2014,"rating": 6.8,"votes": 349853,"running_times": 6780},{"title": "The Meaning of Life","year": 1983,"rating": 7.6,"votes": 95426,"running_times": 6720},{"title": "The Mechanic","year": 2011,"rating": 6.6,"votes": 132870,"running_times": 5580},{"title": "The Medallion","year": 2003,"rating": 5.2,"votes": 33182,"running_times": 6480},{"title": "The Men Who Stare at Goats","year": 2009,"rating": 6.2,"votes": 115503,"running_times": 5640},{"title": "The Merchant of Venice","year": 2004,"rating": 7.1,"votes": 31425,"running_times": 8040},{"title": "The Message","year": 1976,"rating": 8.3,"votes": 37406,"running_times": 10620},{"title": "The Messenger","year": 2009,"rating": 7.1,"votes": 31080,"running_times": 6780},{"title": "The Messengers","year": 2007,"rating": 5.4,"votes": 35223,"running_times": 5400},{"title": "The Mexican","year": 2001,"rating": 6.1,"votes": 92498,"running_times": 7380},{"title": "The Meyerowitz Stories (New and Selected)","year": 2017,"rating": 7.1,"votes": 15162,"running_times": 6720},{"title": "The Midnight Meat Train","year": 2008,"rating": 6.1,"votes": 52051,"running_times": 6180},{"title": "The Mighty","year": 1998,"rating": 7.3,"votes": 11094,"running_times": 6000},{"title": "The Mighty Ducks","year": 1992,"rating": 6.5,"votes": 48711,"running_times": 6000},{"title": "The Million Dollar Hotel","year": 2000,"rating": 5.9,"votes": 19243,"running_times": 7320},{"title": "The Miracle Worker","year": 1962,"rating": 8.1,"votes": 13427,"running_times": 6360},{"title": "The Mirror Has Two Faces","year": 1996,"rating": 6.5,"votes": 12283,"running_times": 7560},{"title": "The Misfits","year": 1961,"rating": 7.4,"votes": 14251,"running_times": 7500},{"title": "The Missing","year": 2003,"rating": 6.5,"votes": 29324,"running_times": 9240},{"title": "The Mission","year": 1986,"rating": 7.5,"votes": 48098,"running_times": 7500},{"title": "The Mist","year": 2007,"rating": 7.2,"votes": 242656,"running_times": 7560},{"title": "The Money Pit","year": 1986,"rating": 6.3,"votes": 41778,"running_times": 5460},{"title": "The Monster","year": 2016,"rating": 5.4,"votes": 10461,"running_times": 5460},{"title": "The Monster Squad","year": 1987,"rating": 7.1,"votes": 21965,"running_times": 4740},{"title": "The Monuments Men","year": 2014,"rating": 6.1,"votes": 111036,"running_times": 7080},{"title": "The Mortal Instruments: City of Bones","year": 2013,"rating": 5.9,"votes": 115406,"running_times": 7800},{"title": "The Mosquito Coast","year": 1986,"rating": 6.6,"votes": 23286,"running_times": 7020},{"title": "The Mothman Prophecies","year": 2002,"rating": 6.5,"votes": 67631,"running_times": 7680},{"title": "The Mountain Between Us","year": 2017,"rating": 6.3,"votes": 12554,"running_times": 6720},{"title": "The Mummy","year": 1932,"rating": 7.2,"votes": 18569,"running_times": 4380},{"title": "The Mummy","year": 1999,"rating": 7,"votes": 343729,"running_times": 7440},{"title": "The Mummy","year": 2017,"rating": 5.5,"votes": 114356,"running_times": 6600},{"title": "The Mummy Returns","year": 2001,"rating": 6.3,"votes": 266813,"running_times": 7800},{"title": "The Mummy: Tomb of the Dragon Emperor","year": 2008,"rating": 5.2,"votes": 129879,"running_times": 6720},{"title": "The Muppet Christmas Carol","year": 1992,"rating": 7.7,"votes": 38106,"running_times": 5340},{"title": "The Muppet Movie","year": 1979,"rating": 7.6,"votes": 27403,"running_times": 5700},{"title": "The Muppets","year": 2011,"rating": 7.1,"votes": 78899,"running_times": 6180},{"title": "The Muppets Take Manhattan","year": 1984,"rating": 6.9,"votes": 16510,"running_times": 5640},{"title": "The Music Man","year": 1962,"rating": 7.7,"votes": 13834,"running_times": 9060},{"title": "The Musketeer","year": 2001,"rating": 4.7,"votes": 13252,"running_times": 6240},{"title": "The Naked Gun 2½: The Smell of Fear","year": 1991,"rating": 6.8,"votes": 90089,"running_times": 5100},{"title": "The Naked Gun: From the Files of Police Squad!","year": 1988,"rating": 7.6,"votes": 126110,"running_times": 5100},{"title": "The Namesake","year": 2006,"rating": 7.6,"votes": 17432,"running_times": 7320},{"title": "The Nanny Diaries","year": 2007,"rating": 6.2,"votes": 51391,"running_times": 6360},{"title": "The Natural","year": 1984,"rating": 7.5,"votes": 36890,"running_times": 8640},{"title": "The Necessary Death of Charlie Countryman","year": 2013,"rating": 6.4,"votes": 23761,"running_times": 6180},{"title": "The Negotiator","year": 1998,"rating": 7.3,"votes": 114963,"running_times": 8400},{"title": "The Neon Demon","year": 2016,"rating": 6.2,"votes": 59341,"running_times": 7080},{"title": "The Net","year": 1995,"rating": 5.9,"votes": 52305,"running_times": 6840},{"title": "The NeverEnding Story II: The Next Chapter","year": 1990,"rating": 5.1,"votes": 19978,"running_times": 5400},{"title": "The New Daughter","year": 2009,"rating": 5.3,"votes": 12381,"running_times": 6480},{"title": "The New Guy","year": 2002,"rating": 5.9,"votes": 30223,"running_times": 5520},{"title": "The New World","year": 2005,"rating": 6.7,"votes": 75203,"running_times": 10320},{"title": "The Next Karate Kid","year": 1994,"rating": 4.3,"votes": 20316,"running_times": 6420},{"title": "The Next Three Days","year": 2010,"rating": 7.4,"votes": 156806,"running_times": 7980},{"title": "The Nice Guys","year": 2016,"rating": 7.4,"votes": 200979,"running_times": 6960},{"title": "The Night Before","year": 2015,"rating": 6.4,"votes": 49476,"running_times": 6060},{"title": "The Night Listener","year": 2006,"rating": 5.9,"votes": 13514,"running_times": 5460},{"title": "The Night of the Hunter","year": 1955,"rating": 8,"votes": 70141,"running_times": 5520},{"title": "The Nightmare Before Christmas","year": 1993,"rating": 8,"votes": 247257,"running_times": 4560},{"title": "The Nines","year": 2007,"rating": 6.4,"votes": 30202,"running_times": 6000},{"title": "The Ninth Gate","year": 1999,"rating": 6.7,"votes": 146217,"running_times": 7980},{"title": "The Notebook","year": 2004,"rating": 7.9,"votes": 436020,"running_times": 7380},{"title": "The November Man","year": 2014,"rating": 6.3,"votes": 55446,"running_times": 6480},{"title": "The Number 23","year": 2007,"rating": 6.4,"votes": 175665,"running_times": 6060},{"title": "The Numbers Station","year": 2013,"rating": 5.6,"votes": 17235,"running_times": 5340},{"title": "The Nut Job","year": 2014,"rating": 5.8,"votes": 22351,"running_times": 5100},{"title": "The Nutty Professor","year": 1963,"rating": 6.7,"votes": 13282,"running_times": 6420},{"title": "The Nutty Professor","year": 1996,"rating": 5.6,"votes": 93784,"running_times": 5700},{"title": "The Object of My Affection","year": 1998,"rating": 6,"votes": 16633,"running_times": 6660},{"title": "The Odd Couple","year": 1968,"rating": 7.7,"votes": 27013,"running_times": 6300},{"title": "The Odd Life of Timothy Green","year": 2012,"rating": 6.6,"votes": 40357,"running_times": 6300},{"title": "The Omega Man","year": 1971,"rating": 6.6,"votes": 24872,"running_times": 5880},{"title": "The Omen","year": 1976,"rating": 7.6,"votes": 89724,"running_times": 6660},{"title": "The Omen","year": 2006,"rating": 5.5,"votes": 51300,"running_times": 6600},{"title": "The One","year": 2001,"rating": 5.9,"votes": 82216,"running_times": 5220},{"title": "The One I Love","year": 2014,"rating": 7.1,"votes": 27718,"running_times": 5460},{"title": "The Onion Movie","year": 2008,"rating": 6.3,"votes": 14278,"running_times": 4800},{"title": "The Oogieloves in the Big Balloon Adventure","year": 2012,"rating": 6.3,"votes": 14494,"running_times": 5280},{"title": "The Opposite of Sex","year": 1998,"rating": 6.5,"votes": 18864,"running_times": 6300},{"title": "The Oranges","year": 2011,"rating": 5.9,"votes": 11158,"running_times": 5400},{"title": "The Order","year": 2003,"rating": 5.2,"votes": 15687,"running_times": 6120},{"title": "The Other Boleyn Girl","year": 2008,"rating": 6.7,"votes": 90521,"running_times": 6900},{"title": "The Other Guys","year": 2010,"rating": 6.7,"votes": 206139,"running_times": 6960},{"title": "The Other Side of the Door","year": 2016,"rating": 5.3,"votes": 14034,"running_times": 5760},{"title": "The Other Sister","year": 1999,"rating": 6.5,"votes": 10939,"running_times": 7740},{"title": "The Other Woman","year": 2014,"rating": 6,"votes": 114420,"running_times": 6540},{"title": "The Others","year": 2001,"rating": 7.6,"votes": 294127,"running_times": 6240},{"title": "The Ottoman Lieutenant","year": 2017,"rating": 6.9,"votes": 19405,"running_times": 6360},{"title": "The Out-of-Towners","year": 1999,"rating": 5.3,"votes": 11334,"running_times": 5400},{"title": "The Outlaw Josey Wales","year": 1976,"rating": 7.9,"votes": 55131,"running_times": 8100},{"title": "The Outsiders","year": 1983,"rating": 7.2,"votes": 62501,"running_times": 6840},{"title": "The Overnight","year": 2015,"rating": 6.1,"votes": 13121,"running_times": 4740},{"title": "The Ox-Bow Incident","year": 1943,"rating": 8.1,"votes": 17397,"running_times": 4500},{"title": "The Oxford Murders","year": 2008,"rating": 6.1,"votes": 24510,"running_times": 6240},{"title": "The Pacifier","year": 2005,"rating": 5.6,"votes": 73772,"running_times": 5700},{"title": "The Pact","year": 2012,"rating": 5.8,"votes": 21193,"running_times": 5340},{"title": "The Pagemaster","year": 1994,"rating": 6,"votes": 17586,"running_times": 4800},{"title": "The Painted Veil","year": 2006,"rating": 7.5,"votes": 82205,"running_times": 7500},{"title": "The Panic in Needle Park","year": 1971,"rating": 7.1,"votes": 13115,"running_times": 6600},{"title": "The Paper","year": 1994,"rating": 6.6,"votes": 11209,"running_times": 6720},{"title": "The Paperboy","year": 2012,"rating": 5.8,"votes": 31446,"running_times": 6420},{"title": "The Parallax View","year": 1974,"rating": 7.2,"votes": 12309,"running_times": 6120},{"title": "The Parent Trap","year": 1961,"rating": 7.1,"votes": 15693,"running_times": 7740},{"title": "The Parent Trap","year": 1998,"rating": 6.5,"votes": 97899,"running_times": 7680},{"title": "The Party","year": 1968,"rating": 7.6,"votes": 32463,"running_times": 5940},{"title": "The Patriot","year": 1998,"rating": 4.1,"votes": 10623,"running_times": 5640},{"title": "The Patriot","year": 2000,"rating": 7.2,"votes": 223677,"running_times": 10500},{"title": "The Peacemaker","year": 1997,"rating": 5.9,"votes": 48800,"running_times": 7440},{"title": "The Peanuts Movie","year": 2015,"rating": 7.1,"votes": 35551,"running_times": 5280},{"title": "The Pelican Brief","year": 1993,"rating": 6.6,"votes": 64563,"running_times": 8460},{"title": "The People Under the Stairs","year": 1991,"rating": 6.3,"votes": 26112,"running_times": 6120},{"title": "The People vs. Larry Flynt","year": 1996,"rating": 7.3,"votes": 76653,"running_times": 7740},{"title": "The Perfect Host","year": 2010,"rating": 6.8,"votes": 22080,"running_times": 5580},{"title": "The Perfect Man","year": 2005,"rating": 5.5,"votes": 25126,"running_times": 6000},{"title": "The Perfect Score","year": 2004,"rating": 5.7,"votes": 20986,"running_times": 5580},{"title": "The Perfect Storm","year": 2000,"rating": 6.4,"votes": 140346,"running_times": 7800},{"title": "The Perks of Being a Wallflower","year": 2012,"rating": 8,"votes": 391846,"running_times": 6120},{"title": "The Petrified Forest","year": 1936,"rating": 7.6,"votes": 10327,"running_times": 4920},{"title": "The Phantom","year": 1996,"rating": 4.9,"votes": 29100,"running_times": 6000},{"title": "The Phantom of the Opera","year": 2004,"rating": 7.3,"votes": 103249,"running_times": 8580},{"title": "The Philadelphia Experiment","year": 1984,"rating": 6.1,"votes": 12160,"running_times": 6120},{"title": "The Philadelphia Story","year": 1940,"rating": 8,"votes": 54146,"running_times": 6720},{"title": "The Physician","year": 2013,"rating": 7.2,"votes": 29595,"running_times": 9000},{"title": "The Pianist","year": 2002,"rating": 8.5,"votes": 567718,"running_times": 9000},{"title": "The Piano","year": 1993,"rating": 7.6,"votes": 68631,"running_times": 7260},{"title": "The Pillow Book","year": 1996,"rating": 6.7,"votes": 11158,"running_times": 7560},{"title": "The Pink Panther","year": 1963,"rating": 7.2,"votes": 41425,"running_times": 6900},{"title": "The Pink Panther","year": 2006,"rating": 5.6,"votes": 70795,"running_times": 5580},{"title": "The Pink Panther 2","year": 2009,"rating": 5.6,"votes": 36263,"running_times": 5520},{"title": "The Pink Panther Strikes Again","year": 1976,"rating": 7.3,"votes": 23815,"running_times": 6180},{"title": "The Pirates! In an Adventure with Scientists!","year": 2012,"rating": 6.7,"votes": 39134,"running_times": 5280},{"title": "The Place Beyond the Pines","year": 2012,"rating": 7.3,"votes": 208561,"running_times": 8400},{"title": "The Player","year": 1992,"rating": 7.6,"votes": 45754,"running_times": 7440},{"title": "The Pleasure of Your Company","year": 2006,"rating": 5.7,"votes": 13637,"running_times": 5400},{"title": "The Pledge","year": 2001,"rating": 6.8,"votes": 46026,"running_times": 7440},{"title": "The Polar Express","year": 2004,"rating": 6.6,"votes": 137765,"running_times": 6000},{"title": "The Poseidon Adventure","year": 1972,"rating": 7.1,"votes": 35192,"running_times": 7020},{"title": "The Possession","year": 2012,"rating": 5.9,"votes": 50728,"running_times": 5520},{"title": "The Postman","year": 1997,"rating": 6,"votes": 60345,"running_times": 10620},{"title": "The Postman Always Rings Twice","year": 1946,"rating": 7.6,"votes": 15385,"running_times": 6780},{"title": "The Postman Always Rings Twice","year": 1981,"rating": 6.6,"votes": 18313,"running_times": 7320},{"title": "The Poughkeepsie Tapes","year": 2007,"rating": 6.1,"votes": 11016,"running_times": 4860},{"title": "The Presidio","year": 1988,"rating": 6,"votes": 14000,"running_times": 5820},{"title": "The Prestige","year": 2006,"rating": 8.5,"votes": 958889,"running_times": 7800},{"title": "The Prince & Me","year": 2004,"rating": 5.9,"votes": 34100,"running_times": 6660},{"title": "The Prince","year": 2014,"rating": 4.6,"votes": 14635,"running_times": 5580},{"title": "The Prince of Egypt","year": 1998,"rating": 7,"votes": 99560,"running_times": 5940},{"title": "The Prince of Tides","year": 1991,"rating": 6.7,"votes": 13542,"running_times": 7920},{"title": "The Princess Bride","year": 1987,"rating": 8.1,"votes": 325463,"running_times": 5880},{"title": "The Princess Diaries","year": 2001,"rating": 6.3,"votes": 105164,"running_times": 6660},{"title": "The Princess Diaries 2: Royal Engagement","year": 2004,"rating": 5.7,"votes": 60658,"running_times": 6780},{"title": "The Princess and the Frog","year": 2009,"rating": 7.1,"votes": 99027,"running_times": 5820},{"title": "The Private Lives of Pippa Lee","year": 2009,"rating": 6.4,"votes": 11693,"running_times": 5880},{"title": "The Producers","year": 1967,"rating": 7.7,"votes": 43152,"running_times": 5280},{"title": "The Producers","year": 2005,"rating": 6.4,"votes": 36865,"running_times": 8040},{"title": "The Professionals","year": 1966,"rating": 7.4,"votes": 11097,"running_times": 7380},{"title": "The Program","year": 2015,"rating": 6.5,"votes": 12447,"running_times": 5940},{"title": "The Promise","year": 2016,"rating": 6,"votes": 158352,"running_times": 7980},{"title": "The Promotion","year": 2008,"rating": 5.7,"votes": 17075,"running_times": 5160},{"title": "The Prophecy","year": 1995,"rating": 6.6,"votes": 25816,"running_times": 5880},{"title": "The Proposal","year": 2009,"rating": 6.7,"votes": 250312,"running_times": 6480},{"title": "The Proposition","year": 2005,"rating": 7.4,"votes": 45238,"running_times": 6240},{"title": "The Public Enemy","year": 1931,"rating": 7.7,"votes": 14696,"running_times": 4980},{"title": "The Punisher","year": 1989,"rating": 5.7,"votes": 18060,"running_times": 5340},{"title": "The Punisher","year": 2004,"rating": 6.5,"votes": 134403,"running_times": 8400},{"title": "The Purge","year": 2013,"rating": 5.7,"votes": 161386,"running_times": 5100},{"title": "The Purge: Anarchy","year": 2014,"rating": 6.5,"votes": 111618,"running_times": 6180},{"title": "The Purge: Election Year","year": 2016,"rating": 6,"votes": 62579,"running_times": 6480},{"title": "The Purple Rose of Cairo","year": 1985,"rating": 7.7,"votes": 40054,"running_times": 4920},{"title": "The Pursuit of Happyness","year": 2006,"rating": 8,"votes": 374451,"running_times": 7020},{"title": "The Pyramid","year": 2014,"rating": 4.6,"votes": 19641,"running_times": 5340},{"title": "The Queen","year": 2006,"rating": 7.3,"votes": 92368,"running_times": 6180},{"title": "The Queen of Versailles","year": 2012,"rating": 7.1,"votes": 11417,"running_times": 6000},{"title": "The Quest","year": 1996,"rating": 5.5,"votes": 20623,"running_times": 5700},{"title": "The Quick and the Dead","year": 1995,"rating": 6.4,"votes": 73840,"running_times": 6420},{"title": "The Quiet","year": 2005,"rating": 6.4,"votes": 14028,"running_times": 5760},{"title": "The Quiet American","year": 2002,"rating": 7.1,"votes": 24933,"running_times": 6060},{"title": "The Quiet Earth","year": 1985,"rating": 6.8,"votes": 21712,"running_times": 5460},{"title": "The Quiet Man","year": 1952,"rating": 7.9,"votes": 29304,"running_times": 7740},{"title": "The Quiet Ones","year": 2014,"rating": 5.1,"votes": 16808,"running_times": 5880},{"title": "The Rage: Carrie 2","year": 1999,"rating": 4.6,"votes": 13798,"running_times": 6240},{"title": "The Raid 2: Berandal","year": 2014,"rating": 8,"votes": 95124,"running_times": 9000},{"title": "The Railway Man","year": 2013,"rating": 7.1,"votes": 31511,"running_times": 6960},{"title": "The Rainmaker","year": 1997,"rating": 7.1,"votes": 50689,"running_times": 8100},{"title": "The Raven","year": 2012,"rating": 6.4,"votes": 76793,"running_times": 6600},{"title": "The Reader","year": 2008,"rating": 7.6,"votes": 204566,"running_times": 7440},{"title": "The Reaping","year": 2007,"rating": 5.7,"votes": 39200,"running_times": 5940},{"title": "The Rebound","year": 2009,"rating": 6.3,"votes": 42033,"running_times": 5820},{"title": "The Recruit","year": 2003,"rating": 6.6,"votes": 119599,"running_times": 6900},{"title": "The Red Shoes","year": 1948,"rating": 8.3,"votes": 22241,"running_times": 8160},{"title": "The Reef","year": 2010,"rating": 5.8,"votes": 13613,"running_times": 5640},{"title": "The Ref","year": 1994,"rating": 6.9,"votes": 20844,"running_times": 5760},{"title": "The Relic","year": 1997,"rating": 5.7,"votes": 20776,"running_times": 6600},{"title": "The Reluctant Fundamentalist","year": 2012,"rating": 6.9,"votes": 11665,"running_times": 7800},{"title": "The Remains of the Day","year": 1993,"rating": 7.9,"votes": 50598,"running_times": 8040},{"title": "The Replacement Killers","year": 1998,"rating": 6.1,"votes": 24445,"running_times": 5760},{"title": "The Replacements","year": 2000,"rating": 6.5,"votes": 51436,"running_times": 7080},{"title": "The Rescuers","year": 1977,"rating": 6.9,"votes": 47886,"running_times": 4680},{"title": "The Rescuers Down Under","year": 1990,"rating": 6.9,"votes": 30652,"running_times": 4620},{"title": "The Resident","year": 2011,"rating": 5.3,"votes": 22986,"running_times": 5460},{"title": "The Return","year": 2006,"rating": 4.8,"votes": 10496,"running_times": 5100},{"title": "The Return of the Living Dead","year": 1985,"rating": 7.3,"votes": 44081,"running_times": 6480},{"title": "The Return of the Pink Panther","year": 1975,"rating": 7.1,"votes": 21148,"running_times": 6780},{"title": "The Return of the Texas Chainsaw Massacre","year": 1994,"rating": 3.2,"votes": 16423,"running_times": 5700},{"title": "The Revenant","year": 2015,"rating": 8,"votes": 534685,"running_times": 9360},{"title": "The Rewrite","year": 2014,"rating": 6.2,"votes": 14434,"running_times": 6420},{"title": "The Ridiculous 6","year": 2015,"rating": 4.8,"votes": 33152,"running_times": 7140},{"title": "The Right Stuff","year": 1983,"rating": 7.9,"votes": 48740,"running_times": 11580},{"title": "The Ring","year": 2002,"rating": 7.1,"votes": 278872,"running_times": 6900},{"title": "The Ring Two","year": 2005,"rating": 5.4,"votes": 79526,"running_times": 7680},{"title": "The Ringer","year": 2005,"rating": 5.8,"votes": 32454,"running_times": 5700},{"title": "The Riot Club","year": 2014,"rating": 6,"votes": 17763,"running_times": 6420},{"title": "The Rite","year": 2011,"rating": 6,"votes": 81084,"running_times": 6840},{"title": "The River Wild","year": 1994,"rating": 6.3,"votes": 35528,"running_times": 6660},{"title": "The Road","year": 2009,"rating": 7.3,"votes": 193198,"running_times": 6660},{"title": "The Road Within","year": 2014,"rating": 7.1,"votes": 11272,"running_times": 6000},{"title": "The Road to El Dorado","year": 2000,"rating": 6.9,"votes": 67039,"running_times": 5340},{"title": "The Road to Guantanamo","year": 2006,"rating": 7.5,"votes": 10739,"running_times": 5700},{"title": "The Road to Wellville","year": 1994,"rating": 5.8,"votes": 10290,"running_times": 7080},{"title": "The Roaring Twenties","year": 1939,"rating": 7.9,"votes": 10363,"running_times": 6360},{"title": "The Rock","year": 1996,"rating": 7.4,"votes": 276498,"running_times": 8160},{"title": "The Rocker","year": 2008,"rating": 6.2,"votes": 34007,"running_times": 6120},{"title": "The Rocketeer","year": 1991,"rating": 6.4,"votes": 45916,"running_times": 6480},{"title": "The Rocky Horror Picture Show","year": 1975,"rating": 7.4,"votes": 113940,"running_times": 6000},{"title": "The Romantics","year": 2010,"rating": 5.1,"votes": 10614,"running_times": 5700},{"title": "The Rookie","year": 1990,"rating": 5.8,"votes": 21836,"running_times": 7200},{"title": "The Rookie","year": 2002,"rating": 7,"votes": 28296,"running_times": 7620},{"title": "The Room","year": 2003,"rating": 3.6,"votes": 47057,"running_times": 5940},{"title": "The Roommate","year": 2011,"rating": 4.9,"votes": 31218,"running_times": 5460},{"title": "The Rover","year": 2014,"rating": 6.4,"votes": 37334,"running_times": 6180},{"title": "The Royal Tenenbaums","year": 2001,"rating": 7.6,"votes": 227998,"running_times": 6600},{"title": "The Rugrats Movie","year": 1998,"rating": 5.9,"votes": 15377,"running_times": 5400},{"title": "The Ruins","year": 2008,"rating": 5.9,"votes": 63013,"running_times": 5580},{"title": "The Rules of Attraction","year": 2002,"rating": 6.7,"votes": 46137,"running_times": 6600},{"title": "The Rum Diary","year": 2011,"rating": 6.2,"votes": 91193,"running_times": 7140},{"title": "The Runaways","year": 2010,"rating": 6.6,"votes": 41923,"running_times": 6360},{"title": "The Rundown","year": 2003,"rating": 6.7,"votes": 87944,"running_times": 6240},{"title": "The Running Man","year": 1987,"rating": 6.7,"votes": 121624,"running_times": 6060},{"title": "The Russia House","year": 1990,"rating": 6.1,"votes": 12429,"running_times": 7380},{"title": "The Sacrament","year": 2013,"rating": 6.1,"votes": 13925,"running_times": 5940},{"title": "The Saint","year": 1997,"rating": 6.2,"votes": 54873,"running_times": 6960},{"title": "The Salt of the Earth","year": 2014,"rating": 8.4,"votes": 15191,"running_times": 6600},{"title": "The Salton Sea","year": 2002,"rating": 7.2,"votes": 27675,"running_times": 6180},{"title": "The Salvation","year": 2014,"rating": 6.8,"votes": 29594,"running_times": 5520},{"title": "The Sand Pebbles","year": 1966,"rating": 7.7,"votes": 11150,"running_times": 11760},{"title": "The Sandlot","year": 1993,"rating": 7.8,"votes": 64212,"running_times": 6060},{"title": "The Santa Clause","year": 1994,"rating": 6.4,"votes": 74291,"running_times": 5820},{"title": "The Santa Clause 2","year": 2002,"rating": 5.6,"votes": 39364,"running_times": 6240},{"title": "The Santa Clause 3: The Escape Clause","year": 2006,"rating": 4.7,"votes": 25133,"running_times": 5820},{"title": "The Sapphires","year": 2012,"rating": 7.1,"votes": 11309,"running_times": 6180},{"title": "The Savages","year": 2007,"rating": 7.2,"votes": 33269,"running_times": 6840},{"title": "The Scarlet Letter","year": 1995,"rating": 5.2,"votes": 12823,"running_times": 8100},{"title": "The School of Rock","year": 2003,"rating": 7.1,"votes": 226397,"running_times": 6480},{"title": "The Score","year": 2001,"rating": 6.8,"votes": 107813,"running_times": 7440},{"title": "The Scorpion King","year": 2002,"rating": 5.5,"votes": 112073,"running_times": 6000},{"title": "The Searchers","year": 1956,"rating": 8,"votes": 67908,"running_times": 7140},{"title": "The Second Best Exotic Marigold Hotel","year": 2015,"rating": 6.6,"votes": 26293,"running_times": 7320},{"title": "The Secret Garden","year": 1993,"rating": 7.3,"votes": 31316,"running_times": 6060},{"title": "The Secret Life of Bees","year": 2008,"rating": 7.3,"votes": 21358,"running_times": 6840},{"title": "The Secret Life of Pets","year": 2016,"rating": 6.6,"votes": 137977,"running_times": 5220},{"title": "The Secret Life of Walter Mitty","year": 2013,"rating": 7.3,"votes": 257706,"running_times": 6780},{"title": "The Secret Life of Words","year": 2005,"rating": 7.5,"votes": 10709,"running_times": 6900},{"title": "The Secret of Kells","year": 2009,"rating": 7.7,"votes": 25776,"running_times": 4500},{"title": "The Secret of My Succe$s","year": 1987,"rating": 6.5,"votes": 24924,"running_times": 6660},{"title": "The Secret of NIMH","year": 1982,"rating": 7.6,"votes": 30265,"running_times": 4920},{"title": "The Seeker: The Dark Is Rising","year": 2007,"rating": 4.8,"votes": 13743,"running_times": 5940},{"title": "The Sentinel","year": 2006,"rating": 6.1,"votes": 44185,"running_times": 6480},{"title": "The Serpent and the Rainbow","year": 1988,"rating": 6.5,"votes": 18758,"running_times": 5880},{"title": "The Sessions","year": 2012,"rating": 7.2,"votes": 38256,"running_times": 5700},{"title": "The Seven Year Itch","year": 1955,"rating": 7.2,"votes": 28217,"running_times": 6300},{"title": "The Seventh Sign","year": 1988,"rating": 5.9,"votes": 11175,"running_times": 5820},{"title": "The Shack","year": 2017,"rating": 6.3,"votes": 18221,"running_times": 7920},{"title": "The Shadow","year": 1994,"rating": 6,"votes": 20129,"running_times": 6480},{"title": "The Shaggy Dog","year": 2006,"rating": 4.4,"votes": 15990,"running_times": 5880},{"title": "The Shallows","year": 2016,"rating": 6.3,"votes": 89641,"running_times": 5160},{"title": "The Shape of Things","year": 2003,"rating": 6.7,"votes": 10095,"running_times": 5760},{"title": "The Shawshank Redemption","year": 1994,"rating": 9.3,"votes": 1888533,"running_times": 8520},{"title": "The Shining","year": 1980,"rating": 8.4,"votes": 692021,"running_times": 8760},{"title": "The Shipping News","year": 2001,"rating": 6.8,"votes": 29935,"running_times": 6660},{"title": "The Shootist","year": 1976,"rating": 7.7,"votes": 18572,"running_times": 6000},{"title": "The Shop Around the Corner","year": 1940,"rating": 8.1,"votes": 22183,"running_times": 5940},{"title": "The Siege","year": 1998,"rating": 6.3,"votes": 61557,"running_times": 6960},{"title": "The Siege of Jadotville","year": 2016,"rating": 7.3,"votes": 17814,"running_times": 6480},{"title": "The Signal","year": 2007,"rating": 6.1,"votes": 18972,"running_times": 6180},{"title": "The Signal","year": 2014,"rating": 6.1,"votes": 53979,"running_times": 5820},{"title": "The Silence of the Lambs","year": 1991,"rating": 8.6,"votes": 1005824,"running_times": 8280},{"title": "The Simpsons Movie","year": 2007,"rating": 7.4,"votes": 275789,"running_times": 5220},{"title": "The Sisterhood of the Traveling Pants","year": 2005,"rating": 6.5,"votes": 48049,"running_times": 7140},{"title": "The Sisterhood of the Traveling Pants 2","year": 2008,"rating": 6.2,"votes": 23987,"running_times": 7140},{"title": "The Sitter","year": 2011,"rating": 5.7,"votes": 63242,"running_times": 5220},{"title": "The Sixth Sense","year": 1999,"rating": 8.1,"votes": 776053,"running_times": 6420},{"title": "The Skeleton Key","year": 2005,"rating": 6.5,"votes": 94403,"running_times": 6240},{"title": "The Skeleton Twins","year": 2014,"rating": 6.8,"votes": 34525,"running_times": 5580},{"title": "The Skulls","year": 2000,"rating": 5.6,"votes": 28314,"running_times": 6360},{"title": "The Slammin' Salmon","year": 2009,"rating": 6.5,"votes": 11416,"running_times": 5400},{"title": "The Smurfs","year": 2011,"rating": 5.5,"votes": 72567,"running_times": 6180},{"title": "The Smurfs 2","year": 2013,"rating": 5.4,"votes": 31061,"running_times": 6300},{"title": "The Snowman","year": 2017,"rating": 5.1,"votes": 14779,"running_times": 7140},{"title": "The Social Network","year": 2010,"rating": 7.7,"votes": 528377,"running_times": 7200},{"title": "The Soloist","year": 2009,"rating": 6.7,"votes": 46174,"running_times": 7020},{"title": "The Son of No One","year": 2011,"rating": 5.1,"votes": 15063,"running_times": 5400},{"title": "The Sons of Katie Elder","year": 1965,"rating": 7.2,"votes": 11668,"running_times": 7320},{"title": "The Sorcerer's Apprentice","year": 2010,"rating": 6.1,"votes": 134792,"running_times": 6540},{"title": "The Sound of Music","year": 1965,"rating": 8,"votes": 163945,"running_times": 10440},{"title": "The Space Between Us","year": 2017,"rating": 6.4,"votes": 29211,"running_times": 7200},{"title": "The Spanish Prisoner","year": 1997,"rating": 7.3,"votes": 19572,"running_times": 6600},{"title": "The Specialist","year": 1994,"rating": 5.5,"votes": 54437,"running_times": 6600},{"title": "The Spectacular Now","year": 2013,"rating": 7.1,"votes": 121292,"running_times": 5700},{"title": "The Spiderwick Chronicles","year": 2008,"rating": 6.6,"votes": 75232,"running_times": 6420},{"title": "The Spirit","year": 2008,"rating": 4.8,"votes": 55852,"running_times": 6180},{"title": "The SpongeBob Movie: Sponge Out of Water","year": 2015,"rating": 6,"votes": 39185,"running_times": 5520},{"title": "The SpongeBob SquarePants Movie","year": 2004,"rating": 7,"votes": 64917,"running_times": 5220},{"title": "The Spy Next Door","year": 2010,"rating": 5.4,"votes": 33445,"running_times": 5640},{"title": "The Spy Who Came in from the Cold","year": 1965,"rating": 7.7,"votes": 11988,"running_times": 6720},{"title": "The Spy Who Loved Me","year": 1977,"rating": 7.1,"votes": 83086,"running_times": 7500},{"title": "The Square","year": 2017,"rating": 7.7,"votes": 10452,"running_times": 8520},{"title": "The Squid and the Whale","year": 2005,"rating": 7.4,"votes": 65586,"running_times": 5280},{"title": "The Stanford Prison Experiment","year": 2015,"rating": 6.9,"votes": 24929,"running_times": 7320},{"title": "The Starving Games","year": 2013,"rating": 3.3,"votes": 15908,"running_times": 5580},{"title": "The Station Agent","year": 2003,"rating": 7.7,"votes": 61383,"running_times": 5340},{"title": "The Stepfather","year": 1987,"rating": 6.8,"votes": 10118,"running_times": 5340},{"title": "The Stepfather","year": 2009,"rating": 5.6,"votes": 25548,"running_times": 6060},{"title": "The Stepford Wives","year": 1975,"rating": 6.9,"votes": 13376,"running_times": 6900},{"title": "The Stepford Wives","year": 2004,"rating": 5.2,"votes": 52642,"running_times": 5580},{"title": "The Sting","year": 1973,"rating": 8.3,"votes": 196224,"running_times": 7740},{"title": "The Stoning of Soraya M.","year": 2008,"rating": 8,"votes": 15633,"running_times": 6840},{"title": "The Story of Us","year": 1999,"rating": 5.9,"votes": 19337,"running_times": 5700},{"title": "The Straight Story","year": 1999,"rating": 8,"votes": 69476,"running_times": 6720},{"title": "The Stranger","year": 1946,"rating": 7.4,"votes": 14987,"running_times": 5700},{"title": "The Strangers","year": 2008,"rating": 6.2,"votes": 100210,"running_times": 5280},{"title": "The Substitute","year": 1996,"rating": 5.9,"votes": 10182,"running_times": 6840},{"title": "The Sugarland Express","year": 1974,"rating": 6.8,"votes": 12491,"running_times": 6600},{"title": "The Sum of All Fears","year": 2002,"rating": 6.4,"votes": 91728,"running_times": 7680},{"title": "The Sure Thing","year": 1985,"rating": 7,"votes": 16657,"running_times": 6000},{"title": "The Survivalist","year": 2015,"rating": 6.3,"votes": 11292,"running_times": 6240},{"title": "The Swan Princess","year": 1994,"rating": 6.4,"votes": 19213,"running_times": 5400},{"title": "The Sweeney","year": 2012,"rating": 6.1,"votes": 17373,"running_times": 6720},{"title": "The Sweet Hereafter","year": 1997,"rating": 7.6,"votes": 28526,"running_times": 6720},{"title": "The Sweetest Thing","year": 2002,"rating": 5.1,"votes": 49102,"running_times": 5400},{"title": "The Switch","year": 2010,"rating": 6.1,"votes": 84752,"running_times": 6060},{"title": "The Sword in the Stone","year": 1963,"rating": 7.2,"votes": 72723,"running_times": 4740},{"title": "The Tailor of Panama","year": 2001,"rating": 6.1,"votes": 25172,"running_times": 6540},{"title": "The Taking","year": 2014,"rating": 6,"votes": 19155,"running_times": 5400},{"title": "The Taking of Pelham 123","year": 2009,"rating": 6.4,"votes": 162021,"running_times": 6360},{"title": "The Taking of Pelham One Two Three","year": 1974,"rating": 7.7,"votes": 21595,"running_times": 6240},{"title": "The Tale of Despereaux","year": 2008,"rating": 6.1,"votes": 32678,"running_times": 5580},{"title": "The Talented Mr. Ripley","year": 1999,"rating": 7.3,"votes": 150246,"running_times": 8340},{"title": "The Tall Man","year": 2012,"rating": 5.9,"votes": 33866,"running_times": 6360},{"title": "The Ten","year": 2007,"rating": 5,"votes": 15676,"running_times": 5760},{"title": "The Ten Commandments","year": 1956,"rating": 7.9,"votes": 52473,"running_times": 13200},{"title": "The Terminal","year": 2004,"rating": 7.3,"votes": 335257,"running_times": 7680},{"title": "The Terminator","year": 1984,"rating": 8,"votes": 665696,"running_times": 6420},{"title": "The Texas Chain Saw Massacre","year": 1974,"rating": 7.5,"votes": 109598,"running_times": 5280},{"title": "The Texas Chainsaw Massacre","year": 2003,"rating": 6.2,"votes": 116056,"running_times": 5880},{"title": "The Texas Chainsaw Massacre 2","year": 1986,"rating": 5.6,"votes": 21886,"running_times": 6060},{"title": "The Texas Chainsaw Massacre: The Beginning","year": 2006,"rating": 5.9,"votes": 60550,"running_times": 5760},{"title": "The Thaw","year": 2009,"rating": 5.2,"votes": 10084,"running_times": 5400},{"title": "The Theory of Everything","year": 2014,"rating": 7.7,"votes": 316106,"running_times": 7380},{"title": "The Thin Blue Line","year": 1988,"rating": 8.1,"votes": 17925,"running_times": 6060},{"title": "The Thin Man","year": 1934,"rating": 8.1,"votes": 22285,"running_times": 5460},{"title": "The Thin Red Line","year": 1998,"rating": 7.6,"votes": 150404,"running_times": 12900},{"title": "The Thing","year": 1982,"rating": 8.2,"votes": 293518,"running_times": 6540},{"title": "The Thing","year": 2011,"rating": 6.2,"votes": 103362,"running_times": 6180},{"title": "The Thing from Another World","year": 1951,"rating": 7.2,"votes": 20919,"running_times": 5220},{"title": "The Third Man","year": 1949,"rating": 8.2,"votes": 127466,"running_times": 6240},{"title": "The Thirteenth Floor","year": 1999,"rating": 7,"votes": 57011,"running_times": 6000},{"title": "The Thomas Crown Affair","year": 1968,"rating": 7,"votes": 18269,"running_times": 6120},{"title": "The Thomas Crown Affair","year": 1999,"rating": 6.8,"votes": 77349,"running_times": 6780},{"title": "The Three Burials of Melquiades Estrada","year": 2005,"rating": 7.4,"votes": 35698,"running_times": 7260},{"title": "The Three Musketeers","year": 1973,"rating": 7.3,"votes": 13230,"running_times": 6360},{"title": "The Three Musketeers","year": 1993,"rating": 6.4,"votes": 44143,"running_times": 6300},{"title": "The Three Musketeers","year": 2011,"rating": 5.8,"votes": 94299,"running_times": 6600},{"title": "The Three Stooges","year": 2012,"rating": 5.1,"votes": 26998,"running_times": 5520},{"title": "The Tigger Movie","year": 2000,"rating": 6.3,"votes": 14400,"running_times": 4620},{"title": "The Time Machine","year": 1960,"rating": 7.6,"votes": 30163,"running_times": 6180},{"title": "The Time Machine","year": 2002,"rating": 5.9,"votes": 108614,"running_times": 5760},{"title": "The Time Traveler's Wife","year": 2009,"rating": 7.1,"votes": 124143,"running_times": 6420},{"title": "The To Do List","year": 2013,"rating": 5.8,"votes": 32406,"running_times": 6240},{"title": "The Tourist","year": 2010,"rating": 6,"votes": 192546,"running_times": 6180},{"title": "The Tournament","year": 2009,"rating": 6.1,"votes": 32011,"running_times": 5700},{"title": "The Towering Inferno","year": 1974,"rating": 6.9,"votes": 32856,"running_times": 9900},{"title": "The Town","year": 2010,"rating": 7.6,"votes": 302386,"running_times": 9180},{"title": "The Town That Dreaded Sundown","year": 2014,"rating": 5.6,"votes": 11248,"running_times": 5160},{"title": "The Toxic Avenger","year": 1984,"rating": 6.2,"votes": 20890,"running_times": 5460},{"title": "The Tragedy of Macbeth","year": 1971,"rating": 7.5,"votes": 10629,"running_times": 8400},{"title": "The Train","year": 1964,"rating": 7.9,"votes": 11335,"running_times": 8400},{"title": "The Transformers: The Movie","year": 1986,"rating": 7.3,"votes": 33807,"running_times": 5100},{"title": "The Transporter","year": 2002,"rating": 6.8,"votes": 255330,"running_times": 5520},{"title": "The Transporter Refueled","year": 2015,"rating": 5.1,"votes": 32968,"running_times": 5760},{"title": "The Treasure of the Sierra Madre","year": 1948,"rating": 8.3,"votes": 88818,"running_times": 7560},{"title": "The Tree of Life","year": 2011,"rating": 6.8,"votes": 147663,"running_times": 8340},{"title": "The Trip","year": 2010,"rating": 7,"votes": 19086,"running_times": 6720},{"title": "The Trip to Italy","year": 2014,"rating": 6.6,"votes": 12519,"running_times": 10500},{"title": "The Trouble with Harry","year": 1955,"rating": 7.2,"votes": 27605,"running_times": 5940},{"title": "The Truman Show","year": 1998,"rating": 8.1,"votes": 752414,"running_times": 6180},{"title": "The Trust","year": 2016,"rating": 5.4,"votes": 13898,"running_times": 5520},{"title": "The Truth About Cats & Dogs","year": 1996,"rating": 6.3,"votes": 23194,"running_times": 5820},{"title": "The Tunnel","year": 2011,"rating": 5.9,"votes": 16883,"running_times": 5400},{"title": "The Tuxedo","year": 2002,"rating": 5.3,"votes": 67876,"running_times": 5880},{"title": "The Twilight Saga: Breaking Dawn - Part 1","year": 2011,"rating": 4.9,"votes": 194719,"running_times": 7500},{"title": "The Twilight Saga: Breaking Dawn - Part 2","year": 2012,"rating": 5.5,"votes": 199491,"running_times": 7320},{"title": "The Twilight Saga: Eclipse","year": 2010,"rating": 4.9,"votes": 197473,"running_times": 7860},{"title": "The Twilight Saga: New Moon","year": 2009,"rating": 4.7,"votes": 234090,"running_times": 7800},{"title": "The Two Faces of January","year": 2014,"rating": 6.2,"votes": 25170,"running_times": 5760},{"title": "The Ugly Truth","year": 2009,"rating": 6.5,"votes": 177843,"running_times": 5760},{"title": "The Ultimate Gift","year": 2006,"rating": 7.4,"votes": 15293,"running_times": 6840},{"title": "The Unbearable Lightness of Being","year": 1988,"rating": 7.4,"votes": 29201,"running_times": 10260},{"title": "The Unborn","year": 2009,"rating": 4.8,"votes": 44583,"running_times": 5340},{"title": "The Uninvited","year": 2009,"rating": 6.4,"votes": 67429,"running_times": 5220},{"title": "The United States of Leland","year": 2003,"rating": 7.1,"votes": 21022,"running_times": 6480},{"title": "The Untouchables","year": 1987,"rating": 7.9,"votes": 236735,"running_times": 7140},{"title": "The Upside of Anger","year": 2005,"rating": 6.9,"votes": 19799,"running_times": 7080},{"title": "The Usual Suspects","year": 1995,"rating": 8.6,"votes": 825415,"running_times": 6360},{"title": "The VVitch: A New-England Folktale","year": 2015,"rating": 6.8,"votes": 116302,"running_times": 5520},{"title": "The Vanishing","year": 1993,"rating": 6.3,"votes": 20064,"running_times": 6540},{"title": "The Vatican Tapes","year": 2015,"rating": 5,"votes": 14242,"running_times": 5460},{"title": "The Verdict","year": 1982,"rating": 7.8,"votes": 29321,"running_times": 7740},{"title": "The Vikings","year": 1958,"rating": 7.1,"votes": 10339,"running_times": 6960},{"title": "The Village","year": 2004,"rating": 6.5,"votes": 211351,"running_times": 6480},{"title": "The Virgin Suicides","year": 1999,"rating": 7.2,"votes": 126377,"running_times": 5820},{"title": "The Visit","year": 2015,"rating": 6.2,"votes": 89398,"running_times": 5640},{"title": "The Visitor","year": 2007,"rating": 7.7,"votes": 38887,"running_times": 6240},{"title": "The Voices","year": 2014,"rating": 6.4,"votes": 42329,"running_times": 6180},{"title": "The Void","year": 2016,"rating": 5.8,"votes": 17759,"running_times": 5400},{"title": "The Vow","year": 2012,"rating": 6.8,"votes": 161595,"running_times": 6240},{"title": "The Wackness","year": 2008,"rating": 7,"votes": 28228,"running_times": 5940},{"title": "The Walk","year": 2015,"rating": 7.3,"votes": 99230,"running_times": 7380},{"title": "The Wall","year": 2017,"rating": 6.1,"votes": 13630,"running_times": 5280},{"title": "The War","year": 1994,"rating": 6.7,"votes": 10819,"running_times": 7560},{"title": "The War of the Roses","year": 1989,"rating": 6.8,"votes": 41078,"running_times": 6960},{"title": "The War of the Worlds","year": 1953,"rating": 7.1,"votes": 27465,"running_times": 5100},{"title": "The Ward","year": 2010,"rating": 5.6,"votes": 36222,"running_times": 5340},{"title": "The Warrior's Way","year": 2010,"rating": 6.3,"votes": 23298,"running_times": 6000},{"title": "The Warriors","year": 1979,"rating": 7.7,"votes": 78567,"running_times": 5520},{"title": "The Watch","year": 2012,"rating": 5.7,"votes": 110365,"running_times": 6120},{"title": "The Watcher","year": 2000,"rating": 5.3,"votes": 23272,"running_times": 5820},{"title": "The Water Diviner","year": 2014,"rating": 7.1,"votes": 61571,"running_times": 6660},{"title": "The Water Horse","year": 2007,"rating": 6.5,"votes": 33841,"running_times": 6720},{"title": "The Waterboy","year": 1998,"rating": 6.1,"votes": 128608,"running_times": 5400},{"title": "The Way","year": 2010,"rating": 7.4,"votes": 25485,"running_times": 7380},{"title": "The Way Back","year": 2010,"rating": 7.3,"votes": 95405,"running_times": 7980},{"title": "The Way Way Back","year": 2013,"rating": 7.4,"votes": 125222,"running_times": 6180},{"title": "The Way We Were","year": 1973,"rating": 7.1,"votes": 18180,"running_times": 7080},{"title": "The Way of the Gun","year": 2000,"rating": 6.7,"votes": 28622,"running_times": 7200},{"title": "The Weather Man","year": 2005,"rating": 6.6,"votes": 72135,"running_times": 6120},{"title": "The Wedding Date","year": 2005,"rating": 6.1,"votes": 41956,"running_times": 5400},{"title": "The Wedding Planner","year": 2001,"rating": 5.2,"votes": 66485,"running_times": 6180},{"title": "The Wedding Ringer","year": 2015,"rating": 6.7,"votes": 61464,"running_times": 6060},{"title": "The Wedding Singer","year": 1998,"rating": 6.8,"votes": 117472,"running_times": 5700},{"title": "The Whistleblower","year": 2010,"rating": 7.2,"votes": 27422,"running_times": 6720},{"title": "The Whole Nine Yards","year": 2000,"rating": 6.7,"votes": 96501,"running_times": 5880},{"title": "The Whole Ten Yards","year": 2004,"rating": 5.5,"votes": 48689,"running_times": 5880},{"title": "The Whole Truth","year": 2016,"rating": 6.2,"votes": 14683,"running_times": 5640},{"title": "The Wicker Man","year": 1973,"rating": 7.6,"votes": 53387,"running_times": 5940},{"title": "The Wicker Man","year": 2006,"rating": 3.7,"votes": 56687,"running_times": 6120},{"title": "The Wild","year": 2006,"rating": 5.3,"votes": 20527,"running_times": 4920},{"title": "The Wild Bunch","year": 1969,"rating": 8,"votes": 67529,"running_times": 8700},{"title": "The Wild Geese","year": 1978,"rating": 6.8,"votes": 10009,"running_times": 8040},{"title": "The Wild One","year": 1953,"rating": 6.9,"votes": 12360,"running_times": 4740},{"title": "The Wild Thornberrys Movie","year": 2002,"rating": 5.3,"votes": 12815,"running_times": 5100},{"title": "The Wind That Shakes the Barley","year": 2006,"rating": 7.5,"votes": 39810,"running_times": 7620},{"title": "The Witches","year": 1990,"rating": 6.8,"votes": 27846,"running_times": 5460},{"title": "The Witches of Eastwick","year": 1987,"rating": 6.5,"votes": 52381,"running_times": 7080},{"title": "The Wiz","year": 1978,"rating": 5.3,"votes": 11821,"running_times": 8160},{"title": "The Wizard","year": 1989,"rating": 6,"votes": 11413,"running_times": 6000},{"title": "The Wizard of Oz","year": 1939,"rating": 8.1,"votes": 321107,"running_times": 6120},{"title": "The Wolf Man","year": 1941,"rating": 7.4,"votes": 18812,"running_times": 4200},{"title": "The Wolf of Wall Street","year": 2013,"rating": 8.2,"votes": 911859,"running_times": 14400},{"title": "The Wolfman","year": 2010,"rating": 5.8,"votes": 93751,"running_times": 7140},{"title": "The Wolverine","year": 2013,"rating": 6.7,"votes": 369113,"running_times": 8280},{"title": "The Woman","year": 2011,"rating": 6,"votes": 18754,"running_times": 6060},{"title": "The Woman in Black","year": 2012,"rating": 6.4,"votes": 155529,"running_times": 5700},{"title": "The Woman in Black 2: Angel of Death","year": 2014,"rating": 4.9,"votes": 22594,"running_times": 5880},{"title": "The Woman in Red","year": 1984,"rating": 5.9,"votes": 11392,"running_times": 5220},{"title": "The Woman in the Window","year": 1944,"rating": 7.8,"votes": 10497,"running_times": 6420},{"title": "The Women","year": 1939,"rating": 8,"votes": 10584,"running_times": 7980},{"title": "The Women","year": 2008,"rating": 4.9,"votes": 18004,"running_times": 6840},{"title": "The Woodsman","year": 2004,"rating": 7.2,"votes": 29060,"running_times": 5220},{"title": "The Words","year": 2012,"rating": 7.1,"votes": 65538,"running_times": 6120},{"title": "The World According to Garp","year": 1982,"rating": 7.2,"votes": 22128,"running_times": 8160},{"title": "The World Is Not Enough","year": 1999,"rating": 6.4,"votes": 166771,"running_times": 9600},{"title": "The World's End","year": 2013,"rating": 7,"votes": 210573,"running_times": 6540},{"title": "The World's Fastest Indian","year": 2005,"rating": 7.8,"votes": 46860,"running_times": 7620},{"title": "The Wraith","year": 1986,"rating": 5.9,"votes": 11815,"running_times": 5580},{"title": "The Wrestler","year": 2008,"rating": 7.9,"votes": 266299,"running_times": 6540},{"title": "The Wrong Man","year": 1956,"rating": 7.5,"votes": 21010,"running_times": 6300},{"title": "The Wrong Trousers","year": 1993,"rating": 8.4,"votes": 44121,"running_times": 1800},{"title": "The X Files","year": 1998,"rating": 7,"votes": 91195,"running_times": 7260},{"title": "The X Files: I Want to Believe","year": 2008,"rating": 5.9,"votes": 82186,"running_times": 6480},{"title": "The Yards","year": 2000,"rating": 6.4,"votes": 17330,"running_times": 6900},{"title": "The Year of Living Dangerously","year": 1982,"rating": 7.2,"votes": 16789,"running_times": 6900},{"title": "The Young Victoria","year": 2009,"rating": 7.3,"votes": 49898,"running_times": 6300},{"title": "The Young and Prodigious T.S. Spivet","year": 2013,"rating": 7.1,"votes": 13735,"running_times": 6300},{"title": "The Zero Theorem","year": 2013,"rating": 6.1,"votes": 38906,"running_times": 6420},{"title": "The Zookeeper's Wife","year": 2017,"rating": 7,"votes": 18921,"running_times": 7620},{"title": "Their Finest","year": 2016,"rating": 6.8,"votes": 10101,"running_times": 7020},{"title": "Thelma & Louise","year": 1991,"rating": 7.4,"votes": 111181,"running_times": 7800},{"title": "Them!","year": 1954,"rating": 7.3,"votes": 16401,"running_times": 5640},{"title": "There Will Be Blood","year": 2007,"rating": 8.1,"votes": 418664,"running_times": 9480},{"title": "There's Something About Mary","year": 1998,"rating": 7.1,"votes": 261762,"running_times": 7800},{"title": "These Final Hours","year": 2013,"rating": 6.7,"votes": 12815,"running_times": 5220},{"title": "They","year": 2002,"rating": 4.8,"votes": 11399,"running_times": 5340},{"title": "They Came Together","year": 2014,"rating": 5.5,"votes": 18600,"running_times": 4980},{"title": "They Live","year": 1988,"rating": 7.3,"votes": 85066,"running_times": 5640},{"title": "They Shoot Horses, Don't They?","year": 1969,"rating": 7.9,"votes": 13393,"running_times": 7740},{"title": "Thick as Thieves","year": 2009,"rating": 6,"votes": 30544,"running_times": 6240},{"title": "Thief","year": 1981,"rating": 7.4,"votes": 18773,"running_times": 7320},{"title": "Things We Lost in the Fire","year": 2007,"rating": 7.2,"votes": 25533,"running_times": 7080},{"title": "Things to Do in Denver When You're Dead","year": 1995,"rating": 6.8,"votes": 23523,"running_times": 6900},{"title": "Think Like a Man","year": 2012,"rating": 6.6,"votes": 37687,"running_times": 7320},{"title": "Think Like a Man Too","year": 2014,"rating": 5.8,"votes": 16909,"running_times": 6360},{"title": "Thinner","year": 1996,"rating": 5.7,"votes": 22657,"running_times": 5580},{"title": "Thir13en Ghosts","year": 2001,"rating": 5.6,"votes": 69826,"running_times": 5460},{"title": "Third Person","year": 2013,"rating": 6.4,"votes": 23048,"running_times": 8220},{"title": "Thirteen","year": 2003,"rating": 6.8,"votes": 72716,"running_times": 6000},{"title": "Thirteen Days","year": 2000,"rating": 7.3,"votes": 48091,"running_times": 8700},{"title": "This Boy's Life","year": 1993,"rating": 7.3,"votes": 39017,"running_times": 6900},{"title": "This Film Is Not Yet Rated","year": 2006,"rating": 7.5,"votes": 26134,"running_times": 5880},{"title": "This Is 40","year": 2012,"rating": 6.2,"votes": 110651,"running_times": 8040},{"title": "This Is England","year": 2006,"rating": 7.7,"votes": 104758,"running_times": 6060},{"title": "This Is It","year": 2009,"rating": 7.3,"votes": 34810,"running_times": 6660},{"title": "This Is Spinal Tap","year": 1984,"rating": 8,"votes": 113091,"running_times": 4920},{"title": "This Is Where I Leave You","year": 2014,"rating": 6.6,"votes": 60539,"running_times": 6180},{"title": "This Is the End","year": 2013,"rating": 6.6,"votes": 338167,"running_times": 6420},{"title": "This Means War","year": 2012,"rating": 6.3,"votes": 158614,"running_times": 6180},{"title": "This Must Be the Place","year": 2011,"rating": 6.7,"votes": 28430,"running_times": 7080},{"title": "Thor","year": 2011,"rating": 7,"votes": 597270,"running_times": 6900},{"title": "Thor: Ragnarok","year": 2017,"rating": 8.1,"votes": 170098,"running_times": 7800},{"title": "Thor: The Dark World","year": 2013,"rating": 7,"votes": 466861,"running_times": 6720},{"title": "Three Billboards Outside Ebbing, Missouri","year": 2017,"rating": 8.5,"votes": 12269,"running_times": 6900},{"title": "Three Days of the Condor","year": 1975,"rating": 7.5,"votes": 38865,"running_times": 7020},{"title": "Three Kings","year": 1999,"rating": 7.1,"votes": 146204,"running_times": 6840},{"title": "Three to Tango","year": 1999,"rating": 6.1,"votes": 16986,"running_times": 5880},{"title": "Threesome","year": 1994,"rating": 6.2,"votes": 11466,"running_times": 5340},{"title": "Throw Momma from the Train","year": 1987,"rating": 6.2,"votes": 28749,"running_times": 5280},{"title": "Thumbelina","year": 1994,"rating": 6.4,"votes": 12645,"running_times": 5220},{"title": "Thumbsucker","year": 2005,"rating": 6.6,"votes": 19455,"running_times": 5760},{"title": "Thunderball","year": 1965,"rating": 7,"votes": 88693,"running_times": 7800},{"title": "Thunderbirds","year": 2004,"rating": 4.2,"votes": 11828,"running_times": 5700},{"title": "Thunderbolt and Lightfoot","year": 1974,"rating": 7.1,"votes": 17590,"running_times": 6900},{"title": "Thunderheart","year": 1992,"rating": 6.8,"votes": 12172,"running_times": 7140},{"title": "Thursday","year": 1998,"rating": 7.2,"votes": 15020,"running_times": 5220},{"title": "TiMER","year": 2009,"rating": 6.6,"votes": 11302,"running_times": 5940},{"title": "Tian jiang xiong shi","year": 2015,"rating": 6.1,"votes": 14550,"running_times": 7620},{"title": "Tideland","year": 2005,"rating": 6.5,"votes": 28552,"running_times": 7200},{"title": "Tigerland","year": 2000,"rating": 7,"votes": 34855,"running_times": 6060},{"title": "Tightrope","year": 1984,"rating": 6.3,"votes": 12721,"running_times": 6840},{"title": "Timbuktu","year": 2014,"rating": 7.2,"votes": 13276,"running_times": 5820},{"title": "Time After Time","year": 1979,"rating": 7.2,"votes": 12886,"running_times": 6720},{"title": "Time Bandits","year": 1981,"rating": 7,"votes": 49534,"running_times": 6960},{"title": "Time Lapse","year": 2014,"rating": 6.5,"votes": 33700,"running_times": 6240},{"title": "Timecop","year": 1994,"rating": 5.8,"votes": 48177,"running_times": 5940},{"title": "Timeline","year": 2003,"rating": 5.6,"votes": 55343,"running_times": 6960},{"title": "Tin Cup","year": 1996,"rating": 6.3,"votes": 40422,"running_times": 8100},{"title": "Tinker Tailor Soldier Spy","year": 2011,"rating": 7.1,"votes": 162349,"running_times": 7320},{"title": "Tiny Furniture","year": 2010,"rating": 6.2,"votes": 12833,"running_times": 5880},{"title": "Titan A.E.","year": 2000,"rating": 6.6,"votes": 54378,"running_times": 5640},{"title": "Titanic","year": 1997,"rating": 7.8,"votes": 872744,"running_times": 11640},{"title": "Titus","year": 1999,"rating": 7.2,"votes": 18157,"running_times": 9720},{"title": "To Be or Not to Be","year": 1942,"rating": 8.2,"votes": 21156,"running_times": 5940},{"title": "To Catch a Thief","year": 1955,"rating": 7.5,"votes": 51136,"running_times": 6360},{"title": "To Die For","year": 1995,"rating": 6.8,"votes": 37325,"running_times": 6600},{"title": "To Have and Have Not","year": 1944,"rating": 8,"votes": 25610,"running_times": 6000},{"title": "To Kill a Mockingbird","year": 1962,"rating": 8.3,"votes": 243039,"running_times": 7740},{"title": "To Live and Die in L.A.","year": 1985,"rating": 7.3,"votes": 23530,"running_times": 6960},{"title": "To Rome with Love","year": 2012,"rating": 6.3,"votes": 74663,"running_times": 6720},{"title": "To Sir, with Love","year": 1967,"rating": 7.7,"votes": 13076,"running_times": 6300},{"title": "To Wong Foo Thanks for Everything, Julie Newmar","year": 1995,"rating": 6.4,"votes": 23230,"running_times": 6540},{"title": "To the Bone","year": 2017,"rating": 6.9,"votes": 21942,"running_times": 6420},{"title": "To the Wonder","year": 2012,"rating": 5.9,"votes": 23641,"running_times": 6720},{"title": "Tokarev","year": 2014,"rating": 5,"votes": 20189,"running_times": 5880},{"title": "Tokyo Goddofazazu","year": 2003,"rating": 7.9,"votes": 22743,"running_times": 5580},{"title": "Tom yum goong","year": 2005,"rating": 7.1,"votes": 31950,"running_times": 6660},{"title": "Tombstone","year": 1993,"rating": 7.8,"votes": 104882,"running_times": 8040},{"title": "Tomcats","year": 2001,"rating": 5.3,"votes": 16003,"running_times": 5700},{"title": "Tommy","year": 1975,"rating": 6.6,"votes": 16577,"running_times": 6660},{"title": "Tommy Boy","year": 1995,"rating": 7.1,"votes": 66806,"running_times": 5820},{"title": "Tomorrow Never Dies","year": 1997,"rating": 6.5,"votes": 159140,"running_times": 7140},{"title": "Tomorrow, When the War Began","year": 2010,"rating": 6.2,"votes": 28223,"running_times": 6180},{"title": "Tomorrowland","year": 2015,"rating": 6.5,"votes": 149378,"running_times": 7800},{"title": "Toni Erdmann","year": 2016,"rating": 7.5,"votes": 30830,"running_times": 9720},{"title": "Tooth Fairy","year": 2010,"rating": 5,"votes": 33791,"running_times": 6060},{"title": "Tootsie","year": 1982,"rating": 7.4,"votes": 83730,"running_times": 6960},{"title": "Top Five","year": 2014,"rating": 6.4,"votes": 23587,"running_times": 6120},{"title": "Top Gun","year": 1986,"rating": 6.9,"votes": 239755,"running_times": 6600},{"title": "Top Hat","year": 1935,"rating": 7.8,"votes": 14522,"running_times": 6060},{"title": "Top Secret!","year": 1984,"rating": 7.2,"votes": 50375,"running_times": 5400},{"title": "Topaz","year": 1969,"rating": 6.3,"votes": 13928,"running_times": 8580},{"title": "Topsy-Turvy","year": 1999,"rating": 7.4,"votes": 10533,"running_times": 9240},{"title": "Tora! Tora! Tora!","year": 1970,"rating": 7.5,"votes": 27158,"running_times": 8940},{"title": "Torn Curtain","year": 1966,"rating": 6.7,"votes": 20568,"running_times": 7680},{"title": "Torque","year": 2004,"rating": 4,"votes": 24817,"running_times": 5040},{"title": "Total Eclipse","year": 1995,"rating": 6.6,"votes": 11463,"running_times": 6660},{"title": "Total Recall","year": 1990,"rating": 7.5,"votes": 260008,"running_times": 6780},{"title": "Total Recall","year": 2012,"rating": 6.3,"votes": 216376,"running_times": 7800},{"title": "Touch of Evil","year": 1958,"rating": 8.1,"votes": 80814,"running_times": 6720},{"title": "Touching the Void","year": 2003,"rating": 8.1,"votes": 29255,"running_times": 6360},{"title": "Tower Heist","year": 2011,"rating": 6.2,"votes": 117332,"running_times": 6240},{"title": "Town Creek","year": 2009,"rating": 5.4,"votes": 10254,"running_times": 5400},{"title": "Toy Soldiers","year": 1991,"rating": 6.5,"votes": 17221,"running_times": 6660},{"title": "Toy Story","year": 1995,"rating": 8.3,"votes": 704806,"running_times": 4860},{"title": "Toy Story 2","year": 1999,"rating": 7.9,"votes": 425458,"running_times": 5520},{"title": "Toy Story 3","year": 2010,"rating": 8.3,"votes": 612021,"running_times": 6180},{"title": "Toys","year": 1992,"rating": 5,"votes": 27937,"running_times": 7320},{"title": "Tracers","year": 2015,"rating": 5.6,"votes": 15688,"running_times": 5640},{"title": "Tracks","year": 2013,"rating": 7.2,"votes": 22926,"running_times": 6720},{"title": "Trade","year": 2007,"rating": 7.4,"votes": 15564,"running_times": 7200},{"title": "Trading Places","year": 1983,"rating": 7.5,"votes": 113180,"running_times": 6960},{"title": "Traffic","year": 2000,"rating": 7.6,"votes": 178628,"running_times": 11400},{"title": "Trailer Park Boys: The Movie","year": 2006,"rating": 7.3,"votes": 10730,"running_times": 5700},{"title": "Training Day","year": 2001,"rating": 7.7,"votes": 332078,"running_times": 7320},{"title": "Trainspotting","year": 1996,"rating": 8.2,"votes": 538219,"running_times": 5640},{"title": "Trainwreck","year": 2015,"rating": 6.2,"votes": 111924,"running_times": 7740},{"title": "Traitor","year": 2008,"rating": 7,"votes": 51231,"running_times": 6840},{"title": "Trance","year": 2013,"rating": 6.9,"votes": 100012,"running_times": 6060},{"title": "Transamerica","year": 2005,"rating": 7.4,"votes": 37802,"running_times": 6180},{"title": "Transcendence","year": 2014,"rating": 6.3,"votes": 191749,"running_times": 7140},{"title": "Transformers","year": 2007,"rating": 7.1,"votes": 544522,"running_times": 8640},{"title": "Transformers: Age of Extinction","year": 2014,"rating": 5.7,"votes": 266571,"running_times": 9900},{"title": "Transformers: Dark of the Moon","year": 2011,"rating": 6.3,"votes": 348266,"running_times": 9240},{"title": "Transformers: Revenge of the Fallen","year": 2009,"rating": 6,"votes": 346287,"running_times": 9000},{"title": "Transformers: The Last Knight","year": 2017,"rating": 5.2,"votes": 83297,"running_times": 9300},{"title": "Transporter 2","year": 2005,"rating": 6.3,"votes": 169325,"running_times": 5220},{"title": "Transporter 3","year": 2008,"rating": 6.1,"votes": 137799,"running_times": 6240},{"title": "Transsiberian","year": 2008,"rating": 6.7,"votes": 45274,"running_times": 6660},{"title": "Trapped","year": 2002,"rating": 6.2,"votes": 20815,"running_times": 6360},{"title": "Trapped in Paradise","year": 1994,"rating": 5.9,"votes": 10743,"running_times": 6660},{"title": "Trash","year": 2014,"rating": 7.2,"votes": 17202,"running_times": 6840},{"title": "Treasure Planet","year": 2002,"rating": 7.1,"votes": 81221,"running_times": 5700},{"title": "Trees Lounge","year": 1996,"rating": 7.2,"votes": 12006,"running_times": 5700},{"title": "Tremors","year": 1990,"rating": 7.1,"votes": 99377,"running_times": 5760},{"title": "Trespass","year": 2011,"rating": 5.3,"votes": 37084,"running_times": 5460},{"title": "Triangle","year": 2009,"rating": 6.9,"votes": 78209,"running_times": 5940},{"title": "Trick 'r Treat","year": 2007,"rating": 6.8,"votes": 69181,"running_times": 4920},{"title": "Triple 9","year": 2016,"rating": 6.3,"votes": 52847,"running_times": 6900},{"title": "Tristan + Isolde","year": 2006,"rating": 6.8,"votes": 47170,"running_times": 7500},{"title": "Troll 2","year": 1990,"rating": 2.8,"votes": 26609,"running_times": 5700},{"title": "Trolljegeren","year": 2010,"rating": 7,"votes": 59467,"running_times": 6180},{"title": "Trolls","year": 2016,"rating": 6.5,"votes": 52257,"running_times": 5520},{"title": "Tron","year": 2010,"rating": 6.8,"votes": 280444,"running_times": 7500},{"title": "Tropic Thunder","year": 2008,"rating": 7,"votes": 330614,"running_times": 7260},{"title": "Trouble in Paradise","year": 1932,"rating": 8.2,"votes": 10603,"running_times": 4980},{"title": "Trouble with the Curve","year": 2012,"rating": 6.8,"votes": 52238,"running_times": 6660},{"title": "Troy","year": 2004,"rating": 7.2,"votes": 418856,"running_times": 11760},{"title": "True Crime","year": 1999,"rating": 6.6,"votes": 27548,"running_times": 7620},{"title": "True Grit","year": 1969,"rating": 7.4,"votes": 36110,"running_times": 7680},{"title": "True Grit","year": 2010,"rating": 7.6,"votes": 262595,"running_times": 6600},{"title": "True Lies","year": 1994,"rating": 7.2,"votes": 204843,"running_times": 8460},{"title": "True Romance","year": 1993,"rating": 7.9,"votes": 176419,"running_times": 7260},{"title": "True Story","year": 2015,"rating": 6.3,"votes": 45075,"running_times": 5940},{"title": "Trumbo","year": 2015,"rating": 7.5,"votes": 61971,"running_times": 7440},{"title": "Trust","year": 2010,"rating": 6.9,"votes": 37077,"running_times": 6360},{"title": "Truth","year": 2015,"rating": 6.8,"votes": 14963,"running_times": 7500},{"title": "Tsotsi","year": 2005,"rating": 7.3,"votes": 25959,"running_times": 5640},{"title": "Tuck Everlasting","year": 2002,"rating": 6.7,"votes": 19122,"running_times": 5760},{"title": "Tucker and Dale vs Evil","year": 2010,"rating": 7.6,"votes": 142633,"running_times": 5340},{"title": "Tucker: The Man and His Dream","year": 1988,"rating": 6.9,"votes": 12569,"running_times": 6600},{"title": "Turbo","year": 2013,"rating": 6.5,"votes": 68370,"running_times": 5760},{"title": "Turbo Kid","year": 2015,"rating": 6.7,"votes": 20823,"running_times": 5580},{"title": "Turist","year": 2014,"rating": 7.3,"votes": 35515,"running_times": 7200},{"title": "Turistas","year": 2006,"rating": 5.4,"votes": 32784,"running_times": 5760},{"title": "Turner & Hooch","year": 1989,"rating": 6.1,"votes": 53216,"running_times": 5820},{"title": "Tusk","year": 2014,"rating": 5.4,"votes": 36058,"running_times": 6120},{"title": "Twelve","year": 2010,"rating": 5.7,"votes": 11188,"running_times": 5700},{"title": "Twelve Monkeys","year": 1995,"rating": 8,"votes": 506089,"running_times": 7740},{"title": "Twelve O'Clock High","year": 1949,"rating": 7.8,"votes": 10789,"running_times": 7920},{"title": "Twenty Feet from Stardom","year": 2013,"rating": 7.4,"votes": 10501,"running_times": 5460},{"title": "Twilight","year": 2008,"rating": 5.2,"votes": 369363,"running_times": 7320},{"title": "Twilight Zone: The Movie","year": 1983,"rating": 6.5,"votes": 28051,"running_times": 6060},{"title": "Twin Peaks: Fire Walk with Me","year": 1992,"rating": 7.2,"votes": 68624,"running_times": 8100},{"title": "Twins","year": 1988,"rating": 6,"votes": 95388,"running_times": 6420},{"title": "Twisted","year": 2004,"rating": 5.2,"votes": 18116,"running_times": 5820},{"title": "Twister","year": 1996,"rating": 6.3,"votes": 153606,"running_times": 6780},{"title": "Two Lovers","year": 2008,"rating": 7.1,"votes": 31847,"running_times": 6600},{"title": "Two Mules for Sister Sara","year": 1970,"rating": 7,"votes": 19054,"running_times": 6960},{"title": "Two Night Stand","year": 2014,"rating": 6.4,"votes": 53970,"running_times": 5160},{"title": "Two Weeks Notice","year": 2002,"rating": 6.1,"votes": 92598,"running_times": 6060},{"title": "Two for the Money","year": 2005,"rating": 6.2,"votes": 38961,"running_times": 7320},{"title": "Tyrannosaur","year": 2011,"rating": 7.6,"votes": 26375,"running_times": 5520},{"title": "Tyson","year": 2008,"rating": 7.5,"votes": 11211,"running_times": 5400},{"title": "Tystnaden","year": 1963,"rating": 8,"votes": 13626,"running_times": 5760},{"title": "Tôkyô monogatari","year": 1953,"rating": 8.2,"votes": 33514,"running_times": 8160},{"title": "U Turn","year": 1997,"rating": 6.8,"votes": 44393,"running_times": 7500},{"title": "U-571","year": 2000,"rating": 6.6,"votes": 69146,"running_times": 6960},{"title": "U.S. Marshals","year": 1998,"rating": 6.5,"votes": 83366,"running_times": 7860},{"title": "UHF","year": 1989,"rating": 7,"votes": 22543,"running_times": 9000},{"title": "Udaan","year": 2010,"rating": 8.2,"votes": 35711,"running_times": 8040},{"title": "Ultimo tango a Parigi","year": 1972,"rating": 7.1,"votes": 40747,"running_times": 15000},{"title": "Ultraviolet","year": 2006,"rating": 4.4,"votes": 73834,"running_times": 5640},{"title": "Un monstre à Paris","year": 2011,"rating": 6.7,"votes": 17120,"running_times": 5400},{"title": "Unbreakable","year": 2000,"rating": 7.2,"votes": 284513,"running_times": 6360},{"title": "Unbroken","year": 2014,"rating": 7.2,"votes": 119486,"running_times": 8220},{"title": "Uncle Buck","year": 1989,"rating": 7,"votes": 69088,"running_times": 6000},{"title": "Undead","year": 2003,"rating": 5.5,"votes": 11859,"running_times": 6240},{"title": "Under Siege","year": 1992,"rating": 6.5,"votes": 66049,"running_times": 6180},{"title": "Under Siege 2: Dark Territory","year": 1995,"rating": 5.4,"votes": 38553,"running_times": 6000},{"title": "Under Suspicion","year": 2000,"rating": 6.5,"votes": 19443,"running_times": 6660},{"title": "Under sandet","year": 2015,"rating": 7.8,"votes": 19375,"running_times": 6000},{"title": "Under the Skin","year": 2013,"rating": 6.3,"votes": 100131,"running_times": 6480},{"title": "Under the Tuscan Sun","year": 2003,"rating": 6.8,"votes": 39571,"running_times": 6780},{"title": "Undercover Brother","year": 2002,"rating": 5.8,"votes": 30747,"running_times": 5280},{"title": "Underdog","year": 2007,"rating": 4.8,"votes": 16932,"running_times": 5040},{"title": "Underground","year": 1995,"rating": 8.1,"votes": 47977,"running_times": 19200},{"title": "Underworld","year": 2003,"rating": 7,"votes": 227288,"running_times": 7980},{"title": "Underworld Awakening","year": 2012,"rating": 6.4,"votes": 131014,"running_times": 5280},{"title": "Underworld: Blood Wars","year": 2016,"rating": 5.8,"votes": 52723,"running_times": 5460},{"title": "Underworld: Evolution","year": 2006,"rating": 6.7,"votes": 171177,"running_times": 6360},{"title": "Underworld: Rise of the Lycans","year": 2009,"rating": 6.6,"votes": 133868,"running_times": 5520},{"title": "Undisputed","year": 2002,"rating": 6.2,"votes": 24816,"running_times": 5760},{"title": "Unfaithful","year": 2002,"rating": 6.7,"votes": 68502,"running_times": 7500},{"title": "Unfinished Business","year": 2015,"rating": 5.4,"votes": 26311,"running_times": 5460},{"title": "Unforgiven","year": 1992,"rating": 8.2,"votes": 308492,"running_times": 7800},{"title": "Unfriended","year": 2014,"rating": 5.6,"votes": 54063,"running_times": 4980},{"title": "United 93","year": 2006,"rating": 7.6,"votes": 88351,"running_times": 6660},{"title": "Universal Soldier","year": 1992,"rating": 6,"votes": 73321,"running_times": 6120},{"title": "Universal Soldier: Day of Reckoning","year": 2012,"rating": 5,"votes": 17251,"running_times": 6840},{"title": "Universal Soldier: Regeneration","year": 2009,"rating": 5.2,"votes": 22922,"running_times": 5820},{"title": "Universal Soldier: The Return","year": 1999,"rating": 4.1,"votes": 25435,"running_times": 4980},{"title": "Unknown","year": 2006,"rating": 6.5,"votes": 27168,"running_times": 5100},{"title": "Unknown","year": 2011,"rating": 6.9,"votes": 223409,"running_times": 6780},{"title": "Unlawful Entry","year": 1992,"rating": 6.3,"votes": 12116,"running_times": 7020},{"title": "Unleashed","year": 2005,"rating": 7,"votes": 90174,"running_times": 6180},{"title": "Unlocked","year": 2017,"rating": 6.2,"votes": 12382,"running_times": 5880},{"title": "Unstoppable","year": 2010,"rating": 6.8,"votes": 162057,"running_times": 5880},{"title": "Untamed Heart","year": 1993,"rating": 6.8,"votes": 10899,"running_times": 6120},{"title": "Unthinkable","year": 2010,"rating": 7.1,"votes": 76928,"running_times": 5820},{"title": "Untraceable","year": 2008,"rating": 6.2,"votes": 43124,"running_times": 6060},{"title": "Up","year": 2009,"rating": 8.3,"votes": 754724,"running_times": 5760},{"title": "Up Close & Personal","year": 1996,"rating": 6.1,"votes": 12047,"running_times": 7440},{"title": "Up in Smoke","year": 1978,"rating": 7,"votes": 31136,"running_times": 5160},{"title": "Up in the Air","year": 2009,"rating": 7.4,"votes": 285417,"running_times": 6540},{"title": "Upside Down","year": 2012,"rating": 6.4,"votes": 63039,"running_times": 6540},{"title": "Upstream Color","year": 2013,"rating": 6.7,"votes": 26189,"running_times": 5760},{"title": "Uptown Girls","year": 2003,"rating": 6.1,"votes": 31104,"running_times": 5520},{"title": "Urban Cowboy","year": 1980,"rating": 6.2,"votes": 10991,"running_times": 7920},{"title": "Urban Legend","year": 1998,"rating": 5.5,"votes": 51232,"running_times": 5940},{"title": "Urban Legends: Final Cut","year": 2000,"rating": 4.2,"votes": 13917,"running_times": 5820},{"title": "Used Cars","year": 1980,"rating": 6.8,"votes": 11538,"running_times": 6780},{"title": "V for Vendetta","year": 2005,"rating": 8.2,"votes": 878025,"running_times": 7920},{"title": "V/H/S","year": 2012,"rating": 5.8,"votes": 49302,"running_times": 6960},{"title": "V/H/S Viral","year": 2014,"rating": 4.2,"votes": 12558,"running_times": 5880},{"title": "V/H/S/2","year": 2013,"rating": 6.1,"votes": 30647,"running_times": 5760},{"title": "Vacancy","year": 2007,"rating": 6.2,"votes": 84820,"running_times": 5100},{"title": "Vacation","year": 2015,"rating": 6.1,"votes": 78709,"running_times": 5940},{"title": "Valentine","year": 2001,"rating": 4.7,"votes": 21677,"running_times": 5760},{"title": "Valentine's Day","year": 2010,"rating": 5.7,"votes": 101218,"running_times": 7500},{"title": "Valerian and the City of a Thousand Planets","year": 2017,"rating": 6.6,"votes": 81807,"running_times": 8220},{"title": "Valhalla Rising","year": 2009,"rating": 6,"votes": 47989,"running_times": 5580},{"title": "Valiant","year": 2005,"rating": 5.6,"votes": 17433,"running_times": 4560},{"title": "Valkyrie","year": 2008,"rating": 7.1,"votes": 199643,"running_times": 7260},{"title": "Valley Girl","year": 1983,"rating": 6.4,"votes": 10847,"running_times": 5940},{"title": "Valmont","year": 1989,"rating": 7,"votes": 10895,"running_times": 8220},{"title": "Vals Im Bashir","year": 2008,"rating": 8,"votes": 49445,"running_times": 5400},{"title": "Vampire Academy","year": 2014,"rating": 5.6,"votes": 45777,"running_times": 6240},{"title": "Vampire Hunter D: Bloodlust","year": 2000,"rating": 7.7,"votes": 24820,"running_times": 6180},{"title": "Vampire in Brooklyn","year": 1995,"rating": 4.5,"votes": 18539,"running_times": 6000},{"title": "Vampire's Kiss","year": 1988,"rating": 5.9,"votes": 10620,"running_times": 6180},{"title": "Vampires","year": 1998,"rating": 6.1,"votes": 45850,"running_times": 6480},{"title": "Vampires Suck","year": 2010,"rating": 3.5,"votes": 41417,"running_times": 4920},{"title": "Van Helsing","year": 2004,"rating": 6.1,"votes": 213927,"running_times": 7860},{"title": "Van Wilder","year": 2002,"rating": 6.4,"votes": 93922,"running_times": 5640},{"title": "Van Wilder 2: The Rise of Taj","year": 2006,"rating": 4.8,"votes": 20342,"running_times": 5820},{"title": "Vanilla Sky","year": 2001,"rating": 6.9,"votes": 220421,"running_times": 8460},{"title": "Vanishing Point","year": 1971,"rating": 7.3,"votes": 23211,"running_times": 6360},{"title": "Vanishing on 7th Street","year": 2010,"rating": 4.9,"votes": 22968,"running_times": 5520},{"title": "Vanity Fair","year": 2004,"rating": 6.2,"votes": 18278,"running_times": 8460},{"title": "Vantage Point","year": 2008,"rating": 6.6,"votes": 133654,"running_times": 5400},{"title": "Varsity Blues","year": 1999,"rating": 6.4,"votes": 37306,"running_times": 6360},{"title": "Vegas Vacation","year": 1997,"rating": 5.9,"votes": 36659,"running_times": 5580},{"title": "Vehicle 19","year": 2013,"rating": 4.9,"votes": 13186,"running_times": 5100},{"title": "Velvet Goldmine","year": 1998,"rating": 7,"votes": 29482,"running_times": 7080},{"title": "Venus","year": 2006,"rating": 7.1,"votes": 11555,"running_times": 5700},{"title": "Venuto al mondo","year": 2012,"rating": 7.4,"votes": 13309,"running_times": 7620},{"title": "Vera Drake","year": 2004,"rating": 7.7,"votes": 21374,"running_times": 7500},{"title": "Veronica Guerin","year": 2003,"rating": 6.9,"votes": 17197,"running_times": 5880},{"title": "Veronica Mars","year": 2014,"rating": 6.8,"votes": 44371,"running_times": 6420},{"title": "Veronika Decides to Die","year": 2009,"rating": 6.5,"votes": 10862,"running_times": 6180},{"title": "Versus","year": 2000,"rating": 6.5,"votes": 11539,"running_times": 7140},{"title": "Vertical Limit","year": 2000,"rating": 5.9,"votes": 52544,"running_times": 7440},{"title": "Vertigo","year": 1958,"rating": 8.4,"votes": 282823,"running_times": 7740},{"title": "Very Bad Things","year": 1998,"rating": 6.3,"votes": 41265,"running_times": 6000},{"title": "Very Good Girls","year": 2013,"rating": 6,"votes": 12016,"running_times": 5460},{"title": "Vice","year": 2015,"rating": 4.2,"votes": 13323,"running_times": 5760},{"title": "Vicky Cristina Barcelona","year": 2008,"rating": 7.1,"votes": 214956,"running_times": 5760},{"title": "Victor Frankenstein","year": 2015,"rating": 6,"votes": 41566,"running_times": 6600},{"title": "Victor Victoria","year": 1982,"rating": 7.6,"votes": 16492,"running_times": 8040},{"title": "Victoria","year": 2015,"rating": 7.7,"votes": 37987,"running_times": 8280},{"title": "Victory","year": 1981,"rating": 6.6,"votes": 22838,"running_times": 6960},{"title": "Videodrome","year": 1983,"rating": 7.3,"votes": 67766,"running_times": 5340},{"title": "View from the Top","year": 2003,"rating": 5.2,"votes": 22568,"running_times": 5220},{"title": "Village of the Damned","year": 1960,"rating": 7.3,"votes": 12036,"running_times": 4620},{"title": "Village of the Damned","year": 1995,"rating": 5.6,"votes": 23863,"running_times": 5940},{"title": "Vincent","year": 1982,"rating": 8.4,"votes": 19267,"running_times": 360},{"title": "Violet & Daisy","year": 2011,"rating": 6.1,"votes": 10176,"running_times": 5280},{"title": "Viridiana","year": 1961,"rating": 8.2,"votes": 18029,"running_times": 5400},{"title": "Virtuosity","year": 1995,"rating": 5.6,"votes": 24921,"running_times": 6360},{"title": "Virus","year": 1999,"rating": 4.9,"votes": 23377,"running_times": 5940},{"title": "Vizontele Tuuba","year": 2003,"rating": 6.5,"votes": 10727,"running_times": 6660},{"title": "Volcano","year": 1997,"rating": 5.4,"votes": 63055,"running_times": 6240},{"title": "Von Ryan's Express","year": 1965,"rating": 7.1,"votes": 11050,"running_times": 7020},{"title": "W.","year": 2008,"rating": 6.3,"votes": 42728,"running_times": 7740},{"title": "W.E.","year": 2011,"rating": 6.3,"votes": 10607,"running_times": 7140},{"title": "WALL·E","year": 2008,"rating": 8.4,"votes": 812013,"running_times": 5880},{"title": "Waar","year": 2013,"rating": 8.2,"votes": 28439,"running_times": 7800},{"title": "Wag the Dog","year": 1997,"rating": 7.1,"votes": 71281,"running_times": 5820},{"title": "Wait Until Dark","year": 1967,"rating": 7.9,"votes": 22782,"running_times": 6480},{"title": "Waiting for 'Superman'","year": 2010,"rating": 7.5,"votes": 10027,"running_times": 6660},{"title": "Waiting for Forever","year": 2010,"rating": 6,"votes": 18719,"running_times": 5700},{"title": "Waiting for Guffman","year": 1996,"rating": 7.6,"votes": 23751,"running_times": 5040},{"title": "Waiting...","year": 2005,"rating": 6.8,"votes": 79927,"running_times": 5640},{"title": "Waitress","year": 2007,"rating": 7,"votes": 39505,"running_times": 6480},{"title": "Wake Up Sid","year": 2009,"rating": 7.6,"votes": 21957,"running_times": 8280},{"title": "Waking Life","year": 2001,"rating": 7.8,"votes": 53627,"running_times": 6060},{"title": "Waking Ned","year": 1998,"rating": 7.3,"votes": 22591,"running_times": 5520},{"title": "Walk Hard: The Dewey Cox Story","year": 2007,"rating": 6.8,"votes": 58599,"running_times": 7200},{"title": "Walk of Shame","year": 2014,"rating": 6,"votes": 44953,"running_times": 5700},{"title": "Walk the Line","year": 2005,"rating": 7.9,"votes": 200422,"running_times": 9180},{"title": "Walkabout","year": 1971,"rating": 7.7,"votes": 18963,"running_times": 6000},{"title": "Walking Tall","year": 2004,"rating": 6.2,"votes": 57700,"running_times": 5160},{"title": "Wall Street","year": 1987,"rating": 7.4,"votes": 127432,"running_times": 7560},{"title": "Wall Street: Money Never Sleeps","year": 2010,"rating": 6.2,"votes": 89241,"running_times": 8160},{"title": "Wanderlust","year": 2012,"rating": 5.6,"votes": 65787,"running_times": 5880},{"title": "Wanted","year": 2008,"rating": 6.7,"votes": 320677,"running_times": 6600},{"title": "War","year": 2007,"rating": 6.3,"votes": 77054,"running_times": 6180},{"title": "War Dogs","year": 2016,"rating": 7.1,"votes": 128613,"running_times": 6840},{"title": "War Horse","year": 2011,"rating": 7.2,"votes": 126737,"running_times": 8760},{"title": "War Machine","year": 2017,"rating": 6.1,"votes": 26077,"running_times": 7320},{"title": "War Room","year": 2015,"rating": 6.4,"votes": 10436,"running_times": 7200},{"title": "War for the Planet of the Apes","year": 2017,"rating": 7.5,"votes": 137537,"running_times": 8400},{"title": "War of the Worlds","year": 2005,"rating": 6.5,"votes": 361418,"running_times": 6960},{"title": "War on Everyone","year": 2016,"rating": 5.9,"votes": 12576,"running_times": 5880},{"title": "War, Inc.","year": 2008,"rating": 5.7,"votes": 20478,"running_times": 6420},{"title": "WarGames","year": 1983,"rating": 7.1,"votes": 77419,"running_times": 6840},{"title": "Warcraft","year": 2016,"rating": 6.9,"votes": 201525,"running_times": 7380},{"title": "Warlock","year": 1989,"rating": 6.2,"votes": 12599,"running_times": 6180},{"title": "Warm Bodies","year": 2013,"rating": 6.9,"votes": 198209,"running_times": 5880},{"title": "Warrior","year": 2011,"rating": 8.2,"votes": 369802,"running_times": 8400},{"title": "Watchmen","year": 2009,"rating": 7.6,"votes": 423383,"running_times": 12900},{"title": "Water for Elephants","year": 2011,"rating": 6.9,"votes": 100901,"running_times": 7200},{"title": "Watership Down","year": 1978,"rating": 7.7,"votes": 27768,"running_times": 5460},{"title": "Waterworld","year": 1995,"rating": 6.1,"votes": 155351,"running_times": 10560},{"title": "Wayne's World","year": 1992,"rating": 7,"votes": 123659,"running_times": 5640},{"title": "Wayne's World 2","year": 1993,"rating": 6.1,"votes": 67102,"running_times": 5700},{"title": "We Are Marshall","year": 2006,"rating": 7.1,"votes": 50569,"running_times": 7860},{"title": "We Are Still Here","year": 2015,"rating": 5.7,"votes": 13867,"running_times": 5040},{"title": "We Are What We Are","year": 2013,"rating": 5.9,"votes": 17047,"running_times": 6300},{"title": "We Are Your Friends","year": 2015,"rating": 6.2,"votes": 28314,"running_times": 5760},{"title": "We Bought a Zoo","year": 2011,"rating": 7.1,"votes": 119778,"running_times": 7440},{"title": "We Need to Talk About Kevin","year": 2011,"rating": 7.5,"votes": 110469,"running_times": 6720},{"title": "We Own the Night","year": 2007,"rating": 6.9,"votes": 76188,"running_times": 7020},{"title": "We Were Soldiers","year": 2002,"rating": 7.2,"votes": 112887,"running_times": 8580},{"title": "We're Back! A Dinosaur's Story","year": 1993,"rating": 6.1,"votes": 11500,"running_times": 4320},{"title": "We're No Angels","year": 1989,"rating": 6.1,"votes": 18713,"running_times": 6360},{"title": "We're the Millers","year": 2013,"rating": 7,"votes": 346039,"running_times": 7680},{"title": "Wedding Crashers","year": 2005,"rating": 7,"votes": 297708,"running_times": 7680},{"title": "Weekend","year": 2011,"rating": 7.7,"votes": 22804,"running_times": 5820},{"title": "Weekend at Bernie's","year": 1989,"rating": 6.4,"votes": 41289,"running_times": 5820},{"title": "Weekend at Bernie's II","year": 1993,"rating": 4.6,"votes": 11096,"running_times": 5820},{"title": "Weird Science","year": 1985,"rating": 6.6,"votes": 66176,"running_times": 5640},{"title": "Welcome Home, Roscoe Jenkins","year": 2008,"rating": 5.4,"votes": 11552,"running_times": 6840},{"title": "Welcome to Collinwood","year": 2002,"rating": 6.4,"votes": 13020,"running_times": 5160},{"title": "Welcome to Me","year": 2014,"rating": 5.9,"votes": 15623,"running_times": 5220},{"title": "Welcome to Mooseport","year": 2004,"rating": 5.2,"votes": 11146,"running_times": 7020},{"title": "Welcome to the Dollhouse","year": 1995,"rating": 7.4,"votes": 28328,"running_times": 5280},{"title": "Welcome to the Jungle","year": 2013,"rating": 5,"votes": 10638,"running_times": 5700},{"title": "Welcome to the Punch","year": 2013,"rating": 6.1,"votes": 29070,"running_times": 6000},{"title": "Welcome to the Rileys","year": 2010,"rating": 7,"votes": 21278,"running_times": 6600},{"title": "Wendy and Lucy","year": 2008,"rating": 7.1,"votes": 13530,"running_times": 4800},{"title": "West Side Story","year": 1961,"rating": 7.6,"votes": 79399,"running_times": 9180},{"title": "Westworld","year": 1973,"rating": 7,"votes": 41034,"running_times": 5280},{"title": "Wet Hot American Summer","year": 2001,"rating": 6.7,"votes": 45977,"running_times": 5820},{"title": "Whale Rider","year": 2002,"rating": 7.6,"votes": 36011,"running_times": 6060},{"title": "What About Bob?","year": 1991,"rating": 7,"votes": 54257,"running_times": 5940},{"title": "What Doesn't Kill You","year": 2008,"rating": 6.6,"votes": 10317,"running_times": 6000},{"title": "What Dreams May Come","year": 1998,"rating": 7,"votes": 89534,"running_times": 6780},{"title": "What Ever Happened to Baby Jane?","year": 1962,"rating": 8.1,"votes": 40325,"running_times": 8100},{"title": "What Happens in Vegas","year": 2008,"rating": 6.1,"votes": 150102,"running_times": 6060},{"title": "What Just Happened","year": 2008,"rating": 5.7,"votes": 24650,"running_times": 6240},{"title": "What Lies Beneath","year": 2000,"rating": 6.6,"votes": 104333,"running_times": 7800},{"title": "What Maisie Knew","year": 2012,"rating": 7.5,"votes": 23733,"running_times": 5940},{"title": "What We Did on Our Holiday","year": 2014,"rating": 6.9,"votes": 14692,"running_times": 5700},{"title": "What We Do in the Shadows","year": 2014,"rating": 7.6,"votes": 97317,"running_times": 5160},{"title": "What Women Want","year": 2000,"rating": 6.4,"votes": 170689,"running_times": 7620},{"title": "What a Girl Wants","year": 2003,"rating": 5.8,"votes": 51761,"running_times": 6300},{"title": "What the #$*! Do We (K)now!?","year": 2004,"rating": 5.3,"votes": 12450,"running_times": 6780},{"title": "What the Health","year": 2017,"rating": 8,"votes": 18833,"running_times": 5820},{"title": "What to Expect When You're Expecting","year": 2012,"rating": 5.7,"votes": 61745,"running_times": 6600},{"title": "What's Eating Gilbert Grape","year": 1993,"rating": 7.8,"votes": 185200,"running_times": 7080},{"title": "What's Love Got to Do with It","year": 1993,"rating": 7.2,"votes": 14393,"running_times": 7080},{"title": "What's Up, Doc?","year": 1972,"rating": 7.8,"votes": 15727,"running_times": 5640},{"title": "What's Your Number?","year": 2011,"rating": 6.1,"votes": 64002,"running_times": 7020},{"title": "What's the Worst That Could Happen?","year": 2001,"rating": 5.5,"votes": 13371,"running_times": 5640},{"title": "Whatever Works","year": 2009,"rating": 7.2,"votes": 63720,"running_times": 5580},{"title": "When Harry Met Sally...","year": 1989,"rating": 7.6,"votes": 163450,"running_times": 5760},{"title": "When We Were Kings","year": 1996,"rating": 8,"votes": 13204,"running_times": 5280},{"title": "When a Man Loves a Woman","year": 1994,"rating": 6.5,"votes": 17885,"running_times": 7560},{"title": "When a Stranger Calls","year": 2006,"rating": 5.1,"votes": 37689,"running_times": 5220},{"title": "When in Rome","year": 2010,"rating": 5.6,"votes": 54300,"running_times": 5460},{"title": "When the Game Stands Tall","year": 2014,"rating": 6.7,"votes": 13756,"running_times": 6900},{"title": "Where Eagles Dare","year": 1968,"rating": 7.7,"votes": 43900,"running_times": 9480},{"title": "Where the Buffalo Roam","year": 1980,"rating": 6.7,"votes": 10050,"running_times": 5760},{"title": "Where the Heart Is","year": 2000,"rating": 6.8,"votes": 28717,"running_times": 7200},{"title": "Where the Truth Lies","year": 2005,"rating": 6.5,"votes": 15715,"running_times": 6420},{"title": "Where the Wild Things Are","year": 2009,"rating": 6.8,"votes": 92375,"running_times": 6060},{"title": "Where to Invade Next","year": 2015,"rating": 7.6,"votes": 17948,"running_times": 7200},{"title": "While We're Young","year": 2014,"rating": 6.3,"votes": 36693,"running_times": 5820},{"title": "While You Were Sleeping","year": 1995,"rating": 6.7,"votes": 77975,"running_times": 6180},{"title": "Whip It","year": 2009,"rating": 6.9,"votes": 58495,"running_times": 6660},{"title": "Whiplash","year": 2014,"rating": 8.5,"votes": 517001,"running_times": 6420},{"title": "Whiskey Tango Foxtrot","year": 2016,"rating": 6.6,"votes": 40192,"running_times": 6720},{"title": "White Bird in a Blizzard","year": 2014,"rating": 6.4,"votes": 23569,"running_times": 5460},{"title": "White Chicks","year": 2004,"rating": 5.5,"votes": 108969,"running_times": 6900},{"title": "White Christmas","year": 1954,"rating": 7.6,"votes": 24345,"running_times": 7200},{"title": "White Fang","year": 1991,"rating": 6.7,"votes": 16867,"running_times": 6420},{"title": "White Heat","year": 1949,"rating": 8.2,"votes": 22555,"running_times": 6840},{"title": "White House Down","year": 2013,"rating": 6.4,"votes": 178695,"running_times": 7860},{"title": "White Men Can't Jump","year": 1992,"rating": 6.7,"votes": 63633,"running_times": 7080},{"title": "White Noise","year": 2005,"rating": 5.5,"votes": 43784,"running_times": 6060},{"title": "White Noise 2: The Light","year": 2007,"rating": 5.7,"votes": 11785,"running_times": 5940},{"title": "White Oleander","year": 2002,"rating": 7.2,"votes": 26933,"running_times": 6540},{"title": "White Squall","year": 1996,"rating": 6.6,"votes": 19008,"running_times": 7740},{"title": "Whiteout","year": 2009,"rating": 5.5,"votes": 33828,"running_times": 6060},{"title": "Who Am I - Kein System ist sicher","year": 2014,"rating": 7.6,"votes": 33183,"running_times": 6120},{"title": "Who Framed Roger Rabbit","year": 1988,"rating": 7.7,"votes": 155219,"running_times": 6240},{"title": "Who Killed the Electric Car?","year": 2006,"rating": 7.7,"votes": 11606,"running_times": 5520},{"title": "Who's Afraid of Virginia Woolf?","year": 1966,"rating": 8.1,"votes": 60336,"running_times": 7860},{"title": "Who's Harry Crumb?","year": 1989,"rating": 5.8,"votes": 13504,"running_times": 5640},{"title": "Who's Your Caddy?","year": 2007,"rating": 2.1,"votes": 14081,"running_times": 5580},{"title": "Why Did I Get Married?","year": 2007,"rating": 5.7,"votes": 10391,"running_times": 6780},{"title": "Why Him?","year": 2016,"rating": 6.2,"votes": 71669,"running_times": 6660},{"title": "Wicker Park","year": 2004,"rating": 7,"votes": 47786,"running_times": 6840},{"title": "Wild","year": 2014,"rating": 7.1,"votes": 100424,"running_times": 6900},{"title": "Wild Bill","year": 2011,"rating": 7.2,"votes": 10888,"running_times": 5880},{"title": "Wild Card","year": 2015,"rating": 5.6,"votes": 42106,"running_times": 6120},{"title": "Wild Child","year": 2008,"rating": 6.1,"votes": 40936,"running_times": 7440},{"title": "Wild Hogs","year": 2007,"rating": 5.9,"votes": 104851,"running_times": 6000},{"title": "Wild Target","year": 2010,"rating": 6.9,"votes": 32102,"running_times": 5880},{"title": "Wild Things","year": 1998,"rating": 6.5,"votes": 96058,"running_times": 6900},{"title": "Wild Wild West","year": 1999,"rating": 4.8,"votes": 137656,"running_times": 6360},{"title": "Wild at Heart","year": 1990,"rating": 7.2,"votes": 68263,"running_times": 7500},{"title": "Wildcats","year": 1986,"rating": 5.9,"votes": 10337,"running_times": 6360},{"title": "Wilde","year": 1997,"rating": 6.9,"votes": 13098,"running_times": 7080},{"title": "Willard","year": 2003,"rating": 6.2,"votes": 15937,"running_times": 6000},{"title": "Willow","year": 1988,"rating": 7.3,"votes": 86915,"running_times": 7560},{"title": "Willy Wonka & the Chocolate Factory","year": 1971,"rating": 7.8,"votes": 144970,"running_times": 6000},{"title": "Wimbledon","year": 2004,"rating": 6.3,"votes": 54516,"running_times": 5880},{"title": "Win Win","year": 2011,"rating": 7.2,"votes": 50308,"running_times": 6360},{"title": "Win a Date with Tad Hamilton!","year": 2004,"rating": 5.6,"votes": 24089,"running_times": 5700},{"title": "Winchester '73","year": 1950,"rating": 7.7,"votes": 13765,"running_times": 5520},{"title": "Wind Chill","year": 2007,"rating": 5.9,"votes": 19074,"running_times": 5460},{"title": "Wind River","year": 2017,"rating": 7.8,"votes": 74682,"running_times": 6420},{"title": "Windtalkers","year": 2002,"rating": 6,"votes": 59346,"running_times": 9180},{"title": "Wing Commander","year": 1999,"rating": 4.2,"votes": 15194,"running_times": 6000},{"title": "Winnie the Pooh","year": 2011,"rating": 7.2,"votes": 17196,"running_times": 3780},{"title": "Winter's Bone","year": 2010,"rating": 7.2,"votes": 119512,"running_times": 6000},{"title": "Winter's Tale","year": 2014,"rating": 6.2,"votes": 45570,"running_times": 7080},{"title": "Wish I Was Here","year": 2014,"rating": 6.7,"votes": 32549,"running_times": 6360},{"title": "Wishmaster","year": 1997,"rating": 5.8,"votes": 16578,"running_times": 5400},{"title": "With Honors","year": 1994,"rating": 6.7,"votes": 11663,"running_times": 6180},{"title": "Withnail & I","year": 1987,"rating": 7.8,"votes": 33730,"running_times": 6420},{"title": "Without a Paddle","year": 2004,"rating": 5.9,"votes": 39444,"running_times": 5700},{"title": "Witness","year": 1985,"rating": 7.4,"votes": 72313,"running_times": 6720},{"title": "Witness for the Prosecution","year": 1957,"rating": 8.4,"votes": 75714,"running_times": 6960},{"title": "Wolf","year": 1994,"rating": 6.2,"votes": 46491,"running_times": 7500},{"title": "Wolf Creek","year": 2005,"rating": 6.3,"votes": 59931,"running_times": 6240},{"title": "Wolf Creek 2","year": 2013,"rating": 6.1,"votes": 14313,"running_times": 6360},{"title": "Woman in Gold","year": 2015,"rating": 7.3,"votes": 43004,"running_times": 6540},{"title": "Womb","year": 2010,"rating": 6.4,"votes": 11453,"running_times": 6660},{"title": "Wonder","year": 2017,"rating": 8.1,"votes": 13471,"running_times": 6780},{"title": "Wonder Boys","year": 2000,"rating": 7.4,"votes": 56829,"running_times": 6420},{"title": "Wonder Woman","year": 2017,"rating": 7.6,"votes": 343600,"running_times": 8460},{"title": "Wonderland","year": 2003,"rating": 6.6,"votes": 19519,"running_times": 6240},{"title": "Wong Fei Hung","year": 1991,"rating": 7.4,"votes": 14953,"running_times": 8040},{"title": "Woodstock","year": 1970,"rating": 8.1,"votes": 13696,"running_times": 21360},{"title": "Working Girl","year": 1988,"rating": 6.7,"votes": 44715,"running_times": 6780},{"title": "World Trade Center","year": 2006,"rating": 6,"votes": 71119,"running_times": 7740},{"title": "World War Z","year": 2013,"rating": 7,"votes": 513324,"running_times": 7380},{"title": "World's Greatest Dad","year": 2009,"rating": 6.9,"votes": 33881,"running_times": 5940},{"title": "Would You Rather","year": 2012,"rating": 5.8,"votes": 28237,"running_times": 5580},{"title": "Wrath of the Titans","year": 2012,"rating": 5.8,"votes": 163085,"running_times": 5940},{"title": "Wreck-It Ralph","year": 2012,"rating": 7.7,"votes": 302045,"running_times": 6060},{"title": "Wrecked","year": 2010,"rating": 5.3,"votes": 13726,"running_times": 5460},{"title": "Wristcutters: A Love Story","year": 2006,"rating": 7.3,"votes": 48932,"running_times": 5280},{"title": "Wrong Turn","year": 2003,"rating": 6.1,"votes": 94754,"running_times": 5040},{"title": "Wrong Turn 4: Bloody Beginnings","year": 2011,"rating": 4.6,"votes": 18867,"running_times": 5640},{"title": "Wrongfully Accused","year": 1998,"rating": 6.1,"votes": 19976,"running_times": 5220},{"title": "Wuthering Heights","year": 1939,"rating": 7.7,"votes": 13761,"running_times": 6240},{"title": "Wuthering Heights","year": 1992,"rating": 6.9,"votes": 10432,"running_times": 6300},{"title": "Wyatt Earp","year": 1994,"rating": 6.7,"votes": 38522,"running_times": 12720},{"title": "Wyrmwood","year": 2014,"rating": 6.3,"votes": 13514,"running_times": 5880},{"title": "X+Y","year": 2014,"rating": 7.2,"votes": 23033,"running_times": 6660},{"title": "X-Men","year": 2000,"rating": 7.4,"votes": 498117,"running_times": 6240},{"title": "X-Men Origins: Wolverine","year": 2009,"rating": 6.7,"votes": 402237,"running_times": 7140},{"title": "X-Men: Apocalypse","year": 2016,"rating": 7,"votes": 304132,"running_times": 8640},{"title": "X-Men: Days of Future Past","year": 2014,"rating": 8,"votes": 572280,"running_times": 9060},{"title": "X-Men: The Last Stand","year": 2006,"rating": 6.7,"votes": 419674,"running_times": 6240},{"title": "X2","year": 2003,"rating": 7.5,"votes": 445905,"running_times": 8040},{"title": "X: First Class","year": 2011,"rating": 7.8,"votes": 566878,"running_times": 7860},{"title": "Xi yan","year": 1993,"rating": 7.7,"votes": 11724,"running_times": 6360},{"title": "Yahsi Bati","year": 2009,"rating": 7.3,"votes": 20851,"running_times": 6720},{"title": "Yankee Doodle Dandy","year": 1942,"rating": 7.8,"votes": 11975,"running_times": 7560},{"title": "Yat goh ho yan","year": 1997,"rating": 6.2,"votes": 21626,"running_times": 5820},{"title": "Year One","year": 2009,"rating": 4.9,"votes": 80852,"running_times": 6000},{"title": "Year of the Dragon","year": 1985,"rating": 6.9,"votes": 11575,"running_times": 8040},{"title": "Yeh Jawaani Hai Deewani","year": 2013,"rating": 7,"votes": 30273,"running_times": 10560},{"title": "Yellow Submarine","year": 1968,"rating": 7.4,"votes": 20412,"running_times": 5400},{"title": "Yentl","year": 1983,"rating": 6.6,"votes": 10319,"running_times": 7980},{"title": "Yeopgijeogin geunyeo","year": 2001,"rating": 8.1,"votes": 39868,"running_times": 8220},{"title": "Yes Boss","year": 1997,"rating": 6.9,"votes": 10757,"running_times": 9780},{"title": "Yes Man","year": 2008,"rating": 6.8,"votes": 291926,"running_times": 6240},{"title": "Yi yi","year": 2000,"rating": 8.1,"votes": 14903,"running_times": 10380},{"title": "Ying hung boon sik","year": 1986,"rating": 7.6,"votes": 17056,"running_times": 5700},{"title": "Yip Man 2","year": 2010,"rating": 7.6,"votes": 79871,"running_times": 6480},{"title": "Yip Man 3","year": 2015,"rating": 7.1,"votes": 32614,"running_times": 6300},{"title": "Yogi Bear","year": 2010,"rating": 4.6,"votes": 17693,"running_times": 4800},{"title": "You Again","year": 2010,"rating": 5.8,"votes": 43923,"running_times": 6300},{"title": "You Can Count on Me","year": 2000,"rating": 7.7,"votes": 24603,"running_times": 6660},{"title": "You Can't Take It with You","year": 1938,"rating": 8,"votes": 19430,"running_times": 7560},{"title": "You Don't Mess with the Zohan","year": 2008,"rating": 5.5,"votes": 167599,"running_times": 6780},{"title": "You Got Served","year": 2004,"rating": 3.5,"votes": 24231,"running_times": 5700},{"title": "You Kill Me","year": 2007,"rating": 6.5,"votes": 16698,"running_times": 5580},{"title": "You Only Live Twice","year": 1967,"rating": 6.9,"votes": 81773,"running_times": 7020},{"title": "You Will Meet a Tall Dark Stranger","year": 2010,"rating": 6.3,"votes": 39424,"running_times": 5880},{"title": "You're Next","year": 2011,"rating": 6.5,"votes": 71913,"running_times": 5700},{"title": "You're Not You","year": 2014,"rating": 7.4,"votes": 19583,"running_times": 6120},{"title": "You've Got Mail","year": 1998,"rating": 6.6,"votes": 165458,"running_times": 7140},{"title": "You, Me and Dupree","year": 2006,"rating": 5.6,"votes": 71919,"running_times": 6600},{"title": "Young Adam","year": 2003,"rating": 6.5,"votes": 12131,"running_times": 5880},{"title": "Young Adult","year": 2011,"rating": 6.3,"votes": 68568,"running_times": 5640},{"title": "Young Frankenstein","year": 1974,"rating": 8,"votes": 125087,"running_times": 6360},{"title": "Young Guns","year": 1988,"rating": 6.8,"votes": 46301,"running_times": 6420},{"title": "Young Guns II","year": 1990,"rating": 6.5,"votes": 26020,"running_times": 6240},{"title": "Young People Fucking","year": 2007,"rating": 6.3,"votes": 18254,"running_times": 5400},{"title": "Young Sherlock Holmes","year": 1985,"rating": 6.8,"votes": 16098,"running_times": 6540},{"title": "Youngblood","year": 1986,"rating": 6.1,"votes": 10495,"running_times": 6600},{"title": "Your Highness","year": 2011,"rating": 5.5,"votes": 89650,"running_times": 6120},{"title": "Your Sister's Sister","year": 2011,"rating": 6.7,"votes": 23443,"running_times": 5400},{"title": "Yours, Mine & Ours","year": 2005,"rating": 5.4,"votes": 23439,"running_times": 5280},{"title": "Youth","year": 2015,"rating": 7.3,"votes": 56877,"running_times": 7440},{"title": "Youth Without Youth","year": 2007,"rating": 6.3,"votes": 11953,"running_times": 7440},{"title": "Youth in Revolt","year": 2009,"rating": 6.5,"votes": 68119,"running_times": 5400},{"title": "Yume","year": 1990,"rating": 7.8,"votes": 19868,"running_times": 7140},{"title": "Z","year": 1969,"rating": 8.2,"votes": 19513,"running_times": 7620},{"title": "Z for Zachariah","year": 2015,"rating": 6,"votes": 22333,"running_times": 5880},{"title": "Zabriskie Point","year": 1970,"rating": 7.1,"votes": 12201,"running_times": 6780},{"title": "Zack and Miri Make a Porno","year": 2008,"rating": 6.6,"votes": 157803,"running_times": 6060},{"title": "Zardoz","year": 1974,"rating": 5.8,"votes": 16295,"running_times": 6300},{"title": "Zathura: A Space Adventure","year": 2005,"rating": 6.1,"votes": 75323,"running_times": 6060},{"title": "Zeitgeist: Moving Forward","year": 2011,"rating": 8.2,"votes": 16308,"running_times": 9660},{"title": "Zelig","year": 1983,"rating": 7.8,"votes": 34767,"running_times": 4740},{"title": "Zero Dark Thirty","year": 2012,"rating": 7.4,"votes": 233700,"running_times": 9420},{"title": "Zero Effect","year": 1998,"rating": 7,"votes": 12886,"running_times": 6960},{"title": "Zindagi Na Milegi Dobara","year": 2011,"rating": 8.1,"votes": 51369,"running_times": 9300},{"title": "Zivot je cudo","year": 2004,"rating": 7.7,"votes": 10794,"running_times": 9300},{"title": "Zodiac","year": 2007,"rating": 7.7,"votes": 349834,"running_times": 9720},{"title": "Zombeavers","year": 2014,"rating": 4.8,"votes": 13180,"running_times": 4620},{"title": "Zombi 2","year": 1979,"rating": 6.9,"votes": 21569,"running_times": 5640},{"title": "Zombie Strippers","year": 2008,"rating": 4.1,"votes": 16387,"running_times": 5640},{"title": "Zombieland","year": 2009,"rating": 7.7,"votes": 423925,"running_times": 5280},{"title": "Zookeeper","year": 2011,"rating": 5.2,"votes": 48679,"running_times": 6120},{"title": "Zoolander","year": 2001,"rating": 6.6,"votes": 217408,"running_times": 5400},{"title": "Zoolander 2","year": 2016,"rating": 4.7,"votes": 52589,"running_times": 6480},{"title": "Zoom","year": 2006,"rating": 4.3,"votes": 16260,"running_times": 5580},{"title": "Zootopia","year": 2016,"rating": 8,"votes": 326111,"running_times": 6480},{"title": "Zulu","year": 1964,"rating": 7.8,"votes": 31229,"running_times": 8280},{"title": "Zulu","year": 2013,"rating": 6.7,"votes": 15316,"running_times": 6600},{"title": "Zwartboek","year": 2006,"rating": 7.8,"votes": 64568,"running_times": 8700},{"title": "eXistenZ","year": 1999,"rating": 6.8,"votes": 82881,"running_times": 6900},{"title": "iBoy","year": 2017,"rating": 6,"votes": 12217,"running_times": 5400},{"title": "xXx","year": 2002,"rating": 5.8,"votes": 157358,"running_times": 7920},{"title": "xXx: Return of Xander Cage","year": 2017,"rating": 5.2,"votes": 63918,"running_times": 6420},{"title": "xXx: State of the Union","year": 2005,"rating": 4.4,"votes": 59449,"running_times": 6060},{"title": "¡Three Amigos!","year": 1986,"rating": 6.4,"votes": 58003,"running_times": 6240},{"title": "À bout de souffle","year": 1960,"rating": 7.9,"votes": 58379,"running_times": 5400},{"title": "Æon Flux","year": 2005,"rating": 5.5,"votes": 115131,"running_times": 5580}] \ No newline at end of file diff --git a/courses/frontend/advanced-javascript/week-1/Working with movies/script.js b/courses/frontend/advanced-javascript/week-1/Working with movies/script.js deleted file mode 100644 index 4aab7e96a..000000000 --- a/courses/frontend/advanced-javascript/week-1/Working with movies/script.js +++ /dev/null @@ -1,199 +0,0 @@ -const container = document.getElementById("moviesContainer") - -// RENDER MOVIES - -function renderMovies(arr){ - -container.innerHTML="" - -arr.forEach(movie=>{ - -const card=document.createElement("div") - -card.classList.add("movieCard") - -card.innerHTML=` -

        ${movie.title}

        -

        Year: ${movie.year}

        -

        Rating: ${movie.rating}

        -${movie.tag ? `

        Tag: ${movie.tag}

        ` : ""} -` - -container.appendChild(card) - -}) - -} - -function renderText(text){ - -container.innerHTML=`

        ${text}

        ` - -} - -// SHORT TITLES - -function showShortTitles(){ - -const shortMovies = movies.filter(movie => -movie.title.length <= 10 -) - -renderMovies(shortMovies) - -} - -// LONG TITLES - -function showLongTitles(){ - -const longTitles = movies.filter(movie => -movie.title.length > 20 -) - -renderMovies(longTitles) - -} - -// MOVIES 1980-1989 - -function count80sMovies(){ - -const count = movies.filter(movie => -movie.year >= 1980 && movie.year <= 1989 -).length - -renderText(`Movies from 1980-1989: ${count}`) - -} - -// TAG MOVIES - -function showTaggedMovies(){ - -const tagged = movies.map(movie=>{ - -let tag - -if(movie.rating >=7){ -tag="Good" -} -else if(movie.rating >=4){ -tag="Average" -} -else{ -tag="Bad" -} - -return {...movie, tag} - -}) - -renderMovies(tagged) - -} - - -// RATING ABOVE 6 - - -function showRatingsAbove6(){ - -const result = movies -.filter(movie => movie.rating > 6) -.map(movie => ({ -title: movie.title, -year: movie.year, -rating: movie.rating -})) - -renderMovies(result) - -} - - -// KEYWORD COUNT - - -function countKeywords(){ - -const keywords=["surfer","alien","benjamin"] - -const count = movies.reduce((total,movie)=>{ - -const title = movie.title.toLowerCase() - -keywords.forEach(word=>{ -if(title.includes(word)){ -total++ -} -}) - -return total - -},0) - -renderText(`Keyword matches: ${count}`) - -} - - -// DUPLICATE WORDS - - -function duplicatedWords(){ - -const result = movies.filter(movie=>{ - -const words = movie.title -.toLowerCase() -.split(" ") - -return new Set(words).size !== words.length - -}) - -renderMovies(result) - -} - -// AVERAGE RATING - -function averageRating(){ - -const avg = movies.reduce((sum,movie)=> -sum + movie.rating -,0) / movies.length - -renderText(`Average rating: ${avg.toFixed(2)}`) - -} - - -// COUNT GOOD/AVERAGE/BAD - -function countRatings(){ - -const result = movies.reduce((acc,movie)=>{ - -if(movie.rating >=7){ -acc.goodMovies++ -} -else if(movie.rating >=4){ -acc.averageMovies++ -} -else{ -acc.badMovies++ -} - -return acc - -},{ -goodMovies:0, -averageMovies:0, -badMovies:0 -}) - -renderText(JSON.stringify(result,null,2)) - -} \ No newline at end of file diff --git a/courses/frontend/advanced-javascript/week-1/Working with movies/style.css b/courses/frontend/advanced-javascript/week-1/Working with movies/style.css deleted file mode 100644 index 9c177ecc7..000000000 --- a/courses/frontend/advanced-javascript/week-1/Working with movies/style.css +++ /dev/null @@ -1,49 +0,0 @@ -body{ -font-family:Arial; -background:#f5f5f5; -padding:20px; -} - -h1{ -text-align:center; -} - -.buttons{ -text-align:center; -margin-bottom:20px; -} - -button{ -padding:10px 15px; -margin:5px; -border:none; -background:#222; -color:white; -cursor:pointer; -border-radius:5px; -} - -button:hover{ -background:#555; -} - -.moviesContainer{ -display:grid; -grid-template-columns:repeat(auto-fill,minmax(200px,1fr)); -gap:20px; -} - -.movieCard{ -background:white; -padding:15px; -border-radius:10px; -box-shadow:0 3px 10px rgba(0,0,0,0.2); -} - -.movieCard h3{ -margin:0 0 10px 0; -} - -.movieCard p{ -margin:3px 0; -} \ No newline at end of file
        + + Get professional support for this package with a Tidelift subscription + +
        + + Tidelift helps make open source sustainable for maintainers while giving companies
        assurances about security, maintenance, and licensing for their dependencies. +
        +