diff --git a/.glitch-assets b/.glitch-assets
new file mode 100644
index 00000000..c74268f8
--- /dev/null
+++ b/.glitch-assets
@@ -0,0 +1,40 @@
+{"name":"drag-in-files.svg","date":"2016-10-22T16:17:49.954Z","url":"https://cdn.hyperdev.com/drag-in-files.svg","type":"image/svg","size":7646,"imageWidth":276,"imageHeight":276,"thumbnail":"https://cdn.hyperdev.com/drag-in-files.svg","thumbnailWidth":276,"thumbnailHeight":276,"dominantColor":"rgb(102, 153, 205)","uuid":"adSBq97hhhpFNUna"}
+{"name":"click-me.svg","date":"2016-10-23T16:17:49.954Z","url":"https://cdn.hyperdev.com/click-me.svg","type":"image/svg","size":7116,"imageWidth":276,"imageHeight":276,"thumbnail":"https://cdn.hyperdev.com/click-me.svg","thumbnailWidth":276,"thumbnailHeight":276,"dominantColor":"rgb(243, 185, 186)","uuid":"adSBq97hhhpFNUnb"}
+{"name":"paste-me.svg","date":"2016-10-24T16:17:49.954Z","url":"https://cdn.hyperdev.com/paste-me.svg","type":"image/svg","size":7242,"imageWidth":276,"imageHeight":276,"thumbnail":"https://cdn.hyperdev.com/paste-me.svg","thumbnailWidth":276,"thumbnailHeight":276,"dominantColor":"rgb(42, 179, 185)","uuid":"adSBq97hhhpFNUnc"}
+{"uuid":"adSBq97hhhpFNUna","deleted":true}
+{"uuid":"adSBq97hhhpFNUnb","deleted":true}
+{"uuid":"adSBq97hhhpFNUnc","deleted":true}
+{"name":"pancakes.webp","date":"2019-09-16T05:36:19.218Z","url":"https://cdn.glitch.com/18fef328-486b-4e80-b387-bcf91cabcef3%2Fpancakes.webp","type":"image/webp","size":166254,"imageWidth":2000,"imageHeight":2500,"thumbnail":"https://cdn.glitch.com/18fef328-486b-4e80-b387-bcf91cabcef3%2Fthumbnails%2Fpancakes.webp","thumbnailWidth":264,"thumbnailHeight":330,"uuid":"s4dLHHAjzQyQMdUR"}
+{"name":"waffles.jpg","date":"2019-09-16T06:12:47.378Z","url":"https://cdn.glitch.com/18fef328-486b-4e80-b387-bcf91cabcef3%2Fwaffles.jpg","type":"image/jpeg","size":72884,"imageWidth":1080,"imageHeight":720,"thumbnail":"https://cdn.glitch.com/18fef328-486b-4e80-b387-bcf91cabcef3%2Fthumbnails%2Fwaffles.jpg","thumbnailWidth":330,"thumbnailHeight":221,"uuid":"W5aWDxBgHzKlr6qu"}
+{"name":"crepes.jpg","date":"2019-09-16T13:50:34.820Z","url":"https://cdn.glitch.com/18fef328-486b-4e80-b387-bcf91cabcef3%2Fcrepes.jpg","type":"image/jpeg","size":38548,"imageWidth":640,"imageHeight":640,"thumbnail":"https://cdn.glitch.com/18fef328-486b-4e80-b387-bcf91cabcef3%2Fthumbnails%2Fcrepes.jpg","thumbnailWidth":330,"thumbnailHeight":330,"uuid":"3PJSdOgtcSSKe0v5"}
+{"name":"waffle.jpg","date":"2019-09-25T03:24:00.202Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fwaffle.jpg","type":"image/jpeg","size":240063,"imageWidth":600,"imageHeight":423,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2Fwaffle.jpg","thumbnailWidth":330,"thumbnailHeight":233,"uuid":"HHycxX6RsqCjuI0q"}
+{"name":"waffle_NRM.jpg","date":"2019-09-25T03:24:07.878Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fwaffle_NRM.jpg","type":"image/jpeg","size":73612,"imageWidth":600,"imageHeight":423,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2Fwaffle_NRM.jpg","thumbnailWidth":330,"thumbnailHeight":233,"uuid":"crZZf01qYFvAbwYi"}
+{"name":"PancakePlain.obj","date":"2019-09-25T03:24:43.900Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2FPancakePlain.obj","type":"","size":81815,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2FPancakePlain.obj","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"sbVURTpWvD8kPOkd"}
+{"name":"PancakeW_Syrup.obj","date":"2019-09-25T03:24:53.495Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2FPancakeW_Syrup.obj","type":"","size":96253,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2FPancakeW_Syrup.obj","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"JRnr1WYHXiScSSBO"}
+{"name":"pack de jus pindra 2.obj","date":"2019-09-25T03:28:46.864Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fpack%20de%20jus%20pindra%202.obj","type":"","size":20173664,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2Fpack%20de%20jus%20pindra%202.obj","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"SD3RRbj4tLVPzjut"}
+{"name":"Waffle_N160715.3ds.obj","date":"2019-09-25T03:32:01.975Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2FWaffle_N160715.3ds.obj","type":"","size":394288,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2FWaffle_N160715.3ds.obj","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"7581zD4BlLIpG4Hc"}
+{"name":"croissant_01_col.obj","date":"2019-09-25T17:22:19.088Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fcroissant_01_col.obj","type":"","size":2069,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2Fcroissant_01_col.obj","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"jW3TqB1tXslP3iYe"}
+{"name":"6e01319e-6ca6-47f7-9b4e-aaca43f9cc11_PancakePlain.obj","date":"2019-09-27T02:42:26.867Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2F6e01319e-6ca6-47f7-9b4e-aaca43f9cc11_PancakePlain.obj","type":"","size":81815,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2F6e01319e-6ca6-47f7-9b4e-aaca43f9cc11_PancakePlain.obj","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"S45vv9xj24kmmyWj"}
+{"name":"newfile.png","date":"2019-09-27T02:47:22.503Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fnewfile.png","type":"","size":53604,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2Fnewfile.png","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"XlOMWBQooeA0hjy3"}
+{"name":"newfile.obj","date":"2019-09-27T02:47:39.509Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fnewfile.obj","type":"","size":53604,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2Fnewfile.obj","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"qjkMI0Fwnk62tWfJ"}
+{"name":"pancake.obj","date":"2019-09-27T02:48:44.662Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fpancake.obj","type":"","size":53589,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2Fpancake.obj","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"8Lh9KV56EmFpiH80"}
+{"name":"scene.gltf","date":"2019-09-27T03:14:50.349Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fscene.gltf","type":"","size":15430,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2Fscene.gltf","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"GMTek1htlx5SlgZb"}
+{"uuid":"sbVURTpWvD8kPOkd","deleted":true}
+{"uuid":"7581zD4BlLIpG4Hc","deleted":true}
+{"uuid":"S45vv9xj24kmmyWj","deleted":true}
+{"uuid":"XlOMWBQooeA0hjy3","deleted":true}
+{"uuid":"qjkMI0Fwnk62tWfJ","deleted":true}
+{"uuid":"8Lh9KV56EmFpiH80","deleted":true}
+{"name":"scene.bin","date":"2019-09-27T03:15:47.425Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fscene.bin","type":"application/octet-stream","size":242472,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2Fscene.bin","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"3O06Ksw0IQyaVomD"}
+{"name":"pancake.glb","date":"2019-09-27T03:19:39.174Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fpancake.glb","type":"","size":9188092,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2Fpancake.glb","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"ZPoNP9kFXuK5WPbB"}
+{"uuid":"3O06Ksw0IQyaVomD","deleted":true}
+{"name":"waffle.glb","date":"2019-09-27T04:15:23.572Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fwaffle.glb","type":"","size":575980,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2Fwaffle.glb","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"1mZFgJRRunHJRgbj"}
+{"uuid":"GMTek1htlx5SlgZb","deleted":true}
+{"uuid":"jW3TqB1tXslP3iYe","deleted":true}
+{"uuid":"SD3RRbj4tLVPzjut","deleted":true}
+{"uuid":"JRnr1WYHXiScSSBO","deleted":true}
+{"uuid":"HHycxX6RsqCjuI0q","deleted":true}
+{"uuid":"crZZf01qYFvAbwYi","deleted":true}
+{"name":"crepe.glb","date":"2019-09-27T04:55:03.641Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fcrepe.glb","type":"","size":8471612,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2Fcrepe.glb","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"ZUeh6i00ZJMgwnDC"}
+{"uuid":"ZUeh6i00ZJMgwnDC","deleted":true}
+{"name":"crepe.glb","date":"2019-09-27T05:16:42.390Z","url":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fcrepe.glb","type":"","size":18214888,"thumbnail":"https://cdn.glitch.com/6e01319e-6ca6-47f7-9b4e-aaca43f9cc11%2Fthumbnails%2Fcrepe.glb","thumbnailWidth":210,"thumbnailHeight":210,"uuid":"uw7F112ie2v9hXk6"}
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 00000000..ef93c8b7
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,6 @@
+{
+"curly": true
+"node": ture
+"evil":true
+"eqeqeq"
+}
\ No newline at end of file
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 00000000..ae4b14ed
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 [NAME]
+
+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/README.md b/README.md
index b62f5cb2..f93bf2de 100644
--- a/README.md
+++ b/README.md
@@ -1,60 +1,31 @@
-# cs4241-FinalProject
-
-For your final project, you'll implement a course project that exhibits your mastery of the course materials.
-Similar to A4, this project gives you an opportunity to be creative and to pursue individual research and learning.
-
-## General description
-
-Your project should consist of a complete Web application, exhibiting facets of the three main sections of the course material:
-
-- Static Web page content and design. You should have a project that is accessible, easily navigable, and features significant content.
-- Dynamic behavior implemented with JavaScript.
-- Server-side programming *using Node.js*. Typically this will take the form of some sort of persistent data, authentication, and possibly server-side computation.
-
-Additionally, you should incorporate features that you independently research, design, and implement for your project.
-
-## Project ideation
-
-Excellent projects serve someone/some group; for this assignment you need to define your users and stakeholders. I encourage you to identify projects that will have impact, either artistically, politically, or in terms of productivity. Consider creating something useful for a cause or hobby you care about.
-
-## Logistics
-
-### Team size
-Students are encouraged to work in teams of 2-5 students for the project. This will allow you to build a good project without expending an excessive amount of effort. While I would expect a team of four or five students to produce a project with more features, I expect a every team's work to exhibit all of the required facets described above.
-
-### Deliverables
-
-__Proposal:__
-Provide an outline of your project direction and the names of the team members.
-The outline should have enough detail so that staff can determine if it meets the minimum expectations, or if it goes too far to be reasonable by the deadline.
-This file must be named proposal.md so we can find it.
-Submit a PR to turn it in by Monday, September 30th, before class
-
-There are no other scheduled checkpoints for your project.
-You must be done in time to present before the final project demo day (October 10th).
-
-#### Turning in Your Outline / Project
-
-**NOTE: code is due before the project presentation day due to the end of term / grading schedule constraints**
-Submit a second PR on the final project repo to turn in your app and code.
-
-Deploy your app, in the form of a webpage, to Glitch/Heroku/Digital Ocean or some other service.
-Folks on the same team do not need to post the same webpage, but must instead clearly state who is on the team in their proposal.
-
-The README for your second pull request doesn’t need to be a formal report, but it should contain:
-
-1. A brief description of what you created, and a link to the project itself.
-2. Any additional instructions that might be needed to fully use your project (login information etc.)
-3. An outline of the technologies you used and how you used them.
-4. What challenges you faced in completing the project.
-5. What each group member was responsible for designing / developing.
-
-Think of 1,3, and 4 in particular in a similar vein to the design / tech achievements for A1—A4… make a case for why what you did was challenging and why your implementation deserves a grade of 100%.
-
-## Final Presentation
-
-Presentations will occur during the final day of class in *Riley Commons*.
-
-## FAQs
-
-- **Can I use XYZ framework?** You can use any web-based frameworks or tools available, but for your server programming you need to use node.js.
+https://glitch.com/~fp-jamevor-tpatterson
+Justin Amevor
+Tyrone Patterson
+Doughboyz Catering
+
+The goal of this application is for customers to order foods form the app. Customers can place an order and also use the
+visualizer to see what there order would look like with different condiments.
+
+To fully use the site you should login by first signing up by making a username and password.
+
+**Important:** The account linked to the text confirmation portion of the application only has 7 more texts it is able to send before the account locks
+and it won't be able to send them anymore. So use them wisely.
+
+Technologies Used:
+Three.js-Justin
+javascript-Tyrone
+Jquerry/DataTables-Justin
+Bootstrap-Justin
+lowDB-Tyrone
+TextMagic Rest Client-Tyrone
+NodeMailer-Tyrone
+
+The entire project was somewhat challenging. Justin struggled with backend development and Tyronne struggled with front end development.
+Luckily we helped each other with our weak areas but getting data to store in the database was especially challenging.
+
+This project deserves a 100 because we not only spent hours working on the implmentation of the technologies, we asked various
+stakeholders features that they would like to have in a ordering application. From their feedback we established using Twello
+to send confirmations to users phones or emails would be a desirable feature. This project also made the application a bit smoother
+adding more Bootstrap, cleaning up backend code, and adding more funcinality to the ordering page. This application can fully be used
+to take orders from customers by storing them in a succinct database. The work and effort shown in this project is over 20 hours of
+programming in the last weeks.
\ No newline at end of file
diff --git a/data/db.json b/data/db.json
new file mode 100644
index 00000000..d73ccbe9
--- /dev/null
+++ b/data/db.json
@@ -0,0 +1,53 @@
+{
+ "idcount": 7,
+ "data": [
+ [
+ "1",
+ "qweqwe",
+ "Justin D Amevor",
+ "7777",
+ "jdamevor98@gmail.com",
+ "15 Ball Street",
+ "jdamevor98@gmail.com",
+ "Blueberries ",
+ "frozen",
+ "email"
+ ],
+ [
+ "3",
+ "qweqwe",
+ "Name",
+ "Phone ",
+ "Email2",
+ "Address",
+ "Order",
+ "Cond 2",
+ "",
+ "email"
+ ],
+ [
+ "5",
+ "t",
+ "Tyrone",
+ "12026699290",
+ "tvpatterson@wpi.edu",
+ "T",
+ "2 Waffles",
+ "Syrup",
+ "",
+ "email"
+ ],
+ [
+ "6",
+ "t",
+ "Tyrone",
+ "12026699290",
+ "tvpatterson@wpi.edu",
+ "q",
+ "2 Waffles",
+ "Butter",
+ "",
+ "text"
+ ]
+ ]
+}
\ No newline at end of file
diff --git a/data/pw.json b/data/pw.json
new file mode 100644
index 00000000..c228b82f
--- /dev/null
+++ b/data/pw.json
@@ -0,0 +1,50 @@
+{
+ "data": [],
+ "users": [
+ {
+ "username": "cas",
+ "id": "ae1c251a-a267-48bc-8b1a-ff8483dec4bb",
+ "password": "$2a$10$D/etk/wR/N8c67MYpnn8/eP/rVvuE5mQs3SQvC85e4Kvpn.ZMnp7S"
+ },
+ {
+ "username": "qweqwe",
+ "id": "3806d4d7-3e1b-414a-bc05-4418ce34b034",
+ "password": "$2a$10$OPote0IDKlp1LJ9uL86hyewfzg582dAQEOd0IDplMbjJnEMclwHLC"
+ },
+ {
+ "username": "jamevor",
+ "id": "c12b370f-bfed-447c-bb59-8ea29825ac95",
+ "password": "$2a$10$p/6u49r1KVwQ8nsegcRtCOV6CqwWVfkpKN2QYMN5R5Dp5lZqPY3SG"
+ },
+ {
+ "username": "qweqweq",
+ "id": "48ed6371-6522-425f-9eb0-e06a6248ed35",
+ "password": "$2a$10$5nCklDV19TnfBEU4RWl4ruD7mq8WeR4SFp4bNY7qUv.5N/zCENT6G"
+ },
+ {
+ "username": "asdasd",
+ "id": "bcc3c609-4a81-487e-a3cb-755635a37a16",
+ "password": "$2a$10$NYRONFroj3ngjReVwAJIfuSErulYk6GLm34/nbIdm9VUkSBXdjPNu"
+ },
+ {
+ "username": "bnm",
+ "id": "64b3fe4a-6a4d-44c6-89d5-78444c832cd3",
+ "password": "$2a$10$Vv2GKvM3pcSwXmSjEXvTOu4LnA6fnKlKM7MPGY5Of5YnH6nfgi8TO"
+ },
+ {
+ "username": "jkl",
+ "id": "e6df127d-8e42-4fa6-a554-1f0bac2d9a57",
+ "password": "$2a$10$rkXRz8k4198SPTz3ojTqLuF/Gp7SJbvjthfCh/GMZGUrIMRBgyDoi"
+ },
+ {
+ "username": "jkljkl",
+ "id": "618c1e43-6611-4b58-8af3-af3c6d0fa31d",
+ "password": "$2a$10$FJRafHBzYYQaqnyiZS/I4.xlWTobZd55o4Eon.VW2if9FglsLwW9S"
+ },
+ {
+ "username": "t",
+ "id": "9a62b8da-6a0f-469e-83d0-879a2868325c",
+ "password": "$2a$10$1jQcYttp61ejpwhfNu1OfumSza3I7oWOWGJmDVE3KuTA4sgYx3r6W"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 00000000..4218d19c
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,2161 @@
+{
+ "requires": true,
+ "lockfileVersion": 1,
+ "dependencies": {
+ "@braintree/wrap-promise": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@braintree/wrap-promise/-/wrap-promise-2.0.0.tgz",
+ "integrity": "sha512-I9s8c/bHBx7gM04yHGKjRoyqX1NhT4d3RIQjLZDW+yFI3DRmi/8JYDpxQeW4fiU6bWX2f3KV1Oa8r2nwKeaAwA=="
+ },
+ "bcryptjs": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
+ "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms="
+ },
+ "body-parser": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+ "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+ "requires": {
+ "bytes": "3.1.0",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "on-finished": "~2.3.0",
+ "qs": "6.7.0",
+ "raw-body": "2.4.0",
+ "type-is": "~1.6.17"
+ },
+ "dependencies": {
+ "bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "http-errors": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+ "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.1",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.0"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+ },
+ "mime-db": {
+ "version": "1.40.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+ "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
+ },
+ "mime-types": {
+ "version": "2.1.24",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+ "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+ "requires": {
+ "mime-db": "1.40.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "qs": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
+ },
+ "raw-body": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+ "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+ "requires": {
+ "bytes": "3.1.0",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "setprototypeof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
+ },
+ "statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+ },
+ "toidentifier": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
+ },
+ "type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ }
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ }
+ }
+ },
+ "braintree": {
+ "version": "2.20.0",
+ "resolved": "https://registry.npmjs.org/braintree/-/braintree-2.20.0.tgz",
+ "integrity": "sha512-/7zlO5JO4cqXxMuO11FhDYjgCm14ZAWONJS7TkohlI4ugPboi2C5P4b0EeOqiNLoiwFmYuWcNGfERp/ltBuhOg==",
+ "requires": {
+ "@braintree/wrap-promise": "2.0.0",
+ "dateformat": "^3.0.3",
+ "depd": "~1.1.0",
+ "readable-stream": "1.1.10",
+ "semver": "5.1.0",
+ "underscore": "^1.9.1",
+ "xml2js": "0.1.13"
+ }
+ },
+ "compression": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
+ "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
+ "requires": {
+ "accepts": "~1.3.5",
+ "bytes": "3.0.0",
+ "compressible": "~2.0.16",
+ "debug": "2.6.9",
+ "on-headers": "~1.0.2",
+ "safe-buffer": "5.1.2",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "accepts": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "requires": {
+ "mime-types": "~2.1.24",
+ "negotiator": "0.6.2"
+ }
+ },
+ "bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
+ },
+ "compressible": {
+ "version": "2.0.17",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz",
+ "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==",
+ "requires": {
+ "mime-db": ">= 1.40.0 < 2"
+ }
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "mime-db": {
+ "version": "1.40.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+ "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
+ },
+ "mime-types": {
+ "version": "2.1.24",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+ "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+ "requires": {
+ "mime-db": "1.40.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "negotiator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
+ },
+ "on-headers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+ }
+ }
+ },
+ "connect": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
+ "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
+ "requires": {
+ "debug": "2.6.9",
+ "finalhandler": "1.1.2",
+ "parseurl": "~1.3.3",
+ "utils-merge": "1.0.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "statuses": "~1.5.0",
+ "unpipe": "~1.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
+ },
+ "statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+ }
+ }
+ },
+ "cookie-parser": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.4.tgz",
+ "integrity": "sha512-lo13tqF3JEtFO7FyA49CqbhaFkskRJ0u/UAiINgrIXeRCY41c88/zxtrECl8AKH3B0hj9q10+h3Kt8I7KlW4tw==",
+ "requires": {
+ "cookie": "0.3.1",
+ "cookie-signature": "1.0.6"
+ },
+ "dependencies": {
+ "cookie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+ }
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "cors": {
+ "version": "2.8.5",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
+ "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
+ "requires": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "dependencies": {
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+ }
+ }
+ },
+ "datatables.net-buttons-dt": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/datatables.net-buttons-dt/-/datatables.net-buttons-dt-1.6.0.tgz",
+ "integrity": "sha512-qzlIa8Ud6JfUDa07EgIXfH2C8/F1H1lrdXwG3U7/pgj6hXWwYYIumMKMXo5V3WyXP0ZrHmL8E0tdXWr2akIhkw==",
+ "requires": {
+ "datatables.net-buttons": "1.6.0",
+ "datatables.net-dt": "^1.10.15",
+ "jquery": ">=1.7"
+ },
+ "dependencies": {
+ "datatables.net": {
+ "version": "1.10.20",
+ "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.10.20.tgz",
+ "integrity": "sha512-4E4S7tTU607N3h0fZPkGmAtr9mwy462u+VJ6gxYZ8MxcRIjZqHy3Dv1GNry7i3zQCktTdWbULVKBbkAJkuHEnQ==",
+ "requires": {
+ "jquery": ">=1.7"
+ }
+ },
+ "datatables.net-buttons": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/datatables.net-buttons/-/datatables.net-buttons-1.6.0.tgz",
+ "integrity": "sha512-FhzBXnN7xrpzBkzGSiQNivdDxzsyYhVlAwFUGnJdrKnLMKyRtKNpnYBjQSn0RjmZDYW3fGB2eGNejydBZQfUgQ==",
+ "requires": {
+ "datatables.net": "^1.10.15",
+ "jquery": ">=1.7"
+ }
+ },
+ "datatables.net-dt": {
+ "version": "1.10.20",
+ "resolved": "https://registry.npmjs.org/datatables.net-dt/-/datatables.net-dt-1.10.20.tgz",
+ "integrity": "sha512-D+65buDke96a3WlJo2re+SbcAVfjPh2nsFZG198Vbkz3i1wKPdB+wkV2K07qYIiIpypcXWOnD2pz3MvnUqM9Tw==",
+ "requires": {
+ "datatables.net": "1.10.20",
+ "jquery": ">=1.7"
+ }
+ },
+ "jquery": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
+ "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw=="
+ }
+ }
+ },
+ "datatables.net-dt": {
+ "version": "1.10.20",
+ "resolved": "https://registry.npmjs.org/datatables.net-dt/-/datatables.net-dt-1.10.20.tgz",
+ "integrity": "sha512-D+65buDke96a3WlJo2re+SbcAVfjPh2nsFZG198Vbkz3i1wKPdB+wkV2K07qYIiIpypcXWOnD2pz3MvnUqM9Tw==",
+ "requires": {
+ "datatables.net": "1.10.20",
+ "jquery": ">=1.7"
+ },
+ "dependencies": {
+ "datatables.net": {
+ "version": "1.10.20",
+ "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.10.20.tgz",
+ "integrity": "sha512-4E4S7tTU607N3h0fZPkGmAtr9mwy462u+VJ6gxYZ8MxcRIjZqHy3Dv1GNry7i3zQCktTdWbULVKBbkAJkuHEnQ==",
+ "requires": {
+ "jquery": ">=1.7"
+ }
+ },
+ "jquery": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
+ "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw=="
+ }
+ }
+ },
+ "dateformat": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz",
+ "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q=="
+ },
+ "debuglog": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-0.0.2.tgz",
+ "integrity": "sha1-bA3PB+LD90UkYpt0Fmi9RsezYus=",
+ "optional": true
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+ },
+ "errorhandler": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz",
+ "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==",
+ "requires": {
+ "accepts": "~1.3.7",
+ "escape-html": "~1.0.3"
+ },
+ "dependencies": {
+ "accepts": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "requires": {
+ "mime-types": "~2.1.24",
+ "negotiator": "0.6.2"
+ }
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "mime-db": {
+ "version": "1.40.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+ "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
+ },
+ "mime-types": {
+ "version": "2.1.24",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+ "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+ "requires": {
+ "mime-db": "1.40.0"
+ }
+ },
+ "negotiator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
+ }
+ }
+ },
+ "express": {
+ "version": "4.17.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
+ "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
+ "requires": {
+ "accepts": "~1.3.7",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.19.0",
+ "content-disposition": "0.5.3",
+ "content-type": "~1.0.4",
+ "cookie": "0.4.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.1.2",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.5",
+ "qs": "6.7.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.1.2",
+ "send": "0.17.1",
+ "serve-static": "1.14.1",
+ "setprototypeof": "1.1.1",
+ "statuses": "~1.5.0",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "accepts": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "requires": {
+ "mime-types": "~2.1.24",
+ "negotiator": "0.6.2"
+ }
+ },
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+ },
+ "body-parser": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+ "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+ "requires": {
+ "bytes": "3.1.0",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "on-finished": "~2.3.0",
+ "qs": "6.7.0",
+ "raw-body": "2.4.0",
+ "type-is": "~1.6.17"
+ }
+ },
+ "bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
+ },
+ "content-disposition": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+ "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+ },
+ "cookie": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+ "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+ },
+ "finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "statuses": "~1.5.0",
+ "unpipe": "~1.0.0"
+ }
+ },
+ "forwarded": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+ },
+ "http-errors": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+ "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.1",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.0"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "ipaddr.js": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
+ "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA=="
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+ },
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
+ },
+ "mime-db": {
+ "version": "1.40.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+ "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
+ },
+ "mime-types": {
+ "version": "2.1.24",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+ "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+ "requires": {
+ "mime-db": "1.40.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "negotiator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+ },
+ "proxy-addr": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
+ "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
+ "requires": {
+ "forwarded": "~0.1.2",
+ "ipaddr.js": "1.9.0"
+ }
+ },
+ "qs": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
+ },
+ "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=="
+ },
+ "raw-body": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+ "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+ "requires": {
+ "bytes": "3.1.0",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "send": {
+ "version": "0.17.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+ "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.7.2",
+ "mime": "1.6.0",
+ "ms": "2.1.1",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.1",
+ "statuses": "~1.5.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+ }
+ }
+ },
+ "serve-static": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
+ "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.17.1"
+ }
+ },
+ "setprototypeof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
+ },
+ "statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+ },
+ "toidentifier": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
+ },
+ "type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ }
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+ }
+ }
+ },
+ "express-session": {
+ "version": "1.16.2",
+ "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.16.2.tgz",
+ "integrity": "sha512-oy0sRsdw6n93E9wpCNWKRnSsxYnSDX9Dnr9mhZgqUEEorzcq5nshGYSZ4ZReHFhKQ80WI5iVUUSPW7u3GaKauw==",
+ "requires": {
+ "cookie": "0.3.1",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~2.0.0",
+ "on-headers": "~1.0.2",
+ "parseurl": "~1.3.3",
+ "safe-buffer": "5.1.2",
+ "uid-safe": "~2.1.5"
+ },
+ "dependencies": {
+ "cookie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "on-headers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
+ },
+ "random-bytes": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
+ "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "uid-safe": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
+ "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
+ "requires": {
+ "random-bytes": "~1.0.0"
+ }
+ }
+ }
+ },
+ "express-validator": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.2.0.tgz",
+ "integrity": "sha512-892cPistoSPzMuoG2p1W+2ZxBi0bAvPaaYgXK1E1C8/QncLo2d1HbiDDWkXUtTthjGEzEmwiELLJHu1Ez2hOEg==",
+ "requires": {
+ "lodash": "^4.17.15",
+ "validator": "^11.1.0"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+ },
+ "validator": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-11.1.0.tgz",
+ "integrity": "sha512-qiQ5ktdO7CD6C/5/mYV4jku/7qnqzjrxb3C/Q5wR3vGGinHTgJZN/TdFT3ZX4vXhX2R1PXx42fB1cn5W+uJ4lg=="
+ }
+ }
+ },
+ "helmet": {
+ "version": "3.21.1",
+ "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.21.1.tgz",
+ "integrity": "sha512-IC/54Lxvvad2YiUdgLmPlNFKLhNuG++waTF5KPYq/Feo3NNhqMFbcLAlbVkai+9q0+4uxjxGPJ9bNykG+3zZNg==",
+ "requires": {
+ "depd": "2.0.0",
+ "dns-prefetch-control": "0.2.0",
+ "dont-sniff-mimetype": "1.1.0",
+ "expect-ct": "0.2.0",
+ "feature-policy": "0.3.0",
+ "frameguard": "3.1.0",
+ "helmet-crossdomain": "0.4.0",
+ "helmet-csp": "2.9.2",
+ "hide-powered-by": "1.1.0",
+ "hpkp": "2.0.0",
+ "hsts": "2.2.0",
+ "ienoopen": "1.1.0",
+ "nocache": "2.1.0",
+ "referrer-policy": "1.2.0",
+ "x-xss-protection": "1.3.0"
+ },
+ "dependencies": {
+ "bowser": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.7.0.tgz",
+ "integrity": "sha512-aIlMvstvu8x+34KEiOHD3AsBgdrzg6sxALYiukOWhFvGMbQI6TRP/iY0LMhUrHs56aD6P1G0Z7h45PUJaa5m9w=="
+ },
+ "camelize": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
+ "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
+ },
+ "content-security-policy-builder": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-2.1.0.tgz",
+ "integrity": "sha512-/MtLWhJVvJNkA9dVLAp6fg9LxD2gfI6R2Fi1hPmfjYXSahJJzcfvoeDOxSyp4NvxMuwWv3WMssE9o31DoULHrQ=="
+ },
+ "dasherize": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz",
+ "integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg="
+ },
+ "depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
+ },
+ "dns-prefetch-control": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.2.0.tgz",
+ "integrity": "sha512-hvSnros73+qyZXhHFjx2CMLwoj3Fe7eR9EJsFsqmcI1bB2OBWL/+0YzaEaKssCHnj/6crawNnUyw74Gm2EKe+Q=="
+ },
+ "dont-sniff-mimetype": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.1.0.tgz",
+ "integrity": "sha512-ZjI4zqTaxveH2/tTlzS1wFp+7ncxNZaIEWYg3lzZRHkKf5zPT/MnEG6WL0BhHMJUabkh8GeU5NL5j+rEUCb7Ug=="
+ },
+ "expect-ct": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/expect-ct/-/expect-ct-0.2.0.tgz",
+ "integrity": "sha512-6SK3MG/Bbhm8MsgyJAylg+ucIOU71/FzyFalcfu5nY19dH8y/z0tBJU0wrNBXD4B27EoQtqPF/9wqH0iYAd04g=="
+ },
+ "feature-policy": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/feature-policy/-/feature-policy-0.3.0.tgz",
+ "integrity": "sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ=="
+ },
+ "frameguard": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.1.0.tgz",
+ "integrity": "sha512-TxgSKM+7LTA6sidjOiSZK9wxY0ffMPY3Wta//MqwmX0nZuEHc8QrkV8Fh3ZhMJeiH+Uyh/tcaarImRy8u77O7g=="
+ },
+ "helmet-crossdomain": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/helmet-crossdomain/-/helmet-crossdomain-0.4.0.tgz",
+ "integrity": "sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA=="
+ },
+ "helmet-csp": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.9.2.tgz",
+ "integrity": "sha512-Lt5WqNfbNjEJ6ysD4UNpVktSyjEKfU9LVJ1LaFmPfYseg/xPealPfgHhtqdAdjPDopp5zbg/VWCyp4cluMIckw==",
+ "requires": {
+ "bowser": "^2.6.1",
+ "camelize": "1.0.0",
+ "content-security-policy-builder": "2.1.0",
+ "dasherize": "2.0.0"
+ }
+ },
+ "hide-powered-by": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.1.0.tgz",
+ "integrity": "sha512-Io1zA2yOA1YJslkr+AJlWSf2yWFkKjvkcL9Ni1XSUqnGLr/qRQe2UI3Cn/J9MsJht7yEVCe0SscY1HgVMujbgg=="
+ },
+ "hpkp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz",
+ "integrity": "sha1-EOFCJk52IVpdMMROxD3mTe5tFnI="
+ },
+ "hsts": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.2.0.tgz",
+ "integrity": "sha512-ToaTnQ2TbJkochoVcdXYm4HOCliNozlviNsg+X2XQLQvZNI/kCHR9rZxVYpJB3UPcHz80PgxRyWQ7PdU1r+VBQ==",
+ "requires": {
+ "depd": "2.0.0"
+ }
+ },
+ "ienoopen": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.1.0.tgz",
+ "integrity": "sha512-MFs36e/ca6ohEKtinTJ5VvAJ6oDRAYFdYXweUnGY9L9vcoqFOU4n2ZhmJ0C4z/cwGZ3YIQRSB3XZ1+ghZkY5NQ=="
+ },
+ "nocache": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz",
+ "integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q=="
+ },
+ "referrer-policy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.2.0.tgz",
+ "integrity": "sha512-LgQJIuS6nAy1Jd88DCQRemyE3mS+ispwlqMk3b0yjZ257fI1v9c+/p6SD5gP5FGyXUIgrNOAfmyioHwZtYv2VA=="
+ },
+ "x-xss-protection": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.3.0.tgz",
+ "integrity": "sha512-kpyBI9TlVipZO4diReZMAHWtS0MMa/7Kgx8hwG/EuZLiA6sg4Ah/4TRdASHhRRN3boobzcYgFRUFSgHRge6Qhg=="
+ }
+ }
+ },
+ "jquery": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
+ "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw=="
+ },
+ "jshint": {
+ "version": "2.10.2",
+ "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.10.2.tgz",
+ "integrity": "sha512-e7KZgCSXMJxznE/4WULzybCMNXNAd/bf5TSrvVEq78Q/K8ZwFpmBqQeDtNiHc3l49nV4E/+YeHU/JZjSUIrLAA==",
+ "requires": {
+ "cli": "~1.0.0",
+ "console-browserify": "1.1.x",
+ "exit": "0.1.x",
+ "htmlparser2": "3.8.x",
+ "lodash": "~4.17.11",
+ "minimatch": "~3.0.2",
+ "shelljs": "0.3.x",
+ "strip-json-comments": "1.0.x"
+ },
+ "dependencies": {
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "cli": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz",
+ "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=",
+ "requires": {
+ "exit": "0.1.2",
+ "glob": "^7.1.1"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "console-browserify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
+ "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
+ "requires": {
+ "date-now": "^0.1.4"
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "date-now": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
+ "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs="
+ },
+ "dom-serializer": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.1.tgz",
+ "integrity": "sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q==",
+ "requires": {
+ "domelementtype": "^2.0.1",
+ "entities": "^2.0.0"
+ },
+ "dependencies": {
+ "domelementtype": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz",
+ "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ=="
+ },
+ "entities": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz",
+ "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw=="
+ }
+ }
+ },
+ "domelementtype": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
+ },
+ "domhandler": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz",
+ "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=",
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "domutils": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
+ "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
+ "entities": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz",
+ "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY="
+ },
+ "exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw="
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "glob": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "htmlparser2": {
+ "version": "3.8.3",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz",
+ "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=",
+ "requires": {
+ "domelementtype": "1",
+ "domhandler": "2.3",
+ "domutils": "1.5",
+ "entities": "1.0",
+ "readable-stream": "1.1"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+ },
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "readable-stream": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.1",
+ "isarray": "0.0.1",
+ "string_decoder": "~0.10.x"
+ }
+ },
+ "shelljs": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz",
+ "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E="
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+ },
+ "strip-json-comments": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz",
+ "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E="
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ }
+ }
+ },
+ "lowdb": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-1.0.0.tgz",
+ "integrity": "sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==",
+ "requires": {
+ "graceful-fs": "^4.1.3",
+ "is-promise": "^2.1.0",
+ "lodash": "4",
+ "pify": "^3.0.0",
+ "steno": "^0.4.1"
+ },
+ "dependencies": {
+ "graceful-fs": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz",
+ "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q=="
+ },
+ "is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
+ },
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+ },
+ "steno": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz",
+ "integrity": "sha1-BxEFvfwobmYVwEA8J+nXtdy4Vcs=",
+ "requires": {
+ "graceful-fs": "^4.1.3"
+ }
+ }
+ }
+ },
+ "method-override": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz",
+ "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==",
+ "requires": {
+ "debug": "3.1.0",
+ "methods": "~1.1.2",
+ "parseurl": "~1.3.2",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+ }
+ }
+ },
+ "mime": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
+ "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
+ },
+ "morgan": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz",
+ "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==",
+ "requires": {
+ "basic-auth": "~2.0.0",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "on-headers": "~1.0.1"
+ },
+ "dependencies": {
+ "basic-auth": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
+ "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "on-headers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ }
+ }
+ },
+ "nexmo": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/nexmo/-/nexmo-2.5.1.tgz",
+ "integrity": "sha512-TkZZPx76ERV26RSNqUGplMmhTwmnEN6EpeEmWiy/QgNoVoE/F4kFeEUzv9wlGmgs3GRMjHE7Z7wYTF6MPpcmTQ==",
+ "requires": {
+ "jsonwebtoken": "^8.4.0",
+ "request": "^2.88.0",
+ "uuid": "^2.0.2"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+ "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "asn1": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+ "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
+ },
+ "aws4": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
+ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
+ },
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+ },
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "requires": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+ },
+ "form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
+ },
+ "har-validator": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+ "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+ "requires": {
+ "ajv": "^6.5.5",
+ "har-schema": "^2.0.0"
+ }
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+ },
+ "jsonwebtoken": {
+ "version": "8.5.1",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
+ "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
+ "requires": {
+ "jws": "^3.2.2",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
+ "ms": "^2.1.1",
+ "semver": "^5.6.0"
+ }
+ },
+ "jsprim": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+ "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.2.3",
+ "verror": "1.10.0"
+ }
+ },
+ "jwa": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
+ "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
+ "requires": {
+ "buffer-equal-constant-time": "1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "jws": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
+ "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
+ "requires": {
+ "jwa": "^1.4.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
+ },
+ "lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
+ },
+ "lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
+ },
+ "lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
+ },
+ "lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
+ },
+ "lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
+ },
+ "lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
+ },
+ "mime-db": {
+ "version": "1.40.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+ "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
+ },
+ "mime-types": {
+ "version": "2.1.24",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+ "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+ "requires": {
+ "mime-db": "1.40.0"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
+ },
+ "psl": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz",
+ "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw=="
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
+ },
+ "qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+ },
+ "request": {
+ "version": "2.88.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+ "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.0",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.4.3",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ },
+ "dependencies": {
+ "uuid": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
+ "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
+ }
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
+ "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ },
+ "sshpk": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+ "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "tough-cookie": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+ "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
+ "requires": {
+ "psl": "^1.1.24",
+ "punycode": "^1.4.1"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+ }
+ }
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "uuid": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz",
+ "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho="
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ }
+ }
+ },
+ "node-notifier": {
+ "version": "5.4.3",
+ "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz",
+ "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==",
+ "requires": {
+ "growly": "^1.3.0",
+ "is-wsl": "^1.1.0",
+ "semver": "^5.5.0",
+ "shellwords": "^0.1.1",
+ "which": "^1.3.0"
+ },
+ "dependencies": {
+ "growly": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
+ "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE="
+ },
+ "is-wsl": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0="
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+ },
+ "shellwords": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
+ "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww=="
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
+ "nodemailer": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.3.1.tgz",
+ "integrity": "sha512-j0BsSyaMlyadEDEypK/F+xlne2K5m6wzPYMXS/yxKI0s7jmT1kBx6GEKRVbZmyYfKOsjkeC/TiMVDJBI/w5gMQ=="
+ },
+ "passport": {
+ "version": "0.4.0",
+ "requires": {
+ "passport-strategy": "1.x.x",
+ "pause": "0.0.1"
+ },
+ "dependencies": {
+ "passport-strategy": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "pause": {
+ "version": "0.0.1",
+ "bundled": true
+ }
+ }
+ },
+ "passport-local": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
+ "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=",
+ "requires": {
+ "passport-strategy": "1.x.x"
+ },
+ "dependencies": {
+ "passport-strategy": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
+ "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ="
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.10.tgz",
+ "integrity": "sha1-1NwuUxnpyQ0eccaTkO9izZCCf2U=",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "debuglog": "0.0.2",
+ "string_decoder": "~0.10.x"
+ }
+ },
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+ },
+ "semver": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.1.0.tgz",
+ "integrity": "sha1-hfLPhVBGXE3wAM99hvawVBBqueU="
+ },
+ "session-file-store": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/session-file-store/-/session-file-store-1.3.1.tgz",
+ "integrity": "sha512-6W8N+ziXDoT3oNKqLP+38QMO1CELfWHhn7/G/T/Bj2BXLKnkJCCFqWIb9E50Rr3ENtzuxy3FT9KHy39+skBubg==",
+ "requires": {
+ "bagpipe": "^0.3.5",
+ "fs-extra": "^8.0.1",
+ "object-assign": "^4.1.1",
+ "retry": "^0.12.0",
+ "write-file-atomic": "1.3.1"
+ },
+ "dependencies": {
+ "bagpipe": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/bagpipe/-/bagpipe-0.3.5.tgz",
+ "integrity": "sha1-40HRZPyyTN8E6n4Ft2XsEMiupqE="
+ },
+ "fs-extra": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "requires": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz",
+ "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q=="
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs="
+ },
+ "slide": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
+ "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc="
+ },
+ "universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
+ },
+ "write-file-atomic": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.1.tgz",
+ "integrity": "sha1-fUW6MjFjKN0ex9kPYOvA2EW7dZo=",
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "slide": "^1.1.5"
+ }
+ }
+ }
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+ },
+ "textmagic-rest-client": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/textmagic-rest-client/-/textmagic-rest-client-1.0.10.tgz",
+ "integrity": "sha1-DGj4VZ6rL0ZC8ZtFZA9S1XmTY1Y=",
+ "requires": {
+ "lodash": "^4.17.5"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+ }
+ }
+ },
+ "underscore": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
+ "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg=="
+ },
+ "uuid": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
+ "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
+ },
+ "xml2js": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.1.13.tgz",
+ "integrity": "sha1-Q4/zsdhaUa1ln/wuvoNAPhDJhyI=",
+ "requires": {
+ "sax": ">=0.1.1"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..496fa426
--- /dev/null
+++ b/package.json
@@ -0,0 +1,42 @@
+{
+ "name": "",
+ "version": "",
+ "description": "",
+ "author": "",
+ "scripts": {
+ "start": "node server.js"
+ },
+ "dependencies": {
+ "passport": "^0.4.0",
+ "datatables.net-buttons-dt": "^1.5.6",
+ "datatables.net-dt": "^1.10.19",
+ "jquery": "^3.4.1",
+ "mime": "^2.4.4",
+ "errorhandler": "^1.5.1",
+ "connect": "^3.7.0",
+ "node-notifier": "^5.4.2",
+ "body-parser": "^1.19.0",
+ "cors": "^2.8.5",
+ "express": "^4.16.4",
+ "express-session": "^1.16.1",
+ "morgan": "^1.9.1",
+ "method-override": "^3.0.0",
+ "lowdb": "^1.0.0",
+ "passport-local": "^1.0.0",
+ "express-validator": "^6.2.0",
+ "cookie-parser": "^1.4.4",
+ "session-file-store": "^1.3.1",
+ "uuid": "^3.3.3",
+ "bcryptjs": "^2.4.3",
+ "compression": "^1.7.4",
+ "helmet": "^3.21.0",
+ "jshint": "^2.10.2",
+ "nexmo": "^2.4.2",
+ "nodemailer": "^6.3.1",
+ "textmagic-rest-client": "^1.0.10"
+ },
+ "engines": {
+ "node": "8.x"
+ },
+ "license": "MIT"
+}
\ No newline at end of file
diff --git a/public/css/about.css b/public/css/about.css
new file mode 100644
index 00000000..52256e1c
--- /dev/null
+++ b/public/css/about.css
@@ -0,0 +1,8 @@
+/*!
+ * Start Bootstrap - Shop Item (https://startbootstrap.com/template-overviews/shop-item)
+ * Copyright 2013-2019 Start Bootstrap
+ * Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap-shop-item/blob/master/LICENSE)
+ */
+body {
+ padding-top: 56px;
+}
\ No newline at end of file
diff --git a/public/css/login.css b/public/css/login.css
new file mode 100644
index 00000000..0d8fcccd
--- /dev/null
+++ b/public/css/login.css
@@ -0,0 +1,46 @@
+@import url(https://fonts.googleapis.com/css?family=Raleway:300,400,600);
+
+
+body{
+ margin: 0;
+ font-size: .9rem;
+ font-weight: 400;
+ line-height: 1.6;
+ color: #212529;
+ text-align: left;
+ background-color: #f5f8fa;
+}
+
+.navbar-laravel
+{
+ box-shadow: 0 2px 4px rgba(0,0,0,.04);
+}
+
+.navbar-brand , .nav-link, .my-form, .login-form
+{
+ font-family: Raleway, sans-serif;
+}
+
+.my-form
+{
+ padding-top: 1.5rem;
+ padding-bottom: 1.5rem;
+}
+
+.my-form .row
+{
+ margin-left: 0;
+ margin-right: 0;
+}
+
+.login-form
+{
+ padding-top: 1.5rem;
+ padding-bottom: 1.5rem;
+}
+
+.login-form .row
+{
+ margin-left: 0;
+ margin-right: 0;
+}
\ No newline at end of file
diff --git a/public/css/signUp.css b/public/css/signUp.css
new file mode 100644
index 00000000..8574b2fc
--- /dev/null
+++ b/public/css/signUp.css
@@ -0,0 +1,46 @@
+@import url(https://fonts.googleapis.com/css?family=Raleway:300,400,600);
+
+
+body{
+ margin: 0;
+ font-size: .9rem;
+ font-weight: 400;
+ line-height: 1.6;
+ color: #212529;
+ text-align: left;
+ background-color: #f5f8fa;
+}
+
+.navbar-laravel
+{
+ box-shadow: 0 2px 4px rgba(0,0,0,.04);
+}
+
+.navbar-brand , .nav-link, .my-form, .login-form
+{
+ font-family: Raleway, sans-serif;
+}
+
+.my-form
+{
+ padding-top: 1.5rem;
+ padding-bottom: 1.5rem;
+}
+
+.my-form .row
+{
+ margin-left: 0;
+ margin-right: 0;
+}
+
+.login-form
+{
+ padding-top: 1.5rem;
+ padding-bottom: 1.5rem;
+}
+
+.login-form .row
+{
+ margin-left: 0;
+ margin-right: 0;
+}
\ No newline at end of file
diff --git a/public/css/style.css b/public/css/style.css
new file mode 100644
index 00000000..4a0fd727
--- /dev/null
+++ b/public/css/style.css
@@ -0,0 +1,118 @@
+.jumbotron {
+ padding-top: 3rem;
+ padding-bottom: 3rem;
+ margin-bottom: 0;
+ background-color: #ffa500;
+}
+@media (min-width: 768px) {
+ .jumbotron {
+ padding-top: 6rem;
+ padding-bottom: 6rem;
+ }
+}
+.card{
+ float: left;
+ width: 33.333%
+ padding: .75rem;
+ margin-bottom: 2rem;
+ border: 0;
+}
+
+.card > img (
+ margin-bottom: .75rem;
+ max-width: 100%;
+)
+
+.jumbotron p:last-child {
+ margin-bottom: 0;
+}
+
+.jumbotron-heading {
+ font-weight: 300;
+}
+
+.jumbotron .container {
+ max-width: 40rem;
+}
+
+footer {
+ padding-top: 3rem;
+ padding-bottom: 3rem;
+}
+
+footer p {
+ margin-bottom: .25rem;
+}
+
+
+
+.dg.main.taller-than-window .close-button {
+ border-top: 1px solid #ddd;
+}
+
+.dg.main .close-button {
+ background-color: #ccc;
+}
+
+.dg.main .close-button:hover {
+ background-color: #ddd;
+}
+
+.dg {
+ color: #555;
+ text-shadow: none !important;
+}
+
+.dg.main::-webkit-scrollbar {
+ background: #fafafa;
+}
+
+.dg.main::-webkit-scrollbar-thumb {
+ background: #bbb;
+}
+
+.dg li:not(.folder) {
+ background: #fafafa;
+ border-bottom: 1px solid #ddd;
+}
+
+.dg li.save-row .button {
+ text-shadow: none !important;
+}
+
+.dg li.title {
+ background: #e8e8e8 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;
+}
+
+.dg .cr.function:hover,.dg .cr.boolean:hover {
+ background: #fff;
+}
+
+.dg .c input[type=text] {
+ background: #e9e9e9;
+}
+
+.dg .c input[type=text]:hover {
+ background: #eee;
+}
+
+.dg .c input[type=text]:focus {
+ background: #eee;
+ color: #555;
+}
+
+.dg .c .slider {
+ background: #e9e9e9;
+}
+
+.dg .c .slider:hover {
+ background: #eee;
+}
+
+
+.controls {
+ position: fixed;
+ top: 56px;
+ left: 0;
+ z-index: 10;
+}
\ No newline at end of file
diff --git a/public/css/userInfo.css b/public/css/userInfo.css
new file mode 100644
index 00000000..ea9262cb
--- /dev/null
+++ b/public/css/userInfo.css
@@ -0,0 +1,40 @@
+.jumbotron {
+ padding-top: 3rem;
+ padding-bottom: 3rem;
+ margin-bottom: 0;
+ background-color: #fff;
+}
+@media (min-width: 768px) {
+ .jumbotron {
+ padding-top: 6rem;
+ padding-bottom: 6rem;
+ }
+}
+
+.jumbotron p:last-child {
+ margin-bottom: 0;
+}
+
+.jumbotron-heading {
+ font-weight: 300;
+}
+
+.jumbotron .container {
+ max-width: 40rem;
+}
+.pancake {
+ float: left;
+ width: 33.333%
+ padding: .75rem;
+ margin-bottom: 2rem;
+ border: 0;
+}
+
+footer {
+ padding-top: 3rem;
+ padding-bottom: 3rem;
+}
+
+footer p {
+ margin-bottom: .25rem;
+}
\ No newline at end of file
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 00000000..f78da2b8
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,118 @@
+
+
+
+ CS4241 Assignment 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Welcome to Doughboyz Catering!
+
Flapjacks and Good Snacks.
+
+
+
+
+
+
+
+
+
+

+
+
Our world's famous pancakes. Each order comes in a short stack of three, get them while there hot!
+
+
+
+
+
+
+
+
+

+
+
Obviously not as good as the pancakes but still a great meal to start your day.
+
+
+
+
+
+
+
+
+

+
+
Try our all natural brand new crepes prepared fresh for you by Chef Zeph!
+
+
+
+
+
+
Browse our selection of options then place your order on the "Order" page.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/public/js/GLTFLoader.js b/public/js/GLTFLoader.js
new file mode 100644
index 00000000..c071cec5
--- /dev/null
+++ b/public/js/GLTFLoader.js
@@ -0,0 +1,3214 @@
+/**
+ * @author Rich Tibbett / https://github.com/richtr
+ * @author mrdoob / http://mrdoob.com/
+ * @author Tony Parisi / http://www.tonyparisi.com/
+ * @author Takahiro / https://github.com/takahirox
+ * @author Don McCurdy / https://www.donmccurdy.com
+ */
+
+THREE.GLTFLoader = ( function () {
+
+ function GLTFLoader( manager ) {
+
+ this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
+ this.dracoLoader = null;
+ this.ddsLoader = null;
+
+ }
+
+ GLTFLoader.prototype = {
+
+ constructor: GLTFLoader,
+
+ crossOrigin: 'anonymous',
+
+ load: function ( url, onLoad, onProgress, onError ) {
+
+ var scope = this;
+
+ var resourcePath;
+
+ if ( this.resourcePath !== undefined ) {
+
+ resourcePath = this.resourcePath;
+
+ } else if ( this.path !== undefined ) {
+
+ resourcePath = this.path;
+
+ } else {
+
+ resourcePath = THREE.LoaderUtils.extractUrlBase( url );
+
+ }
+
+ // Tells the LoadingManager to track an extra item, which resolves after
+ // the model is fully loaded. This means the count of items loaded will
+ // be incorrect, but ensures manager.onLoad() does not fire early.
+ scope.manager.itemStart( url );
+
+ var _onError = function ( e ) {
+
+ if ( onError ) {
+
+ onError( e );
+
+ } else {
+
+ console.error( e );
+
+ }
+
+ scope.manager.itemError( url );
+ scope.manager.itemEnd( url );
+
+ };
+
+ var loader = new THREE.FileLoader( scope.manager );
+
+ loader.setPath( this.path );
+ loader.setResponseType( 'arraybuffer' );
+
+ if ( scope.crossOrigin === 'use-credentials' ) {
+
+ loader.setWithCredentials( true );
+
+ }
+
+ loader.load( url, function ( data ) {
+
+ try {
+
+ scope.parse( data, resourcePath, function ( gltf ) {
+
+ onLoad( gltf );
+
+ scope.manager.itemEnd( url );
+
+ }, _onError );
+
+ } catch ( e ) {
+
+ _onError( e );
+
+ }
+
+ }, onProgress, _onError );
+
+ },
+
+ setCrossOrigin: function ( value ) {
+
+ this.crossOrigin = value;
+ return this;
+
+ },
+
+ setPath: function ( value ) {
+
+ this.path = value;
+ return this;
+
+ },
+
+ setResourcePath: function ( value ) {
+
+ this.resourcePath = value;
+ return this;
+
+ },
+
+ setDRACOLoader: function ( dracoLoader ) {
+
+ this.dracoLoader = dracoLoader;
+ return this;
+
+ },
+
+ setDDSLoader: function ( ddsLoader ) {
+
+ this.ddsLoader = ddsLoader;
+ return this;
+
+ },
+
+ parse: function ( data, path, onLoad, onError ) {
+
+ var content;
+ var extensions = {};
+
+ if ( typeof data === 'string' ) {
+
+ content = data;
+
+ } else {
+
+ var magic = THREE.LoaderUtils.decodeText( new Uint8Array( data, 0, 4 ) );
+
+ if ( magic === BINARY_EXTENSION_HEADER_MAGIC ) {
+
+ try {
+
+ extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data );
+
+ } catch ( error ) {
+
+ if ( onError ) onError( error );
+ return;
+
+ }
+
+ content = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content;
+
+ } else {
+
+ content = THREE.LoaderUtils.decodeText( new Uint8Array( data ) );
+
+ }
+
+ }
+
+ var json = JSON.parse( content );
+
+ if ( json.asset === undefined || json.asset.version[ 0 ] < 2 ) {
+
+ if ( onError ) onError( new Error( 'THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported. Use LegacyGLTFLoader instead.' ) );
+ return;
+
+ }
+
+ if ( json.extensionsUsed ) {
+
+ for ( var i = 0; i < json.extensionsUsed.length; ++ i ) {
+
+ var extensionName = json.extensionsUsed[ i ];
+ var extensionsRequired = json.extensionsRequired || [];
+
+ switch ( extensionName ) {
+
+ case EXTENSIONS.KHR_LIGHTS_PUNCTUAL:
+ extensions[ extensionName ] = new GLTFLightsExtension( json );
+ break;
+
+ case EXTENSIONS.KHR_MATERIALS_UNLIT:
+ extensions[ extensionName ] = new GLTFMaterialsUnlitExtension();
+ break;
+
+ case EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:
+ extensions[ extensionName ] = new GLTFMaterialsPbrSpecularGlossinessExtension();
+ break;
+
+ case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:
+ extensions[ extensionName ] = new GLTFDracoMeshCompressionExtension( json, this.dracoLoader );
+ break;
+
+ case EXTENSIONS.MSFT_TEXTURE_DDS:
+ extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] = new GLTFTextureDDSExtension( this.ddsLoader );
+ break;
+
+ case EXTENSIONS.KHR_TEXTURE_TRANSFORM:
+ extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] = new GLTFTextureTransformExtension();
+ break;
+
+ default:
+
+ if ( extensionsRequired.indexOf( extensionName ) >= 0 ) {
+
+ console.warn( 'THREE.GLTFLoader: Unknown extension "' + extensionName + '".' );
+
+ }
+
+ }
+
+ }
+
+ }
+
+ var parser = new GLTFParser( json, extensions, {
+
+ path: path || this.resourcePath || '',
+ crossOrigin: this.crossOrigin,
+ manager: this.manager
+
+ } );
+
+ parser.parse( onLoad, onError );
+
+ }
+
+ };
+
+ /* GLTFREGISTRY */
+
+ function GLTFRegistry() {
+
+ var objects = {};
+
+ return {
+
+ get: function ( key ) {
+
+ return objects[ key ];
+
+ },
+
+ add: function ( key, object ) {
+
+ objects[ key ] = object;
+
+ },
+
+ remove: function ( key ) {
+
+ delete objects[ key ];
+
+ },
+
+ removeAll: function () {
+
+ objects = {};
+
+ }
+
+ };
+
+ }
+
+ /*********************************/
+ /********** EXTENSIONS ***********/
+ /*********************************/
+
+ var EXTENSIONS = {
+ KHR_BINARY_GLTF: 'KHR_binary_glTF',
+ KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',
+ KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
+ KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
+ KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
+ KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',
+ MSFT_TEXTURE_DDS: 'MSFT_texture_dds'
+ };
+
+ /**
+ * DDS Texture Extension
+ *
+ * Specification:
+ * https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_texture_dds
+ *
+ */
+ function GLTFTextureDDSExtension( ddsLoader ) {
+
+ if ( ! ddsLoader ) {
+
+ throw new Error( 'THREE.GLTFLoader: Attempting to load .dds texture without importing THREE.DDSLoader' );
+
+ }
+
+ this.name = EXTENSIONS.MSFT_TEXTURE_DDS;
+ this.ddsLoader = ddsLoader;
+
+ }
+
+ /**
+ * Lights Extension
+ *
+ * Specification: PENDING
+ */
+ function GLTFLightsExtension( json ) {
+
+ this.name = EXTENSIONS.KHR_LIGHTS_PUNCTUAL;
+
+ var extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ] ) || {};
+ this.lightDefs = extension.lights || [];
+
+ }
+
+ GLTFLightsExtension.prototype.loadLight = function ( lightIndex ) {
+
+ var lightDef = this.lightDefs[ lightIndex ];
+ var lightNode;
+
+ var color = new THREE.Color( 0xffffff );
+ if ( lightDef.color !== undefined ) color.fromArray( lightDef.color );
+
+ var range = lightDef.range !== undefined ? lightDef.range : 0;
+
+ switch ( lightDef.type ) {
+
+ case 'directional':
+ lightNode = new THREE.DirectionalLight( color );
+ lightNode.target.position.set( 0, 0, - 1 );
+ lightNode.add( lightNode.target );
+ break;
+
+ case 'point':
+ lightNode = new THREE.PointLight( color );
+ lightNode.distance = range;
+ break;
+
+ case 'spot':
+ lightNode = new THREE.SpotLight( color );
+ lightNode.distance = range;
+ // Handle spotlight properties.
+ lightDef.spot = lightDef.spot || {};
+ lightDef.spot.innerConeAngle = lightDef.spot.innerConeAngle !== undefined ? lightDef.spot.innerConeAngle : 0;
+ lightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== undefined ? lightDef.spot.outerConeAngle : Math.PI / 4.0;
+ lightNode.angle = lightDef.spot.outerConeAngle;
+ lightNode.penumbra = 1.0 - lightDef.spot.innerConeAngle / lightDef.spot.outerConeAngle;
+ lightNode.target.position.set( 0, 0, - 1 );
+ lightNode.add( lightNode.target );
+ break;
+
+ default:
+ throw new Error( 'THREE.GLTFLoader: Unexpected light type, "' + lightDef.type + '".' );
+
+ }
+
+ // Some lights (e.g. spot) default to a position other than the origin. Reset the position
+ // here, because node-level parsing will only override position if explicitly specified.
+ lightNode.position.set( 0, 0, 0 );
+
+ lightNode.decay = 2;
+
+ if ( lightDef.intensity !== undefined ) lightNode.intensity = lightDef.intensity;
+
+ lightNode.name = lightDef.name || ( 'light_' + lightIndex );
+
+ return Promise.resolve( lightNode );
+
+ };
+
+ /**
+ * Unlit Materials Extension (pending)
+ *
+ * PR: https://github.com/KhronosGroup/glTF/pull/1163
+ */
+ function GLTFMaterialsUnlitExtension() {
+
+ this.name = EXTENSIONS.KHR_MATERIALS_UNLIT;
+
+ }
+
+ GLTFMaterialsUnlitExtension.prototype.getMaterialType = function () {
+
+ return THREE.MeshBasicMaterial;
+
+ };
+
+ GLTFMaterialsUnlitExtension.prototype.extendParams = function ( materialParams, materialDef, parser ) {
+
+ var pending = [];
+
+ materialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );
+ materialParams.opacity = 1.0;
+
+ var metallicRoughness = materialDef.pbrMetallicRoughness;
+
+ if ( metallicRoughness ) {
+
+ if ( Array.isArray( metallicRoughness.baseColorFactor ) ) {
+
+ var array = metallicRoughness.baseColorFactor;
+
+ materialParams.color.fromArray( array );
+ materialParams.opacity = array[ 3 ];
+
+ }
+
+ if ( metallicRoughness.baseColorTexture !== undefined ) {
+
+ pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture ) );
+
+ }
+
+ }
+
+ return Promise.all( pending );
+
+ };
+
+ /* BINARY EXTENSION */
+ var BINARY_EXTENSION_HEADER_MAGIC = 'glTF';
+ var BINARY_EXTENSION_HEADER_LENGTH = 12;
+ var BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4E4F534A, BIN: 0x004E4942 };
+
+ function GLTFBinaryExtension( data ) {
+
+ this.name = EXTENSIONS.KHR_BINARY_GLTF;
+ this.content = null;
+ this.body = null;
+
+ var headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH );
+
+ this.header = {
+ magic: THREE.LoaderUtils.decodeText( new Uint8Array( data.slice( 0, 4 ) ) ),
+ version: headerView.getUint32( 4, true ),
+ length: headerView.getUint32( 8, true )
+ };
+
+ if ( this.header.magic !== BINARY_EXTENSION_HEADER_MAGIC ) {
+
+ throw new Error( 'THREE.GLTFLoader: Unsupported glTF-Binary header.' );
+
+ } else if ( this.header.version < 2.0 ) {
+
+ throw new Error( 'THREE.GLTFLoader: Legacy binary file detected. Use LegacyGLTFLoader instead.' );
+
+ }
+
+ var chunkView = new DataView( data, BINARY_EXTENSION_HEADER_LENGTH );
+ var chunkIndex = 0;
+
+ while ( chunkIndex < chunkView.byteLength ) {
+
+ var chunkLength = chunkView.getUint32( chunkIndex, true );
+ chunkIndex += 4;
+
+ var chunkType = chunkView.getUint32( chunkIndex, true );
+ chunkIndex += 4;
+
+ if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON ) {
+
+ var contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength );
+ this.content = THREE.LoaderUtils.decodeText( contentArray );
+
+ } else if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN ) {
+
+ var byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex;
+ this.body = data.slice( byteOffset, byteOffset + chunkLength );
+
+ }
+
+ // Clients must ignore chunks with unknown types.
+
+ chunkIndex += chunkLength;
+
+ }
+
+ if ( this.content === null ) {
+
+ throw new Error( 'THREE.GLTFLoader: JSON content not found.' );
+
+ }
+
+ }
+
+ /**
+ * DRACO Mesh Compression Extension
+ *
+ * Specification: https://github.com/KhronosGroup/glTF/pull/874
+ */
+ function GLTFDracoMeshCompressionExtension( json, dracoLoader ) {
+
+ if ( ! dracoLoader ) {
+
+ throw new Error( 'THREE.GLTFLoader: No DRACOLoader instance provided.' );
+
+ }
+
+ this.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION;
+ this.json = json;
+ this.dracoLoader = dracoLoader;
+
+ }
+
+ GLTFDracoMeshCompressionExtension.prototype.decodePrimitive = function ( primitive, parser ) {
+
+ var json = this.json;
+ var dracoLoader = this.dracoLoader;
+ var bufferViewIndex = primitive.extensions[ this.name ].bufferView;
+ var gltfAttributeMap = primitive.extensions[ this.name ].attributes;
+ var threeAttributeMap = {};
+ var attributeNormalizedMap = {};
+ var attributeTypeMap = {};
+
+ for ( var attributeName in gltfAttributeMap ) {
+
+ var threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();
+
+ threeAttributeMap[ threeAttributeName ] = gltfAttributeMap[ attributeName ];
+
+ }
+
+ for ( attributeName in primitive.attributes ) {
+
+ var threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();
+
+ if ( gltfAttributeMap[ attributeName ] !== undefined ) {
+
+ var accessorDef = json.accessors[ primitive.attributes[ attributeName ] ];
+ var componentType = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];
+
+ attributeTypeMap[ threeAttributeName ] = componentType;
+ attributeNormalizedMap[ threeAttributeName ] = accessorDef.normalized === true;
+
+ }
+
+ }
+
+ return parser.getDependency( 'bufferView', bufferViewIndex ).then( function ( bufferView ) {
+
+ return new Promise( function ( resolve ) {
+
+ dracoLoader.decodeDracoFile( bufferView, function ( geometry ) {
+
+ for ( var attributeName in geometry.attributes ) {
+
+ var attribute = geometry.attributes[ attributeName ];
+ var normalized = attributeNormalizedMap[ attributeName ];
+
+ if ( normalized !== undefined ) attribute.normalized = normalized;
+
+ }
+
+ resolve( geometry );
+
+ }, threeAttributeMap, attributeTypeMap );
+
+ } );
+
+ } );
+
+ };
+
+ /**
+ * Texture Transform Extension
+ *
+ * Specification:
+ */
+ function GLTFTextureTransformExtension() {
+
+ this.name = EXTENSIONS.KHR_TEXTURE_TRANSFORM;
+
+ }
+
+ GLTFTextureTransformExtension.prototype.extendTexture = function ( texture, transform ) {
+
+ texture = texture.clone();
+
+ if ( transform.offset !== undefined ) {
+
+ texture.offset.fromArray( transform.offset );
+
+ }
+
+ if ( transform.rotation !== undefined ) {
+
+ texture.rotation = transform.rotation;
+
+ }
+
+ if ( transform.scale !== undefined ) {
+
+ texture.repeat.fromArray( transform.scale );
+
+ }
+
+ if ( transform.texCoord !== undefined ) {
+
+ console.warn( 'THREE.GLTFLoader: Custom UV sets in "' + this.name + '" extension not yet supported.' );
+
+ }
+
+ texture.needsUpdate = true;
+
+ return texture;
+
+ };
+
+ /**
+ * Specular-Glossiness Extension
+ *
+ * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness
+ */
+ function GLTFMaterialsPbrSpecularGlossinessExtension() {
+
+ return {
+
+ name: EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS,
+
+ specularGlossinessParams: [
+ 'color',
+ 'map',
+ 'lightMap',
+ 'lightMapIntensity',
+ 'aoMap',
+ 'aoMapIntensity',
+ 'emissive',
+ 'emissiveIntensity',
+ 'emissiveMap',
+ 'bumpMap',
+ 'bumpScale',
+ 'normalMap',
+ 'displacementMap',
+ 'displacementScale',
+ 'displacementBias',
+ 'specularMap',
+ 'specular',
+ 'glossinessMap',
+ 'glossiness',
+ 'alphaMap',
+ 'envMap',
+ 'envMapIntensity',
+ 'refractionRatio',
+ ],
+
+ getMaterialType: function () {
+
+ return THREE.ShaderMaterial;
+
+ },
+
+ extendParams: function ( materialParams, materialDef, parser ) {
+
+ var pbrSpecularGlossiness = materialDef.extensions[ this.name ];
+
+ var shader = THREE.ShaderLib[ 'standard' ];
+
+ var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
+
+ var specularMapParsFragmentChunk = [
+ '#ifdef USE_SPECULARMAP',
+ ' uniform sampler2D specularMap;',
+ '#endif'
+ ].join( '\n' );
+
+ var glossinessMapParsFragmentChunk = [
+ '#ifdef USE_GLOSSINESSMAP',
+ ' uniform sampler2D glossinessMap;',
+ '#endif'
+ ].join( '\n' );
+
+ var specularMapFragmentChunk = [
+ 'vec3 specularFactor = specular;',
+ '#ifdef USE_SPECULARMAP',
+ ' vec4 texelSpecular = texture2D( specularMap, vUv );',
+ ' texelSpecular = sRGBToLinear( texelSpecular );',
+ ' // reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture',
+ ' specularFactor *= texelSpecular.rgb;',
+ '#endif'
+ ].join( '\n' );
+
+ var glossinessMapFragmentChunk = [
+ 'float glossinessFactor = glossiness;',
+ '#ifdef USE_GLOSSINESSMAP',
+ ' vec4 texelGlossiness = texture2D( glossinessMap, vUv );',
+ ' // reads channel A, compatible with a glTF Specular-Glossiness (RGBA) texture',
+ ' glossinessFactor *= texelGlossiness.a;',
+ '#endif'
+ ].join( '\n' );
+
+ var lightPhysicalFragmentChunk = [
+ 'PhysicalMaterial material;',
+ 'material.diffuseColor = diffuseColor.rgb;',
+ 'material.specularRoughness = clamp( 1.0 - glossinessFactor, 0.04, 1.0 );',
+ 'material.specularColor = specularFactor.rgb;',
+ ].join( '\n' );
+
+ var fragmentShader = shader.fragmentShader
+ .replace( 'uniform float roughness;', 'uniform vec3 specular;' )
+ .replace( 'uniform float metalness;', 'uniform float glossiness;' )
+ .replace( '#include ', specularMapParsFragmentChunk )
+ .replace( '#include ', glossinessMapParsFragmentChunk )
+ .replace( '#include ', specularMapFragmentChunk )
+ .replace( '#include ', glossinessMapFragmentChunk )
+ .replace( '#include ', lightPhysicalFragmentChunk );
+
+ delete uniforms.roughness;
+ delete uniforms.metalness;
+ delete uniforms.roughnessMap;
+ delete uniforms.metalnessMap;
+
+ uniforms.specular = { value: new THREE.Color().setHex( 0x111111 ) };
+ uniforms.glossiness = { value: 0.5 };
+ uniforms.specularMap = { value: null };
+ uniforms.glossinessMap = { value: null };
+
+ materialParams.vertexShader = shader.vertexShader;
+ materialParams.fragmentShader = fragmentShader;
+ materialParams.uniforms = uniforms;
+ materialParams.defines = { 'STANDARD': '' }
+
+ materialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );
+ materialParams.opacity = 1.0;
+
+ var pending = [];
+
+ if ( Array.isArray( pbrSpecularGlossiness.diffuseFactor ) ) {
+
+ var array = pbrSpecularGlossiness.diffuseFactor;
+
+ materialParams.color.fromArray( array );
+ materialParams.opacity = array[ 3 ];
+
+ }
+
+ if ( pbrSpecularGlossiness.diffuseTexture !== undefined ) {
+
+ pending.push( parser.assignTexture( materialParams, 'map', pbrSpecularGlossiness.diffuseTexture ) );
+
+ }
+
+ materialParams.emissive = new THREE.Color( 0.0, 0.0, 0.0 );
+ materialParams.glossiness = pbrSpecularGlossiness.glossinessFactor !== undefined ? pbrSpecularGlossiness.glossinessFactor : 1.0;
+ materialParams.specular = new THREE.Color( 1.0, 1.0, 1.0 );
+
+ if ( Array.isArray( pbrSpecularGlossiness.specularFactor ) ) {
+
+ materialParams.specular.fromArray( pbrSpecularGlossiness.specularFactor );
+
+ }
+
+ if ( pbrSpecularGlossiness.specularGlossinessTexture !== undefined ) {
+
+ var specGlossMapDef = pbrSpecularGlossiness.specularGlossinessTexture;
+ pending.push( parser.assignTexture( materialParams, 'glossinessMap', specGlossMapDef ) );
+ pending.push( parser.assignTexture( materialParams, 'specularMap', specGlossMapDef ) );
+
+ }
+
+ return Promise.all( pending );
+
+ },
+
+ createMaterial: function ( params ) {
+
+ // setup material properties based on MeshStandardMaterial for Specular-Glossiness
+
+ var material = new THREE.ShaderMaterial( {
+ defines: params.defines,
+ vertexShader: params.vertexShader,
+ fragmentShader: params.fragmentShader,
+ uniforms: params.uniforms,
+ fog: true,
+ lights: true,
+ opacity: params.opacity,
+ transparent: params.transparent
+ } );
+
+ material.isGLTFSpecularGlossinessMaterial = true;
+
+ material.color = params.color;
+
+ material.map = params.map === undefined ? null : params.map;
+
+ material.lightMap = null;
+ material.lightMapIntensity = 1.0;
+
+ material.aoMap = params.aoMap === undefined ? null : params.aoMap;
+ material.aoMapIntensity = 1.0;
+
+ material.emissive = params.emissive;
+ material.emissiveIntensity = 1.0;
+ material.emissiveMap = params.emissiveMap === undefined ? null : params.emissiveMap;
+
+ material.bumpMap = params.bumpMap === undefined ? null : params.bumpMap;
+ material.bumpScale = 1;
+
+ material.normalMap = params.normalMap === undefined ? null : params.normalMap;
+
+ if ( params.normalScale ) material.normalScale = params.normalScale;
+
+ material.displacementMap = null;
+ material.displacementScale = 1;
+ material.displacementBias = 0;
+
+ material.specularMap = params.specularMap === undefined ? null : params.specularMap;
+ material.specular = params.specular;
+
+ material.glossinessMap = params.glossinessMap === undefined ? null : params.glossinessMap;
+ material.glossiness = params.glossiness;
+
+ material.alphaMap = null;
+
+ material.envMap = params.envMap === undefined ? null : params.envMap;
+ material.envMapIntensity = 1.0;
+
+ material.refractionRatio = 0.98;
+
+ material.extensions.derivatives = true;
+
+ return material;
+
+ },
+
+ /**
+ * Clones a GLTFSpecularGlossinessMaterial instance. The ShaderMaterial.copy() method can
+ * copy only properties it knows about or inherits, and misses many properties that would
+ * normally be defined by MeshStandardMaterial.
+ *
+ * This method allows GLTFSpecularGlossinessMaterials to be cloned in the process of
+ * loading a glTF model, but cloning later (e.g. by the user) would require these changes
+ * AND also updating `.onBeforeRender` on the parent mesh.
+ *
+ * @param {THREE.ShaderMaterial} source
+ * @return {THREE.ShaderMaterial}
+ */
+ cloneMaterial: function ( source ) {
+
+ var target = source.clone();
+
+ target.isGLTFSpecularGlossinessMaterial = true;
+
+ var params = this.specularGlossinessParams;
+
+ for ( var i = 0, il = params.length; i < il; i ++ ) {
+
+ var value = source[ params[ i ] ];
+ target[ params[ i ] ] = ( value && value.isColor ) ? value.clone() : value;
+
+ }
+
+ return target;
+
+ },
+
+ // Here's based on refreshUniformsCommon() and refreshUniformsStandard() in WebGLRenderer.
+ refreshUniforms: function ( renderer, scene, camera, geometry, material ) {
+
+ if ( material.isGLTFSpecularGlossinessMaterial !== true ) {
+
+ return;
+
+ }
+
+ var uniforms = material.uniforms;
+ var defines = material.defines;
+
+ uniforms.opacity.value = material.opacity;
+
+ uniforms.diffuse.value.copy( material.color );
+ uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
+
+ uniforms.map.value = material.map;
+ uniforms.specularMap.value = material.specularMap;
+ uniforms.alphaMap.value = material.alphaMap;
+
+ uniforms.lightMap.value = material.lightMap;
+ uniforms.lightMapIntensity.value = material.lightMapIntensity;
+
+ uniforms.aoMap.value = material.aoMap;
+ uniforms.aoMapIntensity.value = material.aoMapIntensity;
+
+ // uv repeat and offset setting priorities
+ // 1. color map
+ // 2. specular map
+ // 3. normal map
+ // 4. bump map
+ // 5. alpha map
+ // 6. emissive map
+
+ var uvScaleMap;
+
+ if ( material.map ) {
+
+ uvScaleMap = material.map;
+
+ } else if ( material.specularMap ) {
+
+ uvScaleMap = material.specularMap;
+
+ } else if ( material.displacementMap ) {
+
+ uvScaleMap = material.displacementMap;
+
+ } else if ( material.normalMap ) {
+
+ uvScaleMap = material.normalMap;
+
+ } else if ( material.bumpMap ) {
+
+ uvScaleMap = material.bumpMap;
+
+ } else if ( material.glossinessMap ) {
+
+ uvScaleMap = material.glossinessMap;
+
+ } else if ( material.alphaMap ) {
+
+ uvScaleMap = material.alphaMap;
+
+ } else if ( material.emissiveMap ) {
+
+ uvScaleMap = material.emissiveMap;
+
+ }
+
+ if ( uvScaleMap !== undefined ) {
+
+ // backwards compatibility
+ if ( uvScaleMap.isWebGLRenderTarget ) {
+
+ uvScaleMap = uvScaleMap.texture;
+
+ }
+
+ if ( uvScaleMap.matrixAutoUpdate === true ) {
+
+ uvScaleMap.updateMatrix();
+
+ }
+
+ uniforms.uvTransform.value.copy( uvScaleMap.matrix );
+
+ }
+
+ if ( material.envMap ) {
+
+ uniforms.envMap.value = material.envMap;
+ uniforms.envMapIntensity.value = material.envMapIntensity;
+
+ // don't flip CubeTexture envMaps, flip everything else:
+ // WebGLRenderTargetCube will be flipped for backwards compatibility
+ // WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture
+ // this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future
+ uniforms.flipEnvMap.value = material.envMap.isCubeTexture ? - 1 : 1;
+
+ uniforms.reflectivity.value = material.reflectivity;
+ uniforms.refractionRatio.value = material.refractionRatio;
+
+ uniforms.maxMipLevel.value = renderer.properties.get( material.envMap ).__maxMipLevel;
+
+ }
+
+ uniforms.specular.value.copy( material.specular );
+ uniforms.glossiness.value = material.glossiness;
+
+ uniforms.glossinessMap.value = material.glossinessMap;
+
+ uniforms.emissiveMap.value = material.emissiveMap;
+ uniforms.bumpMap.value = material.bumpMap;
+ uniforms.normalMap.value = material.normalMap;
+
+ uniforms.displacementMap.value = material.displacementMap;
+ uniforms.displacementScale.value = material.displacementScale;
+ uniforms.displacementBias.value = material.displacementBias;
+
+ if ( uniforms.glossinessMap.value !== null && defines.USE_GLOSSINESSMAP === undefined ) {
+
+ defines.USE_GLOSSINESSMAP = '';
+ // set USE_ROUGHNESSMAP to enable vUv
+ defines.USE_ROUGHNESSMAP = '';
+
+ }
+
+ if ( uniforms.glossinessMap.value === null && defines.USE_GLOSSINESSMAP !== undefined ) {
+
+ delete defines.USE_GLOSSINESSMAP;
+ delete defines.USE_ROUGHNESSMAP;
+
+ }
+
+ }
+
+ };
+
+ }
+
+ /*********************************/
+ /********** INTERPOLATION ********/
+ /*********************************/
+
+ // Spline Interpolation
+ // Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#appendix-c-spline-interpolation
+ function GLTFCubicSplineInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
+
+ THREE.Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
+
+ }
+
+ GLTFCubicSplineInterpolant.prototype = Object.create( THREE.Interpolant.prototype );
+ GLTFCubicSplineInterpolant.prototype.constructor = GLTFCubicSplineInterpolant;
+
+ GLTFCubicSplineInterpolant.prototype.copySampleValue_ = function ( index ) {
+
+ // Copies a sample value to the result buffer. See description of glTF
+ // CUBICSPLINE values layout in interpolate_() function below.
+
+ var result = this.resultBuffer,
+ values = this.sampleValues,
+ valueSize = this.valueSize,
+ offset = index * valueSize * 3 + valueSize;
+
+ for ( var i = 0; i !== valueSize; i ++ ) {
+
+ result[ i ] = values[ offset + i ];
+
+ }
+
+ return result;
+
+ };
+
+ GLTFCubicSplineInterpolant.prototype.beforeStart_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_;
+
+ GLTFCubicSplineInterpolant.prototype.afterEnd_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_;
+
+ GLTFCubicSplineInterpolant.prototype.interpolate_ = function ( i1, t0, t, t1 ) {
+
+ var result = this.resultBuffer;
+ var values = this.sampleValues;
+ var stride = this.valueSize;
+
+ var stride2 = stride * 2;
+ var stride3 = stride * 3;
+
+ var td = t1 - t0;
+
+ var p = ( t - t0 ) / td;
+ var pp = p * p;
+ var ppp = pp * p;
+
+ var offset1 = i1 * stride3;
+ var offset0 = offset1 - stride3;
+
+ var s2 = - 2 * ppp + 3 * pp;
+ var s3 = ppp - pp;
+ var s0 = 1 - s2;
+ var s1 = s3 - pp + p;
+
+ // Layout of keyframe output values for CUBICSPLINE animations:
+ // [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2, splineVertex_2, ... ]
+ for ( var i = 0; i !== stride; i ++ ) {
+
+ var p0 = values[ offset0 + i + stride ]; // splineVertex_k
+ var m0 = values[ offset0 + i + stride2 ] * td; // outTangent_k * (t_k+1 - t_k)
+ var p1 = values[ offset1 + i + stride ]; // splineVertex_k+1
+ var m1 = values[ offset1 + i ] * td; // inTangent_k+1 * (t_k+1 - t_k)
+
+ result[ i ] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1;
+
+ }
+
+ return result;
+
+ };
+
+ /*********************************/
+ /********** INTERNALS ************/
+ /*********************************/
+
+ /* CONSTANTS */
+
+ var WEBGL_CONSTANTS = {
+ FLOAT: 5126,
+ //FLOAT_MAT2: 35674,
+ FLOAT_MAT3: 35675,
+ FLOAT_MAT4: 35676,
+ FLOAT_VEC2: 35664,
+ FLOAT_VEC3: 35665,
+ FLOAT_VEC4: 35666,
+ LINEAR: 9729,
+ REPEAT: 10497,
+ SAMPLER_2D: 35678,
+ POINTS: 0,
+ LINES: 1,
+ LINE_LOOP: 2,
+ LINE_STRIP: 3,
+ TRIANGLES: 4,
+ TRIANGLE_STRIP: 5,
+ TRIANGLE_FAN: 6,
+ UNSIGNED_BYTE: 5121,
+ UNSIGNED_SHORT: 5123
+ };
+
+ var WEBGL_COMPONENT_TYPES = {
+ 5120: Int8Array,
+ 5121: Uint8Array,
+ 5122: Int16Array,
+ 5123: Uint16Array,
+ 5125: Uint32Array,
+ 5126: Float32Array
+ };
+
+ var WEBGL_FILTERS = {
+ 9728: THREE.NearestFilter,
+ 9729: THREE.LinearFilter,
+ 9984: THREE.NearestMipmapNearestFilter,
+ 9985: THREE.LinearMipmapNearestFilter,
+ 9986: THREE.NearestMipmapLinearFilter,
+ 9987: THREE.LinearMipmapLinearFilter
+ };
+
+ var WEBGL_WRAPPINGS = {
+ 33071: THREE.ClampToEdgeWrapping,
+ 33648: THREE.MirroredRepeatWrapping,
+ 10497: THREE.RepeatWrapping
+ };
+
+ var WEBGL_TYPE_SIZES = {
+ 'SCALAR': 1,
+ 'VEC2': 2,
+ 'VEC3': 3,
+ 'VEC4': 4,
+ 'MAT2': 4,
+ 'MAT3': 9,
+ 'MAT4': 16
+ };
+
+ var ATTRIBUTES = {
+ POSITION: 'position',
+ NORMAL: 'normal',
+ TANGENT: 'tangent',
+ TEXCOORD_0: 'uv',
+ TEXCOORD_1: 'uv2',
+ COLOR_0: 'color',
+ WEIGHTS_0: 'skinWeight',
+ JOINTS_0: 'skinIndex',
+ };
+
+ var PATH_PROPERTIES = {
+ scale: 'scale',
+ translation: 'position',
+ rotation: 'quaternion',
+ weights: 'morphTargetInfluences'
+ };
+
+ var INTERPOLATION = {
+ CUBICSPLINE: undefined, // We use a custom interpolant (GLTFCubicSplineInterpolation) for CUBICSPLINE tracks. Each
+ // keyframe track will be initialized with a default interpolation type, then modified.
+ LINEAR: THREE.InterpolateLinear,
+ STEP: THREE.InterpolateDiscrete
+ };
+
+ var ALPHA_MODES = {
+ OPAQUE: 'OPAQUE',
+ MASK: 'MASK',
+ BLEND: 'BLEND'
+ };
+
+ var MIME_TYPE_FORMATS = {
+ 'image/png': THREE.RGBAFormat,
+ 'image/jpeg': THREE.RGBFormat
+ };
+
+ /* UTILITY FUNCTIONS */
+
+ function resolveURL( url, path ) {
+
+ // Invalid URL
+ if ( typeof url !== 'string' || url === '' ) return '';
+
+ // Host Relative URL
+ if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) {
+
+ path = path.replace( /(^https?:\/\/[^\/]+).*/i , '$1' );
+
+ }
+
+ // Absolute URL http://,https://,//
+ if ( /^(https?:)?\/\//i.test( url ) ) return url;
+
+ // Data URI
+ if ( /^data:.*,.*$/i.test( url ) ) return url;
+
+ // Blob URL
+ if ( /^blob:.*$/i.test( url ) ) return url;
+
+ // Relative URL
+ return path + url;
+
+ }
+
+ var defaultMaterial;
+
+ /**
+ * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material
+ */
+ function createDefaultMaterial() {
+
+ defaultMaterial = defaultMaterial || new THREE.MeshStandardMaterial( {
+ color: 0xFFFFFF,
+ emissive: 0x000000,
+ metalness: 1,
+ roughness: 1,
+ transparent: false,
+ depthTest: true,
+ side: THREE.FrontSide
+ } );
+
+ return defaultMaterial;
+
+ }
+
+ function addUnknownExtensionsToUserData( knownExtensions, object, objectDef ) {
+
+ // Add unknown glTF extensions to an object's userData.
+
+ for ( var name in objectDef.extensions ) {
+
+ if ( knownExtensions[ name ] === undefined ) {
+
+ object.userData.gltfExtensions = object.userData.gltfExtensions || {};
+ object.userData.gltfExtensions[ name ] = objectDef.extensions[ name ];
+
+ }
+
+ }
+
+ }
+
+ /**
+ * @param {THREE.Object3D|THREE.Material|THREE.BufferGeometry} object
+ * @param {GLTF.definition} gltfDef
+ */
+ function assignExtrasToUserData( object, gltfDef ) {
+
+ if ( gltfDef.extras !== undefined ) {
+
+ if ( typeof gltfDef.extras === 'object' ) {
+
+ Object.assign( object.userData, gltfDef.extras );
+
+ } else {
+
+ console.warn( 'THREE.GLTFLoader: Ignoring primitive type .extras, ' + gltfDef.extras );
+
+ }
+
+ }
+
+ }
+
+ /**
+ * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets
+ *
+ * @param {THREE.BufferGeometry} geometry
+ * @param {Array} targets
+ * @param {GLTFParser} parser
+ * @return {Promise}
+ */
+ function addMorphTargets( geometry, targets, parser ) {
+
+ var hasMorphPosition = false;
+ var hasMorphNormal = false;
+
+ for ( var i = 0, il = targets.length; i < il; i ++ ) {
+
+ var target = targets[ i ];
+
+ if ( target.POSITION !== undefined ) hasMorphPosition = true;
+ if ( target.NORMAL !== undefined ) hasMorphNormal = true;
+
+ if ( hasMorphPosition && hasMorphNormal ) break;
+
+ }
+
+ if ( ! hasMorphPosition && ! hasMorphNormal ) return Promise.resolve( geometry );
+
+ var pendingPositionAccessors = [];
+ var pendingNormalAccessors = [];
+
+ for ( var i = 0, il = targets.length; i < il; i ++ ) {
+
+ var target = targets[ i ];
+
+ if ( hasMorphPosition ) {
+
+ var pendingAccessor = target.POSITION !== undefined
+ ? parser.getDependency( 'accessor', target.POSITION )
+ : geometry.attributes.position;
+
+ pendingPositionAccessors.push( pendingAccessor );
+
+ }
+
+ if ( hasMorphNormal ) {
+
+ var pendingAccessor = target.NORMAL !== undefined
+ ? parser.getDependency( 'accessor', target.NORMAL )
+ : geometry.attributes.normal;
+
+ pendingNormalAccessors.push( pendingAccessor );
+
+ }
+
+ }
+
+ return Promise.all( [
+ Promise.all( pendingPositionAccessors ),
+ Promise.all( pendingNormalAccessors )
+ ] ).then( function ( accessors ) {
+
+ var morphPositions = accessors[ 0 ];
+ var morphNormals = accessors[ 1 ];
+
+ // Clone morph target accessors before modifying them.
+
+ for ( var i = 0, il = morphPositions.length; i < il; i ++ ) {
+
+ if ( geometry.attributes.position === morphPositions[ i ] ) continue;
+
+ morphPositions[ i ] = cloneBufferAttribute( morphPositions[ i ] );
+
+ }
+
+ for ( var i = 0, il = morphNormals.length; i < il; i ++ ) {
+
+ if ( geometry.attributes.normal === morphNormals[ i ] ) continue;
+
+ morphNormals[ i ] = cloneBufferAttribute( morphNormals[ i ] );
+
+ }
+
+ for ( var i = 0, il = targets.length; i < il; i ++ ) {
+
+ var target = targets[ i ];
+ var attributeName = 'morphTarget' + i;
+
+ if ( hasMorphPosition ) {
+
+ // Three.js morph position is absolute value. The formula is
+ // basePosition
+ // + weight0 * ( morphPosition0 - basePosition )
+ // + weight1 * ( morphPosition1 - basePosition )
+ // ...
+ // while the glTF one is relative
+ // basePosition
+ // + weight0 * glTFmorphPosition0
+ // + weight1 * glTFmorphPosition1
+ // ...
+ // then we need to convert from relative to absolute here.
+
+ if ( target.POSITION !== undefined ) {
+
+ var positionAttribute = morphPositions[ i ];
+ positionAttribute.name = attributeName;
+
+ var position = geometry.attributes.position;
+
+ for ( var j = 0, jl = positionAttribute.count; j < jl; j ++ ) {
+
+ positionAttribute.setXYZ(
+ j,
+ positionAttribute.getX( j ) + position.getX( j ),
+ positionAttribute.getY( j ) + position.getY( j ),
+ positionAttribute.getZ( j ) + position.getZ( j )
+ );
+
+ }
+
+ }
+
+ }
+
+ if ( hasMorphNormal ) {
+
+ // see target.POSITION's comment
+
+ if ( target.NORMAL !== undefined ) {
+
+ var normalAttribute = morphNormals[ i ];
+ normalAttribute.name = attributeName;
+
+ var normal = geometry.attributes.normal;
+
+ for ( var j = 0, jl = normalAttribute.count; j < jl; j ++ ) {
+
+ normalAttribute.setXYZ(
+ j,
+ normalAttribute.getX( j ) + normal.getX( j ),
+ normalAttribute.getY( j ) + normal.getY( j ),
+ normalAttribute.getZ( j ) + normal.getZ( j )
+ );
+
+ }
+
+ }
+
+ }
+
+ }
+
+ if ( hasMorphPosition ) geometry.morphAttributes.position = morphPositions;
+ if ( hasMorphNormal ) geometry.morphAttributes.normal = morphNormals;
+
+ return geometry;
+
+ } );
+
+ }
+
+ /**
+ * @param {THREE.Mesh} mesh
+ * @param {GLTF.Mesh} meshDef
+ */
+ function updateMorphTargets( mesh, meshDef ) {
+
+ mesh.updateMorphTargets();
+
+ if ( meshDef.weights !== undefined ) {
+
+ for ( var i = 0, il = meshDef.weights.length; i < il; i ++ ) {
+
+ mesh.morphTargetInfluences[ i ] = meshDef.weights[ i ];
+
+ }
+
+ }
+
+ // .extras has user-defined data, so check that .extras.targetNames is an array.
+ if ( meshDef.extras && Array.isArray( meshDef.extras.targetNames ) ) {
+
+ var targetNames = meshDef.extras.targetNames;
+
+ if ( mesh.morphTargetInfluences.length === targetNames.length ) {
+
+ mesh.morphTargetDictionary = {};
+
+ for ( var i = 0, il = targetNames.length; i < il; i ++ ) {
+
+ mesh.morphTargetDictionary[ targetNames[ i ] ] = i;
+
+ }
+
+ } else {
+
+ console.warn( 'THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.' );
+
+ }
+
+ }
+
+ }
+
+ function createPrimitiveKey( primitiveDef ) {
+
+ var dracoExtension = primitiveDef.extensions && primitiveDef.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ];
+ var geometryKey;
+
+ if ( dracoExtension ) {
+
+ geometryKey = 'draco:' + dracoExtension.bufferView
+ + ':' + dracoExtension.indices
+ + ':' + createAttributesKey( dracoExtension.attributes );
+
+ } else {
+
+ geometryKey = primitiveDef.indices + ':' + createAttributesKey( primitiveDef.attributes ) + ':' + primitiveDef.mode;
+
+ }
+
+ return geometryKey;
+
+ }
+
+ function createAttributesKey( attributes ) {
+
+ var attributesKey = '';
+
+ var keys = Object.keys( attributes ).sort();
+
+ for ( var i = 0, il = keys.length; i < il; i ++ ) {
+
+ attributesKey += keys[ i ] + ':' + attributes[ keys[ i ] ] + ';';
+
+ }
+
+ return attributesKey;
+
+ }
+
+ function cloneBufferAttribute( attribute ) {
+
+ if ( attribute.isInterleavedBufferAttribute ) {
+
+ var count = attribute.count;
+ var itemSize = attribute.itemSize;
+ var array = attribute.array.slice( 0, count * itemSize );
+
+ for ( var i = 0, j = 0; i < count; ++ i ) {
+
+ array[ j ++ ] = attribute.getX( i );
+ if ( itemSize >= 2 ) array[ j ++ ] = attribute.getY( i );
+ if ( itemSize >= 3 ) array[ j ++ ] = attribute.getZ( i );
+ if ( itemSize >= 4 ) array[ j ++ ] = attribute.getW( i );
+
+ }
+
+ return new THREE.BufferAttribute( array, itemSize, attribute.normalized );
+
+ }
+
+ return attribute.clone();
+
+ }
+
+ /* GLTF PARSER */
+
+ function GLTFParser( json, extensions, options ) {
+
+ this.json = json || {};
+ this.extensions = extensions || {};
+ this.options = options || {};
+
+ // loader object cache
+ this.cache = new GLTFRegistry();
+
+ // BufferGeometry caching
+ this.primitiveCache = {};
+
+ this.textureLoader = new THREE.TextureLoader( this.options.manager );
+ this.textureLoader.setCrossOrigin( this.options.crossOrigin );
+
+ this.fileLoader = new THREE.FileLoader( this.options.manager );
+ this.fileLoader.setResponseType( 'arraybuffer' );
+
+ if ( this.options.crossOrigin === 'use-credentials' ) {
+
+ this.fileLoader.setWithCredentials( true );
+
+ }
+
+ }
+
+ GLTFParser.prototype.parse = function ( onLoad, onError ) {
+
+ var parser = this;
+ var json = this.json;
+ var extensions = this.extensions;
+
+ // Clear the loader cache
+ this.cache.removeAll();
+
+ // Mark the special nodes/meshes in json for efficient parse
+ this.markDefs();
+
+ Promise.all( [
+
+ this.getDependencies( 'scene' ),
+ this.getDependencies( 'animation' ),
+ this.getDependencies( 'camera' ),
+
+ ] ).then( function ( dependencies ) {
+
+ var result = {
+ scene: dependencies[ 0 ][ json.scene || 0 ],
+ scenes: dependencies[ 0 ],
+ animations: dependencies[ 1 ],
+ cameras: dependencies[ 2 ],
+ asset: json.asset,
+ parser: parser,
+ userData: {}
+ };
+
+ addUnknownExtensionsToUserData( extensions, result, json );
+
+ assignExtrasToUserData( result, json );
+
+ onLoad( result );
+
+ } ).catch( onError );
+
+ };
+
+ /**
+ * Marks the special nodes/meshes in json for efficient parse.
+ */
+ GLTFParser.prototype.markDefs = function () {
+
+ var nodeDefs = this.json.nodes || [];
+ var skinDefs = this.json.skins || [];
+ var meshDefs = this.json.meshes || [];
+
+ var meshReferences = {};
+ var meshUses = {};
+
+ // Nothing in the node definition indicates whether it is a Bone or an
+ // Object3D. Use the skins' joint references to mark bones.
+ for ( var skinIndex = 0, skinLength = skinDefs.length; skinIndex < skinLength; skinIndex ++ ) {
+
+ var joints = skinDefs[ skinIndex ].joints;
+
+ for ( var i = 0, il = joints.length; i < il; i ++ ) {
+
+ nodeDefs[ joints[ i ] ].isBone = true;
+
+ }
+
+ }
+
+ // Meshes can (and should) be reused by multiple nodes in a glTF asset. To
+ // avoid having more than one THREE.Mesh with the same name, count
+ // references and rename instances below.
+ //
+ // Example: CesiumMilkTruck sample model reuses "Wheel" meshes.
+ for ( var nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) {
+
+ var nodeDef = nodeDefs[ nodeIndex ];
+
+ if ( nodeDef.mesh !== undefined ) {
+
+ if ( meshReferences[ nodeDef.mesh ] === undefined ) {
+
+ meshReferences[ nodeDef.mesh ] = meshUses[ nodeDef.mesh ] = 0;
+
+ }
+
+ meshReferences[ nodeDef.mesh ] ++;
+
+ // Nothing in the mesh definition indicates whether it is
+ // a SkinnedMesh or Mesh. Use the node's mesh reference
+ // to mark SkinnedMesh if node has skin.
+ if ( nodeDef.skin !== undefined ) {
+
+ meshDefs[ nodeDef.mesh ].isSkinnedMesh = true;
+
+ }
+
+ }
+
+ }
+
+ this.json.meshReferences = meshReferences;
+ this.json.meshUses = meshUses;
+
+ };
+
+ /**
+ * Requests the specified dependency asynchronously, with caching.
+ * @param {string} type
+ * @param {number} index
+ * @return {Promise}
+ */
+ GLTFParser.prototype.getDependency = function ( type, index ) {
+
+ var cacheKey = type + ':' + index;
+ var dependency = this.cache.get( cacheKey );
+
+ if ( ! dependency ) {
+
+ switch ( type ) {
+
+ case 'scene':
+ dependency = this.loadScene( index );
+ break;
+
+ case 'node':
+ dependency = this.loadNode( index );
+ break;
+
+ case 'mesh':
+ dependency = this.loadMesh( index );
+ break;
+
+ case 'accessor':
+ dependency = this.loadAccessor( index );
+ break;
+
+ case 'bufferView':
+ dependency = this.loadBufferView( index );
+ break;
+
+ case 'buffer':
+ dependency = this.loadBuffer( index );
+ break;
+
+ case 'material':
+ dependency = this.loadMaterial( index );
+ break;
+
+ case 'texture':
+ dependency = this.loadTexture( index );
+ break;
+
+ case 'skin':
+ dependency = this.loadSkin( index );
+ break;
+
+ case 'animation':
+ dependency = this.loadAnimation( index );
+ break;
+
+ case 'camera':
+ dependency = this.loadCamera( index );
+ break;
+
+ case 'light':
+ dependency = this.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].loadLight( index );
+ break;
+
+ default:
+ throw new Error( 'Unknown type: ' + type );
+
+ }
+
+ this.cache.add( cacheKey, dependency );
+
+ }
+
+ return dependency;
+
+ };
+
+ /**
+ * Requests all dependencies of the specified type asynchronously, with caching.
+ * @param {string} type
+ * @return {Promise>}
+ */
+ GLTFParser.prototype.getDependencies = function ( type ) {
+
+ var dependencies = this.cache.get( type );
+
+ if ( ! dependencies ) {
+
+ var parser = this;
+ var defs = this.json[ type + ( type === 'mesh' ? 'es' : 's' ) ] || [];
+
+ dependencies = Promise.all( defs.map( function ( def, index ) {
+
+ return parser.getDependency( type, index );
+
+ } ) );
+
+ this.cache.add( type, dependencies );
+
+ }
+
+ return dependencies;
+
+ };
+
+ /**
+ * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views
+ * @param {number} bufferIndex
+ * @return {Promise}
+ */
+ GLTFParser.prototype.loadBuffer = function ( bufferIndex ) {
+
+ var bufferDef = this.json.buffers[ bufferIndex ];
+ var loader = this.fileLoader;
+
+ if ( bufferDef.type && bufferDef.type !== 'arraybuffer' ) {
+
+ throw new Error( 'THREE.GLTFLoader: ' + bufferDef.type + ' buffer type is not supported.' );
+
+ }
+
+ // If present, GLB container is required to be the first buffer.
+ if ( bufferDef.uri === undefined && bufferIndex === 0 ) {
+
+ return Promise.resolve( this.extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body );
+
+ }
+
+ var options = this.options;
+
+ return new Promise( function ( resolve, reject ) {
+
+ loader.load( resolveURL( bufferDef.uri, options.path ), resolve, undefined, function () {
+
+ reject( new Error( 'THREE.GLTFLoader: Failed to load buffer "' + bufferDef.uri + '".' ) );
+
+ } );
+
+ } );
+
+ };
+
+ /**
+ * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views
+ * @param {number} bufferViewIndex
+ * @return {Promise}
+ */
+ GLTFParser.prototype.loadBufferView = function ( bufferViewIndex ) {
+
+ var bufferViewDef = this.json.bufferViews[ bufferViewIndex ];
+
+ return this.getDependency( 'buffer', bufferViewDef.buffer ).then( function ( buffer ) {
+
+ var byteLength = bufferViewDef.byteLength || 0;
+ var byteOffset = bufferViewDef.byteOffset || 0;
+ return buffer.slice( byteOffset, byteOffset + byteLength );
+
+ } );
+
+ };
+
+ /**
+ * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#accessors
+ * @param {number} accessorIndex
+ * @return {Promise}
+ */
+ GLTFParser.prototype.loadAccessor = function ( accessorIndex ) {
+
+ var parser = this;
+ var json = this.json;
+
+ var accessorDef = this.json.accessors[ accessorIndex ];
+
+ if ( accessorDef.bufferView === undefined && accessorDef.sparse === undefined ) {
+
+ // Ignore empty accessors, which may be used to declare runtime
+ // information about attributes coming from another source (e.g. Draco
+ // compression extension).
+ return Promise.resolve( null );
+
+ }
+
+ var pendingBufferViews = [];
+
+ if ( accessorDef.bufferView !== undefined ) {
+
+ pendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.bufferView ) );
+
+ } else {
+
+ pendingBufferViews.push( null );
+
+ }
+
+ if ( accessorDef.sparse !== undefined ) {
+
+ pendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.indices.bufferView ) );
+ pendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.values.bufferView ) );
+
+ }
+
+ return Promise.all( pendingBufferViews ).then( function ( bufferViews ) {
+
+ var bufferView = bufferViews[ 0 ];
+
+ var itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ];
+ var TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];
+
+ // For VEC3: itemSize is 3, elementBytes is 4, itemBytes is 12.
+ var elementBytes = TypedArray.BYTES_PER_ELEMENT;
+ var itemBytes = elementBytes * itemSize;
+ var byteOffset = accessorDef.byteOffset || 0;
+ var byteStride = accessorDef.bufferView !== undefined ? json.bufferViews[ accessorDef.bufferView ].byteStride : undefined;
+ var normalized = accessorDef.normalized === true;
+ var array, bufferAttribute;
+
+ // The buffer is not interleaved if the stride is the item size in bytes.
+ if ( byteStride && byteStride !== itemBytes ) {
+
+ // Each "slice" of the buffer, as defined by 'count' elements of 'byteStride' bytes, gets its own InterleavedBuffer
+ // This makes sure that IBA.count reflects accessor.count properly
+ var ibSlice = Math.floor( byteOffset / byteStride );
+ var ibCacheKey = 'InterleavedBuffer:' + accessorDef.bufferView + ':' + accessorDef.componentType + ':' + ibSlice + ':' + accessorDef.count;
+ var ib = parser.cache.get( ibCacheKey );
+
+ if ( ! ib ) {
+
+ array = new TypedArray( bufferView, ibSlice * byteStride, accessorDef.count * byteStride / elementBytes );
+
+ // Integer parameters to IB/IBA are in array elements, not bytes.
+ ib = new THREE.InterleavedBuffer( array, byteStride / elementBytes );
+
+ parser.cache.add( ibCacheKey, ib );
+
+ }
+
+ bufferAttribute = new THREE.InterleavedBufferAttribute( ib, itemSize, (byteOffset % byteStride) / elementBytes, normalized );
+
+ } else {
+
+ if ( bufferView === null ) {
+
+ array = new TypedArray( accessorDef.count * itemSize );
+
+ } else {
+
+ array = new TypedArray( bufferView, byteOffset, accessorDef.count * itemSize );
+
+ }
+
+ bufferAttribute = new THREE.BufferAttribute( array, itemSize, normalized );
+
+ }
+
+ // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#sparse-accessors
+ if ( accessorDef.sparse !== undefined ) {
+
+ var itemSizeIndices = WEBGL_TYPE_SIZES.SCALAR;
+ var TypedArrayIndices = WEBGL_COMPONENT_TYPES[ accessorDef.sparse.indices.componentType ];
+
+ var byteOffsetIndices = accessorDef.sparse.indices.byteOffset || 0;
+ var byteOffsetValues = accessorDef.sparse.values.byteOffset || 0;
+
+ var sparseIndices = new TypedArrayIndices( bufferViews[ 1 ], byteOffsetIndices, accessorDef.sparse.count * itemSizeIndices );
+ var sparseValues = new TypedArray( bufferViews[ 2 ], byteOffsetValues, accessorDef.sparse.count * itemSize );
+
+ if ( bufferView !== null ) {
+
+ // Avoid modifying the original ArrayBuffer, if the bufferView wasn't initialized with zeroes.
+ bufferAttribute.setArray( bufferAttribute.array.slice() );
+
+ }
+
+ for ( var i = 0, il = sparseIndices.length; i < il; i ++ ) {
+
+ var index = sparseIndices[ i ];
+
+ bufferAttribute.setX( index, sparseValues[ i * itemSize ] );
+ if ( itemSize >= 2 ) bufferAttribute.setY( index, sparseValues[ i * itemSize + 1 ] );
+ if ( itemSize >= 3 ) bufferAttribute.setZ( index, sparseValues[ i * itemSize + 2 ] );
+ if ( itemSize >= 4 ) bufferAttribute.setW( index, sparseValues[ i * itemSize + 3 ] );
+ if ( itemSize >= 5 ) throw new Error( 'THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.' );
+
+ }
+
+ }
+
+ return bufferAttribute;
+
+ } );
+
+ };
+
+ /**
+ * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#textures
+ * @param {number} textureIndex
+ * @return {Promise}
+ */
+ GLTFParser.prototype.loadTexture = function ( textureIndex ) {
+
+ var parser = this;
+ var json = this.json;
+ var options = this.options;
+ var textureLoader = this.textureLoader;
+
+ var URL = window.URL || window.webkitURL;
+
+ var textureDef = json.textures[ textureIndex ];
+
+ var textureExtensions = textureDef.extensions || {};
+
+ var source;
+
+ if ( textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] ) {
+
+ source = json.images[ textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].source ];
+
+ } else {
+
+ source = json.images[ textureDef.source ];
+
+ }
+
+ var sourceURI = source.uri;
+ var isObjectURL = false;
+
+ if ( source.bufferView !== undefined ) {
+
+ // Load binary image data from bufferView, if provided.
+
+ sourceURI = parser.getDependency( 'bufferView', source.bufferView ).then( function ( bufferView ) {
+
+ isObjectURL = true;
+ var blob = new Blob( [ bufferView ], { type: source.mimeType } );
+ sourceURI = URL.createObjectURL( blob );
+ return sourceURI;
+
+ } );
+
+ }
+
+ return Promise.resolve( sourceURI ).then( function ( sourceURI ) {
+
+ // Load Texture resource.
+
+ var loader = THREE.Loader.Handlers.get( sourceURI );
+
+ if ( ! loader ) {
+
+ loader = textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ]
+ ? parser.extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].ddsLoader
+ : textureLoader;
+
+ }
+
+ return new Promise( function ( resolve, reject ) {
+
+ loader.load( resolveURL( sourceURI, options.path ), resolve, undefined, reject );
+
+ } );
+
+ } ).then( function ( texture ) {
+
+ // Clean up resources and configure Texture.
+
+ if ( isObjectURL === true ) {
+
+ URL.revokeObjectURL( sourceURI );
+
+ }
+
+ texture.flipY = false;
+
+ if ( textureDef.name !== undefined ) texture.name = textureDef.name;
+
+ // Ignore unknown mime types, like DDS files.
+ if ( source.mimeType in MIME_TYPE_FORMATS ) {
+
+ texture.format = MIME_TYPE_FORMATS[ source.mimeType ];
+
+ }
+
+ var samplers = json.samplers || {};
+ var sampler = samplers[ textureDef.sampler ] || {};
+
+ texture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || THREE.LinearFilter;
+ texture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || THREE.LinearMipmapLinearFilter;
+ texture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || THREE.RepeatWrapping;
+ texture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || THREE.RepeatWrapping;
+
+ return texture;
+
+ } );
+
+ };
+
+ /**
+ * Asynchronously assigns a texture to the given material parameters.
+ * @param {Object} materialParams
+ * @param {string} mapName
+ * @param {Object} mapDef
+ * @return {Promise}
+ */
+ GLTFParser.prototype.assignTexture = function ( materialParams, mapName, mapDef ) {
+
+ var parser = this;
+
+ return this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {
+
+ if ( ! texture.isCompressedTexture ) {
+
+ switch ( mapName ) {
+
+ case 'aoMap':
+ case 'emissiveMap':
+ case 'metalnessMap':
+ case 'normalMap':
+ case 'roughnessMap':
+ texture.format = THREE.RGBFormat;
+ break;
+
+ }
+
+ }
+
+ if ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) {
+
+ var transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined;
+
+ if ( transform ) {
+
+ texture = parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ].extendTexture( texture, transform );
+
+ }
+
+ }
+
+ materialParams[ mapName ] = texture;
+
+ } );
+
+ };
+
+ /**
+ * Assigns final material to a Mesh, Line, or Points instance. The instance
+ * already has a material (generated from the glTF material options alone)
+ * but reuse of the same glTF material may require multiple threejs materials
+ * to accomodate different primitive types, defines, etc. New materials will
+ * be created if necessary, and reused from a cache.
+ * @param {THREE.Object3D} mesh Mesh, Line, or Points instance.
+ */
+ GLTFParser.prototype.assignFinalMaterial = function ( mesh ) {
+
+ var geometry = mesh.geometry;
+ var material = mesh.material;
+ var extensions = this.extensions;
+
+ var useVertexTangents = geometry.attributes.tangent !== undefined;
+ var useVertexColors = geometry.attributes.color !== undefined;
+ var useFlatShading = geometry.attributes.normal === undefined;
+ var useSkinning = mesh.isSkinnedMesh === true;
+ var useMorphTargets = Object.keys( geometry.morphAttributes ).length > 0;
+ var useMorphNormals = useMorphTargets && geometry.morphAttributes.normal !== undefined;
+
+ if ( mesh.isPoints ) {
+
+ var cacheKey = 'PointsMaterial:' + material.uuid;
+
+ var pointsMaterial = this.cache.get( cacheKey );
+
+ if ( ! pointsMaterial ) {
+
+ pointsMaterial = new THREE.PointsMaterial();
+ THREE.Material.prototype.copy.call( pointsMaterial, material );
+ pointsMaterial.color.copy( material.color );
+ pointsMaterial.map = material.map;
+ pointsMaterial.lights = false; // PointsMaterial doesn't support lights yet
+ pointsMaterial.sizeAttenuation = false; // glTF spec says points should be 1px
+
+ this.cache.add( cacheKey, pointsMaterial );
+
+ }
+
+ material = pointsMaterial;
+
+ } else if ( mesh.isLine ) {
+
+ var cacheKey = 'LineBasicMaterial:' + material.uuid;
+
+ var lineMaterial = this.cache.get( cacheKey );
+
+ if ( ! lineMaterial ) {
+
+ lineMaterial = new THREE.LineBasicMaterial();
+ THREE.Material.prototype.copy.call( lineMaterial, material );
+ lineMaterial.color.copy( material.color );
+ lineMaterial.lights = false; // LineBasicMaterial doesn't support lights yet
+
+ this.cache.add( cacheKey, lineMaterial );
+
+ }
+
+ material = lineMaterial;
+
+ }
+
+ // Clone the material if it will be modified
+ if ( useVertexTangents || useVertexColors || useFlatShading || useSkinning || useMorphTargets ) {
+
+ var cacheKey = 'ClonedMaterial:' + material.uuid + ':';
+
+ if ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:';
+ if ( useSkinning ) cacheKey += 'skinning:';
+ if ( useVertexTangents ) cacheKey += 'vertex-tangents:';
+ if ( useVertexColors ) cacheKey += 'vertex-colors:';
+ if ( useFlatShading ) cacheKey += 'flat-shading:';
+ if ( useMorphTargets ) cacheKey += 'morph-targets:';
+ if ( useMorphNormals ) cacheKey += 'morph-normals:';
+
+ var cachedMaterial = this.cache.get( cacheKey );
+
+ if ( ! cachedMaterial ) {
+
+ cachedMaterial = material.isGLTFSpecularGlossinessMaterial
+ ? extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].cloneMaterial( material )
+ : material.clone();
+
+ if ( useSkinning ) cachedMaterial.skinning = true;
+ if ( useVertexTangents ) cachedMaterial.vertexTangents = true;
+ if ( useVertexColors ) cachedMaterial.vertexColors = THREE.VertexColors;
+ if ( useFlatShading ) cachedMaterial.flatShading = true;
+ if ( useMorphTargets ) cachedMaterial.morphTargets = true;
+ if ( useMorphNormals ) cachedMaterial.morphNormals = true;
+
+ this.cache.add( cacheKey, cachedMaterial );
+
+ }
+
+ material = cachedMaterial;
+
+ }
+
+ // workarounds for mesh and geometry
+
+ if ( material.aoMap && geometry.attributes.uv2 === undefined && geometry.attributes.uv !== undefined ) {
+
+ console.log( 'THREE.GLTFLoader: Duplicating UVs to support aoMap.' );
+ geometry.addAttribute( 'uv2', new THREE.BufferAttribute( geometry.attributes.uv.array, 2 ) );
+
+ }
+
+ if ( material.isGLTFSpecularGlossinessMaterial ) {
+
+ // for GLTFSpecularGlossinessMaterial(ShaderMaterial) uniforms runtime update
+ mesh.onBeforeRender = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].refreshUniforms;
+
+ }
+
+ mesh.material = material;
+
+ };
+
+ /**
+ * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#materials
+ * @param {number} materialIndex
+ * @return {Promise}
+ */
+ GLTFParser.prototype.loadMaterial = function ( materialIndex ) {
+
+ var parser = this;
+ var json = this.json;
+ var extensions = this.extensions;
+ var materialDef = json.materials[ materialIndex ];
+
+ var materialType;
+ var materialParams = {};
+ var materialExtensions = materialDef.extensions || {};
+
+ var pending = [];
+
+ if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ] ) {
+
+ var sgExtension = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ];
+ materialType = sgExtension.getMaterialType();
+ pending.push( sgExtension.extendParams( materialParams, materialDef, parser ) );
+
+ } else if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) {
+
+ var kmuExtension = extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ];
+ materialType = kmuExtension.getMaterialType();
+ pending.push( kmuExtension.extendParams( materialParams, materialDef, parser ) );
+
+ } else {
+
+ // Specification:
+ // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material
+
+ materialType = THREE.MeshStandardMaterial;
+
+ var metallicRoughness = materialDef.pbrMetallicRoughness || {};
+
+ materialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );
+ materialParams.opacity = 1.0;
+
+ if ( Array.isArray( metallicRoughness.baseColorFactor ) ) {
+
+ var array = metallicRoughness.baseColorFactor;
+
+ materialParams.color.fromArray( array );
+ materialParams.opacity = array[ 3 ];
+
+ }
+
+ if ( metallicRoughness.baseColorTexture !== undefined ) {
+
+ pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture ) );
+
+ }
+
+ materialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;
+ materialParams.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0;
+
+ if ( metallicRoughness.metallicRoughnessTexture !== undefined ) {
+
+ pending.push( parser.assignTexture( materialParams, 'metalnessMap', metallicRoughness.metallicRoughnessTexture ) );
+ pending.push( parser.assignTexture( materialParams, 'roughnessMap', metallicRoughness.metallicRoughnessTexture ) );
+
+ }
+
+ }
+
+ if ( materialDef.doubleSided === true ) {
+
+ materialParams.side = THREE.DoubleSide;
+
+ }
+
+ var alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE;
+
+ if ( alphaMode === ALPHA_MODES.BLEND ) {
+
+ materialParams.transparent = true;
+
+ } else {
+
+ materialParams.transparent = false;
+
+ if ( alphaMode === ALPHA_MODES.MASK ) {
+
+ materialParams.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;
+
+ }
+
+ }
+
+ if ( materialDef.normalTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {
+
+ pending.push( parser.assignTexture( materialParams, 'normalMap', materialDef.normalTexture ) );
+
+ materialParams.normalScale = new THREE.Vector2( 1, 1 );
+
+ if ( materialDef.normalTexture.scale !== undefined ) {
+
+ materialParams.normalScale.set( materialDef.normalTexture.scale, materialDef.normalTexture.scale );
+
+ }
+
+ }
+
+ if ( materialDef.occlusionTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {
+
+ pending.push( parser.assignTexture( materialParams, 'aoMap', materialDef.occlusionTexture ) );
+
+ if ( materialDef.occlusionTexture.strength !== undefined ) {
+
+ materialParams.aoMapIntensity = materialDef.occlusionTexture.strength;
+
+ }
+
+ }
+
+ if ( materialDef.emissiveFactor !== undefined && materialType !== THREE.MeshBasicMaterial ) {
+
+ materialParams.emissive = new THREE.Color().fromArray( materialDef.emissiveFactor );
+
+ }
+
+ if ( materialDef.emissiveTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {
+
+ pending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture ) );
+
+ }
+
+ return Promise.all( pending ).then( function () {
+
+ var material;
+
+ if ( materialType === THREE.ShaderMaterial ) {
+
+ material = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].createMaterial( materialParams );
+
+ } else {
+
+ material = new materialType( materialParams );
+
+ }
+
+ if ( materialDef.name !== undefined ) material.name = materialDef.name;
+
+ // baseColorTexture, emissiveTexture, and specularGlossinessTexture use sRGB encoding.
+ if ( material.map ) material.map.encoding = THREE.sRGBEncoding;
+ if ( material.emissiveMap ) material.emissiveMap.encoding = THREE.sRGBEncoding;
+ if ( material.specularMap ) material.specularMap.encoding = THREE.sRGBEncoding;
+
+ assignExtrasToUserData( material, materialDef );
+
+ if ( materialDef.extensions ) addUnknownExtensionsToUserData( extensions, material, materialDef );
+
+ return material;
+
+ } );
+
+ };
+
+ /**
+ * @param {THREE.BufferGeometry} geometry
+ * @param {GLTF.Primitive} primitiveDef
+ * @param {GLTFParser} parser
+ * @return {Promise}
+ */
+ function addPrimitiveAttributes( geometry, primitiveDef, parser ) {
+
+ var attributes = primitiveDef.attributes;
+
+ var pending = [];
+
+ function assignAttributeAccessor( accessorIndex, attributeName ) {
+
+ return parser.getDependency( 'accessor', accessorIndex )
+ .then( function ( accessor ) {
+
+ geometry.addAttribute( attributeName, accessor );
+
+ } );
+
+ }
+
+ for ( var gltfAttributeName in attributes ) {
+
+ var threeAttributeName = ATTRIBUTES[ gltfAttributeName ] || gltfAttributeName.toLowerCase();
+
+ // Skip attributes already provided by e.g. Draco extension.
+ if ( threeAttributeName in geometry.attributes ) continue;
+
+ pending.push( assignAttributeAccessor( attributes[ gltfAttributeName ], threeAttributeName ) );
+
+ }
+
+ if ( primitiveDef.indices !== undefined && ! geometry.index ) {
+
+ var accessor = parser.getDependency( 'accessor', primitiveDef.indices ).then( function ( accessor ) {
+
+ geometry.setIndex( accessor );
+
+ } );
+
+ pending.push( accessor );
+
+ }
+
+ assignExtrasToUserData( geometry, primitiveDef );
+
+ return Promise.all( pending ).then( function () {
+
+ return primitiveDef.targets !== undefined
+ ? addMorphTargets( geometry, primitiveDef.targets, parser )
+ : geometry;
+
+ } );
+
+ }
+
+ /**
+ * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#geometry
+ *
+ * Creates BufferGeometries from primitives.
+ *
+ * @param {Array} primitives
+ * @return {Promise>}
+ */
+ GLTFParser.prototype.loadGeometries = function ( primitives ) {
+
+ var parser = this;
+ var extensions = this.extensions;
+ var cache = this.primitiveCache;
+
+ function createDracoPrimitive( primitive ) {
+
+ return extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ]
+ .decodePrimitive( primitive, parser )
+ .then( function ( geometry ) {
+
+ return addPrimitiveAttributes( geometry, primitive, parser );
+
+ } );
+
+ }
+
+ var pending = [];
+
+ for ( var i = 0, il = primitives.length; i < il; i ++ ) {
+
+ var primitive = primitives[ i ];
+ var cacheKey = createPrimitiveKey( primitive );
+
+ // See if we've already created this geometry
+ var cached = cache[ cacheKey ];
+
+ if ( cached ) {
+
+ // Use the cached geometry if it exists
+ pending.push( cached.promise );
+
+ } else {
+
+ var geometryPromise;
+
+ if ( primitive.extensions && primitive.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] ) {
+
+ // Use DRACO geometry if available
+ geometryPromise = createDracoPrimitive( primitive );
+
+ } else {
+
+ // Otherwise create a new geometry
+ geometryPromise = addPrimitiveAttributes( new THREE.BufferGeometry(), primitive, parser );
+
+ }
+
+ // Cache this geometry
+ cache[ cacheKey ] = { primitive: primitive, promise: geometryPromise };
+
+ pending.push( geometryPromise );
+
+ }
+
+ }
+
+ return Promise.all( pending );
+
+ };
+
+ /**
+ * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#meshes
+ * @param {number} meshIndex
+ * @return {Promise}
+ */
+ GLTFParser.prototype.loadMesh = function ( meshIndex ) {
+
+ var parser = this;
+ var json = this.json;
+
+ var meshDef = json.meshes[ meshIndex ];
+ var primitives = meshDef.primitives;
+
+ var pending = [];
+
+ for ( var i = 0, il = primitives.length; i < il; i ++ ) {
+
+ var material = primitives[ i ].material === undefined
+ ? createDefaultMaterial()
+ : this.getDependency( 'material', primitives[ i ].material );
+
+ pending.push( material );
+
+ }
+
+ return Promise.all( pending ).then( function ( originalMaterials ) {
+
+ return parser.loadGeometries( primitives ).then( function ( geometries ) {
+
+ var meshes = [];
+
+ for ( var i = 0, il = geometries.length; i < il; i ++ ) {
+
+ var geometry = geometries[ i ];
+ var primitive = primitives[ i ];
+
+ // 1. create Mesh
+
+ var mesh;
+
+ var material = originalMaterials[ i ];
+
+ if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES ||
+ primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ||
+ primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ||
+ primitive.mode === undefined ) {
+
+ // .isSkinnedMesh isn't in glTF spec. See .markDefs()
+ mesh = meshDef.isSkinnedMesh === true
+ ? new THREE.SkinnedMesh( geometry, material )
+ : new THREE.Mesh( geometry, material );
+
+ if ( mesh.isSkinnedMesh === true && ! mesh.geometry.attributes.skinWeight.normalized ) {
+
+ // we normalize floating point skin weight array to fix malformed assets (see #15319)
+ // it's important to skip this for non-float32 data since normalizeSkinWeights assumes non-normalized inputs
+ mesh.normalizeSkinWeights();
+
+ }
+
+ if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {
+
+ mesh.drawMode = THREE.TriangleStripDrawMode;
+
+ } else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {
+
+ mesh.drawMode = THREE.TriangleFanDrawMode;
+
+ }
+
+ } else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
+
+ mesh = new THREE.LineSegments( geometry, material );
+
+ } else if ( primitive.mode === WEBGL_CONSTANTS.LINE_STRIP ) {
+
+ mesh = new THREE.Line( geometry, material );
+
+ } else if ( primitive.mode === WEBGL_CONSTANTS.LINE_LOOP ) {
+
+ mesh = new THREE.LineLoop( geometry, material );
+
+ } else if ( primitive.mode === WEBGL_CONSTANTS.POINTS ) {
+
+ mesh = new THREE.Points( geometry, material );
+
+ } else {
+
+ throw new Error( 'THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode );
+
+ }
+
+ if ( Object.keys( mesh.geometry.morphAttributes ).length > 0 ) {
+
+ updateMorphTargets( mesh, meshDef );
+
+ }
+
+ mesh.name = meshDef.name || ( 'mesh_' + meshIndex );
+
+ if ( geometries.length > 1 ) mesh.name += '_' + i;
+
+ assignExtrasToUserData( mesh, meshDef );
+
+ parser.assignFinalMaterial( mesh );
+
+ meshes.push( mesh );
+
+ }
+
+ if ( meshes.length === 1 ) {
+
+ return meshes[ 0 ];
+
+ }
+
+ var group = new THREE.Group();
+
+ for ( var i = 0, il = meshes.length; i < il; i ++ ) {
+
+ group.add( meshes[ i ] );
+
+ }
+
+ return group;
+
+ } );
+
+ } );
+
+ };
+
+ /**
+ * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#cameras
+ * @param {number} cameraIndex
+ * @return {Promise}
+ */
+ GLTFParser.prototype.loadCamera = function ( cameraIndex ) {
+
+ var camera;
+ var cameraDef = this.json.cameras[ cameraIndex ];
+ var params = cameraDef[ cameraDef.type ];
+
+ if ( ! params ) {
+
+ console.warn( 'THREE.GLTFLoader: Missing camera parameters.' );
+ return;
+
+ }
+
+ if ( cameraDef.type === 'perspective' ) {
+
+ camera = new THREE.PerspectiveCamera( THREE.Math.radToDeg( params.yfov ), params.aspectRatio || 1, params.znear || 1, params.zfar || 2e6 );
+
+ } else if ( cameraDef.type === 'orthographic' ) {
+
+ camera = new THREE.OrthographicCamera( params.xmag / - 2, params.xmag / 2, params.ymag / 2, params.ymag / - 2, params.znear, params.zfar );
+
+ }
+
+ if ( cameraDef.name !== undefined ) camera.name = cameraDef.name;
+
+ assignExtrasToUserData( camera, cameraDef );
+
+ return Promise.resolve( camera );
+
+ };
+
+ /**
+ * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins
+ * @param {number} skinIndex
+ * @return {Promise