commit 057e9306df2ee5e30524878765144e5cd9dea72a Author: modeht Date: Mon Oct 3 19:59:51 2022 +0200 init commit diff --git a/.env b/.env new file mode 100644 index 0000000..ded867e --- /dev/null +++ b/.env @@ -0,0 +1,80 @@ +VERSION=2.0.0 +MODE=development +NODE_ENV=development +ENV=development +PLATFORM_NAME=Test +MAIL_FROM= +MAIL_DOMAIN= +MAILGUN_KEY= +TWILIO_PHONE_NUMBER= +TWILIO_SID= +TWILIO_TOKEN= +COPYRIGHT=Copyright © 2021 MKD. All rights reserved. +POWERED_BY=Powered By MKD.ca +NODE_PORT=3001 +GRAPHQL_PORT=9001 +EMAIL_SMTP_PROTOCOL=smtp +EMAIL_SMTP_SMTP_HOST=smtp.mailtrap.io +EMAIL_SMTP_SMTP_PORT=2525 +EMAIL_SMTP_SMTP_USER=7e8f296dd6a493 +EMAIL_SMTP_SMTP_PASS=ac4e30d39321bc +EMAIL_SMTP_CRLF=\r\n +EMAIL_SMTP_NEWLINE=\r\n +EMAIL_SMTP_MAILTYPE=html +EMAIL_SMTP_CHARSET=utf-8 +CSRF_EXCLUDE_URIS=["v1/api.*+","member/login","member/forgot","member/reset/.*","member/register","admin/login","admin/forgot","admin/reset/.*","admin/register","sale/login","sale/forgot","sale/reset/.*","sale/register"] +ENCRYPTION_KEY=1n4uUX6d1Us3quFXKA7ZmqFIaQVC5MtgXlV9ho8F +SUBCLASS_PREFIX=Manaknight_ +MIGRATION_NUMBER=9377770345344 +LANGUAGE=english +BASE_URL=http://localhost:3001 +SITE_TITLE=Manaknight Saas +COMPANY=MKd +IMAGE_UPLOAD=local +FILE_UPLOAD=local +UPLOAD_BYTE_SIZE_LIMIT=1000000000 +SESSION_SECRET=ACbe28dfeaeb2635aac92c05660664588b +SHOPIFY_SITE=skincare.myshopify.com +SHOPIFY_API_KEY=22a +SHOPIFY_API_PASSWORD=shppa +SHOPIFY_SECRET_KEY=shpss +SHOPIFY_SCOPES=write_script_tags,read_script_tags,read_content,write_content,read_products +API_URL=http://localhost:3001 +DYNAMIC_CONFIG_JWT_KEY=544e +DYNAMIC_CONFIG_PERMISSION_ENCRYPT_KEY=vOV +DYNAMIC_CONFIG_JWT_EXPIRE_AT=3600 +DYNAMIC_CONFIG_JWT_REFRESH_EXPIRE_AT=7200 +DYNAMIC_CONFIG_GOOGLE_CLIENT_ID=466040660536-l5pq116jdp6cs3b58a7k4t52f5lpa5se.apps.googleusercontent.com +DYNAMIC_CONFIG_GOOGLE_CLIENT_SECRET=W_bYoRhly8pf0XJ1IUsk8wC_ +DYNAMIC_CONFIG_GOOGLE_REDIRECT_URI=http://localhost:3001/google +DYNAMIC_CONFIG_APPLICATION_NAME= +DYNAMIC_CONFIG_FACEBOOK_CLIENT_ID=906124643482094 +DYNAMIC_CONFIG_FACEBOOK_CLIENT_SECRET=ee289adf5399aaa48c2bbfd33b83c301 +DYNAMIC_CONFIG_FACEBOOK_REDIRECT_URI=http://localhost:3001/facebook +DYNAMIC_CONFIG_FACEBOOK_OATH_URI=https://www.facebook.com/v3.0/dialog/oauth +DYNAMIC_CONFIG_AWS_VERSION=latest +DYNAMIC_CONFIG_AWS_REGION=us-east-2 +DYNAMIC_CONFIG_AWS_KEY=AKIAJD27VH2ITMIWT4IQ +DYNAMIC_CONFIG_AWS_SECRET=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 +DYNAMIC_CONFIG_AWS_BUCKET=com.konfor.images +DB_ADAPTER=mysql +DB_PORT=3306 +DB_DSN= +DB_HOSTNAME=localhost +DB_USERNAME=root +DB_PASSWORD= +DB_DATABASE=mkd +DB_DBDRIVER=mysqli +DB_DBPREFIX= +DB_PCONNECT=false +DB_DB_DEBUG=false +DB_CACHE_ON=false +DB_CACHEDIR= +DB_CHAR_SET=utf8 +DB_DBCOLLAT=utf8_general_ci +DB_SWAP_PRE= +DB_ENCRYPT=false +DB_COMPRESS=false +DB_STRICTON=false +DB_FAILOVER= +DB_SAVE_QUERIES=true \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea9fd22 --- /dev/null +++ b/.gitignore @@ -0,0 +1,106 @@ +#testing files +!public/uploads/.gitkeep +# services/SessionService.js +test.js +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json +.DS_Store +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# Next.js build output +.next + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and *not* Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port diff --git a/.gitkeep b/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md new file mode 100644 index 0000000..6237be5 --- /dev/null +++ b/README.md @@ -0,0 +1,66 @@ +# Explain project + +## Files and folders you will working on for the quiz are the following + +- /public/quiz-test.html +- /public/frontend_css/styles and mobile_styles.css +- /public/frontend_js/quiz-test.js +- /models/ +- /controllers/admin/ +- /views/admin +- /views/partials/admin/nav.eta + +Admin login + +localhost:3001/admin/login + +email: admin@manaknight.com + +password: a123456 + +View the quiz on localhost:3001/quiz-test.html + +Video Demo https://www.loom.com/share/cb8be1cf3fad45bc8f2ecaca4704e367 + +### Quiz 1 + +Response page of question What would you like to be called?.
+Make the name appears centered inside of the jar gif.
+![Name centered example](./name_centered.png/ "Jar with centered name")
+You can change the html or the css to do this task.
+ +### Quiz 2 + +Each response page should be closed after a set amount of time
+The setTimeout of the response page of previous quiz is not working
+Figure out where this is handled and make a setTimeout to close the response and move on to the next question using the time stored in variable called "closeResponseTimeoutCounter"
+ +### Quiz 3 + +We have multiple types of questions type 7 being "multiple select"
+You are required to find where it is handled
+Then make the button of each option call checkAllergie function that you will be implementing in the next quiz
+Then add an option at the end of all options that says None of the above and onclick it should call this function handleNoneOfTheAbove()
+ +### Quiz 4 + +implement a function that is called checkAllergie()
+pseudo steps of the function + +- find a way to read the dataset values on the html button element that generated the click +- each button should have data-val that contains the label of the option +- check if that previous val is equal to one of these values ["Banana", "Olive", "Sunflowers"] +- if true -> terminate the quiz +- function terminateQuiz should do the following + - the termination process need to display a message to the user with a faded black background that has a message and a counter that when it reachs 0 it redirect to / + - ex: ![Termination screen example](./termination_screen.png/ "Termination screen") + - message and counter should be controlled from admin portal + - create a terminate configuration table with the appropriate fields + - create a tab in admin portal to edit these fields + - create an api to get these configuration and use it here to construct the termination screen + +### Quiz 5 + +implement 2nd step of calculation on quiz answers + +- after quiz is done. a calculation step takes place. you are required to figure out how to implement the missing function. diff --git a/app.js b/app.js new file mode 100644 index 0000000..814f051 --- /dev/null +++ b/app.js @@ -0,0 +1,127 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2020*/ +/** + * App + * @copyright 2020 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +require("dotenv").config(); +const { getLocalPath } = require("./core/helpers"); +const fs = require("fs"); +const express = require("express"); +const path = require("path"); +const body_parser = require("body-parser"); +const logger = require("morgan"); +const helmet = require("helmet"); +const PowerByService = require("./services/PowerByService"); +const UploadService = require("./services/UploadService"); +const cookieParser = require("cookie-parser"); +const controllersEndpoints = require("./controllers/index"); +const portalsEndpoints = require("./routes/index"); +const db = require("./models"); +const sessionClass = require("express-session"); +const flash = require("connect-flash"); +const cors = require("cors"); +const sizeOf = require("image-size"); +let app = express(); +const expressip = require("express-ip"); + +if (process.NODE_ENV === "maintenance") { + app.all("*", (req, res) => { + res.status(503).json({ message: "website under maintenance" }); + }); +} +app.set("iocContainer", process.env); +app.set("db", db); +app.use(expressip().getIpInfoMiddleware); +app.use(logger("dev")); +app.use( + express.json({ + limit: "50mb", + verify: (req, res, buf) => { + req.rawBody = buf; + }, + }) +); +app.use( + express.urlencoded({ + extended: false, + }) +); +app.use(cors()); +app.use(flash()); +let session = { + secret: process.env.SESSION_SECRET, + resave: true, + saveUninitialized: true, + name: "session", + proxy: true, + cookie: { maxAge: 60 * 60 * 1000 }, +}; + +app.set("trust proxy", true); +if (process.env.NODE_ENV === "production") { + session.cookie.secure = true; // serve secure cookies +} +app.use(sessionClass(session)); +app.set("view engine", "eta"); +app.set("views", path.join(__dirname, "/views")); +app.use(cookieParser()); +app.use(helmet()); + +app.use(PowerByService); +app.use(express.static(path.join(__dirname, "/public"))); + +app.get("/version", (req, res) => res.status(200).json({ version: process.env.VERSION })); +app.get("/", (req, res, next) => { + return res.send("

Live!

"); +}); + +app.use((err, req, res, next) => { + // set locals, only providing error in development + res.locals.message = err.message; + res.locals.error = req.app.get("env") === "development" ? err : {}; + + // render the error page + res.status(err.status || 500); + res.json({ + message: err.message, + }); +}); + +//local upload default +const upload = UploadService.local_upload(); +app.post("/v1/upload/file", upload.single("file"), async function (req, res, next) { + try { + const url = getLocalPath(req.file.path); + let params = { + url: url, + user_id: req.session?.user || null, + caption: req.body?.caption || null, + type: +req.body?.type || null, + }; + const uploadedfile = fs.readFileSync(req.file.path); + if (!req.file.mimetype.includes("video")) { + const dimensions = sizeOf(uploadedfile); + params.width = dimensions.width; + params.height = dimensions.height; + } + let createdImage = await db.image.insert(params); + return res.status(201).json({ id: createdImage, url }); + } catch (error) { + console.log(error); + return res.status(500).json({ error: true, message: error.message }); + } +}); + +app.use(portalsEndpoints); +app.use(controllersEndpoints); + +app.use((req, res, next) => { + return res.status(404).send("

Not found!

"); +}); + +module.exports = app; diff --git a/claudia.json b/claudia.json new file mode 100644 index 0000000..06bd6cc --- /dev/null +++ b/claudia.json @@ -0,0 +1,7 @@ +{ + "lambda": { + "role": "graphql_provider-executor", + "name": "graphql_project", + "region": "us-east-2" + } +} \ No newline at end of file diff --git a/controllers/admin/Admin_actives_controller.js b/controllers/admin/Admin_actives_controller.js new file mode 100644 index 0000000..c7ab395 --- /dev/null +++ b/controllers/admin/Admin_actives_controller.js @@ -0,0 +1,336 @@ +"use strict"; +const axios = require("axios"); + +const app = require("express").Router(); +const Sequelize = require("sequelize"); +const logger = require("../../services/LoggingService"); +let pagination = require("../../services/PaginationService"); +let SessionService = require("../../services/SessionService"); +let JwtService = require("../../services/JwtService"); +const ValidationService = require("../../services/ValidationService"); +const PermissionService = require("../../services/PermissionService"); +const UploadService = require("../../services/UploadService"); +const AuthService = require("../../services/AuthService"); +const db = require("../../models"); +const helpers = require("../../core/helpers"); + +const role = 1; + +app.get("/admin/actives/:num", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + try { + let session = req.session; + let paginateListViewModel = require("../../view_models/actives_admin_list_paginate_view_model"); + + var viewModel = new paginateListViewModel(db.active, "Actives", session.success, session.error, "/admin/actives"); + + viewModel._column = ["ID", "Name", "Handle", "Description", "Variables scores", "Action"]; + viewModel._readable_column = ["ID", "Name", "Handle", "Description", "Variables scores"]; + + const format = req.query.format ? req.query.format : "view"; + const direction = req.query.direction ? req.query.direction : "ASC"; + const per_page = req.query.per_page ? req.query.per_page : 10; + let order_by = req.query.order_by ? req.query.order_by : viewModel.get_field_column()[0]; + let orderAssociations = []; + viewModel.set_order_by(order_by); + let joins = order_by.includes(".") ? order_by.split(".") : []; + order_by = order_by.includes(".") ? joins[joins.length - 1] : order_by; + if (joins.length > 0) { + for (let i = joins.length - 1; i > 0; i--) { + orderAssociations.push(`${joins[i - 1]}`); + } + } + // Check for flash messages + const flashMessageSuccess = req.flash("success"); + if (flashMessageSuccess && flashMessageSuccess.length > 0) { + viewModel.success = flashMessageSuccess[0]; + } + const flashMessageError = req.flash("error"); + if (flashMessageError && flashMessageError.length > 0) { + viewModel.error = flashMessageError[0]; + } + + viewModel.set_id(req.query.id ? req.query.id : ""); + viewModel.set_name(req.query.name ? req.query.name : ""); + + let where = helpers.filterEmptyFields({ + id: viewModel.get_id(), + name: viewModel.get_name(), + }); + + const count = await db.active._count(where, []); + + viewModel.set_total_rows(count); + viewModel.set_per_page(+per_page); + viewModel.set_page(+req.params.num); + viewModel.set_query(req.query); + viewModel.set_sort_base_url(`/admin/actives/${+req.params.num}`); + viewModel.set_sort(direction); + + const list = await db.active.getPaginated(viewModel.get_page() - 1 < 0 ? 0 : viewModel.get_page(), viewModel.get_per_page(), where, order_by, direction, orderAssociations); + + viewModel.set_list(list); + + if (format == "csv") { + const csv = viewModel.to_csv(); + return res + .set({ + "Content-Type": "text/csv", + "Content-Disposition": 'attachment; filename="export.csv"', + }) + .send(csv); + } + + return res.render("admin/Actives", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Actives", viewModel); + } +}); + +app.get("/admin/actives-add", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const activesAdminAddViewModel = require("../../view_models/actives_admin_add_view_model"); + + const viewModel = new activesAdminAddViewModel(db.active, "Add active", "", "", "/admin/actives"); + viewModel.output_variables = await db.output_variable.getAll(); + res.render("admin/Add_Actives", viewModel); +}); + +app.post("/admin/actives-add", SessionService.verifySessionMiddleware(role, "admin"), ValidationService.validateInput({ name: "required", handle: "required" }), async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const activesAdminAddViewModel = require("../../view_models/actives_admin_add_view_model"); + + const viewModel = new activesAdminAddViewModel(db.active, "Add active", "", "", "/admin/actives"); + viewModel.output_variables = await db.output_variable.getAll(); + + // TODO use separate controller for image upload + // {{{upload_field_setter}}} + + const { name, description, handle, ...rest } = req.body; + + viewModel.form_fields = { + ...viewModel.form_fields, + name, + handle, + description, + }; + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render("admin/Add_Actives", viewModel); + } + + viewModel.session = req.session; + + const data = await db.active.insert({ name, description, handle, variables_scores: JSON.stringify(rest) }); + + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Add_Actives", viewModel); + } + + req.flash("success", "Active created successfully"); + return res.redirect("/admin/actives/0"); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Add_Actives", viewModel); + } +}); + +app.get("/admin/actives-edit/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const activesAdminEditViewModel = require("../../view_models/actives_admin_edit_view_model"); + + const viewModel = new activesAdminEditViewModel(db.active, "Edit active", "", "", "/admin/actives"); + viewModel.output_variables = await db.output_variable.getAll(); + + try { + const exists = await db.active.getByPK(id); + + if (!exists) { + req.flash("error", "Active not found"); + return res.redirect("/admin/actives/0"); + } + const values = exists; + Object.keys(viewModel.form_fields).forEach((field) => { + viewModel.form_fields[field] = values[field] || ""; + }); + if (exists.variables_scores) { + const currentOutputVariablesScores = JSON.parse(exists.variables_scores); + Object.keys(currentOutputVariablesScores).forEach((varScore) => { + viewModel.form_fields[varScore] = currentOutputVariablesScores[varScore]; + }); + } + return res.render("admin/Edit_Actives", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Edit_Actives", viewModel); + } +}); + +app.post("/admin/actives-edit/:id", SessionService.verifySessionMiddleware(role, "admin"), ValidationService.validateInput({ name: "required", handle: "required" }), async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const activesAdminEditViewModel = require("../../view_models/actives_admin_edit_view_model"); + + const viewModel = new activesAdminEditViewModel(db.active, "Edit active", "", "", "/admin/actives"); + viewModel.form_fields = { variables_scores: "", name: "", id: "" }; + viewModel.output_variables = await db.output_variable.getAll(); + const { name, description, handle, ...rest } = req.body; + + viewModel.form_fields = { + ...viewModel.form_fields, + name, + description, + handle, + }; + + delete viewModel.form_fields.id; + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render("admin/Edit_Actives", viewModel); + } + + const resourceExists = await db.active.getByPK(id); + if (!resourceExists) { + req.flash("error", "Active not found"); + return res.redirect("/admin/actives/0"); + } + + viewModel.session = req.session; + + let data = await db.active.edit({ name, description, handle, variables_scores: JSON.stringify(rest) }, id); + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Edit_Actives", viewModel); + } + + req.flash("success", "Active edited successfully"); + + return res.redirect("/admin/actives/0"); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Edit_Actives", viewModel); + } +}); + +app.get("/admin/resync/actives", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + try { + var config = { + method: "get", + url: `https://${process.env.SHOPIFY_API_KEY}:${process.env.SHOPIFY_API_PASSWORD}@${process.env.SHOPIFY_SITE}/admin/api/2021-10/products.json`, + headers: {}, + }; + const data = await axios(config).then((response) => response.data); + console.log(data.products); + for (const product of data.products) { + if (product.tags == "Personalized Cream" && product.title !== "Blank") { + const activeExists = await db.active.getByFields({ name: product.title }); + if (activeExists) { + await db.active.edit( + { + handle: `https://localhost:3001/products/${product.handle}`, + }, + activeExists.id + ); + } else { + await db.active.insert({ + name: product.title, + handle: `https://localhost:3001/products/${product.handle}`, + }); + } + } + } + + req.flash("success", "Actives resynced successfully"); + return res.redirect("/admin/actives/0"); + } catch (error) { + console.error(error); + req.flash("error", error.message); + return res.redirect("/admin/actives/0"); + } +}); + +app.get( + "/admin/actives-view/:id", + SessionService.verifySessionMiddleware(role, "admin"), + + async function (req, res, next) { + try { + let id = req.params.id; + + const activesAdminDetailViewModel = require("../../view_models/actives_admin_detail_view_model"); + + var viewModel = new activesAdminDetailViewModel(db.active, "Active details", "", "", "/admin/actives"); + + const data = await db.active.getByPK(id); + + if (!data) { + viewModel.error = "Active not found"; + viewModel.detail_fields = { ...viewModel.detail_fields, id: "N/A", name: "N/A", handle: "N/A", description: "N/A" }; + } else { + viewModel.detail_fields = { ...viewModel.detail_fields, id: data["id"] || "N/A", name: data["name"] || "N/A", handle: data["handle"] || "N/A", description: data["description"] || "N/A" }; + } + + res.render("admin/View_Actives", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + viewModel.detail_fields = { ...viewModel.detail_fields, id: "N/A", name: "N/A", handle: "N/A", description: "N/A" }; + res.render("admin/View_Actives", viewModel); + } + } +); + +app.get("/admin/actives-delete/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + + const activesAdminDeleteViewModel = require("../../view_models/actives_admin_delete_view_model"); + + const viewModel = new activesAdminDeleteViewModel(db.active); + + try { + const exists = await db.active.getByPK(id); + + if (!exists) { + req.flash("error", "Active not found"); + return res.redirect("/admin/actives/0"); + } + + viewModel.session = req.session; + + await db.active.realDelete(id); + await db.answer.destroy({ + where: { + answer: exists.name, + }, + }); + req.flash("success", "Active was deleted successfully"); + + return res.redirect("/admin/actives/0"); + } catch (error) { + console.error(error); + req.flash("error", error.message || "Something went wrong"); + return res.redirect("/admin/actives/0"); + } +}); + +module.exports = app; diff --git a/controllers/admin/Admin_answer_controller.js b/controllers/admin/Admin_answer_controller.js new file mode 100644 index 0000000..2b471d3 --- /dev/null +++ b/controllers/admin/Admin_answer_controller.js @@ -0,0 +1,614 @@ +"use strict"; + +const app = require("express").Router(); +const Sequelize = require("sequelize"); +const logger = require("../../services/LoggingService"); +let pagination = require("../../services/PaginationService"); +let SessionService = require("../../services/SessionService"); +let JwtService = require("../../services/JwtService"); +const ValidationService = require("../../services/ValidationService"); +const PermissionService = require("../../services/PermissionService"); +const UploadService = require("../../services/UploadService"); +const AuthService = require("../../services/AuthService"); +const db = require("../../models"); +const helpers = require("../../core/helpers"); + +const role = 1; + +app.get("/admin/answers/:num", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + try { + let session = req.session; + let paginateListViewModel = require("../../view_models/answers_admin_list_paginate_view_model"); + + var viewModel = new paginateListViewModel(db.answer, "Answers", session.success, session.error, "/admin/answers"); + + const format = req.query.format ? req.query.format : "view"; + const direction = req.query.direction ? req.query.direction : "ASC"; + const per_page = req.query.per_page ? req.query.per_page : 10; + // let order_by = req.query.order_by ? req.query.order_by : viewModel.get_field_column()[0]; + let order_by = [ + ["question", "quiz_id", direction], + ["question", "order", direction], + ["question_id", direction], + ["order", direction], + ]; + // Check for flash messages + const flashMessageSuccess = req.flash("success"); + if (flashMessageSuccess && flashMessageSuccess.length > 0) { + viewModel.success = flashMessageSuccess[0]; + } + const flashMessageError = req.flash("error"); + if (flashMessageError && flashMessageError.length > 0) { + viewModel.error = flashMessageError[0]; + } + + viewModel.set_id(req.query.id ? req.query.id : ""); + viewModel.set_question_id(req.query.question_id ? req.query.question_id : ""); + + let where = helpers.filterEmptyFields({ + id: viewModel.get_id(), + question_id: viewModel.get_question_id(), + }); + + const count = await db.answer._count(where, [{ all: true, nested: true }]); + + viewModel.set_total_rows(count); + viewModel.set_per_page(+per_page); + viewModel.set_page(+req.params.num); + viewModel.set_query(req.query); + viewModel.set_sort_base_url(`/admin/answers/${+req.params.num}`); + viewModel.set_sort(direction); + + const list = await db.answer.getPaginatedV2(viewModel.get_page() - 1 < 0 ? 0 : viewModel.get_page(), viewModel.get_per_page(), where, order_by, direction, [{ all: true, nested: true }]); + + viewModel.set_list(list); + + viewModel.question = await db.question; + viewModel.image = await db.image; + + if (format == "csv") { + const csv = viewModel.to_csv(); + return res + .set({ + "Content-Type": "text/csv", + "Content-Disposition": 'attachment; filename="export.csv"', + }) + .send(csv); + } + + return res.render("admin/Answers", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Answers", viewModel); + } +}); + +app.get("/admin/answers-add", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const answersAdminAddViewModel = require("../../view_models/answers_admin_add_view_model"); + + const viewModel = new answersAdminAddViewModel(db.answer, "Add answer", "", "", "/admin/answers"); + viewModel.questions = await db.question.getAll({ + type: { + [Sequelize.Op.notIn]: [1, 2, 3], + }, + }); + viewModel.actives = await db.active.getAll(); + res.render("admin/Add_Answers", viewModel); +}); + +app.post( + "/admin/answers-add", + SessionService.verifySessionMiddleware(role, "admin"), + ValidationService.validateInput({ question_id: "required", order: "required" }, { "question_id.required": "QuestionId is required", "order.required": "Order is required" }), + async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const addedFromQuestion = req.query.question; + const answersAdminAddViewModel = require("../../view_models/answers_admin_add_view_model"); + + const viewModel = new answersAdminAddViewModel(db.answer, "Add answer", "", "", "/admin/answers"); + viewModel.questions = await db.question.getAll({ + type: { + [Sequelize.Op.notIn]: [1, 2, 3], + }, + }); + viewModel.actives = await db.active.getAll(); + + const { + question_id, + answer, + answer_value, + hide_answer, + order, + explaination, + image_id, + response_header, + response_body, + // response_arguments, + black_list_actives, + } = req.body; + + viewModel.form_fields = { + ...viewModel.form_fields, + question_id, + answer, + answer_value, + hide_answer, + order, + explaination, + image_id, + response_header, + response_body, + // response_arguments, + black_list_actives, + }; + + try { + if (req.validationError) { + viewModel.error = req.validationError; + if (addedFromQuestion) { + req.flash("error", req.validationError); + return res.redirect(`/admin/questions-edit/${addedFromQuestion}`); + } + return res.render("admin/Add_Answers", viewModel); + } + + viewModel.session = req.session; + + const data = await db.answer.insert( + helpers.filterEmptyFields({ + question_id, + answer, + answer_value, + hide_answer, + order, + explaination, + image_id, + response_header, + response_body, + // response_arguments, + black_list_actives: !Array.isArray(black_list_actives) ? JSON.stringify([black_list_actives]) : JSON.stringify(black_list_actives), + }) + ); + + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Add_Answers", viewModel); + } + + await db.activity_log.insert({ + action: "ADD", + name: "Admin_answer_controller.js", + portal: "admin", + data: JSON.stringify({ + question_id, + answer, + answer_value, + hide_answer, + order, + explaination, + image_id, + response_header, + response_body, + // response_arguments, + black_list_actives: !Array.isArray(black_list_actives) ? JSON.stringify([black_list_actives]) : JSON.stringify(black_list_actives), + }), + }); + if (addedFromQuestion) { + req.flash("success", "Answer created successfully"); + return res.redirect(`/admin/questions-edit/${addedFromQuestion}`); + } + req.flash("success", "Answer created successfully"); + return res.redirect("/admin/answers/0"); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + if (addedFromQuestion) { + req.flash("error", viewModel.error); + return res.redirect(`/admin/questions-edit/${addedFromQuestion}`); + } + return res.render("admin/Add_Answers", viewModel); + } + } +); + +app.get("/admin/answers-edit/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const answersAdminEditViewModel = require("../../view_models/answers_admin_edit_view_model"); + + const viewModel = new answersAdminEditViewModel(db.answer, "Edit answer", "", "", "/admin/answers"); + + try { + const exists = await db.answer.findOne({ + where: { + id, + }, + include: [{ all: true, nested: true }], + }); + + if (!exists) { + req.flash("error", "Answer not found"); + return res.redirect("/admin/answers/0"); + } + + viewModel.answer = exists; + viewModel.question = await db.question.getByPK(exists.question_id); + viewModel.questions = await db.question.getAll({ + type: { + [Sequelize.Op.notIn]: [1, 2, 3], + }, + }); + viewModel.actives = await db.active.getAll(); + return res.render("admin/Edit_Answers", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Edit_Answers", viewModel); + } +}); + +app.post( + "/admin/answers-edit/:id", + SessionService.verifySessionMiddleware(role, "admin"), + ValidationService.validateInput( + { question_id: "required", answer: "required", order: "required" }, + { "question_id.required": "QuestionId is required", "answer.required": "Answer is required", "order.required": "Order is required" } + ), + async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const answersAdminEditViewModel = require("../../view_models/answers_admin_edit_view_model"); + + const viewModel = new answersAdminEditViewModel(db.answer, "Edit answer", "", "", "/admin/answers"); + viewModel.questions = await db.question.getAll({ + type: { + [Sequelize.Op.notIn]: [1, 2, 3], + }, + }); + viewModel.actives = await db.active.getAll(); + const { + question_id, + answer, + answer_value, + hide_answer, + order, + explaination, + image_id, + response_header, + response_body, + // response_arguments, + black_list_actives, + } = req.body; + + viewModel.form_fields = { + ...viewModel.form_fields, + question_id, + answer, + answer_value, + hide_answer, + order, + explaination, + image_id, + response_header, + response_body, + // response_arguments, + black_list_actives, + }; + + delete viewModel.form_fields.id; + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render("admin/Edit_Answers", viewModel); + } + + const resourceExists = await db.answer.getByPK(id); + if (!resourceExists) { + req.flash("error", "Answer not found"); + return res.redirect("/admin/answers/0"); + } + + viewModel.question = await db.question.getByPK(resourceExists.question_id); + viewModel.session = req.session; + + let data = await db.answer.edit( + helpers.filterEmptyFields({ + question_id, + answer, + answer_value, + hide_answer, + order, + explaination, + image_id, + response_header, + response_body, + // response_arguments, + black_list_actives: JSON.stringify(black_list_actives), + }), + id + ); + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Edit_Answers", viewModel); + } + + if (resourceExists.question) { + data = await db.question.edit(helpers.filterEmptyFields({}), resourceExists.question.id); + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Edit_Answers", viewModel); + } + } + + await db.activity_log.insert({ + action: "EDIT", + name: "Admin_answer_controller.js", + portal: "admin", + data: JSON.stringify({ + question_id, + answer, + answer_value, + order, + explaination, + image_id, + response_header, + response_body, + // response_arguments, + black_list_actives: JSON.stringify(black_list_actives), + }), + }); + + req.flash("success", "Answer edited successfully"); + + return res.redirect("/admin/answers/0"); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Edit_Answers", viewModel); + } + } +); + +app.get( + "/admin/answers-view/:id", + SessionService.verifySessionMiddleware(role, "admin"), + + async function (req, res, next) { + try { + let id = req.params.id; + + const answersAdminDetailViewModel = require("../../view_models/answers_admin_detail_view_model"); + + var viewModel = new answersAdminDetailViewModel(db.answer, "Answer details", "", "", "/admin/answers"); + + const data = await db.answer.findOne({ + where: { + id, + }, + include: [{ all: true, nested: true }], + }); + + data["question.note_type"] = db.question.note_type_mapping()[data.question.note_type]; + data["question.target"] = db.question.target_mapping()[data.question.target]; + data["question.type"] = db.question.type_mapping()[data.question.type]; + + if (!data) { + viewModel.error = "Answer not found"; + viewModel.detail_fields = { + ...viewModel.detail_fields, + id: "N/A", + question_id: "N/A", + "question.question": "N/A", + answer: "N/A", + answer_value: "N/A", + order: "N/A", + explaination: "N/A", + image_id: "N/A", + response_header: "N/A", + response_body: "N/A", + response_arguments: "N/A", + black_list_actives: "N/A", + }; + } else { + viewModel.answer = data; + } + + res.render("admin/View_Answers", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + viewModel.detail_fields = { + ...viewModel.detail_fields, + id: "N/A", + question_id: "N/A", + "question.question": "N/A", + answer: "N/A", + answer_value: "N/A", + order: "N/A", + explaination: "N/A", + image_id: "N/A", + response_header: "N/A", + response_body: "N/A", + response_arguments: "N/A", + black_list_actives: "N/A", + }; + res.render("admin/View_Answers", viewModel); + } + } +); + +app.get("/admin/answers-delete/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + + const answersAdminDeleteViewModel = require("../../view_models/answers_admin_delete_view_model"); + + const viewModel = new answersAdminDeleteViewModel(db.answer); + + try { + const exists = await db.answer.getByPK(id); + + if (!exists) { + req.flash("error", "Answer not found"); + return res.redirect("/admin/answers/0"); + } + + viewModel.session = req.session; + + await db.answer.realDelete(id); + + await db.activity_log.insert({ + action: "DELETE", + name: "Admin_answer_controller.js", + portal: "admin", + data: JSON.stringify(exists), + }); + + req.flash("success", "Answer was deleted successfully"); + + return res.redirect("/admin/answers/0"); + } catch (error) { + console.error(error); + req.flash("error", error.message || "Something went wrong"); + return res.redirect("/admin/answers/0"); + } +}); + +// APIS + +app.get("/admin/api/answers", JwtService.verifyTokenMiddleware(role), async function (req, res, next) { + try { + const user_id = req.user_id; + const session = req.session; + let listViewModel = require("../../view_models/answers_admin_list_paginate_view_model"); + let viewModel = new listViewModel(db.answer, "Answers", session.success, session.error, "/admin/answers"); + const direction = req.query.direction ? req.query.direction : "ASC"; + const page = req.query.page ? parseInt(req.query.page) : 1; + const limit = req.query.limit ? parseInt(req.query.limit) : 10; + const offset = (page - 1) * limit; + let order_by = req.query.order_by ? req.query.order_by : viewModel.get_field_column()[0]; + let orderAssociations = []; + viewModel.set_order_by(order_by); + let joins = order_by.includes(".") ? order_by.split(".") : []; + order_by = order_by.includes(".") ? joins[joins.length - 1] : order_by; + if (joins.length > 0) { + for (let i = joins.length - 1; i > 0; i--) { + orderAssociations.push(`${joins[i - 1]}`); + } + } + + viewModel.set_id(req.query.id ? req.query.id : ""); + viewModel.set_question_id(req.query.question_id ? req.query.question_id : ""); + + let where = helpers.filterEmptyFields({ + id: viewModel.get_id(), + question_id: viewModel.get_question_id(), + }); + + let associatedWhere = helpers.filterEmptyFields({}); + const isAssociationRequired = Object.keys(associatedWhere).length > 0 ? true : false; + + let include = [{ model: db.question, where: associatedWhere, required: isAssociationRequired, as: "question" }]; + + const { rows: allItems, count } = await db.answer.findAndCountAll({ + where: where, + limit: limit == 0 ? null : limit, + offset: offset, + include: include, + distinct: true, + }); + + const response = { + items: allItems, + page, + nextPage: count > offset + limit ? page + 1 : false, + retrievedCount: allItems.length, + fullCount: count, + }; + + return res.status(201).json({ success: true, data: response }); + } catch (error) { + console.error(error); + return res.status(500).json({ success: false, message: error.message || "Something went wrong" }); + } +}); + +app.post( + "/admin/answers-bulk-edit/:id", + SessionService.verifySessionMiddleware(role, "admin"), + ValidationService.validateInput({ answer: "required", order: "required" }, { "answer.required": "Answer is required", "order.required": "Order is required" }), + async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const questionId = req.params.id; + const { ids, answer, answer_value, hide_answer, order, explaination, image_id, response_header, response_body } = req.body; + + try { + if (req.validationError) { + req.flash("error", req.validationError); + return res.redirect(`/admin/questions-edit/${questionId}`); + } + for (let i = 0; i < ids.length; i++) { + await db.answer.edit( + helpers.filterEmptyFields({ + answer: answer ? answer[i] : null, + answer_value: answer_value ? answer_value[i] : null, + hide_answer: hide_answer ? hide_answer[i] : null, + // order: order ? order[i] : null, + order: i + 1, + explaination: explaination ? explaination[i] : null, + image_id: image_id ? image_id[i] : null, + response_header: response_header ? response_header[i] : null, + response_body: response_body ? response_body[i] : null, + black_list_actives: req.body[`black_list_actives_${ids[i]}`] ? JSON.stringify(req.body[`black_list_actives_${ids[i]}`]) : null, + }), + ids[i] + ); + } + // req.flash("success", "Answers edited successfully"); + // return res.redirect(`/admin/questions-edit/${questionId}`); + return res.json({ success: true, message: "Answers edited successfully" }); + } catch (error) { + console.error(error); + req.flash("error", error.message || "Something went wrong. please contact admin."); + return res.redirect(`/admin/questions-edit/${questionId}`); + } + } +); + +app.get("/admin/question/:question/answer-delete/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let { id, question } = req.params; + + try { + const exists = await db.answer.getByPK(id); + + if (!exists) { + req.flash("error", "Answer not found"); + return res.redirect("/admin/questions-edit/" + question); + } + + await db.answer.realDelete(id); + + req.flash("success", "Answer was deleted successfully"); + return res.redirect("/admin/questions-edit/" + question); + } catch (error) { + console.error(error); + req.flash("error", error.message || "Something went wrong"); + return res.redirect("/admin/questions-edit/" + question); + } +}); + +module.exports = app; diff --git a/controllers/admin/Admin_order_controller.js b/controllers/admin/Admin_order_controller.js new file mode 100644 index 0000000..b86a688 --- /dev/null +++ b/controllers/admin/Admin_order_controller.js @@ -0,0 +1,179 @@ +"use strict"; + +const app = require("express").Router(); +const Sequelize = require("sequelize"); +const logger = require("../../services/LoggingService"); +let pagination = require("../../services/PaginationService"); +let SessionService = require("../../services/SessionService"); +let JwtService = require("../../services/JwtService"); +const ValidationService = require("../../services/ValidationService"); +const PermissionService = require("../../services/PermissionService"); +const UploadService = require("../../services/UploadService"); +const AuthService = require("../../services/AuthService"); +const db = require("../../models"); +const helpers = require("../../core/helpers"); + +const role = 1; + +app.get("/admin/orders/:num", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + try { + let session = req.session; + let paginateListViewModel = require("../../view_models/orders_admin_list_paginate_view_model"); + + var viewModel = new paginateListViewModel(db.order, "Orders", session.success, session.error, "/admin/orders"); + + const format = req.query.format ? req.query.format : "view"; + const direction = req.query.direction ? req.query.direction : "DESC"; + const per_page = req.query.per_page ? req.query.per_page : 10; + let order_by = req.query.order_by ? req.query.order_by : viewModel.get_field_column()[0]; + let orderAssociations = []; + viewModel.set_order_by(order_by); + let joins = order_by.includes(".") ? order_by.split(".") : []; + order_by = order_by.includes(".") ? joins[joins.length - 1] : order_by; + if (joins.length > 0) { + for (let i = joins.length - 1; i > 0; i--) { + orderAssociations.push(`${joins[i - 1]}`); + } + } + // Check for flash messages + const flashMessageSuccess = req.flash("success"); + if (flashMessageSuccess && flashMessageSuccess.length > 0) { + viewModel.success = flashMessageSuccess[0]; + } + const flashMessageError = req.flash("error"); + if (flashMessageError && flashMessageError.length > 0) { + viewModel.error = flashMessageError[0]; + } + + viewModel.set_id(req.query.id ? req.query.id : ""); + viewModel.set_customer_shopify_id(req.query.customer_shopify_id ? req.query.customer_shopify_id : ""); + viewModel.set_shopify_id(req.query.shopify_id ? req.query.shopify_id : ""); + viewModel.set_financial_status(req.query.financial_status ? req.query.financial_status : ""); + viewModel.set_fulfillment_status(req.query.fulfillment_status ? req.query.fulfillment_status : ""); + + let where = helpers.filterEmptyFields({ + id: viewModel.get_id(), + customer_shopify_id: viewModel.get_customer_shopify_id(), + shopify_id: viewModel.get_shopify_id(), + financial_status: viewModel.get_financial_status(), + fulfillment_status: viewModel.get_fulfillment_status(), + }); + + const count = await db.order._count(where, []); + + viewModel.set_total_rows(count); + viewModel.set_per_page(+per_page); + viewModel.set_page(+req.params.num); + viewModel.set_query(req.query); + viewModel.set_sort_base_url(`/admin/orders/${+req.params.num}`); + viewModel.set_sort(direction); + + const list = await db.order.getPaginated(viewModel.get_page() - 1 < 0 ? 0 : viewModel.get_page(), viewModel.get_per_page(), where, order_by, direction, orderAssociations); + + viewModel.set_list(list); + + if (format == "csv") { + const csv = viewModel.to_csv(); + return res + .set({ + "Content-Type": "text/csv", + "Content-Disposition": 'attachment; filename="export.csv"', + }) + .send(csv); + } + + // if (format != 'view') { + // res.json(viewModel.to_json()); + // } else { + // } + + return res.render("admin/Orders", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Orders", viewModel); + } +}); + +// APIS + +app.get("/admin/api/orders", JwtService.verifyTokenMiddleware(role), async function (req, res, next) { + try { + const user_id = req.user_id; + const session = req.session; + let listViewModel = require("../../view_models/orders_admin_list_paginate_view_model"); + let viewModel = new listViewModel(db.order, "Orders", session.success, session.error, "/admin/orders"); + const direction = req.query.direction ? req.query.direction : "ASC"; + const page = req.query.page ? parseInt(req.query.page) : 1; + const limit = req.query.limit ? parseInt(req.query.limit) : 10; + const offset = (page - 1) * limit; + let order_by = req.query.order_by ? req.query.order_by : viewModel.get_field_column()[0]; + let orderAssociations = []; + viewModel.set_order_by(order_by); + let joins = order_by.includes(".") ? order_by.split(".") : []; + order_by = order_by.includes(".") ? joins[joins.length - 1] : order_by; + if (joins.length > 0) { + for (let i = joins.length - 1; i > 0; i--) { + orderAssociations.push(`${joins[i - 1]}`); + } + } + + viewModel.set_id(req.query.id ? req.query.id : ""); + viewModel.set_customer_shopify_id(req.query.customer_shopify_id ? req.query.customer_shopify_id : ""); + viewModel.set_shopify_id(req.query.shopify_id ? req.query.shopify_id : ""); + viewModel.set_financial_status(req.query.financial_status ? req.query.financial_status : ""); + viewModel.set_fulfillment_status(req.query.fulfillment_status ? req.query.fulfillment_status : ""); + + let where = helpers.filterEmptyFields({ + id: viewModel.get_id(), + customer_shopify_id: viewModel.get_customer_shopify_id(), + shopify_id: viewModel.get_shopify_id(), + financial_status: viewModel.get_financial_status(), + fulfillment_status: viewModel.get_fulfillment_status(), + }); + + let include = []; + + const { rows: allItems, count } = await db.order.findAndCountAll({ + where: where, + limit: limit == 0 ? null : limit, + offset: offset, + include: include, + distinct: true, + }); + + const response = { + items: allItems, + page, + nextPage: count > offset + limit ? page + 1 : false, + retrievedCount: allItems.length, + fullCount: count, + }; + + return res.status(201).json({ success: true, data: response }); + } catch (error) { + console.error(error); + return res.status(500).json({ success: false, message: error.message || "Something went wrong" }); + } +}); + +app.get("/v1/api/order/customer", async function (req, res, next) { + try { + const { id } = req.query; + console.log(id); + if (!id) { + return res.status(400).json({ success: false, message: "Id not valid." }); + } + const orders = await db.order.findAll({ where: { customer_shopify_id: id }, order: [["updated_at", "DESC"]] }); + console.log(orders); + if (!orders || !orders.length) return res.status(404).json({ success: false, message: "Customer doesn't have any orders." }); + const answers = orders[0].answers ? JSON.parse(orders[0].answers) : []; + + return res.status(201).json({ success: true, data: answers }); + } catch (error) { + console.error(error); + return res.status(500).json({ success: false, message: error.message || "Something went wrong" }); + } +}); + +module.exports = app; diff --git a/controllers/admin/Admin_output_variables_controller.js b/controllers/admin/Admin_output_variables_controller.js new file mode 100644 index 0000000..66ab730 --- /dev/null +++ b/controllers/admin/Admin_output_variables_controller.js @@ -0,0 +1,358 @@ +"use strict"; + +const app = require("express").Router(); +// const Sequelize = require("sequelize"); +// const logger = require("../../services/LoggingService"); +// let pagination = require("../../services/PaginationService"); +// let JwtService = require("../../services/JwtService"); +let SessionService = require("../../services/SessionService"); +const ValidationService = require("../../services/ValidationService"); +// const PermissionService = require("../../services/PermissionService"); +// const UploadService = require("../../services/UploadService"); +// const AuthService = require("../../services/AuthService"); +const db = require("../../models"); +const helpers = require("../../core/helpers"); + +const role = 1; + +app.get("/admin/output-variables/:num", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + try { + let session = req.session; + let paginateListViewModel = require("../../view_models/output_variables_admin_list_paginate_view_model"); + + var viewModel = new paginateListViewModel(db.output_variable, "Output variables", session.success, session.error, "/admin/output-variables"); + + const format = req.query.format ? req.query.format : "view"; + const direction = req.query.direction ? req.query.direction : "ASC"; + const per_page = req.query.per_page ? req.query.per_page : 10; + let order_by = req.query.order_by ? req.query.order_by : viewModel.get_field_column()[0]; + let orderAssociations = []; + viewModel.set_order_by(order_by); + let joins = order_by.includes(".") ? order_by.split(".") : []; + order_by = order_by.includes(".") ? joins[joins.length - 1] : order_by; + if (joins.length > 0) { + for (let i = joins.length - 1; i > 0; i--) { + orderAssociations.push(`${joins[i - 1]}`); + } + } + // Check for flash messages + const flashMessageSuccess = req.flash("success"); + if (flashMessageSuccess && flashMessageSuccess.length > 0) { + viewModel.success = flashMessageSuccess[0]; + } + const flashMessageError = req.flash("error"); + if (flashMessageError && flashMessageError.length > 0) { + viewModel.error = flashMessageError[0]; + } + + viewModel.set_id(req.query.id ? req.query.id : ""); + viewModel.set_name(req.query.name ? req.query.name : ""); + + let where = helpers.filterEmptyFields({ + id: viewModel.get_id(), + name: viewModel.get_name(), + }); + + const count = await db.output_variable._count(where, []); + + viewModel.set_total_rows(count); + viewModel.set_per_page(+per_page); + viewModel.set_page(+req.params.num); + viewModel.set_query(req.query); + viewModel.set_sort_base_url(`/admin/output-variables/${+req.params.num}`); + viewModel.set_sort(direction); + + const list = await db.output_variable.getPaginated(viewModel.get_page() - 1 < 0 ? 0 : viewModel.get_page(), viewModel.get_per_page(), where, order_by, direction, orderAssociations); + for (const item of list) { + if (item.active_list) { + const actives = await db.active.findAll({ + where: { + id: JSON.parse(item.active_list), + }, + }); + item.active_list = actives.map((active) => { + return { name: active.name, id: active.id }; + }); + } + } + viewModel.set_list(list); + + if (format == "csv") { + const csv = viewModel.to_csv(); + return res + .set({ + "Content-Type": "text/csv", + "Content-Disposition": 'attachment; filename="export.csv"', + }) + .send(csv); + } + + // if (format != 'view') { + // res.json(viewModel.to_json()); + // } else { + // } + + return res.render("admin/Output_variables", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Output_variables", viewModel); + } +}); + +app.get("/admin/output-variables-add", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const outputVariablesAdminAddViewModel = require("../../view_models/output_variables_admin_add_view_model"); + + const viewModel = new outputVariablesAdminAddViewModel(db.output_variable, "Add output variable", "", "", "/admin/output-variables"); + viewModel.actives = await db.active.getAll(); + res.render("admin/Add_Output_variables", viewModel); +}); + +app.post( + "/admin/output-variables-add", + SessionService.verifySessionMiddleware(role, "admin"), + ValidationService.validateInput({ name: "required", active_list: "required" }, { "name.required": "Name is required", "active_list.required": "ActiveList is required" }), + async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const outputVariablesAdminAddViewModel = require("../../view_models/output_variables_admin_add_view_model"); + + const viewModel = new outputVariablesAdminAddViewModel(db.output_variable, "Add output variable", "", "", "/admin/output-variables"); + viewModel.actives = await db.active.getAll(); + + const { name, active_list, ranges, responses } = req.body; + let ranges_response = [], + i = 0; + if (Array.isArray(ranges) && Array.isArray(responses)) { + for (const range of ranges) { + let tempObj = {}; + tempObj[range] = responses[i]; + ranges_response.push(tempObj); + i++; + } + } else { + ranges_response.push({ + [ranges]: responses, + }); + } + viewModel.form_fields = { + ...viewModel.form_fields, + name, + active_list, + ranges_response, + }; + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render("admin/Add_Output_variables", viewModel); + } + + viewModel.session = req.session; + + const data = await db.output_variable.insert({ name, active_list: JSON.stringify(active_list), ranges_response: JSON.stringify(ranges_response) }); + + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Add_Output_variables", viewModel); + } + + req.flash("success", "Output variable created successfully"); + return res.redirect("/admin/output-variables/0"); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Add_Output_variables", viewModel); + } + } +); + +app.get("/admin/output-variables-edit/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const outputVariablesAdminEditViewModel = require("../../view_models/output_variables_admin_edit_view_model"); + + const viewModel = new outputVariablesAdminEditViewModel(db.output_variable, "Edit output variable", "", "", "/admin/output-variables"); + + try { + const exists = await db.output_variable.getByPK(id); + + if (!exists) { + req.flash("error", "Output variable not found"); + return res.redirect("/admin/output-variables/0"); + } + + viewModel.outputVariable = exists; + viewModel.actives = await db.active.getAll(); + return res.render("admin/Edit_Output_variables", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Edit_Output_variables", viewModel); + } +}); + +app.post( + "/admin/output-variables-edit/:id", + SessionService.verifySessionMiddleware(role, "admin"), + ValidationService.validateInput({ name: "required" }, { "name.required": "Name is required" }), + async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const outputVariablesAdminEditViewModel = require("../../view_models/output_variables_admin_edit_view_model"); + + const viewModel = new outputVariablesAdminEditViewModel(db.output_variable, "Edit output variable", "", "", "/admin/output-variables"); + + const { name, active_list, ranges, responses } = req.body; + let ranges_response = [], + i = 0; + + if (Array.isArray(ranges) && Array.isArray(responses)) { + for (const range of ranges) { + let tempObj = {}; + tempObj[range] = responses[i]; + ranges_response.push(tempObj); + i++; + } + } else { + ranges_response.push({ + [ranges]: responses, + }); + } + ranges_response = JSON.stringify(ranges_response); + viewModel.form_fields = { + ...viewModel.form_fields, + name, + active_list, + ranges_response, + }; + delete viewModel.form_fields.id; + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render("admin/Edit_Output_variables", viewModel); + } + + const resourceExists = await db.output_variable.getByPK(id); + if (!resourceExists) { + req.flash("error", "Output variable not found"); + return res.redirect("/admin/output-variables/0"); + } + + viewModel.outputVariable = resourceExists; + viewModel.session = req.session; + + let data = await db.output_variable.edit( + { + name, + active_list: active_list ? JSON.stringify(active_list) : null, + // active_list, + ranges_response, + }, + id + ); + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Edit_Output_variables", viewModel); + } + + req.flash("success", "Output variable edited successfully"); + + return res.redirect("/admin/output-variables/0"); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Edit_Output_variables", viewModel); + } + } +); + +app.get( + "/admin/output-variables-view/:id", + SessionService.verifySessionMiddleware(role, "admin"), + + async function (req, res, next) { + try { + let id = req.params.id; + + const outputVariablesAdminDetailViewModel = require("../../view_models/output_variables_admin_detail_view_model"); + + var viewModel = new outputVariablesAdminDetailViewModel(db.output_variable, "Output variable details", "", "", "/admin/output-variables"); + + const data = await db.output_variable.getByPK(id); + + if (data.active_list) { + const actives = await db.active.findAll({ + where: { + id: JSON.parse(data.active_list), + }, + }); + data.active_list = actives.map((active) => { + return { name: active.name, id: active.id }; + }); + } + + if (!data) { + viewModel.error = "Output variable not found"; + viewModel.detail_fields = { ...viewModel.detail_fields, id: "N/A", name: "N/A", active_list: "N/A", ranges_response: "N/A" }; + } else { + viewModel.detail_fields = { + ...viewModel.detail_fields, + id: data["id"] || "N/A", + name: data["name"] || "N/A", + active_list: data["active_list"] || "N/A", + ranges_response: data["ranges_response"] || "N/A", + }; + } + + res.render("admin/View_Output_variables", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + viewModel.detail_fields = { ...viewModel.detail_fields, id: "N/A", name: "N/A", active_list: "N/A", ranges_response: "N/A" }; + res.render("admin/View_Output_variables", viewModel); + } + } +); + +app.get("/admin/output-variables-delete/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + + const outputVariablesAdminDeleteViewModel = require("../../view_models/output_variables_admin_delete_view_model"); + + const viewModel = new outputVariablesAdminDeleteViewModel(db.output_variable); + + try { + const exists = await db.output_variable.getByPK(id); + + if (!exists) { + req.flash("error", "Output variable not found"); + return res.redirect("/admin/output-variables/0"); + } + + viewModel.session = req.session; + + await db.output_variable.realDelete(id); + + req.flash("success", "Output variable was deleted successfully"); + + return res.redirect("/admin/output-variables/0"); + } catch (error) { + console.error(error); + req.flash("error", error.message || "Something went wrong"); + return res.redirect("/admin/output-variables/0"); + } +}); + +module.exports = app; diff --git a/controllers/admin/Admin_question_controller.js b/controllers/admin/Admin_question_controller.js new file mode 100644 index 0000000..e8e599c --- /dev/null +++ b/controllers/admin/Admin_question_controller.js @@ -0,0 +1,624 @@ +"use strict"; + +const app = require("express").Router(); +const Sequelize = require("sequelize"); +const logger = require("../../services/LoggingService"); +let pagination = require("../../services/PaginationService"); +let SessionService = require("../../services/SessionService"); +let JwtService = require("../../services/JwtService"); +const ValidationService = require("../../services/ValidationService"); +const PermissionService = require("../../services/PermissionService"); +const UploadService = require("../../services/UploadService"); +const AuthService = require("../../services/AuthService"); +const db = require("../../models"); +const helpers = require("../../core/helpers"); + +const role = 1; + +app.get("/admin/questions/:num", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + try { + let session = req.session; + let paginateListViewModel = require("../../view_models/questions_admin_list_paginate_view_model"); + + var viewModel = new paginateListViewModel(db.question, "Questiones", session.success, session.error, "/admin/questions"); + + const format = req.query.format ? req.query.format : "view"; + const direction = req.query.direction ? req.query.direction : "ASC"; + const per_page = req.query.per_page ? req.query.per_page : 10; + // req.query.order_by ? req.query.order_by : + let order_by = [ + ["quiz_id", direction], + ["order", direction], + ]; + // Check for flash messages + const flashMessageSuccess = req.flash("success"); + if (flashMessageSuccess && flashMessageSuccess.length > 0) { + viewModel.success = flashMessageSuccess[0]; + } + const flashMessageError = req.flash("error"); + if (flashMessageError && flashMessageError.length > 0) { + viewModel.error = flashMessageError[0]; + } + + viewModel.set_id(req.query.id ? req.query.id : ""); + viewModel.set_quiz_id(req.query.quiz_id ? req.query.quiz_id : ""); + viewModel.set_type(req.query.type ? req.query.type : ""); + + let where = helpers.filterEmptyFields({ + id: viewModel.get_id(), + quiz_id: viewModel.get_quiz_id(), + type: viewModel.get_type(), + }); + + const count = await db.question._count(where, [ + { model: db.quiz, as: "quiz", required: true }, + { model: db.answer, as: "answers", required: false }, + ]); + + viewModel.set_total_rows(count); + viewModel.set_per_page(+per_page); + viewModel.set_page(+req.params.num); + viewModel.set_query(req.query); + viewModel.set_sort_base_url(`/admin/questions/${+req.params.num}`); + viewModel.set_sort(direction); + + const list = await db.question.getPaginatedV2(viewModel.get_page() - 1 < 0 ? 0 : viewModel.get_page(), viewModel.get_per_page(), where, order_by, direction, [ + { model: db.quiz, as: "quiz", required: true }, + { model: db.answer, as: "answers", required: false }, + ]); + + viewModel.set_list(list); + + viewModel.quiz = await db.quiz; + + if (format == "csv") { + const csv = viewModel.to_csv(); + return res + .set({ + "Content-Type": "text/csv", + "Content-Disposition": 'attachment; filename="export.csv"', + }) + .send(csv); + } + return res.render("admin/Questions", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Questions", viewModel); + } +}); + +app.get("/admin/questions-add", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const questionsAdminAddViewModel = require("../../view_models/questions_admin_add_view_model"); + + const viewModel = new questionsAdminAddViewModel(db.question, "Add question", "", "", "/admin/questions"); + viewModel.quizzes = await db.quiz.getAll(); + for (const quiz of viewModel.quizzes) { + const question = await db.question.findAll({ + where: { + quiz_id: quiz.id, + }, + limit: 1, + order: [["order", "DESC"]], + }); + quiz.lastOrder = question[0].order; + } + viewModel.questions = await db.question.getAll(); + viewModel.outputVariables = await db.output_variable.getAll(); + res.render("admin/Add_Questions", viewModel); +}); + +app.post( + "/admin/questions-add", + SessionService.verifySessionMiddleware(role, "admin"), + ValidationService.validateInput( + { quiz_id: "required", question: "required", type: "required", order: "required" }, + { + "quiz_id.required": "QuizId is required", + "question.required": "Question is required", + "type.required": "Type is required", + "order.required": "Order is required", + } + ), + async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const questionsAdminAddViewModel = require("../../view_models/questions_admin_add_view_model"); + + const viewModel = new questionsAdminAddViewModel(db.question, "Add question", "", "", "/admin/questions"); + viewModel.quizzes = await db.quiz.getAll(); + viewModel.questions = await db.question.getAll(); + viewModel.outputVariables = await db.output_variable.getAll(); + + // TODO use separate controller for image upload + // {{{upload_field_setter}}} + + const { quiz_id, question, order, image_width, image_height, note, note_type, depends_on, slider_range, output_variable_name, weight, extra_output_variable, type } = req.body; + + viewModel.form_fields = { + ...viewModel.form_fields, + quiz_id, + question, + order, + note, + image_width, + image_height, + note_type, + depends_on, + slider_range, + output_variable_name, + weight, + extra_output_variable, + type, + }; + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render("admin/Add_Questions", viewModel); + } + + viewModel.session = req.session; + + const data = await db.question.insert({ + quiz_id, + question, + order, + image_width: image_width ? image_width : null, + image_height: image_height ? image_height : null, + note: note ? note : null, + note_type: note_type ? note_type : null, + depends_on: depends_on ? depends_on : null, + slider_range: slider_range ? slider_range : null, + output_variable_name: output_variable_name ? output_variable_name : null, + weight: weight ? weight : null, + extra_output_variable: extra_output_variable ? extra_output_variable : null, + type, + }); + + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Add_Questions", viewModel); + } + + req.flash("success", "Question created successfully"); + return res.redirect("/admin/questions/0"); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Add_Questions", viewModel); + } + } +); + +app.get("/admin/questions-edit/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const questionsAdminEditViewModel = require("../../view_models/questions_admin_edit_view_model"); + + const viewModel = new questionsAdminEditViewModel(db.question, "Edit question", "", "", "/admin/questions"); + const flashMessageSuccess = req.flash("success"); + if (flashMessageSuccess && flashMessageSuccess.length > 0) { + viewModel.success = flashMessageSuccess[0]; + } + const flashMessageError = req.flash("error"); + if (flashMessageError && flashMessageError.length > 0) { + viewModel.error = flashMessageError[0]; + } + try { + const exists = await db.question.findOne({ + where: { id }, + order: [["answers", "order", "ASC"]], + include: [{ model: db.answer, as: "answers", include: [{ model: db.image, as: "image" }] }], + }); + + if (!exists) { + req.flash("error", "Question not found"); + return res.redirect("/admin/questions/0"); + } + const values = exists; + Object.keys(viewModel.form_fields).forEach((field) => { + viewModel.form_fields[field] = values[field] || ""; + }); + viewModel.question = exists; + viewModel.quiz = db.quiz; + viewModel.quizzes = await db.quiz.getAll(); + viewModel.questions = await db.question.getAll(); + viewModel.outputVariables = await db.output_variable.getAll(); + viewModel.actives = await db.active.getAll(); + viewModel.nextQuestionId; + let lastQuestionId = await db.question.findAll({ order_by: ["id", "DESC"] }).then((data) => data[0].id); + let found = false; + let nextId = parseInt(exists.id) + 1; + while (!found) { + const nextQuestion = await db.question.getByPK(nextId); + if (nextQuestion) { + viewModel.nextQuestionId = nextQuestion.id; + found = true; + } else { + if (nextId >= lastQuestionId) break; + } + nextId++; + } + //remaining actives unselected + if (exists.answers && exists.answers?.length > 0) { + viewModel.lastOrderCount = exists.answers[exists.answers.length - 1].order; + } + + return res.render("admin/Edit_Questions", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Edit_Questions", viewModel); + } +}); +app.get("/admin/answers/refill/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + try { + const actives = await db.active.getAll(); + await db.answer.destroy({ where: { question_id: id } }); + + await db.answer.insert({ + question_id: id, + order: 1, + answer: "Banana", + }); + await db.answer.insert({ + question_id: id, + order: 2, + answer: "Olive", + }); + await db.answer.insert({ + question_id: id, + order: 3, + answer: "Sunflowers", + }); + + let order = 3; + for (const active of actives) { + if (active.name !== "Blank") { + await db.answer.insert({ + question_id: id, + order: order + 1, + answer: active.name, + }); + } + order++; + } + req.flash("success", "Answers refilled successfully"); + return res.redirect("/admin/questions-edit/" + id); + } catch (error) { + console.error(error); + req.flash("error", error.message || "Something went wrong"); + return res.redirect("/admin/questions-edit/" + id); + } +}); + +app.post( + "/admin/questions-edit/:id", + SessionService.verifySessionMiddleware(role, "admin"), + ValidationService.validateInput( + { quiz_id: "required", question: "required", type: "required", question_order: "required" }, + { + "quiz_id.required": "QuizId is required", + "question.required": "Question is required", + "type.required": "Type is required", + "question_order.required": "Order is required", + } + ), + async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const questionsAdminEditViewModel = require("../../view_models/questions_admin_edit_view_model"); + + const viewModel = new questionsAdminEditViewModel(db.question, "Edit question", "", "", "/admin/questions"); + viewModel.quizzes = await db.quiz.getAll(); + viewModel.questions = await db.question.getAll(); + viewModel.outputVariables = await db.output_variable.getAll(); + viewModel.nextQuestionId; + let lastQuestionId = await db.question.findAll({ order_by: ["id", "DESC"] }).then((data) => data[0].id); + let found = false; + let nextId = parseInt(id) + 1; + while (!found) { + const nextQuestion = await db.question.getByPK(nextId); + if (nextQuestion) { + viewModel.nextQuestionId = nextQuestion.id; + found = true; + } else { + if (nextId >= lastQuestionId) break; + } + nextId++; + } + + const { quiz_id, question, question_order, note, image_width, image_height, note_type, depends_on, slider_range, output_variable_name, weight, extra_output_variable, type } = req.body; + const { ids, answer, answer_value, hide_answer, explaination, image_id, response_header, response_body } = req.body; + + viewModel.form_fields = { + ...viewModel.form_fields, + quiz_id, + question, + order: question_order, + note, + image_width, + image_height, + note_type, + depends_on, + slider_range, + output_variable_name, + weight, + extra_output_variable, + type, + }; + + delete viewModel.form_fields.id; + + try { + if (req.validationError) { + console.error(error); + req.flash("error", req.validationError); + return res.redirect(`/admin/questions-edit/${id}`); + } + + const resourceExists = await db.question.getByPK(id); + if (!resourceExists) { + req.flash("error", "Question not found"); + return res.redirect(`/admin/questions-edit/${id}`); + } + + viewModel.session = req.session; + await db.question.edit( + { + quiz_id, + question, + question_order, + type, + image_width: image_width ? image_width : null, + image_height: image_height ? image_height : null, + note: note ? note : null, + note_type: note_type ? note_type : null, + depends_on: depends_on ? depends_on : null, + slider_range: slider_range ? slider_range : null, + output_variable_name: output_variable_name ? output_variable_name : null, + weight: weight ? weight : null, + extra_output_variable: extra_output_variable ? extra_output_variable : null, + }, + id + ); + if (Array.isArray(ids) && ids.length) { + for (let i = 0; i < ids.length; i++) { + await db.answer.edit( + { + answer: answer[i] ? answer[i] : null, + answer_value: answer_value[i] ? answer_value[i] : null, + hide_answer: hide_answer[i] ? hide_answer[i] : null, + order: i + 1, + explaination: explaination[i] ? explaination[i] : null, + image_id: image_id[i] ? image_id[i] : null, + response_header: response_header[i] ? response_header[i] : null, + response_body: response_body[i] ? response_body[i] : null, + black_list_actives: req.body[`black_list_actives_${ids[i]}`] + ? !Array.isArray(req.body[`black_list_actives_${ids[i]}`]) + ? JSON.stringify([req.body[`black_list_actives_${ids[i]}`]]) + : JSON.stringify(req.body[`black_list_actives_${ids[i]}`]) + : null, + }, + ids[i] + ); + } + } else if (!Array.isArray(ids) && ids) { + await db.answer.edit( + { + answer: answer ? answer : null, + answer_value: answer_value ? answer_value : null, + hide_answer: hide_answer ? hide_answer : null, + order: 1, + explaination: explaination ? explaination : null, + image_id: image_id ? image_id : null, + response_header: response_header ? response_header : null, + response_body: response_body ? response_body : null, + black_list_actives: req.body[`black_list_actives_${ids}`] + ? !Array.isArray(req.body[`black_list_actives_${ids}`]) + ? JSON.stringify([req.body[`black_list_actives_${ids}`]]) + : JSON.stringify(req.body[`black_list_actives_${ids}`]) + : null, + }, + ids + ); + } + + req.flash("success", "Question edited successfully"); + return res.redirect(`/admin/questions-edit/${id}`); + } catch (error) { + console.error(error); + req.flash("error", error.message || "Something went wrong"); + return res.redirect(`/admin/questions-edit/${id}`); + } + } +); + +app.get( + "/admin/questions-view/:id", + SessionService.verifySessionMiddleware(role, "admin"), + + async function (req, res, next) { + try { + let id = req.params.id; + + const questionsAdminDetailViewModel = require("../../view_models/questions_admin_detail_view_model"); + + var viewModel = new questionsAdminDetailViewModel(db.question, "Question details", "", "", "/admin/questions"); + + const data = await db.question.get_question_quiz(id, db); + data.type = db.question.type_mapping()[data.type]; + data.target = db.question.target_mapping()[data.target]; + data.note_type = db.question.note_type_mapping()[data.note_type]; + + if (!data) { + viewModel.error = "Question not found"; + viewModel.detail_fields = { + ...viewModel.detail_fields, + id: "N/A", + "quiz.name": "N/A", + question: "N/A", + question_arguments: "N/A", + order: "N/A", + note: "N/A", + note_type: "N/A", + target: "N/A", + response: "N/A", + save_response_into: "N/A", + depends_on: "N/A", + slider_range: "N/A", + output_variable_name: "N/A", + weight: "N/A", + extra_output_variable: "N/A", + type: "N/A", + }; + } else { + viewModel.detail_fields = { + ...viewModel.detail_fields, + id: data["id"] || "N/A", + "quiz.name": data["quiz"]["name"] || "N/A", + question: data["question"] || "N/A", + question_arguments: data["question_arguments"] || "N/A", + order: data["order"] || "N/A", + note: data["note"] || "N/A", + note_type: data["note_type"] || "N/A", + target: data["target"] || "N/A", + response: data["response"] || "N/A", + save_response_into: data["save_response_into"] || "N/A", + depends_on: data["depends_on"] || "N/A", + slider_range: data["slider_range"] || "N/A", + output_variable_name: data["output_variable_name"] || "N/A", + weight: data["weight"] || "N/A", + extra_output_variable: data["extra_output_variable"] || "N/A", + type: data["type"] || "N/A", + }; + } + + res.render("admin/View_Questions", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + viewModel.detail_fields = { + ...viewModel.detail_fields, + id: "N/A", + "quiz.name": "N/A", + question: "N/A", + question_arguments: "N/A", + order: "N/A", + note: "N/A", + note_type: "N/A", + target: "N/A", + response: "N/A", + save_response_into: "N/A", + depends_on: "N/A", + slider_range: "N/A", + output_variable_name: "N/A", + weight: "N/A", + extra_output_variable: "N/A", + type: "N/A", + }; + res.render("admin/View_Questions", viewModel); + } + } +); + +app.get("/admin/questions-delete/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + + const questionsAdminDeleteViewModel = require("../../view_models/questions_admin_delete_view_model"); + + const viewModel = new questionsAdminDeleteViewModel(db.question); + + try { + const exists = await db.question.getByPK(id); + + if (!exists) { + req.flash("error", "Question not found"); + return res.redirect("/admin/questions/0"); + } + + viewModel.session = req.session; + + await db.question.realDelete(id); + await db.answer.destroy({ + where: { question_id: id }, + }); + req.flash("success", "Question was deleted successfully"); + + return res.redirect("/admin/questions/0"); + } catch (error) { + console.error(error); + req.flash("error", error.message || "Something went wrong"); + return res.redirect("/admin/questions/0"); + } +}); + +// APIS + +app.get("/admin/api/questions", async function (req, res, next) { + try { + const session = req.session; + let listViewModel = require("../../view_models/questions_admin_list_paginate_view_model"); + let viewModel = new listViewModel(db.question, "Questiones", session.success, session.error, "/admin/questions"); + const direction = req.query.direction ? req.query.direction : "ASC"; + const page = req.query.page ? parseInt(req.query.page) : 1; + const limit = req.query.limit ? parseInt(req.query.limit) : 10; + const offset = (page - 1) * limit; + let order_by = req.query.order_by ? req.query.order_by : viewModel.get_field_column()[0]; + let orderAssociations = []; + viewModel.set_order_by(order_by); + let joins = order_by.includes(".") ? order_by.split(".") : []; + order_by = order_by.includes(".") ? joins[joins.length - 1] : order_by; + if (joins.length > 0) { + for (let i = joins.length - 1; i > 0; i--) { + orderAssociations.push(`${joins[i - 1]}`); + } + } + viewModel.set_id(req.query.id ? req.query.id : ""); + viewModel.set_quiz_id(req.query.quiz_id ? req.query.quiz_id : ""); + viewModel.set_type(req.query.type ? req.query.type : ""); + + let where = helpers.filterEmptyFields({ + id: viewModel.get_id(), + quiz_id: viewModel.get_quiz_id(), + type: viewModel.get_type(), + }); + const { rows: allItems, count } = await db.question.findAndCountAll({ + where: where, + limit: limit == 0 ? null : limit, + offset: offset, + include: { all: true, nested: true }, + order: [["id", direction]], + distinct: true, + }); + + const response = { + items: allItems, + page, + nextPage: limit == 0 ? false : count > offset + limit ? page + 1 : false, + retrievedCount: allItems.length, + fullCount: count, + }; + + return res.status(201).json({ success: true, data: response }); + } catch (error) { + console.error(error); + return res.status(500).json({ success: false, message: error.message || "Something went wrong" }); + } +}); +module.exports = app; diff --git a/controllers/admin/Admin_quiz_controller.js b/controllers/admin/Admin_quiz_controller.js new file mode 100644 index 0000000..8cd257d --- /dev/null +++ b/controllers/admin/Admin_quiz_controller.js @@ -0,0 +1,460 @@ +"use strict"; + +const app = require("express").Router(); +const Sequelize = require("sequelize"); +const logger = require("../../services/LoggingService"); +let pagination = require("../../services/PaginationService"); +let SessionService = require("../../services/SessionService"); +let JwtService = require("../../services/JwtService"); +const ValidationService = require("../../services/ValidationService"); +const PermissionService = require("../../services/PermissionService"); +const UploadService = require("../../services/UploadService"); +const AuthService = require("../../services/AuthService"); +const db = require("../../models"); +const helpers = require("../../core/helpers"); + +const role = 1; + +app.get("/admin/quizzes/:num", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + try { + let session = req.session; + let paginateListViewModel = require("../../view_models/quizzes_admin_list_paginate_view_model"); + + var viewModel = new paginateListViewModel(db.quiz, "Quizzes", session.success, session.error, "/admin/quizzes"); + + const format = req.query.format ? req.query.format : "view"; + const direction = req.query.direction ? req.query.direction : "ASC"; + const per_page = req.query.per_page ? req.query.per_page : 10; + let order_by = req.query.order_by ? req.query.order_by : viewModel.get_field_column()[0]; + let orderAssociations = []; + viewModel.set_order_by(order_by); + let joins = order_by.includes(".") ? order_by.split(".") : []; + order_by = order_by.includes(".") ? joins[joins.length - 1] : order_by; + if (joins.length > 0) { + for (let i = joins.length - 1; i > 0; i--) { + orderAssociations.push(`${joins[i - 1]}`); + } + } + // Check for flash messages + const flashMessageSuccess = req.flash("success"); + if (flashMessageSuccess && flashMessageSuccess.length > 0) { + viewModel.success = flashMessageSuccess[0]; + } + const flashMessageError = req.flash("error"); + if (flashMessageError && flashMessageError.length > 0) { + viewModel.error = flashMessageError[0]; + } + + viewModel.set_id(req.query.id ? req.query.id : ""); + viewModel.set_name(req.query.name ? req.query.name : ""); + + let where = helpers.filterEmptyFields({ + id: viewModel.get_id(), + name: viewModel.get_name(), + }); + + let associatedWhere = helpers.filterEmptyFields({}); + const isAssociationRequired = Object.keys(associatedWhere).length > 0 ? true : false; + + const count = await db.quiz._count(where, [{ model: db.question, where: associatedWhere, required: isAssociationRequired, as: "questions" }]); + + viewModel.set_total_rows(count); + viewModel.set_per_page(+per_page); + viewModel.set_page(+req.params.num); + viewModel.set_query(req.query); + viewModel.set_sort_base_url(`/admin/quizzes/${+req.params.num}`); + viewModel.set_sort(direction); + + const list = await db.quiz.get_question_paginated( + db, + associatedWhere, + viewModel.get_page() - 1 < 0 ? 0 : viewModel.get_page(), + viewModel.get_per_page(), + where, + order_by, + direction, + orderAssociations + ); + + viewModel.set_list(list); + + viewModel.question = await db.question; + + if (format == "csv") { + const csv = viewModel.to_csv(); + return res + .set({ + "Content-Type": "text/csv", + "Content-Disposition": 'attachment; filename="export.csv"', + }) + .send(csv); + } + + // if (format != 'view') { + // res.json(viewModel.to_json()); + // } else { + // } + + return res.render("admin/Quizzes", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Quizzes", viewModel); + } +}); + +app.get("/admin/quizzes-add", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const quizzesAdminAddViewModel = require("../../view_models/quizzes_admin_add_view_model"); + + const viewModel = new quizzesAdminAddViewModel(db.quiz, "Add quiz", "", "", "/admin/quizzes"); + + res.render("admin/Add_Quizzes", viewModel); +}); + +app.post( + "/admin/quizzes-add", + SessionService.verifySessionMiddleware(role, "admin"), + ValidationService.validateInput({ name: "required" }, { "name.required": "Name is required" }), + async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const quizzesAdminAddViewModel = require("../../view_models/quizzes_admin_add_view_model"); + + const viewModel = new quizzesAdminAddViewModel(db.quiz, "Add quiz", "", "", "/admin/quizzes"); + + // TODO use separate controller for image upload + // {{{upload_field_setter}}} + + const { name, description } = req.body; + + viewModel.form_fields = { + ...viewModel.form_fields, + name, + description, + }; + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render("admin/Add_Quizzes", viewModel); + } + + viewModel.session = req.session; + + const data = await db.quiz.insert({ name, description }); + + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Add_Quizzes", viewModel); + } + + await db.activity_log.insert({ + action: "ADD", + name: "Admin_quiz_controller.js", + portal: "admin", + data: JSON.stringify({ name, description }), + }); + + req.flash("success", "Quiz created successfully"); + return res.redirect("/admin/quizzes/0"); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Add_Quizzes", viewModel); + } + } +); + +app.get("/admin/quizzes-edit/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const quizzesAdminEditViewModel = require("../../view_models/quizzes_admin_edit_view_model"); + + const viewModel = new quizzesAdminEditViewModel(db.quiz, "Edit quiz", "", "", "/admin/quizzes"); + + try { + const exists = await db.quiz.getByPK(id); + + if (!exists) { + req.flash("error", "Quiz not found"); + return res.redirect("/admin/quizzes/0"); + } + const values = exists; + Object.keys(viewModel.form_fields).forEach((field) => { + viewModel.form_fields[field] = values[field] || ""; + }); + viewModel.question = db.question; + return res.render("admin/Edit_Quizzes", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Edit_Quizzes", viewModel); + } +}); + +app.post( + "/admin/quizzes-edit/:id", + SessionService.verifySessionMiddleware(role, "admin"), + ValidationService.validateInput({ name: "required" }, { "name.required": "Name is required" }), + async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const quizzesAdminEditViewModel = require("../../view_models/quizzes_admin_edit_view_model"); + + const viewModel = new quizzesAdminEditViewModel(db.quiz, "Edit quiz", "", "", "/admin/quizzes"); + + const { name, description } = req.body; + + viewModel.form_fields = { + ...viewModel.form_fields, + name, + description, + }; + + delete viewModel.form_fields.id; + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render("admin/Edit_Quizzes", viewModel); + } + + const resourceExists = await db.quiz.getByPK(id); + if (!resourceExists) { + req.flash("error", "Quiz not found"); + return res.redirect("/admin/quizzes/0"); + } + + viewModel.session = req.session; + + let data = await db.quiz.edit({ name, description }, id); + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Edit_Quizzes", viewModel); + } + + if (resourceExists.questions) { + if (resourceExists.questions.length == 1) { + resourceExists.questions.forEach(async (item) => { + data = await db.question.edit(helpers.filterEmptyFields({}), item.id); + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Edit_Quizzes", viewModel); + } + }); + } else { + resourceExists.questions.forEach(async (item, index) => { + data = await db.question.edit(helpers.filterEmptyFields({}), item.id); + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Edit_Quizzes", viewModel); + } + }); + } + } + + await db.activity_log.insert({ + action: "EDIT", + name: "Admin_quiz_controller.js", + portal: "admin", + data: JSON.stringify({ name, description }), + }); + + req.flash("success", "Quiz edited successfully"); + + return res.redirect("/admin/quizzes/0"); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Edit_Quizzes", viewModel); + } + } +); + +app.get( + "/admin/quizzes-view/:id", + SessionService.verifySessionMiddleware(role, "admin"), + + async function (req, res, next) { + try { + let id = req.params.id; + + const quizzesAdminDetailViewModel = require("../../view_models/quizzes_admin_detail_view_model"); + + var viewModel = new quizzesAdminDetailViewModel(db.quiz, "Quiz details", "", "", "/admin/quizzes"); + + const data = await db.quiz.getByPK(id); + + if (!data) { + viewModel.error = "Quiz not found"; + viewModel.detail_fields = { ...viewModel.detail_fields, id: "N/A", name: "N/A", description: "N/A" }; + } else { + viewModel.detail_fields = { + ...viewModel.detail_fields, + id: data["id"] || "N/A", + name: data["name"] || "N/A", + description: data["description"] || "N/A", + }; + } + + res.render("admin/View_Quizzes", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + viewModel.detail_fields = { ...viewModel.detail_fields, id: "N/A", name: "N/A", description: "N/A" }; + res.render("admin/View_Quizzes", viewModel); + } + } +); + +app.get("/admin/quizzes-delete/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + + const quizzesAdminDeleteViewModel = require("../../view_models/quizzes_admin_delete_view_model"); + + const viewModel = new quizzesAdminDeleteViewModel(db.quiz); + + try { + const exists = await db.quiz.getByPK(id); + + if (!exists) { + req.flash("error", "Quiz not found"); + return res.redirect("/admin/quizzes/0"); + } + + viewModel.session = req.session; + + await db.quiz.realDelete(id); + await db.question.destroy({ + where: { + quiz_id: id, + }, + }); + + await db.activity_log.insert({ + action: "DELETE", + name: "Admin_quiz_controller.js", + portal: "admin", + data: JSON.stringify(exists), + }); + + req.flash("success", "Quiz was deleted successfully"); + + return res.redirect("/admin/quizzes/0"); + } catch (error) { + console.error(error); + req.flash("error", error.message || "Something went wrong"); + return res.redirect("/admin/quizzes/0"); + } +}); + +// APIS + +app.get("/admin/api/quizzes", async function (req, res, next) { + try { + const session = req.session; + let listViewModel = require("../../view_models/quizzes_admin_list_paginate_view_model"); + let viewModel = new listViewModel(db.quiz, "Quizzes", session.success, session.error, "/admin/quizzes"); + const direction = req.query.direction ? req.query.direction : "ASC"; + const page = req.query.page ? parseInt(req.query.page) : 1; + const limit = req.query.limit ? parseInt(req.query.limit) : 10; + const offset = (page - 1) * limit; + let order_by = req.query.order_by ? req.query.order_by : viewModel.get_field_column()[0]; + let orderAssociations = []; + viewModel.set_order_by(order_by); + let joins = order_by.includes(".") ? order_by.split(".") : []; + order_by = order_by.includes(".") ? joins[joins.length - 1] : order_by; + if (joins.length > 0) { + for (let i = joins.length - 1; i > 0; i--) { + orderAssociations.push(`${joins[i - 1]}`); + } + } + + viewModel.set_id(req.query.id ? req.query.id : ""); + viewModel.set_name(req.query.name ? req.query.name : ""); + + let where = helpers.filterEmptyFields({ + id: viewModel.get_id(), + name: viewModel.get_name(), + }); + + const { rows: allItems, count } = await db.quiz.findAndCountAll({ + where: where, + limit: limit == 0 ? null : limit, + offset: offset, + // include: { all: true, nested: true }, + include: [ + { + model: db.question, + as: "questions", + order: [["order", "ASC"]], + separate: true, + required: false, + include: [ + { + model: db.answer, + as: "answers", + required: false, + separate: true, + order: [["order", "ASC"]], + include: [{ model: db.image, as: "image", required: false }], + }, + ], + }, + ], + order: [["id", direction]], + distinct: true, + }); + + for (const row of allItems) { + if (row.questions) { + for (const question of row.questions) { + if (question.answers) { + for (const answer of question.answers) { + if (answer.black_list_actives) { + const blActivesListIds = JSON.parse(answer.black_list_actives); + const blActivesListNames = await db.active + .findAll({ + where: { + id: blActivesListIds, + }, + }) + .then((data) => { + return data.map((item) => { + item = item.name; + return item; + }); + }); + answer.black_list_actives = JSON.stringify(blActivesListNames); + } + } + } + } + } + } + const response = { + items: allItems, + page, + nextPage: limit == 0 ? false : count > offset + limit ? page + 1 : false, + retrievedCount: allItems.length, + fullCount: count, + }; + + return res.status(201).json({ success: true, data: response }); + } catch (error) { + console.error(error); + return res.status(500).json({ success: false, message: error.message || "Something went wrong" }); + } +}); + +module.exports = app; diff --git a/controllers/admin/Admin_result_profile_controller.js b/controllers/admin/Admin_result_profile_controller.js new file mode 100644 index 0000000..59355ff --- /dev/null +++ b/controllers/admin/Admin_result_profile_controller.js @@ -0,0 +1,476 @@ +"use strict"; + +const app = require("express").Router(); +const Sequelize = require("sequelize"); +const logger = require("../../services/LoggingService"); +let pagination = require("../../services/PaginationService"); +let SessionService = require("../../services/SessionService"); +let JwtService = require("../../services/JwtService"); +const ValidationService = require("../../services/ValidationService"); +const PermissionService = require("../../services/PermissionService"); +const UploadService = require("../../services/UploadService"); +const AuthService = require("../../services/AuthService"); +const db = require("../../models"); +const helpers = require("../../core/helpers"); + +const role = 1; + +app.get("/admin/profile-sections/:num", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + try { + let session = req.session; + let paginateListViewModel = require("../../view_models/result_profile_admin_list_paginate_view_model"); + + var viewModel = new paginateListViewModel(db.result_profile, "Profile sections", session.success, session.error, "/admin/profile-sections"); + + const format = req.query.format ? req.query.format : "view"; + const direction = req.query.direction ? req.query.direction : "ASC"; + const per_page = req.query.per_page ? req.query.per_page : 10; + let order_by = req.query.order_by ? req.query.order_by : viewModel.get_field_column()[0]; + let orderAssociations = []; + viewModel.set_order_by(order_by); + let joins = order_by.includes(".") ? order_by.split(".") : []; + order_by = order_by.includes(".") ? joins[joins.length - 1] : order_by; + if (joins.length > 0) { + for (let i = joins.length - 1; i > 0; i--) { + orderAssociations.push(`${joins[i - 1]}`); + } + } + // Check for flash messages + const flashMessageSuccess = req.flash("success"); + if (flashMessageSuccess && flashMessageSuccess.length > 0) { + viewModel.success = flashMessageSuccess[0]; + } + const flashMessageError = req.flash("error"); + if (flashMessageError && flashMessageError.length > 0) { + viewModel.error = flashMessageError[0]; + } + + viewModel.set_id(req.query.id ? req.query.id : ""); + viewModel.set_section_title(req.query.section_title ? req.query.section_title : ""); + + let where = helpers.filterEmptyFields({ + id: viewModel.get_id(), + section_title: viewModel.get_section_title(), + }); + + const count = await db.result_profile._count(where, []); + + viewModel.set_total_rows(count); + viewModel.set_per_page(+per_page); + viewModel.set_page(+req.params.num); + viewModel.set_query(req.query); + viewModel.set_sort_base_url(`/admin/profile-sections/${+req.params.num}`); + viewModel.set_sort(direction); + + const list = await db.result_profile.getPaginated(viewModel.get_page() - 1 < 0 ? 0 : viewModel.get_page(), viewModel.get_per_page(), where, order_by, direction, orderAssociations); + + for (const item of list) { + if (item.output_variable_list) { + const parsedList = JSON.parse(item.output_variable_list); + let actualList = await db.output_variable.findAll({ + where: { + id: parsedList, + }, + }); + actualList = actualList.map((ov) => ov.name); + item.output_variable_list = actualList; + } + } + + viewModel.set_list(list); + + if (format == "csv") { + const csv = viewModel.to_csv(); + return res + .set({ + "Content-Type": "text/csv", + "Content-Disposition": 'attachment; filename="export.csv"', + }) + .send(csv); + } + + // if (format != 'view') { + // res.json(viewModel.to_json()); + // } else { + // } + + return res.render("admin/Result_profile", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Result_profile", viewModel); + } +}); + +app.get("/admin/profile-sections-add", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const resultProfileAdminAddViewModel = require("../../view_models/result_profile_admin_add_view_model"); + + const viewModel = new resultProfileAdminAddViewModel(db.result_profile, "Add result profile", "", "", "/admin/profile-sections"); + viewModel.output_variables = await db.output_variable.getAll(); + res.render("admin/Add_Result_profile", viewModel); +}); + +app.post("/admin/profile-sections-add", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const resultProfileAdminAddViewModel = require("../../view_models/result_profile_admin_add_view_model"); + + const viewModel = new resultProfileAdminAddViewModel(db.result_profile, "Add result profile", "", "", "/admin/profile-sections"); + viewModel.output_variables = await db.output_variable.getAll(); + // TODO use separate controller for image upload + // {{{upload_field_setter}}} + + const { section_title, output_variable_list = [] } = req.body; + + viewModel.form_fields = { + ...viewModel.form_fields, + section_title, + }; + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render("admin/Add_Result_profile", viewModel); + } + + viewModel.session = req.session; + output_variable_list; + const data = await db.result_profile.insert({ + section_title, + output_variable_list: !Array.isArray(output_variable_list) ? JSON.stringify([output_variable_list]) : JSON.stringify(output_variable_list), + }); + + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Add_Result_profile", viewModel); + } + + req.flash("success", "Result profile created successfully"); + return res.redirect("/admin/profile-sections/0"); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Add_Result_profile", viewModel); + } +}); + +app.get("/admin/profile-sections-edit/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const resultProfileAdminEditViewModel = require("../../view_models/result_profile_admin_edit_view_model"); + + const viewModel = new resultProfileAdminEditViewModel(db.result_profile, "Edit result profile", "", "", "/admin/profile-sections"); + + try { + const exists = await db.result_profile.getByPK(id); + + if (!exists) { + req.flash("error", "Result profile not found"); + return res.redirect("/admin/profile-sections/0"); + } + const values = exists; + Object.keys(viewModel.form_fields).forEach((field) => { + viewModel.form_fields[field] = values[field] || ""; + }); + if (viewModel.form_fields["output_variable_list"]) { + const parsedList = JSON.parse(viewModel.form_fields["output_variable_list"]); + let actualList = await db.output_variable.findAll({ + where: { + id: parsedList, + }, + }); + actualList = actualList.map((ov) => ov.name); + viewModel.form_fields["output_variable_list"] = actualList; + } + viewModel.output_variables = await db.output_variable.getAll(); + return res.render("admin/Edit_Result_profile", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Edit_Result_profile", viewModel); + } +}); + +app.post("/admin/profile-sections-edit/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const resultProfileAdminEditViewModel = require("../../view_models/result_profile_admin_edit_view_model"); + + const viewModel = new resultProfileAdminEditViewModel(db.result_profile, "Edit result profile", "", "", "/admin/profile-sections"); + + let { section_title, output_variable_list = [] } = req.body; + + viewModel.form_fields = { + ...viewModel.form_fields, + section_title, + output_variable_list, + }; + + delete viewModel.form_fields.id; + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render("admin/Edit_Result_profile", viewModel); + } + + const resourceExists = await db.result_profile.getByPK(id); + if (!resourceExists) { + req.flash("error", "Result profile not found"); + return res.redirect("/admin/profile-sections/0"); + } + + viewModel.session = req.session; + let data = await db.result_profile.edit( + { section_title, output_variable_list: !Array.isArray(output_variable_list) ? JSON.stringify([output_variable_list]) : JSON.stringify(output_variable_list) }, + id + ); + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Edit_Result_profile", viewModel); + } + + req.flash("success", "Result profile edited successfully"); + + return res.redirect("/admin/profile-sections/0"); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Edit_Result_profile", viewModel); + } +}); + +app.get( + "/admin/profile-sections-view/:id", + SessionService.verifySessionMiddleware(role, "admin"), + + async function (req, res, next) { + try { + let id = req.params.id; + + const resultProfileAdminDetailViewModel = require("../../view_models/result_profile_admin_detail_view_model"); + + var viewModel = new resultProfileAdminDetailViewModel(db.result_profile, "Result profile details", "", "", "/admin/profile-sections"); + + const data = await db.result_profile.getByPK(id); + + if (data["output_variable_list"]) { + const parsedList = JSON.parse(data["output_variable_list"]); + let actualList = await db.output_variable.findAll({ + where: { + id: parsedList, + }, + }); + actualList = actualList.map((ov) => ov.name); + data["output_variable_list"] = actualList; + } + if (!data) { + viewModel.error = "Result profile not found"; + viewModel.detail_fields = { ...viewModel.detail_fields, id: "N/A", section_title: "N/A", output_variable_list: "N/A" }; + } else { + viewModel.detail_fields = { ...viewModel.detail_fields, id: data["id"] || "N/A", section_title: data["section_title"] || "N/A", output_variable_list: data["output_variable_list"] || "N/A" }; + } + + res.render("admin/View_Result_profile", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + viewModel.detail_fields = { ...viewModel.detail_fields, id: "N/A", section_title: "N/A", output_variable_list: "N/A" }; + res.render("admin/View_Result_profile", viewModel); + } + } +); + +app.get("/admin/profile-sections-delete/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + + const resultProfileAdminDeleteViewModel = require("../../view_models/result_profile_admin_delete_view_model"); + + const viewModel = new resultProfileAdminDeleteViewModel(db.result_profile); + + try { + const exists = await db.result_profile.getByPK(id); + + if (!exists) { + req.flash("error", "Result profile not found"); + return res.redirect("/admin/profile-sections/0"); + } + + viewModel.session = req.session; + + await db.result_profile.realDelete(id); + + req.flash("success", "Result profile was deleted successfully"); + + return res.redirect("/admin/profile-sections/0"); + } catch (error) { + console.error(error); + req.flash("error", error.message || "Something went wrong"); + return res.redirect("/admin/profile-sections/0"); + } +}); + +// APIS + +app.get("/admin/api/profile-sections", JwtService.verifyTokenMiddleware(role), async function (req, res, next) { + try { + const user_id = req.user_id; + const session = req.session; + let listViewModel = require("../../view_models/result_profile_admin_list_paginate_view_model"); + let viewModel = new listViewModel(db.result_profile, "Profile sections", session.success, session.error, "/admin/profile-sections"); + const direction = req.query.direction ? req.query.direction : "ASC"; + const page = req.query.page ? parseInt(req.query.page) : 1; + const limit = req.query.limit ? parseInt(req.query.limit) : 10; + const offset = (page - 1) * limit; + let order_by = req.query.order_by ? req.query.order_by : viewModel.get_field_column()[0]; + let orderAssociations = []; + viewModel.set_order_by(order_by); + let joins = order_by.includes(".") ? order_by.split(".") : []; + order_by = order_by.includes(".") ? joins[joins.length - 1] : order_by; + if (joins.length > 0) { + for (let i = joins.length - 1; i > 0; i--) { + orderAssociations.push(`${joins[i - 1]}`); + } + } + + viewModel.set_id(req.query.id ? req.query.id : ""); + viewModel.set_section_title(req.query.section_title ? req.query.section_title : ""); + + let where = helpers.filterEmptyFields({ + id: viewModel.get_id(), + section_title: viewModel.get_section_title(), + }); + + let include = []; + + const { rows: allItems, count } = await db.result_profile.findAndCountAll({ + where: where, + limit: limit == 0 ? null : limit, + offset: offset, + include: include, + distinct: true, + }); + + const response = { + items: allItems, + page, + nextPage: count > offset + limit ? page + 1 : false, + retrievedCount: allItems.length, + fullCount: count, + }; + + return res.status(201).json({ success: true, data: response }); + } catch (error) { + console.error(error); + return res.status(500).json({ success: false, message: error.message || "Something went wrong" }); + } +}); + +app.post("/admin/api/profile-sections-add", JwtService.verifyTokenMiddleware(role), async function (req, res, next) { + const resultProfileAdminAddViewModel = require("../../view_models/result_profile_admin_add_view_model"); + + const viewModel = new resultProfileAdminAddViewModel(db.result_profile); + + const { section_title, output_variable_list } = req.body; + try { + if (req.validationError) { + return res.status(500).json({ success: false, message: req.validationError }); + } + + const data = await db.result_profile.insert({ section_title, output_variable_list }); + + if (!data) { + return res.status(500).json({ success: false, message: "Something went wrong" }); + } + + return res.status(201).json({ success: true, message: "Result profile created successfully" }); + } catch (error) { + return res.status(500).json({ success: false, message: "Something went wrong" }); + } +}); + +app.put("/admin/api/profile-sections-edit/:id", JwtService.verifyTokenMiddleware(role), async function (req, res, next) { + let id = req.params.id; + + const resultProfileAdminEditViewModel = require("../../view_models/result_profile_admin_edit_view_model"); + + const viewModel = new resultProfileAdminEditViewModel(db.result_profile); + + const { section_title, output_variable_list } = req.body; + + try { + if (req.validationError) { + return res.status(500).json({ success: false, message: req.validationError }); + } + + const resourceExists = await db.result_profile.getByPK(id); + if (!resourceExists) { + return res.status(404).json({ success: false, message: "Result profile not found" }); + } + + const data = await db.result_profile.edit({ section_title, output_variable_list }, id); + + if (!data) { + return res.status(500).json({ success: false, message: "Something went wrong" }); + } + + return res.json({ success: true, message: "Result profile edited successfully" }); + } catch (error) { + return res.status(500).json({ success: false, message: "Something went wrong" }); + } +}); + +app.get("/admin/api/profile-sections-view/:id", JwtService.verifyTokenMiddleware(role), async function (req, res, next) { + let id = req.params.id; + + const resultProfileAdminDetailViewModel = require("../../view_models/result_profile_admin_detail_view_model"); + + const viewModel = new resultProfileAdminDetailViewModel(db.result_profile); + + try { + const data = await db.result_profile.getByPK(id); + + if (!data) { + return res.status(404).json({ message: "Result profile not found", data: null }); + } else { + const fields = { ...viewModel.detail_fields, id: data["id"] || "", section_title: data["section_title"] || "", output_variable_list: data["output_variable_list"] || "" }; + return res.status(200).json({ data: fields }); + } + } catch (error) { + return res.status(404).json({ message: "Something went wrong", data: null }); + } +}); + +app.delete("/admin/api/profile-sections-delete/:id", JwtService.verifyTokenMiddleware(role), async function (req, res, next) { + let id = req.params.id; + + const resultProfileAdminDeleteViewModel = require("../../view_models/result_profile_admin_delete_view_model"); + + const viewModel = new resultProfileAdminDeleteViewModel(db.result_profile); + + try { + const exists = await db.result_profile.getByPK(id); + + if (!exists) { + return res.status(404).json({ success: false, message: "Result profile not found" }); + } + + await db.result_profile.realDelete(id); + + return res.status(200).json({ success: true, message: "Result profile deleted successfully" }); + } catch (error) { + return res.status(500).json({ success: false, message: "Something went wrong" }); + } +}); + +module.exports = app; diff --git a/controllers/admin/Admin_rules_controller.js b/controllers/admin/Admin_rules_controller.js new file mode 100644 index 0000000..dc5bdff --- /dev/null +++ b/controllers/admin/Admin_rules_controller.js @@ -0,0 +1,353 @@ +"use strict"; + +const app = require("express").Router(); +const Sequelize = require("sequelize"); +const logger = require("../../services/LoggingService"); +let pagination = require("../../services/PaginationService"); +let SessionService = require("../../services/SessionService"); +let JwtService = require("../../services/JwtService"); +const ValidationService = require("../../services/ValidationService"); +const PermissionService = require("../../services/PermissionService"); +const UploadService = require("../../services/UploadService"); +const AuthService = require("../../services/AuthService"); +const db = require("../../models"); +const helpers = require("../../core/helpers"); + +const role = 1; + +app.get("/admin/rules/:num", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + try { + let session = req.session; + let paginateListViewModel = require("../../view_models/rules_admin_list_paginate_view_model"); + + var viewModel = new paginateListViewModel(db.rule, "Rules", session.success, session.error, "/admin/rules"); + + const format = req.query.format ? req.query.format : "view"; + const direction = req.query.direction ? req.query.direction : "ASC"; + const per_page = req.query.per_page ? req.query.per_page : 10; + let order_by = req.query.order_by ? req.query.order_by : viewModel.get_field_column()[0]; + let orderAssociations = []; + viewModel.set_order_by(order_by); + let joins = order_by.includes(".") ? order_by.split(".") : []; + order_by = order_by.includes(".") ? joins[joins.length - 1] : order_by; + if (joins.length > 0) { + for (let i = joins.length - 1; i > 0; i--) { + orderAssociations.push(`${joins[i - 1]}`); + } + } + // Check for flash messages + const flashMessageSuccess = req.flash("success"); + if (flashMessageSuccess && flashMessageSuccess.length > 0) { + viewModel.success = flashMessageSuccess[0]; + } + const flashMessageError = req.flash("error"); + if (flashMessageError && flashMessageError.length > 0) { + viewModel.error = flashMessageError[0]; + } + + viewModel.set_id(req.query.id ? req.query.id : ""); + viewModel.set_operator(req.query.operator ? req.query.operator : ""); + viewModel.set_action(req.query.action ? req.query.action : ""); + viewModel.set_output_variable_name(req.query.output_variable_name ? req.query.output_variable_name : ""); + + let where = helpers.filterEmptyFields({ + id: viewModel.get_id(), + operator: viewModel.get_operator(), + action: viewModel.get_action(), + output_variable_name: viewModel.get_output_variable_name(), + }); + + const count = await db.rule._count(where, []); + + viewModel.set_total_rows(count); + viewModel.set_per_page(+per_page); + viewModel.set_page(+req.params.num); + viewModel.set_query(req.query); + viewModel.set_sort_base_url(`/admin/rules/${+req.params.num}`); + viewModel.set_sort(direction); + + const list = await db.rule.getPaginated(viewModel.get_page() - 1 < 0 ? 0 : viewModel.get_page(), viewModel.get_per_page(), where, order_by, direction, orderAssociations); + + viewModel.set_list(list); + + if (format == "csv") { + const csv = viewModel.to_csv(); + return res + .set({ + "Content-Type": "text/csv", + "Content-Disposition": 'attachment; filename="export.csv"', + }) + .send(csv); + } + + // if (format != 'view') { + // res.json(viewModel.to_json()); + // } else { + // } + + return res.render("admin/Rules", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Rules", viewModel); + } +}); + +app.get("/admin/rules-add", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const rulesAdminAddViewModel = require("../../view_models/rules_admin_add_view_model"); + + const viewModel = new rulesAdminAddViewModel(db.rule, "Add rule", "", "", "/admin/rules"); + viewModel.outputVariables = await db.output_variable.getAll(); + viewModel.actives = await db.active.getAll(); + res.render("admin/Add_Rules", viewModel); +}); + +app.post( + "/admin/rules-add", + SessionService.verifySessionMiddleware(role, "admin"), + ValidationService.validateInput( + { output_variable_name: "required", actives: "required", operator: "required", compare_value: "required", action: "required" }, + { + "output_variable_name.required": "OutputVariableName is required", + "actives.required": "Actives is required", + "operator.required": "Operator is required", + "compare_value.required": "CompareValue is required", + "action.required": "Action is required", + } + ), + async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const rulesAdminAddViewModel = require("../../view_models/rules_admin_add_view_model"); + + const viewModel = new rulesAdminAddViewModel(db.rule, "Add rule", "", "", "/admin/rules"); + viewModel.outputVariables = await db.output_variable.getAll(); + viewModel.actives = await db.active.getAll(); + + // TODO use separate controller for image upload + // {{{upload_field_setter}}} + + let { output_variable_name, actives, operator, compare_value, min, max, action } = req.body; + if (!Array.isArray(actives)) { + actives = [actives]; + } + viewModel.form_fields = { + ...viewModel.form_fields, + output_variable_name, + actives, + operator, + compare_value, + min, + max, + action, + }; + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render("admin/Add_Rules", viewModel); + } + + viewModel.session = req.session; + + const data = await db.rule.insert({ output_variable_name, actives: JSON.stringify(actives), operator, compare_value, min, max, action }); + + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Add_Rules", viewModel); + } + + req.flash("success", "Rule created successfully"); + return res.redirect("/admin/rules/0"); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Add_Rules", viewModel); + } + } +); + +app.get("/admin/rules-edit/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const rulesAdminEditViewModel = require("../../view_models/rules_admin_edit_view_model"); + + const viewModel = new rulesAdminEditViewModel(db.rule, "Edit rule", "", "", "/admin/rules"); + + try { + const exists = await db.rule.getByPK(id); + + if (!exists) { + req.flash("error", "Rule not found"); + return res.redirect("/admin/rules/0"); + } + const values = exists; + Object.keys(viewModel.form_fields).forEach((field) => { + viewModel.form_fields[field] = values[field] || ""; + }); + + viewModel.outputVariables = await db.output_variable.getAll(); + viewModel.actives = await db.active.getAll(); + return res.render("admin/Edit_Rules", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Edit_Rules", viewModel); + } +}); + +app.post( + "/admin/rules-edit/:id", + SessionService.verifySessionMiddleware(role, "admin"), + ValidationService.validateInput( + { output_variable_name: "required", actives: "required", operator: "required", compare_value: "required", action: "required" }, + { + "output_variable_name.required": "OutputVariableName is required", + "actives.required": "Actives is required", + "operator.required": "Operator is required", + "compare_value.required": "CompareValue is required", + "action.required": "Action is required", + } + ), + async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const rulesAdminEditViewModel = require("../../view_models/rules_admin_edit_view_model"); + + const viewModel = new rulesAdminEditViewModel(db.rule, "Edit rule", "", "", "/admin/rules"); + + viewModel.outputVariables = await db.output_variable.getAll(); + viewModel.actives = await db.active.getAll(); + let { output_variable_name, actives, operator, compare_value, min, max, action } = req.body; + if (!Array.isArray(actives)) { + actives = [actives]; + } + viewModel.form_fields = { + ...viewModel.form_fields, + output_variable_name, + actives, + operator, + compare_value, + min, + max, + action, + }; + + delete viewModel.form_fields.id; + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render("admin/Edit_Rules", viewModel); + } + + const resourceExists = await db.rule.getByPK(id); + if (!resourceExists) { + req.flash("error", "Rule not found"); + return res.redirect("/admin/rules/0"); + } + + viewModel.session = req.session; + + let data = await db.rule.edit({ output_variable_name, actives: JSON.stringify(actives), operator, compare_value, min, max, action }, id); + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Edit_Rules", viewModel); + } + + req.flash("success", "Rule edited successfully"); + + return res.redirect("/admin/rules/0"); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Edit_Rules", viewModel); + } + } +); + +app.get( + "/admin/rules-view/:id", + SessionService.verifySessionMiddleware(role, "admin"), + + async function (req, res, next) { + try { + let id = req.params.id; + + const rulesAdminDetailViewModel = require("../../view_models/rules_admin_detail_view_model"); + + var viewModel = new rulesAdminDetailViewModel(db.rule, "Rule details", "", "", "/admin/rules"); + + const data = await db.rule.getByPK(id); + data.operator = db.rule.operator_mapping()[data.operator]; + data.action = db.rule.action_mapping()[data.action]; + + if (!data) { + viewModel.error = "Rule not found"; + viewModel.detail_fields = { ...viewModel.detail_fields, id: "N/A", output_variable_name: "N/A", actives: "N/A", operator: "N/A", compare_value: "N/A", min: "N/A", max: "N/A", action: "N/A" }; + } else { + viewModel.detail_fields = { + ...viewModel.detail_fields, + id: data["id"] || "N/A", + output_variable_name: data["output_variable_name"] || "N/A", + actives: data["actives"] || "N/A", + operator: data["operator"] || "N/A", + compare_value: data["compare_value"] || "N/A", + min: data["min"] || "N/A", + max: data["max"] || "N/A", + action: data["action"] || "N/A", + }; + } + + res.render("admin/View_Rules", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + viewModel.detail_fields = { ...viewModel.detail_fields, id: "N/A", output_variable_name: "N/A", actives: "N/A", operator: "N/A", compare_value: "N/A", min: "N/A", max: "N/A", action: "N/A" }; + res.render("admin/View_Rules", viewModel); + } + } +); + +app.get("/admin/rules-delete/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + + const rulesAdminDeleteViewModel = require("../../view_models/rules_admin_delete_view_model"); + + const viewModel = new rulesAdminDeleteViewModel(db.rule); + + try { + const exists = await db.rule.getByPK(id); + + if (!exists) { + req.flash("error", "Rule not found"); + return res.redirect("/admin/rules/0"); + } + + viewModel.session = req.session; + + await db.rule.realDelete(id); + + req.flash("success", "Rule was deleted successfully"); + + return res.redirect("/admin/rules/0"); + } catch (error) { + console.error(error); + req.flash("error", error.message || "Something went wrong"); + return res.redirect("/admin/rules/0"); + } +}); + +// APIS + +module.exports = app; diff --git a/controllers/admin/Admin_user_controller.js b/controllers/admin/Admin_user_controller.js new file mode 100644 index 0000000..39f8aeb --- /dev/null +++ b/controllers/admin/Admin_user_controller.js @@ -0,0 +1,342 @@ +"use strict"; + +const app = require("express").Router(); +const Sequelize = require("sequelize"); +const logger = require("../../services/LoggingService"); +let pagination = require("../../services/PaginationService"); +let SessionService = require("../../services/SessionService"); +let JwtService = require("../../services/JwtService"); +const ValidationService = require("../../services/ValidationService"); +const PermissionService = require("../../services/PermissionService"); +const UploadService = require("../../services/UploadService"); +const AuthService = require("../../services/AuthService"); +const db = require("../../models"); +const helpers = require("../../core/helpers"); + +const role = 1; + +app.get("/admin/users/:num", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + try { + let session = req.session; + let paginateListViewModel = require("../../view_models/users_admin_list_paginate_view_model"); + + var viewModel = new paginateListViewModel(db.user, "Users", session.success, session.error, "/admin/users"); + + const format = req.query.format ? req.query.format : "view"; + const direction = req.query.direction ? req.query.direction : "ASC"; + const per_page = req.query.per_page ? req.query.per_page : 10; + let order_by = req.query.order_by ? req.query.order_by : viewModel.get_field_column()[0]; + let orderAssociations = []; + viewModel.set_order_by(order_by); + let joins = order_by.includes(".") ? order_by.split(".") : []; + order_by = order_by.includes(".") ? joins[joins.length - 1] : order_by; + if (joins.length > 0) { + for (let i = joins.length - 1; i > 0; i--) { + orderAssociations.push(`${joins[i - 1]}`); + } + } + // Check for flash messages + const flashMessageSuccess = req.flash("success"); + if (flashMessageSuccess && flashMessageSuccess.length > 0) { + viewModel.success = flashMessageSuccess[0]; + } + const flashMessageError = req.flash("error"); + if (flashMessageError && flashMessageError.length > 0) { + viewModel.error = flashMessageError[0]; + } + + viewModel.set_id(req.query.id ? req.query.id : ""); + viewModel.set_credential_email(req.query.credential_email ? req.query.credential_email : ""); + viewModel.set_first_name(req.query.first_name ? req.query.first_name : ""); + viewModel.set_last_name(req.query.last_name ? req.query.last_name : ""); + + let where = helpers.filterEmptyFields({ + id: viewModel.get_id(), + first_name: viewModel.get_first_name(), + last_name: viewModel.get_last_name(), + }); + + let associatedWhere = helpers.filterEmptyFields({ + email: viewModel.get_credential_email(), + }); + const isAssociationRequired = Object.keys(associatedWhere).length > 0 ? true : false; + + const count = await db.user._count(where, [{ model: db.credential, where: associatedWhere, required: isAssociationRequired, as: "credential" }]); + + viewModel.set_total_rows(count); + viewModel.set_per_page(+per_page); + viewModel.set_page(+req.params.num); + viewModel.set_query(req.query); + viewModel.set_sort_base_url(`/admin/users/${+req.params.num}`); + viewModel.set_sort(direction); + + const list = await db.user.get_credential_paginated( + db, + associatedWhere, + viewModel.get_page() - 1 < 0 ? 0 : viewModel.get_page(), + viewModel.get_per_page(), + where, + order_by, + direction, + orderAssociations + ); + + viewModel.set_list(list); + + viewModel.credential = await db.credential; + + if (format == "csv") { + const csv = viewModel.to_csv(); + return res + .set({ + "Content-Type": "text/csv", + "Content-Disposition": 'attachment; filename="export.csv"', + }) + .send(csv); + } + + // if (format != 'view') { + // res.json(viewModel.to_json()); + // } else { + // } + + return res.render("admin/Users", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Users", viewModel); + } +}); + +app.get("/admin/users-add", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const usersAdminAddViewModel = require("../../view_models/users_admin_add_view_model"); + + const viewModel = new usersAdminAddViewModel(db.user, "Add user", "", "", "/admin/users"); + + res.render("admin/Add_Users", viewModel); +}); + +app.post( + "/admin/users-add", + SessionService.verifySessionMiddleware(role, "admin"), + ValidationService.validateInput( + { first_name: "required", last_name: "required", status: "required" }, + { "first_name.required": "FirstName is required", "last_name.required": "LastName is required", "status.required": "Status is required" } + ), + async function (req, res, next) { + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const usersAdminAddViewModel = require("../../view_models/users_admin_add_view_model"); + + const viewModel = new usersAdminAddViewModel(db.user, "Add user", "", "", "/admin/users"); + + // TODO use separate controller for image upload + // {{{upload_field_setter}}} + + const { email, password, first_name, last_name, image, role_id, phone, status } = req.body; + + viewModel.form_fields = { + ...viewModel.form_fields, + email, + password, + first_name, + last_name, + image, + role_id, + phone, + status, + }; + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render("admin/Add_Users", viewModel); + } + + viewModel.session = req.session; + + const { email, password = "", role_id, ...rest } = viewModel.form_fields; + const data = await AuthService.register(email, password, role_id, rest); + + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Add_Users", viewModel); + } + + await db.activity_log.insert({ + action: "ADD", + name: "Admin_user_controller.js", + portal: "admin", + data: JSON.stringify({ email, password, first_name, last_name, image, role_id, phone, status }), + }); + + req.flash("success", "User created successfully"); + return res.redirect("/admin/users/0"); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Add_Users", viewModel); + } + } +); + +app.get("/admin/users-edit/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + const usersAdminEditViewModel = require("../../view_models/users_admin_edit_view_model"); + + const viewModel = new usersAdminEditViewModel(db.user, "Edit user", "", "", "/admin/users"); + + try { + const exists = await db.user.get_user_credential(id, db); + + if (!exists) { + req.flash("error", "User not found"); + return res.redirect("/admin/users/0"); + } + const values = exists; + Object.keys(viewModel.form_fields).forEach((field) => { + if (field === "credential.email") { + viewModel.form_fields[field] = values["credential"]["email"]; + return; + } + if (field === "credential.password") { + viewModel.form_fields[field] = values["credential"]["password"]; + return; + } + viewModel.form_fields[field] = values[field] || ""; + }); + viewModel.credential = db.credential; + return res.render("admin/Edit_Users", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Edit_Users", viewModel); + } +}); + +app.post("/admin/users-edit/:id", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + let id = req.params.id; + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const usersAdminEditViewModel = require("../../view_models/users_admin_edit_view_model"); + + const viewModel = new usersAdminEditViewModel(db.user, "Edit user", "", "", "/admin/users"); + + const { credential_email, credential_password, first_name, last_name, role_id, image, phone, status } = req.body; + + viewModel.form_fields = { + ...viewModel.form_fields, + "credential.email": credential_email, + "credential.password": credential_password, + first_name, + last_name, + role_id, + image, + phone, + status, + }; + + delete viewModel.form_fields.id; + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render("admin/Edit_Users", viewModel); + } + + const resourceExists = await db.user.get_user_credential(id, db); + if (!resourceExists) { + req.flash("error", "User not found"); + return res.redirect("/admin/users/0"); + } + + viewModel.session = req.session; + + let data = await db.user.edit({ first_name, last_name, role_id, image, phone, status }, id); + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Edit_Users", viewModel); + } + + if (resourceExists.credential) { + data = await db.credential.edit(helpers.filterEmptyFields({ email: credential_email, password: credential_password }), resourceExists.credential.id); + if (!data) { + viewModel.error = "Something went wrong"; + return res.render("admin/Edit_Users", viewModel); + } + } + + await db.activity_log.insert({ + action: "EDIT", + name: "Admin_user_controller.js", + portal: "admin", + data: JSON.stringify({ credential_email, credential_password, first_name, last_name, role_id, image, phone, status }), + }); + + req.flash("success", "User edited successfully"); + + return res.redirect("/admin/users/0"); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Edit_Users", viewModel); + } +}); + +app.get( + "/admin/users-view/:id", + SessionService.verifySessionMiddleware(role, "admin"), + + async function (req, res, next) { + try { + let id = req.params.id; + + const usersAdminDetailViewModel = require("../../view_models/users_admin_detail_view_model"); + + var viewModel = new usersAdminDetailViewModel(db.user, "User details", "", "", "/admin/users"); + + const data = await db.user.get_user_credential(id, db); + data.status = db.user.status_mapping()[data.status]; + data["credential.two_factor_authentication"] = db.credential.two_factor_authentication_mapping()[data.credential.two_factor_authentication]; + data["credential.type"] = db.credential.type_mapping()[data.credential.type]; + data["credential.status"] = db.credential.status_mapping()[data.credential.status]; + data["credential.verify"] = db.credential.verify_mapping()[data.credential.verify]; + + if (!data) { + viewModel.error = "User not found"; + viewModel.detail_fields = { ...viewModel.detail_fields, id: "N/A", "credential.email": "N/A", first_name: "N/A", last_name: "N/A", role_id: "N/A", status: "N/A" }; + } else { + viewModel.detail_fields = { + ...viewModel.detail_fields, + id: data["id"] || "N/A", + "credential.email": data["credential"]["email"] || "N/A", + first_name: data["first_name"] || "N/A", + last_name: data["last_name"] || "N/A", + role_id: data["role_id"] || "N/A", + status: data["status"] || "N/A", + }; + } + + res.render("admin/View_Users", viewModel); + } catch (error) { + console.error(error); + viewModel.error = error.message || "Something went wrong"; + viewModel.detail_fields = { ...viewModel.detail_fields, id: "N/A", "credential.email": "N/A", first_name: "N/A", last_name: "N/A", role_id: "N/A", status: "N/A" }; + res.render("admin/View_Users", viewModel); + } + } +); + +// APIS + +module.exports = app; diff --git a/controllers/admin/Dashboard.js b/controllers/admin/Dashboard.js new file mode 100644 index 0000000..f9fd1b2 --- /dev/null +++ b/controllers/admin/Dashboard.js @@ -0,0 +1,113 @@ +const SessionService = require("../../services/SessionService"); +const app = require("express").Router(); +const db = require("../../models"); +const role = 1; + +app.get("/admin/letters/main", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + const { order: orderId } = req.query; + // const orderId = 2; + const order = await db.order.getByPK(orderId); + const firstName = JSON.parse(order.customer).first_name; + res.render("admin/Letters/Main_Letter", { + firstName, + get_page_name: () => "Letter", + _base_url: "/admin/letters/main", + }); +}); + +app.get("/admin/letters/profile", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + const { order: orderId } = req.query; + + const order = await db.order.getByPK(orderId); + const firstName = order.customer ? JSON.parse(order.customer).first_name ?? null : null; + const profileCharcteristics = order.profile ? JSON.parse(order.profile) : []; + res.render("admin/Letters/Profile_Letter", { firstName, profileCharcteristics, get_page_name: () => "Letter", _base_url: "/admin/letters/profile" }); +}); + +app.get("/admin/letters/formula", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + const { order: orderId } = req.query; + + const order = await db.order.getByPK(orderId); + let activesNames = order.actives ? JSON.parse(order.actives) : []; + if (activesNames && activesNames.length) activesNames = activesNames.filter((active) => active !== "Base"); + const { rows: actives, count } = await db.active.findAndCountAll({ + where: { name: { [db.Sequelize.Op.in]: activesNames } }, + }); + + res.render("admin/Letters/Formula_Letter", { actives, count, get_page_name: () => "Letter", _base_url: "/admin/letters/formula" }); +}); + +app.get("/admin/letters/instructions", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + const { order: orderId } = req.query; + + const order = await db.order.getByPK(orderId); + + res.render("admin/Letters/Instructions_Letter", { get_page_name: () => "Letter", _base_url: "/admin/letters/instructions" }); +}); + +app.get("/admin/letters/all", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + const { order: orderId } = req.query; + + const order = await db.order.getByPK(orderId); + + const firstName = JSON.parse(order.customer).first_name; + const profileCharcteristics = order.profile ? JSON.parse(order.profile) : []; + + let activesNames = order.actives ? JSON.parse(order.actives) : []; + if (activesNames && activesNames.length) activesNames = activesNames.filter((active) => active !== "Base"); + const { rows: actives, count } = await db.active.findAndCountAll({ + where: { name: { [db.Sequelize.Op.in]: activesNames } }, + }); + + res.render("admin/Letters/All", { firstName, profileCharcteristics, actives, count, get_page_name: () => "Letter", _base_url: "/admin/letters/all" }); +}); + +app.get("/admin/dashboard", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + const config = await db.configuration.findOne({ where: { id: 1 }, include: [{ model: db.image, as: "image" }] }); + res.render("admin/Dashboard", { + config, + get_page_name: () => "Dashboard", + _base_url: "/admin/dashboard", + }); +}); + +app.post("/questions/order/save", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + try { + const questions = req.body; + + for (const question of questions) { + if (question.id && question.order) { + await db.question.edit({ order: question.order }, question.id); + } + } + return res.json({ success: true, message: "Successfully updated orders" }); + } catch (error) { + console.log(error); + return res.status(500).json({ success: false, message: "Failed to update orders" }); + } +}); +app.post("/main-image/update", SessionService.verifySessionMiddleware(role, "admin"), async function (req, res, next) { + try { + const { image_url } = req.body; + await db.configuration.edit({ image_id: image_url }, 1); + return res.json({ success: true, message: "Successfully updated image" }); + } catch (error) { + console.log(error); + return res.status(500).json({ success: false, message: "Failed to update image" }); + } +}); + +app.get("/configurations", async function (req, res, next) { + try { + const config = await db.configuration.findOne({ where: { id: 1 }, include: [{ model: db.image, as: "image" }] }); + if (!config) { + return res.status(404).json({ success: false, message: "No configurations found" }); + } + return res.json({ success: true, payload: config }); + } catch (error) { + console.log(error); + return res.status(500).json({ success: false, message: "Failed to fetch configurations" }); + } +}); + +module.exports = app; diff --git a/controllers/admin/getProfileSystem.js b/controllers/admin/getProfileSystem.js new file mode 100644 index 0000000..c984bbb --- /dev/null +++ b/controllers/admin/getProfileSystem.js @@ -0,0 +1,37 @@ +"use strict"; + +const app = require("express").Router(); +// const Sequelize = require('sequelize'); +// const logger = require('../../services/LoggingService'); +// let pagination = require('../../services/PaginationService'); +// let SessionService = require('../../services/SessionService'); +let JwtService = require("../../services/JwtService"); +const ValidationService = require("../../services/ValidationService"); +// const PermissionService = require('../../services/PermissionService'); +// const UploadService = require('../../services/UploadService'); +// const AuthService = require('../../services/AuthService'); +const db = require("../../models"); +const helpers = require("../../core/helpers"); + +const role = 1; + +app.get("/admin/api/profile-system", async function (req, res, next) { + try { + const { rows: allItems, count } = await db.profile_header.findAndCountAll({ + offset: offset, + order: [["id", direction]], + distinct: true, + }); + + const response = { + items: allItems, + count, + }; + + return res.status(201).json({ success: true, data: response }); + } catch (error) { + console.error(error); + return res.status(500).json({ success: false, message: error.message || "Something went wrong" }); + } +}); +module.exports = app; diff --git a/controllers/index.js b/controllers/index.js new file mode 100644 index 0000000..fa5e1cf --- /dev/null +++ b/controllers/index.js @@ -0,0 +1,34 @@ +const AdminUserController = require("./admin/Admin_user_controller"); +const Admin_order_controller = require("./admin/Admin_order_controller"); +const AdminQuizController = require("./admin/Admin_quiz_controller"); +const AdminQuestionController = require("./admin/Admin_question_controller"); +const AdminRulesController = require("./admin/Admin_rules_controller"); +const AdminActivesController = require("./admin/Admin_actives_controller"); +const AdminOutputVariablesController = require("./admin/Admin_output_variables_controller"); +const AdminResultProfileController = require("./admin/Admin_result_profile_controller"); +const AdminGetProfileSystem = require("./admin/getProfileSystem"); +const PublicIndex = require("./public/index"); +const AdminAnswerController = require("./admin/Admin_answer_controller"); +const AdminDashboard = require("./admin/Dashboard"); +const MemberDashboard = require("./member/Dashboard"); +const getProducts = require("./shopify/getProducts"); +const ShopifyWebhook = require("./shopify/webhook"); +const KlaviyoController = require("./klaviyo/index"); +module.exports = [ + KlaviyoController, + Admin_order_controller, + ShopifyWebhook, + AdminResultProfileController, + AdminGetProfileSystem, + AdminUserController, + AdminQuizController, + AdminQuestionController, + AdminRulesController, + AdminActivesController, + AdminOutputVariablesController, + AdminAnswerController, + AdminDashboard, + MemberDashboard, + PublicIndex, + getProducts, +]; diff --git a/controllers/klaviyo/index.js b/controllers/klaviyo/index.js new file mode 100644 index 0000000..7c678ce --- /dev/null +++ b/controllers/klaviyo/index.js @@ -0,0 +1,78 @@ +// const SessionService = require('../../services/SessionService'); +const app = require("express").Router(); +const db = require("../../models"); +const axios = require("axios"); +const cors = require("cors"); + +const quiz_list_id = "SuMRRB"; +const klaviyo_api_key = "pk_026fc9c97c646a73a053c99ef8d8c9c53d"; +const corsOptions = { + origin: ["http://localhost:3001"], + optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204 +}; + +//api: get output variable info +app.post("/klaviyo/identity", cors(corsOptions), async function (req, res, next) { + try { + //body should have actives lsit as array + const { email, firstName, lastName } = req.body; + let data = JSON.stringify({ + token: klaviyo_api_key, + properties: { + $email: email, + $first_name: firstName, + $last_name: lastName, + }, + }); + + let config = { + method: "post", + url: "https://a.klaviyo.com/api/identify", + headers: { + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + console.log(response.data); + + return res.status(201).json({ success: true, payload: response.data }); + } catch (error) { + console.error(error); + return res.status(500).json({ success: false, message: error.message || "Something went wrong" }); + } +}); + +app.post("/klaviyo/list", cors(corsOptions), async function (req, res, next) { + try { + //body should have actives lsit as array + const { email } = req.body; + let data = JSON.stringify({ + profiles: [ + { + email: email, + }, + ], + }); + + let config = { + method: "post", + url: `https://a.klaviyo.com/api/v2/list/${quiz_list_id}/members?api_key=${klaviyo_api_key}`, + headers: { + "Content-Type": "application/json", + }, + data: data, + }; + + const response = await axios(config); + console.log(response.data); + + return res.status(201).json({ success: true, payload: response.data }); + } catch (error) { + console.error(error); + return res.status(500).json({ success: false, message: error.message || "Something went wrong" }); + } +}); + +module.exports = app; diff --git a/controllers/member/Dashboard.js b/controllers/member/Dashboard.js new file mode 100644 index 0000000..b358a2c --- /dev/null +++ b/controllers/member/Dashboard.js @@ -0,0 +1,18 @@ +const SessionService = require('../../services/SessionService'); +const app = require('express').Router(); + +const role = 2; + +app.get( + "/member/dashboard", + SessionService.verifySessionMiddleware(role,"member"), + async function (req, res, next) { + + res.render('member/Dashboard',{ + get_page_name: () => 'Dashboard', + _base_url: '/member/dashboard', + }); + } + ); + +module.exports = app; \ No newline at end of file diff --git a/controllers/public/index.js b/controllers/public/index.js new file mode 100644 index 0000000..d510e29 --- /dev/null +++ b/controllers/public/index.js @@ -0,0 +1,320 @@ +// const SessionService = require('../../services/SessionService'); +const app = require("express").Router(); +const db = require("../../models"); +const axios = require("axios"); + +//api: get output variable info +app.get("/api/v1/output-variable/:name", async function (req, res, next) { + try { + //body should have actives lsit as array + const { name } = req.params; + + const outputVariable = await db.output_variable.getByFields({ name }); + if (!outputVariable) { + return res.status(404).json({ success: false, message: `Output variable of that name ${name} is not found.` }); + } + let payload = {}, + actives = []; + if (outputVariable.active_list) { + let activeList = JSON.parse(outputVariable.active_list); + for (const activeId of activeList) { + const active = await db.active.getByPK(activeId); + if (active) { + actives.push(active.name); + } + } + } + payload = { name: outputVariable.name, actives: actives, ranges_response: JSON.parse(outputVariable.ranges_response) }; + + return res.status(201).json({ success: true, data: payload }); + } catch (error) { + console.error(error); + return res.status(500).json({ success: false, message: error.message || "Something went wrong" }); + } +}); + +app.get("/api/v1/output-variables/actives-list", async function (req, res, next) { + try { + //body should have actives lsit as array + const { names_list } = req.query; + if (!names_list) { + return res.status(401).json({ success: false, message: "Empty list" }); + } + const outputVariablesList = names_list.split(","); + + const outputVars = await db.output_variable.findAll({ + where: { + name: outputVariablesList, + }, + }); + + let allActivesList = []; + outputVars.forEach((outputVar) => { + if (outputVar.active_list) { + let parsedList = JSON.parse(outputVar.active_list); + if (parsedList.length) { + parsedList.forEach((item) => { + if (!allActivesList.includes(item)) { + allActivesList.push(item); + } + }); + } + } + }); + + let actives = await db.active + .findAll({ + where: { + id: allActivesList, + }, + }) + .then((data) => { + return data.map((item) => { + return item.name; + }); + }); + if (!actives) { + return res.status(404).json({ success: false, message: "No actives found for this list" }); + } + return res.status(201).json({ success: true, data: actives }); + } catch (error) { + console.error(error); + return res.status(500).json({ success: false, message: error.message || "Something went wrong" }); + } +}); + +app.get("/api/v1/places/autocomplete", async function (req, res, next) { + try { + const { input } = req.query; + + var config = { + method: "get", + // url: `https://maps.googleapis.com/maps/api/place/autocomplete/json?input=${encodeURIComponent(input)}&types=(regions)&key=${process.env.GOOGLE_PLACES_API_KEY}`, + url: `https://maps.googleapis.com/maps/api/place/autocomplete/json?input=${encodeURIComponent(input)}&key=${process.env.GOOGLE_PLACES_API_KEY}`, + headers: {}, + }; + + const response = await axios(config).then(function (response) { + return response.data; + }); + const payload = response.predictions.map((prediction) => { + return { + name: prediction.description, + id: prediction.place_id, + }; + }); + + return res.status(201).json(payload); + } catch (error) { + console.error(error); + return res.status(500).json({ success: false, message: error.message || "Something went wrong" }); + } +}); +app.get("/api/v1/rules", async function (req, res, next) { + try { + //body should have actives lsit as array + const rules = await db.rule.getAll(); + + if (!rules) { + return res.status(404).json({ success: false, message: `There are no rules` }); + } + + return res.status(201).json({ success: true, data: rules }); + } catch (error) { + console.error(error); + return res.status(500).json({ success: false, message: error.message || "Something went wrong" }); + } +}); + +app.get("/api/v1/profile-sections", async function (req, res, next) { + try { + //body should have actives lsit as array + const profileSections = await db.result_profile.getAll(); + + if (!profileSections) { + return res.status(404).json({ success: false, message: `There are sections to display` }); + } + + for (const section of profileSections) { + if (section.output_variable_list) { + const parsedList = JSON.parse(section.output_variable_list); + let actualList = await db.output_variable.findAll({ + where: { + id: parsedList, + }, + }); + actualList = actualList.map((ov) => ov.name); + section.output_variable_list = actualList; + } + } + return res.status(201).json({ success: true, data: profileSections }); + } catch (error) { + console.error(error); + return res.status(500).json({ success: false, message: error.message || "Something went wrong" }); + } +}); + +app.get("/api/v1/weather-profile", async function (req, res, next) { + try { + const { city_id } = req.query; + var config = { + method: "get", + url: `https://maps.googleapis.com/maps/api/place/details/json?place_id=${city_id}&fields=geometry,formatted_address,address_component&key=${process.env.GOOGLE_PLACES_API_KEY}`, + headers: {}, + }; + + const place_details = await axios(config); + // .then((response) => response.data); + if (place_details?.data?.status !== "OK") { + console.error(place_details); + return res.status(400).json({ success: false, message: "Can't get location" }); + } + const lon = place_details.data.result.geometry.location.lng; + const lat = place_details.data.result.geometry.location.lat; + const country = place_details.data.result.address_components.find((adr) => adr.types.includes("country")); + // const country; + config = { + method: "get", + url: `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${process.env.OPEN_WEATHER_API_KEY}&units=metric`, + }; + + const weather = await axios(config).then((response) => response.data); + + config = { + method: "get", + url: `https://api.openweathermap.org/data/2.5/air_pollution?lat=${lat}&lon=${lon}&appid=${process.env.OPEN_WEATHER_API_KEY}&units=metric`, + }; + const pollutionData = await axios(config).then((response) => response.data); + + // let temperatureWeight = weather.main.temp; + let { sunValue, sunWeight, temperatureWeight } = calculateSun(weather.main.temp); + let { humidityValue, humidityWeight } = calculateHumidity(weather.main.humidity); + let { pollutionValue, pollutionWeight } = calculatePollution(pollutionData.list[0].main.aqi); + let temperature = weather.main.temp; + let unit = "°C"; + if (country.short_name == "GB" || country.short_name == "US") { + temperature = (temperature * 9) / 5 + 32; + unit = "°F"; + } + let payload = { + unit: unit, + humidity: humidityValue, + temperature: Math.round(temperature), + sun: sunValue, + pollution: pollutionValue, + weights: { + Pollution: { + value: pollutionWeight, + base: 33, + }, + Sun: { + value: sunWeight, + base: 10, + }, + Temperature: { + value: temperatureWeight, + base: 0, + }, + Hydration: { + value: humidityWeight, + base: 15, + }, + }, + }; + return res.status(201).json({ + success: true, + data: payload, + }); + } catch (error) { + console.error(error); + return res.status(500).json({ success: false, message: error.message || "Something went wrong" }); + } +}); + +function calculateSun(sunTemp) { + let maxSun = 56.7; + let sun = parseFloat(sunTemp / maxSun) * 100; + if (sun > 0 && sun <= 33.334) { + return { + sunValue: "low", + sunWeight: 33.334 * 10, + temperatureWeight: 0, + }; + } else if (sun > 33.334 && sun <= 66.667) { + return { + sunValue: "medium", + sunWeight: 66.667 * 10, + temperatureWeight: 0, + }; + } else if (sun > 66.667 && sun <= 100) { + return { + sunValue: "High", + sunWeight: 100 * 10, + temperatureWeight: 0, + }; + } else { + return { + sunValue: "", + sunWeight: 0, + temperatureWeight: 0, + }; + } +} +function calculateHumidity(humidity) { + if (humidity < 30) { + return { + humidityValue: "Low", + humidityWeight: 33.334 * 15, + }; + } else if (humidity >= 30 && humidity < 50) { + return { + humidityValue: "Medium", + humidityWeight: 66.667 * 15, + }; + } else if (humidity >= 50) { + return { + humidityValue: "High", + humidityWeight: 100 * 15, + }; + } else { + return { + humidityValue: "", + humidityWeight: 0, + }; + } +} +function calculatePollution(airQuality) { + // Air Quality Index. Possible values: 1, 2, 3, 4, 5. Where 1 = Good, 2 = Fair, 3 = Moderate, 4 = Poor, 5 = Very Poor. + if (airQuality == 1) { + return { + pollutionValue: "Very low", + pollutionWeight: 20 * 33, + }; + } else if (airQuality == 2) { + return { + pollutionValue: "Low", + pollutionWeight: 40 * 33, + }; + } else if (airQuality == 3) { + return { + pollutionValue: "Moderate", + pollutionWeight: 60 * 33, + }; + } else if (airQuality == 4) { + return { + pollutionValue: "High", + pollutionWeight: 80 * 33, + }; + } else if (airQuality == 5) { + return { + pollutionValue: "Very high", + pollutionWeight: 100 * 33, + }; + } else { + return { + pollutionValue: "", + pollutionWeight: 0, + }; + } +} +module.exports = app; diff --git a/controllers/shopify/getProducts.js b/controllers/shopify/getProducts.js new file mode 100644 index 0000000..d279fcc --- /dev/null +++ b/controllers/shopify/getProducts.js @@ -0,0 +1,20 @@ +const axios = require("axios"); + +const app = require("express").Router(); + +app.get("/v1/api/get-shopify-products", async function (req, res, next) { + try { + var config = { + method: "get", + url: `https://${process.env.SHOPIFY_API_KEY}:${process.env.SHOPIFY_API_PASSWORD}@${process.env.SHOPIFY_SITE}/admin/api/2021-10/products.json`, + headers: {}, + }; + + const response = await axios(config); + return res.status(201).json(response.data); + } catch (error) { + return res.status(500).json({ success: false, message: error.message }); + } +}); + +module.exports = app; diff --git a/controllers/shopify/testOrderPaid.js b/controllers/shopify/testOrderPaid.js new file mode 100644 index 0000000..5dd8a5e --- /dev/null +++ b/controllers/shopify/testOrderPaid.js @@ -0,0 +1,1431 @@ +module.exports = { + id: 4884199014561, + admin_graphql_api_id: "gid://shopify/Order/4884199014561", + app_id: 580111, + browser_ip: "107.77.223.130", + buyer_accepts_marketing: true, + cancel_reason: null, + cancelled_at: null, + cart_token: "dfd4153f49214e2625561b11715d8270", + checkout_id: 25960421327009, + checkout_token: "c443b8928ff2c45a954ab5d2f080bbe2", + client_details: { + accept_language: "en-US,en;q=0.9,he-IL;q=0.8,he;q=0.7", + browser_height: 730, + browser_ip: "107.77.223.130", + browser_width: 412, + session_hash: null, + user_agent: + "Mozilla/5.0 (Linux; Android 11; SM-G973U Build/RP1A.200720.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/98.0.4758.101 Mobile Safari/537.36 Instagram 224.2.0.20.116 Android (30/11; 420dpi; 1080x2042; samsung; SM-G973U; beyond1q; qcom; en_US; 354065949)", + }, + closed_at: "2022-03-14T12:11:20-04:00", + confirmed: true, + contact_email: "eransco@gmail.com", + created_at: "2022-03-11T13:10:08-05:00", + currency: "USD", + current_subtotal_price: "81.00", + current_subtotal_price_set: { + shop_money: { + amount: "81.00", + currency_code: "USD", + }, + presentment_money: { + amount: "81.00", + currency_code: "USD", + }, + }, + current_total_discounts: "0.00", + current_total_discounts_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + current_total_duties_set: null, + current_total_price: "81.00", + current_total_price_set: { + shop_money: { + amount: "81.00", + currency_code: "USD", + }, + presentment_money: { + amount: "81.00", + currency_code: "USD", + }, + }, + current_total_tax: "0.00", + current_total_tax_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + customer_locale: "en-US", + device_id: null, + discount_codes: [], + email: "eransco@gmail.com", + estimated_taxes: false, + financial_status: "paid", + fulfillment_status: "fulfilled", + gateway: "shopify_payments", + landing_site: "/", + landing_site_ref: null, + location_id: null, + name: "#1039", + note: "", + note_attributes: [ + { + name: "answers", + value: + '[{"question":{"id":1},"answer":"Eran"},{"question":{"id":2},"weights":{"Bio Age":{"value":4500,"base":100},"Age":{"value":2250,"base":"50"}},"answer":"1977"},{"question":{"id":3},"answer":"Male","black_list_actives":null},{"question":{"id":21},"weights":{"Pollution":{"value":3300,"base":33},"Sun":{"value":333.34000000000003,"base":10},"Temperature":{"value":0,"base":0},"Hydration":{"value":1000.005,"base":15}},"answer":"New York","city_id":"ChIJOwg_06VPwokRYv534QaPC8g"},{"question":{"id":6},"answer":"Moderately","slider_value":48.8236376101533,"weights":{"Sensitivity":{"value":4882.36376101533,"base":100}},"black_list_actives":[]},{"question":{"id":7},"answer":"Normal / Combination","slider_value":49.3035466448172,"weights":{"Hydration":{"value":3451.2482651372043,"base":70}},"black_list_actives":[]},{"question":{"id":9},"weights":{"Color":{"value":2666.67,"base":100},"Sun":{"value":266.667,"base":10},"Hyperpigmentation":{"value":266.667,"base":10}},"answer":"4","black_list_actives":null},{"question":{"id":10},"answer":"Always","slider_value":89.6827918331856,"weights":{"Sun":{"value":1793.655836663712,"base":20}},"black_list_actives":[]},{"question":{"id":11},"answer":"No","slider_value":33.7825861578851,"weights":{"Hyperpigmentation":{"value":3040.432754209659,"base":90},"Sun":{"value":337.825861578851,"base":10}},"black_list_actives":[]},{"question":{"id":12},"answer":"Instant Burn","slider_value":68.8008962761066,"weights":{"Sun":{"value":4128.053776566396,"base":60}},"black_list_actives":[]},{"question":{"id":14},"answer":"eransco@gmail.com"},{"question":{"id":17},"answer":"Some","slider_value":36.7172215440697,"weights":{"Pores":{"value":3671.7221544069703,"base":100}},"black_list_actives":[]},{"question":{"id":15},"answer":"A Few Lines","slider_value":21.4805277327224,"weights":{"Lines":{"value":2148.05277327224,"base":100},"Age":{"value":644.415831981672,"base":30}},"black_list_actives":[]},{"question":{"id":18},"answer":"Some","slider_value":34.1220340116717,"weights":{"Blackheads":{"value":3412.2034011671703,"base":100}},"black_list_actives":[]},{"question":{"id":19},"weights":{"Allergies":{"value":0,"base":100}},"answer":"No","black_list_actives":null},{"question":{"id":25},"answer":"<4","slider_value":5.99923080781901,"weights":{"Sleep":{"value":4998.077019547524,"base":100}},"black_list_actives":[]},{"question":{"id":27},"answer":"6","slider_value":32.0335100245807,"weights":{"Hydration":{"value":480.5026503687105,"base":15}},"black_list_actives":[]},{"question":{"id":29},"answer":"Low","slider_value":55.6242997842918,"weights":{"Oxygenation":{"value":5562.42997842918,"base":100}},"black_list_actives":[]}]', + }, + { + name: "profile", + value: + '{"Skin Sensitivity":[{"name":"Sensitivity","percentage":48.8236376101533},{"name":"Hydration","percentage":49.31755915505914},{"name":"Sun","percentage":62.35947704371781},{"name":"Hyperpigmentation","percentage":33.07099754209659},{"name":"Redness","percentage":0}],"Skin Characteristics":[{"name":"Breakouts","percentage":0},{"name":"Lines","percentage":21.480527732722397},{"name":"Pores","percentage":36.7172215440697},{"name":"Blackheads","percentage":34.1220340116717}],"Environmental Factors":[{"name":"Pollution","percentage":100},{"name":"Stress","percentage":0},{"name":"Oxygenation","percentage":55.6242997842918}]}', + }, + { + name: "actives", + value: '["Base","Moringa","Chia","Gotu Kola","Dragon\'s Blood","Oatmeal","Coconut","Chamomile"]', + }, + ], + number: 39, + order_number: 1039, + order_status_url: "https://localhost:3001/48557752481/orders/494d781f1edc1b0101e520b16f132c65/authenticate?key=8c15f18557e37ab98b7b37b1104a4734", + original_total_duties_set: null, + payment_gateway_names: ["shopify_payments"], + phone: null, + presentment_currency: "USD", + processed_at: "2022-03-11T13:10:03-05:00", + processing_method: "direct", + reference: null, + referring_site: "https://l.instagram.com/", + source_identifier: null, + source_name: "web", + source_url: null, + subtotal_price: "81.00", + subtotal_price_set: { + shop_money: { + amount: "81.00", + currency_code: "USD", + }, + presentment_money: { + amount: "81.00", + currency_code: "USD", + }, + }, + tags: "", + tax_lines: [], + taxes_included: false, + test: false, + token: "494d781f1edc1b0101e520b16f132c65", + total_discounts: "0.00", + total_discounts_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + total_line_items_price: "81.00", + total_line_items_price_set: { + shop_money: { + amount: "81.00", + currency_code: "USD", + }, + presentment_money: { + amount: "81.00", + currency_code: "USD", + }, + }, + total_outstanding: "0.00", + total_price: "81.00", + total_price_set: { + shop_money: { + amount: "81.00", + currency_code: "USD", + }, + presentment_money: { + amount: "81.00", + currency_code: "USD", + }, + }, + total_price_usd: "81.00", + total_shipping_price_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + total_tax: "0.00", + total_tax_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + total_tip_received: "0.00", + total_weight: 255, + updated_at: "2022-03-15T20:07:23-04:00", + user_id: null, + billing_address: { + first_name: "Eran", + address1: "241 Eldridge Street", + phone: "(917) 283-1769", + city: "New York", + zip: "10002", + province: "New York", + country: "United States", + last_name: "Socher", + address2: "3F", + company: "", + latitude: 40.7226658, + longitude: -73.98991269999999, + name: "Eran Socher", + country_code: "US", + province_code: "NY", + }, + customer: { + id: 6018740715681, + email: "eransco@gmail.com", + accepts_marketing: true, + created_at: "2022-03-11T13:09:14-05:00", + updated_at: "2022-03-12T21:06:36-05:00", + first_name: "Eran", + last_name: "Socher", + orders_count: 1, + state: "disabled", + total_spent: "81.00", + last_order_id: 4884199014561, + note: null, + verified_email: true, + multipass_identifier: null, + tax_exempt: false, + phone: null, + tags: "", + last_order_name: "#1039", + currency: "USD", + accepts_marketing_updated_at: "2022-03-11T13:09:14-05:00", + marketing_opt_in_level: "single_opt_in", + tax_exemptions: [], + email_marketing_consent: { + state: "subscribed", + opt_in_level: "single_opt_in", + consent_updated_at: null, + }, + sms_marketing_consent: null, + admin_graphql_api_id: "gid://shopify/Customer/6018740715681", + default_address: { + id: 7239153418401, + customer_id: 6018740715681, + first_name: "Eran", + last_name: "Socher", + company: "", + address1: "241 Eldridge Street", + address2: "3F", + city: "New York", + province: "New York", + country: "United States", + zip: "10002", + phone: "(917) 283-1769", + name: "Eran Socher", + province_code: "NY", + country_code: "US", + country_name: "United States", + default: true, + }, + }, + discount_applications: [], + fulfillments: [ + { + id: 4383119540385, + admin_graphql_api_id: "gid://shopify/Fulfillment/4383119540385", + created_at: "2022-03-14T12:11:18-04:00", + location_id: 55199531169, + name: "#1039.1", + order_id: 4884199014561, + origin_address: {}, + receipt: {}, + service: "manual", + shipment_status: "delivered", + status: "success", + tracking_company: "UPS®", + tracking_number: "1ZY348370390287118", + tracking_numbers: ["1ZY348370390287118"], + tracking_url: "https://www.ups.com/WebTracking?loc=en_US&requester=ST&trackNums=1ZY348370390287118", + tracking_urls: ["https://www.ups.com/WebTracking?loc=en_US&requester=ST&trackNums=1ZY348370390287118"], + updated_at: "2022-03-15T20:07:23-04:00", + line_items: [ + { + id: 12304305422497, + admin_graphql_api_id: "gid://shopify/LineItem/12304305422497", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Oatmeal", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "4.50", + price_set: { + shop_money: { + amount: "4.50", + currency_code: "USD", + }, + presentment_money: { + amount: "4.50", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 7117745127585, + properties: [ + { + name: "score", + value: "23.35", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "2014", + taxable: true, + title: "Oatmeal", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 41205127577761, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12304305455265, + admin_graphql_api_id: "gid://shopify/LineItem/12304305455265", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Moringa", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "5.50", + price_set: { + shop_money: { + amount: "5.50", + currency_code: "USD", + }, + presentment_money: { + amount: "5.50", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 7117738180769, + properties: [ + { + name: "score", + value: "26.44", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "2012", + taxable: true, + title: "Moringa", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 41205119090849, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12304305488033, + admin_graphql_api_id: "gid://shopify/LineItem/12304305488033", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Gotu Kola", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "6.00", + price_set: { + shop_money: { + amount: "6.00", + currency_code: "USD", + }, + presentment_money: { + amount: "6.00", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 7117734838433, + properties: [ + { + name: "score", + value: "24.39", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "2010", + taxable: true, + title: "Gotu Kola", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 41205114437793, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12304305520801, + admin_graphql_api_id: "gid://shopify/LineItem/12304305520801", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Dragon's Blood", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "6.00", + price_set: { + shop_money: { + amount: "6.00", + currency_code: "USD", + }, + presentment_money: { + amount: "6.00", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 7117731987617, + properties: [ + { + name: "score", + value: "24.07", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "2008", + taxable: true, + title: "Dragon's Blood", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 41205111095457, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12304305553569, + admin_graphql_api_id: "gid://shopify/LineItem/12304305553569", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Coconut", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "5.00", + price_set: { + shop_money: { + amount: "5.00", + currency_code: "USD", + }, + presentment_money: { + amount: "5.00", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 7117723402401, + properties: [ + { + name: "score", + value: "22.43", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "2005", + taxable: false, + title: "Coconut", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 41205095727265, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12304305586337, + admin_graphql_api_id: "gid://shopify/LineItem/12304305586337", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Chia", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "5.50", + price_set: { + shop_money: { + amount: "5.50", + currency_code: "USD", + }, + presentment_money: { + amount: "5.50", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 7117721665697, + properties: [ + { + name: "score", + value: "24.67", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "2004", + taxable: false, + title: "Chia", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 41205091795105, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12304305619105, + admin_graphql_api_id: "gid://shopify/LineItem/12304305619105", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Chamomile", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "5.50", + price_set: { + shop_money: { + amount: "5.50", + currency_code: "USD", + }, + presentment_money: { + amount: "5.50", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 7117719109793, + properties: [ + { + name: "score", + value: "22.18", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "2003", + taxable: false, + title: "Chamomile", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 41205087502497, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12304305651873, + admin_graphql_api_id: "gid://shopify/LineItem/12304305651873", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 240, + name: "Base", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "43.00", + price_set: { + shop_money: { + amount: "43.00", + currency_code: "USD", + }, + presentment_money: { + amount: "43.00", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 5705461924001, + properties: [ + { + name: "score", + value: "100.00", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "1001", + taxable: true, + title: "Base", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 36332638240929, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12311078731937, + admin_graphql_api_id: "gid://shopify/LineItem/12311078731937", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Blank", + price: "0.00", + price_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 5873158619297, + properties: [], + quantity: 4, + requires_shipping: true, + sku: "2000", + taxable: false, + title: "Blank", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 36987054850209, + variant_inventory_management: "shopify", + variant_title: null, + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + ], + }, + ], + line_items: [ + { + id: 12304305422497, + admin_graphql_api_id: "gid://shopify/LineItem/12304305422497", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Oatmeal", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "4.50", + price_set: { + shop_money: { + amount: "4.50", + currency_code: "USD", + }, + presentment_money: { + amount: "4.50", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 7117745127585, + properties: [ + { + name: "score", + value: "23.35", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "2014", + taxable: true, + title: "Oatmeal", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 41205127577761, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12304305455265, + admin_graphql_api_id: "gid://shopify/LineItem/12304305455265", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Moringa", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "5.50", + price_set: { + shop_money: { + amount: "5.50", + currency_code: "USD", + }, + presentment_money: { + amount: "5.50", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 7117738180769, + properties: [ + { + name: "score", + value: "26.44", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "2012", + taxable: true, + title: "Moringa", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 41205119090849, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12304305488033, + admin_graphql_api_id: "gid://shopify/LineItem/12304305488033", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Gotu Kola", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "6.00", + price_set: { + shop_money: { + amount: "6.00", + currency_code: "USD", + }, + presentment_money: { + amount: "6.00", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 7117734838433, + properties: [ + { + name: "score", + value: "24.39", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "2010", + taxable: true, + title: "Gotu Kola", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 41205114437793, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12304305520801, + admin_graphql_api_id: "gid://shopify/LineItem/12304305520801", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Dragon's Blood", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "6.00", + price_set: { + shop_money: { + amount: "6.00", + currency_code: "USD", + }, + presentment_money: { + amount: "6.00", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 7117731987617, + properties: [ + { + name: "score", + value: "24.07", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "2008", + taxable: true, + title: "Dragon's Blood", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 41205111095457, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12304305553569, + admin_graphql_api_id: "gid://shopify/LineItem/12304305553569", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Coconut", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "5.00", + price_set: { + shop_money: { + amount: "5.00", + currency_code: "USD", + }, + presentment_money: { + amount: "5.00", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 7117723402401, + properties: [ + { + name: "score", + value: "22.43", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "2005", + taxable: false, + title: "Coconut", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 41205095727265, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12304305586337, + admin_graphql_api_id: "gid://shopify/LineItem/12304305586337", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Chia", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "5.50", + price_set: { + shop_money: { + amount: "5.50", + currency_code: "USD", + }, + presentment_money: { + amount: "5.50", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 7117721665697, + properties: [ + { + name: "score", + value: "24.67", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "2004", + taxable: false, + title: "Chia", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 41205091795105, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12304305619105, + admin_graphql_api_id: "gid://shopify/LineItem/12304305619105", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Chamomile", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "5.50", + price_set: { + shop_money: { + amount: "5.50", + currency_code: "USD", + }, + presentment_money: { + amount: "5.50", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 7117719109793, + properties: [ + { + name: "score", + value: "22.18", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "2003", + taxable: false, + title: "Chamomile", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 41205087502497, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12304305651873, + admin_graphql_api_id: "gid://shopify/LineItem/12304305651873", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 240, + name: "Base", + origin_location: { + id: 3271783514273, + country_code: "US", + province_code: "NY", + name: "Created By", + address1: "4702 2nd Avenue", + address2: "", + city: "Brooklyn", + zip: "11232", + }, + price: "43.00", + price_set: { + shop_money: { + amount: "43.00", + currency_code: "USD", + }, + presentment_money: { + amount: "43.00", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 5705461924001, + properties: [ + { + name: "score", + value: "100.00", + }, + ], + quantity: 1, + requires_shipping: true, + sku: "1001", + taxable: true, + title: "Base", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 36332638240929, + variant_inventory_management: "shopify", + variant_title: "", + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + { + id: 12311078731937, + admin_graphql_api_id: "gid://shopify/LineItem/12311078731937", + fulfillable_quantity: 0, + fulfillment_service: "manual", + fulfillment_status: "fulfilled", + gift_card: false, + grams: 1, + name: "Blank", + price: "0.00", + price_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + product_exists: true, + product_id: 5873158619297, + properties: [], + quantity: 4, + requires_shipping: true, + sku: "2000", + taxable: false, + title: "Blank", + total_discount: "0.00", + total_discount_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + variant_id: 36987054850209, + variant_inventory_management: "shopify", + variant_title: null, + vendor: "Created By", + tax_lines: [], + duties: [], + discount_allocations: [], + }, + ], + payment_details: { + credit_card_bin: "371300", + avs_result_code: "Y", + cvv_result_code: "M", + credit_card_number: "•••• •••• •••• 1004", + credit_card_company: "American Express", + }, + payment_terms: null, + refunds: [], + shipping_address: { + first_name: "Eran", + address1: "241 Eldridge Street", + phone: "(917) 283-1769", + city: "New York", + zip: "10002", + province: "New York", + country: "United States", + last_name: "Socher", + address2: "3F", + company: "", + latitude: 40.7226658, + longitude: -73.98991269999999, + name: "Eran Socher", + country_code: "US", + province_code: "NY", + }, + shipping_lines: [ + { + id: 3997918429345, + carrier_identifier: null, + code: "Standard", + delivery_category: null, + discounted_price: "0.00", + discounted_price_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + phone: null, + price: "0.00", + price_set: { + shop_money: { + amount: "0.00", + currency_code: "USD", + }, + presentment_money: { + amount: "0.00", + currency_code: "USD", + }, + }, + requested_fulfillment_service_id: null, + source: "shopify", + title: "Standard", + tax_lines: [], + discount_allocations: [], + }, + ], +}; diff --git a/controllers/shopify/webhook.js b/controllers/shopify/webhook.js new file mode 100644 index 0000000..e0d32f3 --- /dev/null +++ b/controllers/shopify/webhook.js @@ -0,0 +1,80 @@ +const app = require("express").Router(); +const db = require("../../models"); +const crypto = require("crypto"); +app.post("/v1/api/webhook", async function (req, res, next) { + try { + const hmac = req.get("X-Shopify-Hmac-Sha256"); + const rawBody = req.rawBody; + if (!verify_webhook(rawBody, hmac)) { + return res.sendStatus(403); + } + + const webhookId = req.get("X-Shopify-Webhook-Id"); + const event = req.body; + const currentOrderLineItems = event.line_items.map((item) => item.name); + + //this gets the first ever order of said customer since it can't happen unless he goes thro quiz. + const customerId = event.customer.id; + const customerOrderedBefore = await db.order.findOne({ + where: { + customer_shopify_id: customerId, + }, + }); + + let attributes = event.note_attributes ?? []; + + if (!attributes.length) { + if (!customerOrderedBefore) { + return res.sendStatus(204); + } + attributes.push({ + name: "answers", + value: customerOrderedBefore.answers, //we take old answers + }); + attributes.push({ + name: "profile", + value: customerOrderedBefore.profile, //we take old profile + }); + attributes.push({ + name: "actives", + value: JSON.stringify(currentOrderLineItems ?? []), //we take new actives + }); + } + + if (await db.order.getByFields({ webhook_id: webhookId })) return res.sendStatus(205); //webhook handled before + + const orderExists = await db.order.getByFields({ shopify_id: `${event.id}` }); + const modelParams = { + webhook_id: webhookId, + shopify_id: event.id, + customer_shopify_id: event.customer.id, + customer: JSON.stringify(event.customer), + answers: attributes.find((attr) => attr.name == "answers")?.value ?? "[]", + profile: attributes.find((attr) => attr.name == "profile")?.value ?? "{}", + actives: attributes.find((attr) => attr.name == "actives")?.value ?? "[]", + items: JSON.stringify(event.line_items ?? []), + financial_status: event.financial_status, + fulfillment_status: event.fulfillment_status, + }; + + if (orderExists) { + console.log("Modifying order"); + await db.order.edit(modelParams, orderExists.id); + } else { + console.log("Creating new order"); + await db.order.insert(modelParams); + } + + return res.sendStatus(200); + } catch (error) { + console.error(error); + return res.sendStatus(500); + } +}); + +module.exports = app; + +function verify_webhook(data, hmac_header) { + let calculated_hmac = crypto.createHmac("sha256", process.env.SHOPIFY_SECRET_KEY).update(data).digest("base64"); + return calculated_hmac == hmac_header; +} diff --git a/core/errors.js b/core/errors.js new file mode 100644 index 0000000..0f5821e --- /dev/null +++ b/core/errors.js @@ -0,0 +1,8 @@ +module.exports = { + EMAIL_ADDRESS_NOT_FOUND: 'Email Address Not Found', + EMAIL_ADDRESS_ALREADY_EXIST: 'Email Address Already Exists', + PASSWORD_NOT_MATCH: 'Password Does Not Match', + INVALID_EMAIL_CONFIRMATION_CODE: 'Invalid Email Confirmation Code', + INVALID_EMAIL_OR_PASSWORD: 'Invalid Email Or Password', + USER_NOT_FOUND: 'User Not Found', +}; diff --git a/core/helpers.js b/core/helpers.js new file mode 100644 index 0000000..20a8a48 --- /dev/null +++ b/core/helpers.js @@ -0,0 +1,76 @@ +const fs = require('fs'); +const path = require('path'); +const sanitizeHtml = require('sanitize-html'); +module.exports = { + filterEmptyFields(object) { + Object.keys(object).forEach((key) => { + if (this.empty(object[key])) { + delete object[key]; + } + }); + return object; + }, + empty(value) { + return value === '' || value === null || value === undefined; + }, + getMappingKey(mappingFunction, value) { + return Object.keys(mappingFunction()).find((key) => mappingFunction()[key].toLowerCase() === value.toLowerCase()); + }, + checkFor(requiredFields) { + for (const [key, value] of Object.entries(requiredFields)) { + if (!value) { + throw new Error(`Must provide ${key}`); + } + } + return true; + }, + convertToCents(amount) { + return parseFloat(amount) * 100; + }, + convertFromCents(amount) { + return parseFloat(amount) / 100; + }, + inject_substitute(text, normalKey, value) { + text = text.replace(new RegExp('{{{' + normalKey + '}}}', 'g'), value); + return text; + }, + createDirectoriesRecursive(filePath) { + let fileDirectoryPath = path.dirname(filePath); + if (!fs.existsSync(fileDirectoryPath)) { + fs.mkdirSync(fileDirectoryPath, { recursive: true }); + } + }, + createDirectoriesRecursiveV2(folderPath) { + if (!fs.existsSync(folderPath)) { + fs.mkdirSync(folderPath, { recursive: true }); + } + }, + sanitizeInputs(body) { + if (Array.isArray(body)) { + body.forEach((item) => { + item = sanitizeHtml(item); + }); + return body; + } + if (this.isObject(body)) { + Object.keys(body).forEach((key) => { + body[key] = sanitizeHtml(body[key]); + }); + return body; + } + return sanitizeHtml(body); + }, + isObject(obj) { + return obj === Object(obj); + }, + ucFirst(string) { + return string.charAt(0).toUpperCase() + string.slice(1); + }, + getLocalPath(string) { + if (string.includes('\\')) { + return string.split('\\public')[1].replace(/\\/g, '/'); + } else { + return string.split('/public')[1]; + } + }, +}; diff --git a/core/models.js b/core/models.js new file mode 100644 index 0000000..040bb72 --- /dev/null +++ b/core/models.js @@ -0,0 +1,313 @@ +const { isInteger } = require("lodash"); + +module.exports = async function (Table) { + Table._primaryKey = function () { + return "id"; + }; + Table.getLast = async function (parameters) { + let where = parameters; + if (!where) { + where = {}; + } + for (const key in where) { + const element = where[key]; + if (element == undefined || element == null) { + delete where.key; + } + } + result = await Table.findAll({ + limit: 1, + where: where, + order: [["id", "DESC"]], + }); + return result[0]; + }; + Table.getAll = function (parameters, orderBy = Table._primaryKey(), direction = "ASC", orderAssociations, include = []) { + let where = parameters; + if (!where) { + where = {}; + } + for (const key in where) { + const element = where[key]; + if (element == undefined || element == null) { + delete where.key; + } + } + + let params = { + where: where, + include: include, + distinct: true, + order: [[orderBy, direction]], + }; + + if (Array.isArray(orderAssociations) && orderAssociations.length > 0) { + orderAssociations.forEach(function (order) { + params.order[0].unshift(order); + }); + } + return Table.findAll(params); + }; + Table._count = function (parameters, include = []) { + let where = parameters; + if (!where) { + where = {}; + } + for (const key in where) { + const element = where[key]; + if (element == undefined || element == null) { + delete where.key; + } + } + + Table._customCountingConditions(where); + + return Table.count({ + where: where, + include: include, + distinct: true, + }); + }; + + Table.getPaginated = function (page, limit, parameters, orderBy, direction, orderAssociations = [], include = []) { + let where = parameters; + + for (const key in where) { + if (where.hasOwnProperty.call(where, key)) { + const element = where[key]; + if (element.length || isInteger(element) || element === Object(element)) { + where[key] = element; + } else { + delete where[key]; + } + } + } + + if (!page) { + page = 0; + } + if (!limit) { + limit = 10; + } + if (!where) { + where = {}; + } + if (!orderBy) { + orderBy = Table._primaryKey(); + } + if (!direction) { + direction = "ASC"; + } + + for (const key in where) { + const element = where[key]; + if (element == undefined || element == null) { + delete where.key; + } + } + let params = { + where: where, + offset: page * limit, + limit: limit, + include: include, + order: [[orderBy, direction]], + distinct: true, + }; + if (Array.isArray(orderAssociations) && orderAssociations.length > 0) { + orderAssociations.forEach(function (order) { + params.order[0].unshift(order); + }); + } + return Table.findAll(params); + }; + Table.getPaginatedV2 = function (page, limit, parameters, order, direction, include = []) { + let where = parameters; + + for (const key in where) { + if (where.hasOwnProperty.call(where, key)) { + const element = where[key]; + if (element.length || isInteger(element) || element === Object(element)) { + where[key] = element; + } else { + delete where[key]; + } + } + } + + if (!page) { + page = 0; + } + if (!limit) { + limit = 10; + } + if (!where) { + where = {}; + } + if (!order) { + order = Table._primaryKey(); + } + if (!direction) { + direction = "ASC"; + } + + for (const key in where) { + const element = where[key]; + if (element == undefined || element == null) { + delete where.key; + } + } + let params = { + where: where, + offset: page * limit, + limit: limit, + include: include, + order: order, + distinct: true, + }; + return Table.findAll(params); + }; + Table.getAllByStatus = function (status) { + return Table.findAll({ + where: { + status: status, + }, + }); + }; + + Table.getByField = function (field, value) { + return Table.findOne({ + where: { + [field]: value, + }, + distinct: true, + }); + }; + + Table.getByPK = async function (id, options) { + return await Table.findByPk(id, options); + }; + + Table.getByFields = function (parameters) { + let where = parameters; + if (!where) { + where = {}; + } + for (const key in where) { + const element = where[key]; + if (element == undefined || element == null) { + delete where.key; + } + } + + return Table.findOne({ + where: where, + }); + }; + + Table.getAllByKeyValue = async function (field, parameters) { + let where = parameters; + if (!where) { + where = {}; + } + let data = []; + const results = await Table.findAll({ + where: where, + }); + + for (let i = 0; i < results.length; i++) { + const element = results[i]; + let singleField = element[field]; + data.push({ [element.id]: singleField }); + } + + return data; + }; + + Table.insert = async function (data, { returnAllFields = false } = {}) { + data = Table._preCreateProcessing(data); + const insertedRow = await Table.create(Table._filterAllowKeys(data)); + if (returnAllFields === true) { + return insertedRow; + } + if (insertedRow) { + return insertedRow.id; + } + return false; + }; + + Table.batchInsert = async function (data) { + const insertedRow = await Table.bulkCreate(data, { returning: true }); + + if (insertedRow) { + return insertedRow; + } + + return false; + }; + + Table.edit = async function (data, id) { + data = Table._postCreateProcessing(data); + const updateRow = await Table.update(Table._filterAllowKeys(data), { + where: { + id: id, + }, + }).catch((error) => { + throw new Error(error); + }); + + return updateRow; + }; + + Table.editByField = async function (data, where) { + data = Table._postCreateProcessing(data); + + const updateRow = await Table.update(Table._filterAllowKeys(data), { + where, + }); + + return updateRow; + }; + + Table.delete = async function (id) { + const updateRow = await Table.update( + { + status: 0, + }, + { + where: { + id: id, + }, + } + ); + return updateRow; + }; + + Table.realDelete = async function (id) { + return Table.destroy({ + where: { + id: id, + }, + }); + }; + + Table.realDeleteByFields = async function (parameters, id) { + let where = parameters; + if (!where) { + where = { + id: id, + }; + } else { + where["id"] = id; + } + return Table.destroy({ + where: where, + }); + }; + Table.realDeleteByUniqueField = async function (field, value) { + let where = {}; + where[field] = value; + return Table.destroy({ + where: where, + }); + }; +}; diff --git a/core/utils.js b/core/utils.js new file mode 100644 index 0000000..063eab5 --- /dev/null +++ b/core/utils.js @@ -0,0 +1,10 @@ +exports.validateEmail = (email) => { + const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + + const reStartAndEnd = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}/g; + + if (re.test(email) && reStartAndEnd.test(email)) { + return true; + } + return false; +}; diff --git a/cronjobs/Backup_uploads_cronjob_controller.js b/cronjobs/Backup_uploads_cronjob_controller.js new file mode 100644 index 0000000..8814c38 --- /dev/null +++ b/cronjobs/Backup_uploads_cronjob_controller.js @@ -0,0 +1,64 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ + +/** + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +const archiver = require('archiver'); +const AWS = require('aws-sdk'); +const s3 = new AWS.S3(); +const stream = require('stream'); +const path = require('path'); + +AWS.config.update({ + accessKeyId: process.env.DYNAMIC_CONFIG_AWS_KEY, + secretAccessKey: process.env.DYNAMIC_CONFIG_AWS_SECRET, + region: process.env.DYNAMIC_CONFIG_AWS_REGION, +}); + +const main = async () => { + const archive = archiver('zip', { + zlib: { level: 9 }, // Sets the compression level. + }); + + archive.directory(path.join(__dirname, '../../', '/uploads'), false); + + const uploadStream = new stream.PassThrough(); + archive.pipe(uploadStream); + archive.finalize(); + + archive.on('warning', function (err) { + if (err.code === 'ENOENT') { + console.log(err); + } else { + throw err; + } + }); + + archive.on('error', function (err) { + throw err; + }); + + archive.on('end', function () { + console.log('archive end'); + }); + + await uploadFromStream(uploadStream); + console.log('all done'); +}; + +const uploadFromStream = async (pass) => { + const s3params = { + Bucket: process.env.DYNAMIC_CONFIG_AWS_BUCKET, + Key: `uploads.zip`, + Body: pass, + ContentType: 'application/zip', + }; + return s3.upload(s3params).promise(); +}; + +main(); diff --git a/cronjobs/Clean_image_cronjob_controller.js b/cronjobs/Clean_image_cronjob_controller.js new file mode 100644 index 0000000..7bebd28 --- /dev/null +++ b/cronjobs/Clean_image_cronjob_controller.js @@ -0,0 +1,42 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ + +/** + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +const AWS = require('aws-sdk'); +const S3 = new AWS.S3(); + +const db = require('../models'); + +AWS.config.update({ + accessKeyId: process.env.DYNAMIC_CONFIG_AWS_KEY, + secretAccessKey: process.env.DYNAMIC_CONFIG_AWS_SECRET, + region: process.env.DYNAMIC_CONFIG_AWS_REGION, +}); + +async function main() { + /** @type {Array.<{url: string}>} */ + const images = await db.image.getAllByStatus(0); + + const mapKeys = images.map(({ url }) => { + // TODO: DO MAPPING + return url; + }); + + const params = { + Bucket: process.env.AWS_S3_BUCKET, + Delete: { Objects: mapKeys }, + }; + + S3.deleteObjects(params, (error, data) => { + if (error) console.log(error); + else console.log(data); + }); +} + +main(); diff --git a/cronjobs/Clean_token_cronjob_controller.js b/cronjobs/Clean_token_cronjob_controller.js new file mode 100644 index 0000000..fdded0b --- /dev/null +++ b/cronjobs/Clean_token_cronjob_controller.js @@ -0,0 +1,16 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ + +/** + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +const db = require('../models'); + +(async function tokenCronJob() { + await db.query('UPDATE `token` SET status=0 WHERE `expire_at` < NOW();'); + await db.query('DELETE FROM `token` WHERE status=0;'); +})(); diff --git a/image/router.js b/image/router.js new file mode 100644 index 0000000..864c0d7 --- /dev/null +++ b/image/router.js @@ -0,0 +1,53 @@ +'use strict'; + +const { nanoid} = require('nanoid'); + +const SessionService = require('../../services/SessionService'); +const uploader = require('../../tools/file/uploader'); +const db = require('../../models'); + +module.exports = { + initializeApi: function (app) { + app.post( + "/api/replace-this", + SessionService.verifySessionMiddleware(role), + async function (req, res, next) { + try { + const imageUploadModel = require("../view_models/image_upload_local.js") + + const viewModel = imageUploadModel(db.image) + + + const url = await viewModel.upload_resource(req, rest); + await viewModel.create_resource({ url }); + + return res.status(201).json({success:true, message:"xyzimage_uploaded_successfully"}); + } catch (error) { + return res.status(500).json({success:false, message:"xyzsomething_went_wrong"}) + } + }, +); + + app.post( + "/api/replace-this", + SessionService.verifySessionMiddleware(role), + async function (req, res, next) { + try { + const fileUploadModel = require("../view_models/file_upload_local.js") + + const viewModel = fileUploadModel(db.image) + + + const url = await viewModel.upload_resource(req, rest); + await viewModel.create_resource({ url }); + + return res.status(201).json({success:true, message:"xyzimage_uploaded_successfully"}); + } catch (error) { + return res.status(500).json({success:false, message:"xyzsomething_went_wrong"}) + } + }, +); + + return app; + }, +}; diff --git a/lambda.js b/lambda.js new file mode 100644 index 0000000..d88bf0b --- /dev/null +++ b/lambda.js @@ -0,0 +1,17 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2020*/ +/** + * Lambda + * @copyright 2020 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const awsServerlessExpress = require("aws-serverless-express"); +const app = require("./app"); +const server = awsServerlessExpress.createServer(app); +exports.handler = (event, context) => { + context.callbackWaitsForEmptyEventLoop = false; + awsServerlessExpress.proxy(server, event, context); +}; diff --git a/migration.js b/migration.js new file mode 100644 index 0000000..defb415 --- /dev/null +++ b/migration.js @@ -0,0 +1,2 @@ +const models = require('./models'); +models.sequelize.sync({ force: false, alter: true }).then(function () {}); diff --git a/mkd_original_db.sql b/mkd_original_db.sql new file mode 100644 index 0000000..3667128 --- /dev/null +++ b/mkd_original_db.sql @@ -0,0 +1,695 @@ +-- -------------------------------------------------------- +-- Host: 127.0.0.1 +-- Server version: 10.4.22-MariaDB - mariadb.org binary distribution +-- Server OS: Win64 +-- HeidiSQL Version: 11.3.0.6295 +-- -------------------------------------------------------- + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET NAMES utf8 */; +/*!50503 SET NAMES utf8mb4 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + + +-- Dumping database structure for mkd +DROP DATABASE IF EXISTS `mkd`; +CREATE DATABASE IF NOT EXISTS `mkd` /*!40100 DEFAULT CHARACTER SET utf8mb4 */; +USE `mkd`; + +-- Dumping structure for table mkd.active +DROP TABLE IF EXISTS `active`; +CREATE TABLE IF NOT EXISTS `active` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(255) DEFAULT NULL, + `handle` text DEFAULT NULL, + `description` text DEFAULT NULL, + `variables_scores` text DEFAULT NULL, + `cart_limit` int(11) DEFAULT 1, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.active: ~26 rows (approximately) +DELETE FROM `active`; +INSERT INTO `active` (`id`, `name`, `variables_scores`, `created_at`, `updated_at`, `handle`, `description`, `cart_limit`) VALUES + (1, 'Acai', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"70","Hydration":"70","Breakouts":"","Color":"","Sun":"90","Hyperpigmentation":"50","Hypopigmentation":"","Redness":"90","Lines":"80","Firmness":"90","Pores":"20","Blackheads":"10","Allergies":"","Pollution":"70","Temperature":"","Stress":"70","Diet":"","Sleep":"20","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-08-04 15:20:34', NULL, ' ', 1), + (2, 'Bakuchiol', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"80","Hydration":"0","Breakouts":"100","Color":"","Sun":"100","Hyperpigmentation":"100","Hypopigmentation":"","Redness":"90","Lines":"90","Firmness":"100","Pores":"50","Blackheads":"80","Allergies":"","Pollution":"0","Temperature":"","Stress":"0","Diet":"","Sleep":"80","Blue Light":"","Oxygenation":"80"}', '2021-12-28 17:18:43', '2022-03-11 18:41:01', NULL, NULL, 1), + (3, 'Base', NULL, '2021-12-28 17:18:43', '2022-03-11 18:41:01', NULL, NULL, 1), + (4, 'Base Refill', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"","Hydration":"","Breakouts":"","Color":"","Sun":"","Hyperpigmentation":"","Hypopigmentation":"","Redness":"","Lines":"","Firmness":"","Pores":"","Blackheads":"","Allergies":"","Pollution":"","Temperature":"","Stress":"","Diet":"","Sleep":"","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-08-04 16:29:41', NULL, ' ', 1), + (5, 'Chamomile', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"100","Hydration":"10","Breakouts":"70","Color":"","Sun":"90","Hyperpigmentation":"70","Hypopigmentation":"","Redness":"100","Lines":"50","Firmness":"50","Pores":"70","Blackheads":"50","Allergies":"","Pollution":"70","Temperature":"","Stress":"40","Diet":"","Sleep":"30","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:01', NULL, NULL, 1), + (6, 'Chia', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"90","Hydration":"70","Breakouts":"100","Color":"","Sun":"90","Hyperpigmentation":"70","Hypopigmentation":"","Redness":"20","Lines":"50","Firmness":"40","Pores":"80","Blackheads":"100","Allergies":"","Pollution":"50","Temperature":"","Stress":"10","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:01', NULL, NULL, 1), + (7, 'Coconut', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"80","Hydration":"100","Breakouts":"30","Color":"","Sun":"90","Hyperpigmentation":"20","Hypopigmentation":"","Redness":"70","Lines":"30","Firmness":"40","Pores":"20","Blackheads":"0","Allergies":"","Pollution":"80","Temperature":"","Stress":"10","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:01', NULL, NULL, 1), + (8, 'Cogon Grass', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"40","Hydration":"100","Breakouts":"20","Color":"","Sun":"90","Hyperpigmentation":"40","Hypopigmentation":"","Redness":"10","Lines":"70","Firmness":"80","Pores":"20","Blackheads":"10","Allergies":"","Pollution":"10","Temperature":"","Stress":"10","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:01', NULL, NULL, 1), + (9, 'Cucumber', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"80","Hydration":"100","Breakouts":"60","Color":"","Sun":"90","Hyperpigmentation":"20","Hypopigmentation":"","Redness":"80","Lines":"50","Firmness":"60","Pores":"50","Blackheads":"20","Allergies":"","Pollution":"40","Temperature":"","Stress":"10","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:01', NULL, NULL, 1), + (10, 'Dragon\'s Blood', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"80","Hydration":"80","Breakouts":"70","Color":"","Sun":"90","Hyperpigmentation":"50","Hypopigmentation":"","Redness":"80","Lines":"90","Firmness":"100","Pores":"20","Blackheads":"20","Allergies":"","Pollution":"80","Temperature":"","Stress":"80","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:01', NULL, NULL, 1), + (11, 'Ginseng', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"80","Hydration":"10","Breakouts":"30","Color":"","Sun":"100","Hyperpigmentation":"50","Hypopigmentation":"","Redness":"70","Lines":"90","Firmness":"100","Pores":"10","Blackheads":"10","Allergies":"","Pollution":"90","Temperature":"","Stress":"10","Diet":"","Sleep":"20","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:01', NULL, ' ', 1), + (12, 'Gotu Kola', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"90","Hydration":"80","Breakouts":"60","Color":"","Sun":"90","Hyperpigmentation":"60","Hypopigmentation":"","Redness":"90","Lines":"60","Firmness":"70","Pores":"60","Blackheads":"20","Allergies":"","Pollution":"70","Temperature":"","Stress":"10","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:01', NULL, NULL, 1), + (13, 'Licorice Root', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"0","Hydration":"100","Breakouts":"10","Color":"","Sun":"40","Hyperpigmentation":"100","Hypopigmentation":"","Redness":"90","Lines":"50","Firmness":"20","Pores":"10","Blackheads":"10","Allergies":"","Pollution":"30","Temperature":"","Stress":"10","Diet":"","Sleep":"70","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:01', NULL, ' ', 1), + (14, 'Moringa', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"90","Hydration":"100","Breakouts":"30","Color":"","Sun":"90","Hyperpigmentation":"80","Hypopigmentation":"","Redness":"70","Lines":"70","Firmness":"80","Pores":"30","Blackheads":"30","Allergies":"","Pollution":"80","Temperature":"","Stress":"10","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:02', NULL, NULL, 1), + (15, 'Moth Bean', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"90","Hydration":"10","Breakouts":"90","Color":"","Sun":"30","Hyperpigmentation":"90","Hypopigmentation":"","Redness":"10","Lines":"90","Firmness":"100","Pores":"80","Blackheads":"90","Allergies":"","Pollution":"50","Temperature":"","Stress":"10","Diet":"","Sleep":"80","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:02', NULL, NULL, 1), + (17, 'Colloidal Oat', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"100","Hydration":"100","Breakouts":"10","Color":"","Sun":"100","Hyperpigmentation":"","Hypopigmentation":"","Redness":"70","Lines":"30","Firmness":"40","Pores":"10","Blackheads":"0","Allergies":"","Pollution":"90","Temperature":"","Stress":"10","Diet":"","Sleep":"","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:01', NULL, ' ', 1), + (18, 'Okra Extract', '{"Bio Age":"","Age":"80","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"80","Hydration":"0","Breakouts":"40","Color":"","Sun":"90","Hyperpigmentation":"","Hypopigmentation":"","Redness":"40","Lines":"200","Firmness":"100","Pores":"","Blackheads":"10","Allergies":"","Pollution":"80","Temperature":"","Stress":"0","Diet":"","Sleep":"20","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-22 19:07:54', NULL, ' ', 1), + (19, 'Olive Squalane', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"100","Hydration":"100","Breakouts":"10","Color":"","Sun":"90","Hyperpigmentation":"0","Hypopigmentation":"","Redness":"80","Lines":"30","Firmness":"40","Pores":"10","Blackheads":"0","Allergies":"","Pollution":"60","Temperature":"","Stress":"10","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:02', NULL, NULL, 1), + (20, 'Red Raddish', NULL, '2021-12-28 17:18:43', '2022-03-11 18:41:02', NULL, NULL, 1), + (21, 'Rose Hip', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"30","Hydration":"100","Breakouts":"40","Color":"","Sun":"90","Hyperpigmentation":"50","Hypopigmentation":"","Redness":"60","Lines":"80","Firmness":"90","Pores":"20","Blackheads":"10","Allergies":"","Pollution":"70","Temperature":"","Stress":"70","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:02', NULL, NULL, 1), + (22, 'Sake Extract', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"90","Hydration":"100","Breakouts":"10","Color":"","Sun":"90","Hyperpigmentation":"70","Hypopigmentation":"","Redness":"30","Lines":"80","Firmness":"90","Pores":"10","Blackheads":"10","Allergies":"","Pollution":"10","Temperature":"","Stress":"10","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:02', NULL, NULL, 1), + (23, 'Sandalwood', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"90","Hydration":"60","Breakouts":"40","Color":"","Sun":"90","Hyperpigmentation":"60","Hypopigmentation":"","Redness":"100","Lines":"50","Firmness":"60","Pores":"30","Blackheads":"30","Allergies":"","Pollution":"60","Temperature":"","Stress":"10","Diet":"","Sleep":"40","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:02', NULL, NULL, 1), + (24, 'Tonka Bean', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"70","Hydration":"70","Breakouts":"50","Color":"","Sun":"120","Hyperpigmentation":"10","Hypopigmentation":"","Redness":"10","Lines":"80","Firmness":"100","Pores":"20","Blackheads":"10","Allergies":"","Pollution":"80","Temperature":"","Stress":"10","Diet":"","Sleep":"","Blue Light":"40","Oxygenation":""}', '2021-12-28 17:18:43', '2022-07-12 13:47:38', NULL, ' ', 1), + (25, 'White Willow Bark', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"70","Hydration":"0","Breakouts":"100","Color":"","Sun":"20","Hyperpigmentation":"90","Hypopigmentation":"","Redness":"80","Lines":"80","Firmness":"70","Pores":"80","Blackheads":"100","Allergies":"","Pollution":"40","Temperature":"","Stress":"10","Diet":"","Sleep":"100","Blue Light":"","Oxygenation":""}', '2021-12-28 17:18:43', '2022-03-11 18:41:02', NULL, NULL, 1), + (28, 'Yeast Extract (Collagen)', '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"30","Hydration":"80","Breakouts":"","Color":"","Sun":"90","Hyperpigmentation":"20","Hypopigmentation":"","Redness":"20","Lines":"90","Firmness":"100","Pores":"70","Blackheads":"","Allergies":"","Pollution":"50","Temperature":"","Stress":"10","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', '2022-01-07 12:05:01', '2022-03-11 18:41:02', NULL, NULL, 1), + (29, 'Mushrooms', NULL, '2022-02-21 22:39:59', '2022-03-11 18:41:02', NULL, NULL, 1); +/*!40000 ALTER TABLE `active` ENABLE KEYS */; + +-- Dumping structure for table mkd.activity_log +DROP TABLE IF EXISTS `activity_log`; +CREATE TABLE IF NOT EXISTS `activity_log` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(255) DEFAULT NULL, + `action` varchar(255) DEFAULT NULL, + `data` text DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.activity_log: ~0 rows (approximately) +DELETE FROM `activity_log`; +/*!40000 ALTER TABLE `activity_log` DISABLE KEYS */; +/*!40000 ALTER TABLE `activity_log` ENABLE KEYS */; + +-- Dumping structure for table mkd.admin_operation +DROP TABLE IF EXISTS `admin_operation`; +CREATE TABLE IF NOT EXISTS `admin_operation` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) DEFAULT NULL, + `action` varchar(255) DEFAULT NULL, + `detail` text DEFAULT NULL, + `last_ip` varchar(255) DEFAULT NULL, + `user_agent` varchar(255) DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.admin_operation: ~0 rows (approximately) +DELETE FROM `admin_operation`; +/*!40000 ALTER TABLE `admin_operation` DISABLE KEYS */; +/*!40000 ALTER TABLE `admin_operation` ENABLE KEYS */; + +-- Dumping structure for table mkd.answer +DROP TABLE IF EXISTS `answer`; +CREATE TABLE IF NOT EXISTS `answer` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `question_id` int(11) DEFAULT NULL, + `order` int(11) DEFAULT NULL, + `answer` text DEFAULT NULL, + `answer_value` float DEFAULT NULL, + `hide_answer` tinyint(1) DEFAULT NULL, + `explaination` text DEFAULT NULL, + `image_id` text DEFAULT NULL, + `response_header` text DEFAULT NULL, + `response_body` text DEFAULT NULL, + `response_arguments` text DEFAULT NULL, + `black_list_actives` text DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=97 DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.answer: ~96 rows (approximately) +DELETE FROM `answer`; +/*!40000 ALTER TABLE `answer` DISABLE KEYS */; +INSERT INTO `answer` (`id`, `question_id`, `order`, `answer`, `answer_value`, `hide_answer`, `explaination`, `image_id`, `response_header`, `response_body`, `response_arguments`, `black_list_actives`, `created_at`, `updated_at`) VALUES + (1, 1, 1, NULL, NULL, NULL, NULL, NULL, '<<>>', NULL, '["name"]', NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (2, 2, 1, '<25', NULL, NULL, NULL, NULL, NULL, 'We will focus on actives that will improving your skin health and appearance without adding anything unnecessary.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (3, 2, 2, '25-40', NULL, NULL, NULL, NULL, NULL, 'We will create a custom formula containing actives to ensure we maintain your optimal skin health and appearance. We will spoil you with some wonderful actives that will help delay visible signs of skin aging.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (4, 2, 3, '>40', NULL, NULL, NULL, NULL, NULL, 'We have so many luxurious actives that will work to address any of the desires that come with time and knowledge.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (5, 3, 1, 'Female', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (6, 3, 2, 'Male', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (7, 3, 3, 'Non-binary', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (8, 3, 4, 'Other', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (9, 4, 1, 'Yes', 100, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (10, 4, 2, 'No', 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (11, 5, 1, 'Beard', 100, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (12, 5, 2, 'Stubble', 66, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (13, 5, 3, 'Clean', 33, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (14, 5, 4, 'Shaven', 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (15, 6, 1, 'It\'s not', NULL, NULL, NULL, '2', 'Wonderful!', 'We can now eliminate many active ingredients that are just suited for sensitive skin and focus on just the wonderful actives that will perform other wonderful functions! Don’t worry we won’t be adding anything that can or will lead to extra sensitivity.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (16, 6, 2, 'Moderately', NULL, NULL, NULL, '3', 'Noted.', 'We have many wonderful ingredients that are specifically proven to be soothing even for mildly sensitive skin. We will add these along with other functional actives that are non-sensitizing.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (17, 6, 3, 'Extremely', NULL, NULL, NULL, '4', 'Noted.', 'We have many wonderful ingredients that are specifically proven to be soothing for sensitive skin. We will add these along with other functional actives that are non-sensitizing.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (18, 7, 1, 'Very Dry', NULL, NULL, NULL, '5', 'Let’s hydrate!', 'We will add some wonderful hydrating actives that will specifically address your dry skin needs (some of the later questions will help us determine exactly which of our hydrating actives are perfect for you based on their scientific mode of action)', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (19, 7, 2, 'Normal / Combination', NULL, NULL, NULL, '6', 'We know the feeling!', 'We have some wonderful ingredients that will maintain optimal skin hydration while controlling excess oil production.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (20, 7, 3, 'Very Oily', NULL, NULL, NULL, '7', 'Ok! We’ll balance that out.', 'We will make sure to add actives that will help control excess skin oiliness, while still addressing all your other skin needs.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (21, 8, 1, 'Hardly', NULL, NULL, NULL, NULL, 'Great!', 'We will now just focus on those actives you need', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (22, 8, 2, 'Sometimes', NULL, NULL, NULL, NULL, 'Great!', 'We\'ll make sure not to add any actives that may lead to breakouts in breakout-prone skin', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (23, 8, 3, 'Always', NULL, NULL, NULL, NULL, 'Noted.', 'We will add some of our amazing oil-control actives to alleviate some of the factors that can aggravate breakout prone skin. (Note: due to the personalized nature of our system we cannot make any claims to treat or prevent acne in accordance with FDA regulations.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (24, 9, 1, '15', 100, NULL, NULL, '8', NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (25, 9, 2, '14', 93.3333, NULL, NULL, '9', NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (26, 9, 3, '13', 86.6667, NULL, NULL, '10', NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (27, 9, 4, '12', 80, NULL, NULL, '11', NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (28, 9, 5, '11', 73.3333, NULL, NULL, '12', NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (29, 9, 6, '10', 66.6667, NULL, NULL, '13', NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (30, 9, 7, '9', 60, NULL, NULL, '14', NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (31, 9, 8, '8', 53.3333, NULL, NULL, '15', NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (32, 9, 9, '7', 46.6667, NULL, NULL, '16', NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (33, 9, 10, '6', 40, NULL, NULL, '17', NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (34, 9, 11, '5', 33.3333, NULL, NULL, '18', NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (35, 9, 12, '4', 26.6667, NULL, NULL, '19', NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (36, 9, 13, '3', 20, NULL, NULL, '20', NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (37, 9, 14, '2', 13.3333, NULL, NULL, '21', NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (38, 9, 15, '1', 6.66667, NULL, NULL, '22', NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (39, 10, 1, 'Never', NULL, NULL, NULL, NULL, NULL, 'Keep the sunscreen close! We’ll make sure to add some wonderful actives that will help you with your beautiful glow', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (40, 10, 2, 'Sometimes', NULL, NULL, NULL, NULL, NULL, 'Don’t forget the sunscreen! We’ll make sure to add some wonderful actives that will help you with your beautiful glow', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (41, 10, 3, 'Always', NULL, NULL, NULL, NULL, NULL, 'We’ll make sure to add some wonderful actives that will help you with your beautiful glow.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (42, 11, 2, 'Yes', NULL, NULL, NULL, NULL, NULL, 'We’ll add some of our wonderful actives that will minimize the appearance of any hyper or hypo-pigmentation.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (43, 11, 1, 'No', NULL, NULL, NULL, NULL, NULL, 'Great, we can eliminate the addition of unnecessary actives and only focus on those that you need.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (44, 12, 3, 'Instant Burn', NULL, NULL, NULL, NULL, 'We hear your pain!', 'Make sure to wear proper SPF and we’ll make sure we add actives that are not sun-sensitizing.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (45, 12, 2, 'Middle', NULL, NULL, NULL, NULL, 'Noted.', 'Make sure to wear proper SPF and we’ll make sure we add actives that will not make your skin extra sensitive to the sun during the day.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (46, 12, 1, 'Hardly ever', NULL, NULL, NULL, NULL, 'Lucky!', 'We can focus on all the great actives your skin needs without the sun’s distraction – though we still recommend using a daily SPF.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (47, 13, 1, 'Red? Huh? No red here', NULL, NULL, NULL, '23', 'Great!', 'We’ll just focus on the actives that you need.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (48, 13, 2, 'Occaisonally red & blotchy.', NULL, NULL, NULL, '24', 'Noted.', 'We have amazing actives specifically for redness – keep going till the end to find out what we have chosen specifically for your needs.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (49, 13, 3, 'I am constantly seeing red', NULL, NULL, NULL, '24', 'Noted.', 'We have amazing actives specifically for redness – keep going till the end to find out what we have chosen specifically for your needs.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (50, 15, 1, 'No Wrinkles/Lines', NULL, NULL, NULL, '25', 'Amazing <<>>,', 'We have some amazing anti-wrinkle actives, most with more than ten letters, and you don’t need any of them. Save your money to splurge on things that will actually do something for you.', '["name"]', NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (51, 15, 2, 'A Few Lines', NULL, 1, NULL, '26', NULL, 'We have some wonderful actives that will minimize the appearance of lines. We’ll just focus on those that will give you the best bang for your buck.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (52, 15, 3, 'A Few Lines Observable at all times', NULL, 1, NULL, '27', NULL, 'We have some wonderful actives that will minimize the appearance of lines. We’ll just focus on those that will give you the best bang for your buck.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (53, 15, 4, 'Some Lines', NULL, NULL, NULL, '28', NULL, 'We have some wonderful actives that will minimize the appearance of lines. We’ll just focus on those that will give you the best bang for your buck.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (54, 15, 5, 'Lines Plus Hints of Wrinkles', NULL, 1, NULL, '29', NULL, 'We have some wonderful actives that will minimize the appearance of lines. We’ll just focus on those that will give you the best bang for your buck.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (55, 15, 6, 'A Few Wrinkles', NULL, 1, NULL, '30', 'We’re going to add some of our luxurious anti-wrinkle actives. Keep going till the end to see what we recommend.', NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (56, 15, 7, 'Lots of Wrinkles', NULL, NULL, NULL, '31', 'We’re going to add some of our luxurious anti-wrinkle actives. Keep going till the end to see what we recommend.', NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (57, 16, 1, 'Firm as a baby', NULL, NULL, NULL, NULL, 'Amazing!!', 'We’ll focus on the actives more appropriate to your skin and ensure we maintain your skin’s natural resilience.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (58, 16, 2, 'Middle', NULL, NULL, NULL, NULL, NULL, 'We’ll add some luxurious actives to your formulation that will help prevent and improve your skins firmness.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (59, 16, 3, 'Sagging', NULL, NULL, NULL, NULL, 'We got you!', 'We’ll add some of our wonderful actives that will improve your skin’s appearance of firmness.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (60, 17, 1, 'No - smooth as can be', NULL, NULL, NULL, NULL, 'Lucky you!', 'We can eliminate actives that will just be extra clutter for your wonderful skin.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (61, 17, 2, 'Some', NULL, NULL, NULL, NULL, NULL, 'We’ll keep this in mind (our algorithm’s mind) as we create your perfect formula.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (62, 17, 3, 'A lot', NULL, NULL, NULL, NULL, NULL, 'We’ll keep this in mind (our algorithm’s mind) as we create your perfect formula.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (63, 18, 1, 'No', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (64, 18, 2, 'Some', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (65, 18, 3, 'A lot', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (66, 19, 1, 'Yes', 100, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (67, 19, 2, 'No', 0, NULL, NULL, NULL, 'Lucky You!', NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (68, 20, 1, 'Banana', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (69, 20, 2, 'Olive', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (70, 20, 3, 'Sunflowers', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (71, 22, 1, 'Never', NULL, NULL, NULL, NULL, 'Great!', 'This means your skin is exposed to less pollution and better oxygenation!', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (72, 22, 2, 'Sometimes', NULL, NULL, NULL, NULL, NULL, 'We’ll make sure to add extra actives to address the pollution your skin is exposed to.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (73, 22, 3, 'Multiple per day', NULL, NULL, NULL, NULL, 'Got it.', 'Your formula will include actives for anti-pollution and increased oxygenation to your skin.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (74, 23, 1, 'Cool as a cucumber', NULL, NULL, NULL, NULL, 'Lucky you!', 'We’ll rather focus on areas that are of greater concern to you.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (75, 23, 2, 'Sometimes', NULL, NULL, NULL, NULL, NULL, 'Occasional stress can release cortisol and other factors that can negatively affect the skin. We’ll add some adaptogens and other actives that can help mitigate some of these effects.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (76, 23, 3, 'In a constant state of anxiety', NULL, NULL, NULL, NULL, NULL, 'Stress can release cortisol and other factors that can negatively affect the skin. We’ll add some adaptogens and other actives that can help mitigate some of these effects.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (77, 24, 1, 'Vegan/Vegetarian', 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (78, 24, 2, 'Flexitarian, I sometime eat meat', 25, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (79, 24, 3, 'Pescatarian, I’ll have fish and seafood, but no meat', 50, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (80, 24, 4, 'I stay away from red meat', 75, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (81, 24, 5, 'I eat everything', 100, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (82, 25, 1, '<4', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (83, 25, 2, '5-7', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (84, 25, 3, '8+', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (85, 26, 1, '0-2', NULL, NULL, NULL, NULL, 'Good for you!', 'Blue light emitted from screens can be harmful to your skin’s health and appearance. Your low exposure means we can rather focus on other areas to optimize your skin health and appearance.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (86, 26, 2, '2-6', NULL, NULL, NULL, NULL, NULL, 'Blue light emitted from screens can be harmful to your skin’s health and appearance. No worries though, we’ll add some actives, such as our innovative Rockrose extract that will help mitigate some of these effects.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (87, 26, 3, '6+', NULL, NULL, NULL, NULL, NULL, 'Blue light emitted from screens can affect your skin’s circadian rhythm as well as affect your skin’s health and appearance. We’ll add some actives, such as our innovative Rockrose extract that will help mitigate some of these effect', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (88, 27, 1, '0', NULL, NULL, NULL, '32', NULL, 'We’ll add extra hydrating actives, but we recommend you drink more so your skin gets nourished from within as well.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (89, 27, 2, '4', NULL, NULL, NULL, '33', NULL, 'We’ll add extra hydrating actives, but we recommend you drink more so your skin gets nourished from within as well.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (90, 27, 3, '8+', NULL, NULL, NULL, '34', 'Great!', 'You don’t need extra actives to compensate from a lack of internal hydration.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (91, 28, 1, 'None', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (92, 28, 2, 'Full Coverage', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (93, 29, 1, 'Low', NULL, NULL, NULL, NULL, NULL, 'We’ll add extra actives to give your skin an extra boost on oxygenation and nutrient delivery.', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (94, 29, 2, 'High', NULL, NULL, NULL, NULL, 'Great!', 'By exercising you are providing extra oxygenation and nutrient delivery to your skin, so we don’t have to add extra actives to do what you are already doing an even better job at. ', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (95, 30, 1, 'No', NULL, 0, NULL, NULL, 'Great!', 'We can eliminate the addition of unnecessary actives and only focus on those that you need. ', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (96, 30, 1, 'Yes', NULL, 0, NULL, NULL, NULL, 'We\'ll add some of our wonderful actives that will minimize the appearance of hypopigmentation over time', NULL, NULL, '2022-04-10 11:07:44', '2022-04-10 11:07:44'); +/*!40000 ALTER TABLE `answer` ENABLE KEYS */; + +-- Dumping structure for table mkd.configuration +DROP TABLE IF EXISTS `configuration`; +CREATE TABLE IF NOT EXISTS `configuration` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `image_id` int(11) DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.configuration: ~1 rows (approximately) +DELETE FROM `configuration`; +/*!40000 ALTER TABLE `configuration` DISABLE KEYS */; +INSERT INTO `configuration` (`id`, `image_id`, `created_at`, `updated_at`) VALUES + (1, 35, '2022-04-10 11:07:43', '2022-04-10 11:07:43'); +/*!40000 ALTER TABLE `configuration` ENABLE KEYS */; + +-- Dumping structure for table mkd.credential +DROP TABLE IF EXISTS `credential`; +CREATE TABLE IF NOT EXISTS `credential` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `oauth` varchar(255) DEFAULT NULL, + `email` varchar(255) DEFAULT NULL, + `password` varchar(255) DEFAULT NULL, + `user_id` int(11) DEFAULT NULL, + `type` int(11) DEFAULT NULL, + `verify` int(11) DEFAULT NULL, + `status` int(11) DEFAULT NULL, + `two_factor_authentication` int(11) DEFAULT NULL, + `force_password_change` tinyint(1) DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.credential: ~2 rows (approximately) +DELETE FROM `credential`; +/*!40000 ALTER TABLE `credential` DISABLE KEYS */; +INSERT INTO `credential` (`id`, `oauth`, `email`, `password`, `user_id`, `type`, `verify`, `status`, `two_factor_authentication`, `force_password_change`, `created_at`, `updated_at`) VALUES + (1, NULL, 'admin@manaknight.com', '$2a$04$tQm/w6gJNKOoiZOn0WVISe1xG7BD1ulw72UNHXsXgLObtdKjlMhZK', 1, 0, 1, 1, 0, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (2, NULL, 'member@manaknight.com', '$2a$04$A7JX0xG2Gwt06UKpxq/Yd.oJARP6.BpzkzjOhc67.2dkfqjJPJ0pe', 2, 0, 1, 1, 0, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'); +/*!40000 ALTER TABLE `credential` ENABLE KEYS */; + +-- Dumping structure for table mkd.email +DROP TABLE IF EXISTS `email`; +CREATE TABLE IF NOT EXISTS `email` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `slug` varchar(255) DEFAULT NULL, + `subject` text DEFAULT NULL, + `tag` text DEFAULT NULL, + `html` text DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.email: ~4 rows (approximately) +DELETE FROM `email`; +/*!40000 ALTER TABLE `email` DISABLE KEYS */; +INSERT INTO `email` (`id`, `slug`, `subject`, `tag`, `html`, `created_at`, `updated_at`) VALUES + (1, 'reset-password', 'Reset your password', 'email,reset_token,link', 'Hi {{{email}}},
You have requested to reset your password. Please click the link below to reset it.
Link.
Thanks,
Admin', '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (2, 'register', 'Register', 'email', 'Hi {{{email}}},
Thanks for registering on our platform.
Thanks,
Admin', '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (3, 'confirm-password', 'Confirm your account', 'email,confirm_token,link', 'Hi {{{email}}},
Please click the link below to confirm your account.
LinkThanks,
Admin', '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (4, 'verify', 'Account verification', 'code', 'Your verification # is {{{code}}}', '2022-04-10 11:07:43', '2022-04-10 11:07:43'); +/*!40000 ALTER TABLE `email` ENABLE KEYS */; + +-- Dumping structure for table mkd.image +DROP TABLE IF EXISTS `image`; +CREATE TABLE IF NOT EXISTS `image` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `url` text DEFAULT NULL, + `caption` text DEFAULT NULL, + `user_id` int(11) DEFAULT NULL, + `width` int(11) DEFAULT NULL, + `height` int(11) DEFAULT NULL, + `mobile_width` int(11) DEFAULT NULL, + `mobile_height` int(11) DEFAULT NULL, + `upload_type` int(11) DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.image: ~35 rows (approximately) +DELETE FROM `image`; +/*!40000 ALTER TABLE `image` DISABLE KEYS */; +INSERT INTO `image` (`id`, `url`, `caption`, `user_id`, `width`, `height`, `mobile_width`, `mobile_height`, `upload_type`, `created_at`, `updated_at`) VALUES + (1, '/image/profile.png', '', 1, 581, 581, 348, 348, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (2, '/frontend_images/Icons/SVG/Skin Sensitivity/Non Sensitive Skin.svg', '', 1, 183, 183, 183, 183, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (3, '/frontend_images/Icons/SVG/Skin Sensitivity/Moderately Sensitive.svg', '', 1, 183, 183, 183, 183, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (4, '/frontend_images/Icons/SVG/Skin Sensitivity/Extremely Sensitive.svg', '', 1, 183, 183, 183, 183, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (5, '/frontend_images/Icons/SVG/Dry_Oily Skin/Dry Skin.svg', '', 1, 191, 191, 191, 191, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (6, '/frontend_images/Icons/SVG/Dry_Oily Skin/Normal and Combination.svg', '', 1, 191, 191, 191, 191, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (7, '/frontend_images/Icons/SVG/Dry_Oily Skin/Oily.svg', '', 1, 191, 191, 191, 191, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (8, '/frontend_images/SkintoneGraphics/1.png', '', 1, 74, 135, 74, 135, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (9, '/frontend_images/SkintoneGraphics/2.png', '', 1, 74, 135, 74, 135, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (10, '/frontend_images/SkintoneGraphics/3.png', '', 1, 74, 135, 74, 135, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (11, '/frontend_images/SkintoneGraphics/4.png', '', 1, 74, 135, 74, 135, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (12, '/frontend_images/SkintoneGraphics/5.png', '', 1, 74, 135, 74, 135, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (13, '/frontend_images/SkintoneGraphics/6.png', '', 1, 74, 135, 74, 135, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (14, '/frontend_images/SkintoneGraphics/7.png', '', 1, 74, 135, 74, 135, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (15, '/frontend_images/SkintoneGraphics/8.png', '', 1, 74, 135, 74, 135, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (16, '/frontend_images/SkintoneGraphics/9.png', '', 1, 74, 135, 74, 135, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (17, '/frontend_images/SkintoneGraphics/10.png', '', 1, 74, 135, 74, 135, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (18, '/frontend_images/SkintoneGraphics/11.png', '', 1, 74, 135, 74, 135, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (19, '/frontend_images/SkintoneGraphics/12.png', '', 1, 74, 135, 74, 135, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (20, '/frontend_images/SkintoneGraphics/13.png', '', 1, 74, 135, 74, 135, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (21, '/frontend_images/SkintoneGraphics/14.png', '', 1, 74, 135, 74, 135, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (22, '/frontend_images/SkintoneGraphics/15.png', '', 1, 74, 135, 74, 135, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (23, '/frontend_images/Icons/SVG/Blotchiness/No Blotchiness.svg', '', 1, 240, 240, 240, 240, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (24, '/frontend_images/Icons/PNG/Blotchiness/Lot\'s of Blotchiness.png', '', 1, 240, 240, 240, 240, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (25, '/frontend_images/Icons/SVG/Face Lines/No Wrinkles.svg', '', 1, 240, 240, 240, 240, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (26, '/frontend_images/Icons/SVG/Face Lines/A Few Lines.svg', '', 1, 240, 240, 240, 240, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (27, '/frontend_images/Icons/SVG/Face Lines/A Few Lines Observable at all times.svg', '', 1, 240, 240, 240, 240, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (28, '/frontend_images/Icons/SVG/Face Lines/Some Lines.svg', '', 1, 240, 240, 240, 240, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (29, '/frontend_images/Icons/SVG/Face Lines/Lines Plus Hints of Wrinkles.svg', '', 1, 240, 240, 240, 240, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (30, '/frontend_images/Icons/SVG/Face Lines/A Few Wrinkles.svg', '', 1, 240, 240, 240, 240, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (31, '/frontend_images/Icons/SVG/Face Lines/Lots of Wrinkles.svg', '', 1, 240, 240, 240, 240, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (32, '/frontend_images/Icons/SVG/Water/1 Glass of Water.svg', '', 1, 140, 190, 140, 190, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (33, '/frontend_images/Icons/SVG/Water/4 Glasses of Water.svg', '', 1, 140, 190, 140, 190, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (34, '/frontend_images/Icons/SVG/Water/8 Glasses of Water.svg', '', 1, 140, 190, 140, 190, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (35, '/frontend_images/MainImage/main_quiz_image.png', NULL, 1, NULL, NULL, NULL, NULL, NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'); +/*!40000 ALTER TABLE `image` ENABLE KEYS */; + +-- Dumping structure for table mkd.member_operation +DROP TABLE IF EXISTS `member_operation`; +CREATE TABLE IF NOT EXISTS `member_operation` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `action` varchar(255) DEFAULT NULL, + `detail` text DEFAULT NULL, + `last_ip` varchar(255) DEFAULT NULL, + `user_agent` varchar(255) DEFAULT NULL, + `status` int(11) DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + `user_id` int(11) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.member_operation: ~0 rows (approximately) +DELETE FROM `member_operation`; +/*!40000 ALTER TABLE `member_operation` DISABLE KEYS */; +/*!40000 ALTER TABLE `member_operation` ENABLE KEYS */; + +-- Dumping structure for table mkd.order +DROP TABLE IF EXISTS `order`; +CREATE TABLE IF NOT EXISTS `order` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `webhook_id` varchar(255) DEFAULT NULL, + `shopify_id` varchar(255) DEFAULT NULL, + `event` text DEFAULT NULL, + `customer_shopify_id` varchar(255) DEFAULT NULL, + `customer` text DEFAULT NULL, + `answers` text DEFAULT NULL, + `profile` text DEFAULT NULL, + `actives` text DEFAULT NULL, + `items` text DEFAULT NULL, + `financial_status` varchar(255) DEFAULT NULL, + `fulfillment_status` varchar(255) DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `webhook_id` (`webhook_id`), + UNIQUE KEY `shopify_id` (`shopify_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.order: ~0 rows (approximately) +DELETE FROM `order`; +/*!40000 ALTER TABLE `order` DISABLE KEYS */; +/*!40000 ALTER TABLE `order` ENABLE KEYS */; + +-- Dumping structure for table mkd.output_variable +DROP TABLE IF EXISTS `output_variable`; +CREATE TABLE IF NOT EXISTS `output_variable` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(255) DEFAULT NULL, + `priority` float DEFAULT NULL, + `active_list` text DEFAULT NULL, + `ranges_response` text DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.output_variable: ~25 rows (approximately) +DELETE FROM `output_variable`; +INSERT INTO `output_variable` (`id`, `name`, `priority`, `active_list`, `ranges_response`, `created_at`, `updated_at`) VALUES + (1, 'Bio Age', 0, NULL, '[{"0-33":""},{"34-66":""},{"67-100":""}]', '2021-12-28 15:27:57', '2022-01-04 15:15:29'), + (2, 'Age', 70, NULL, '[{"0-33":""},{"34-66":""},{"67-100":""}]', '2021-12-28 15:27:57', '2022-01-04 15:15:45'), + (3, 'Gender', 75, NULL, '[{"0-33":""},{"34-66":""},{"67-100":""}]', '2021-12-28 15:27:57', '2022-01-04 15:16:07'), + (4, 'Pregnancy', 100, NULL, '[{"0-33":""},{"34-66":""},{"67-100":""}]', '2021-12-28 15:27:57', '2022-01-04 15:16:18'), + (5, 'Hair', 75, NULL, '[{"0-33":""},{"34-66":""},{"67-100":""}]', '2021-12-28 15:27:57', '2022-01-04 15:16:30'), + (6, 'Sensitivity', 90, NULL, '[{"0-33":"Your skin is not that sensitive"},{"34-66":"Your skin is somewhat sensitive"},{"67-100":"Your skin is highly sensitive"}]', '2021-12-28 15:27:57', '2022-01-04 15:16:53'), + (7, 'Hydration', 100, NULL, '[{"0-33":"Your skin is relatively well hydrated"},{"34-66":"Your skin may need a little more hydration"},{"67-100":"Your skin is in need of extra Hydration"}]', '2021-12-28 15:27:57', '2022-02-21 23:43:06'), + (8, 'Breakouts', 100, NULL, '[{"0-33":"Your skin is not very breakout prone"},{"34-66":"Your skin is prone to occasional breakouts"},{"67-100":"Your skin is highly breakout prone"}]', '2021-12-28 15:27:57', '2022-01-04 15:18:40'), + (9, 'Color', 50, NULL, '[{"0-33":""},{"34-66":""},{"67-100":""}]', '2021-12-28 15:27:57', '2022-01-04 15:18:52'), + (10, 'Sun', 95, NULL, '[{"0-33":"Your skin isn\'t as sensitive to the sun but still requires some protection"},{"34-66":"Your skin needs some sun protection"},{"67-100":"Your skin requires extra sun protection"}]', '2021-12-28 15:27:57', '2022-01-23 15:10:31'), + (11, 'Hyperpigmentation', 90, NULL, '[{"0-33":"Your skin is not very prone to hyperpigmentation"},{"34-66":"Your skin is somewhat prone to some hyperpigmentation"},{"67-100":"Your skin is prone to hyperpigmentation"}]', '2021-12-28 15:27:57', '2022-01-23 15:11:30'), + (12, 'Hypopigmentation', 90, NULL, '[{"0-33":""},{"34-66":""},{"67-100":""}]', '2021-12-28 15:27:57', '2022-01-23 15:11:47'), + (13, 'Redness', 85, NULL, '[{"0-33":"Your skin is not especially prone to redness"},{"34-66":"Your skin is somewhat prone to redness"},{"67-100":"Your skin is highly prone to experience redness"}]', '2021-12-28 15:27:57', '2022-02-21 15:21:32'), + (14, 'Lines', 100, NULL, '[{"0-33":"Your skin is relatively smooth"},{"34-66":"Your skin has some fine lines"},{"67-100":"Your skin can use an extra boost of anti-aging actives"}]', '2021-12-28 15:27:57', '2022-01-23 15:17:50'), + (15, 'Firmness', 100, NULL, '[{"0-33":"Your skin is relatively firm"},{"34-66":"Your skin can use a boost to maintain firmness"},{"67-100":"Your skin will benefit from an extra boost to its firmness"}]', '2021-12-28 15:27:57', '2022-02-21 15:22:53'), + (16, 'Pores', 70, NULL, '[{"0-33":"You don\'t have many visible pores"},{"34-66":"You have some visible pores"},{"67-100":"You have significant visible pores"}]', '2021-12-28 15:27:57', '2022-01-23 15:25:45'), + (17, 'Blackheads', 65, NULL, '[{"0-33":"Your skin has relatively few visible blackheads"},{"34-66":"Your skin has some visible blackheads"},{"67-100":"Your skin has visible blackheads"}]', '2021-12-28 15:27:57', '2022-05-27 11:43:45'), + (18, 'Allergies', 100, NULL, '[{"0-33":""},{"34-66":""},{"67-100":""}]', '2021-12-28 15:27:57', '2022-01-23 15:28:22'), + (19, 'Pollution', 80, NULL, '[{"0-33":"Your skin is exposed to relatively low levels of pollution"},{"34-66":"Your skin is exposed to some pollution"},{"67-100":"Your skin is exposed to significant pollution"}]', '2021-12-28 15:27:57', '2022-01-23 15:26:54'), + (20, 'Temperature', 0, NULL, '[{"0-33":""},{"34-66":""},{"67-100":""}]', '2021-12-28 15:27:57', '2022-01-23 15:26:03'), + (21, 'Stress', 40, NULL, '[{"0-33":""},{"34-66":""},{"67-100":""}]', '2021-12-28 15:27:57', '2022-01-23 15:29:18'), + (22, 'Diet', 30, NULL, '[{"0-33":""},{"34-66":""},{"67-100":""}]', '2021-12-28 15:27:57', '2022-01-23 15:30:41'), + (23, 'Sleep', 20, NULL, '[{"0-33":""},{"34-66":""},{"67-100":""}]', '2021-12-28 15:27:57', '2022-01-23 15:30:28'), + (24, 'Blue Light', 45, NULL, '[{"0-33":""},{"34-66":""},{"67-100":""}]', '2021-12-28 15:27:57', '2022-01-23 15:29:04'), + (25, 'Oxygenation', 40, NULL, '[{"0-33":""},{"34-66":""},{"67-100":""}]', '2021-12-28 15:27:57', '2022-01-23 15:28:48'); + +-- Dumping structure for table mkd.question +DROP TABLE IF EXISTS `question`; +CREATE TABLE IF NOT EXISTS `question` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `quiz_id` int(11) DEFAULT NULL, + `question` text DEFAULT NULL, + `question_arguments` text DEFAULT NULL, + `order` int(11) DEFAULT NULL, + `image_width` float DEFAULT NULL, + `image_height` float DEFAULT NULL, + `placeholder` varchar(255) DEFAULT NULL, + `note` text DEFAULT NULL, + `note_type` int(11) DEFAULT NULL, + `target` int(11) DEFAULT NULL, + `response` text DEFAULT NULL, + `save_response_into` varchar(255) DEFAULT NULL, + `depends_on` varchar(255) DEFAULT NULL, + `slider_range` varchar(255) DEFAULT NULL, + `output_variable_name` varchar(255) DEFAULT NULL, + `weight` float DEFAULT NULL, + `extra_output_variable` text DEFAULT NULL, + `type` int(11) DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.question: ~30 rows (approximately) +DELETE FROM `question`; +/*!40000 ALTER TABLE `question` DISABLE KEYS */; +INSERT INTO `question` (`id`, `quiz_id`, `question`, `question_arguments`, `order`, `image_width`, `image_height`, `placeholder`, `note`, `note_type`, `target`, `response`, `save_response_into`, `depends_on`, `slider_range`, `output_variable_name`, `weight`, `extra_output_variable`, `type`, `created_at`, `updated_at`) VALUES + (1, 1, 'What would you like to be called?', NULL, 1, NULL, NULL, 'name', NULL, NULL, 4, NULL, 'name', NULL, NULL, NULL, NULL, NULL, 1, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (2, 1, ' When were you born <<>>?', '["name"]', 2, NULL, NULL, 'year', 'Your age plays an important role on which functional actives we may want to focus on for your skin assessment.', 2, 4, NULL, 'age', NULL, NULL, 'Bio Age', 100, '[{"name":"Age","weight":50}]', 3, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (3, 1, 'What is your hormonal gender', NULL, 3, NULL, NULL, NULL, 'Your hormones play an important role in your skin’s health and appearance.', 1, 4, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 4, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (4, 1, 'Are you pregnant or breastfeeding?', NULL, 4, NULL, NULL, NULL, 'Hormonal changes during pregnancy can lead to visible changes in skin appearance. It’s also very important to ensure that all actives are proven safe for this important period.', 2, 1, NULL, NULL, '3|female', NULL, 'Pregnancy', 100, NULL, 4, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (5, 1, 'What is your facial hair situation?', NULL, 5, NULL, NULL, NULL, 'Presence of hair on face can have an effect on the skin beneath.', 2, 2, NULL, NULL, '3|male', NULL, 'Hair', 100, NULL, 4, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (6, 2, 'How Sensitive is your skin?', NULL, 1, NULL, NULL, NULL, 'We’ll be more careful of which actives we add to formula for those with more sensitive skin types. It’s all about balancing effectivity, complexity and leaving you feeling your best.', 2, 4, NULL, NULL, NULL, '0-100', 'Sensitivity', 100, NULL, 6, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (7, 2, 'How would you describe your skin on an average day?', NULL, 2, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '0-100', 'Hydration', 70, NULL, 6, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (8, 2, 'How often do you have breakouts, such as an occasional pimple or frequent breakouts (such as chronic acne)?', NULL, 3, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '0-100', 'Breakouts', 100, NULL, 6, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (9, 2, 'What’s your skintone without a suntan?', NULL, 4, 60, 110, NULL, 'Different skin tones are associated with different levels of skin melanin, leading to differing reactions of skin to the effects of the sun.', 2, 4, NULL, NULL, NULL, NULL, 'Color', 100, '[{"name":"Sun","weight":10},{"name":"Hyperpigmentation","weight":10}]', 5, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (10, 2, 'How easily does your skin tan?', NULL, 5, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '0-100', 'Sun', 20, NULL, 6, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (11, 2, 'Is your skin prone to Hyperpigmentation?', NULL, 6, NULL, NULL, NULL, 'This is the likelihood of skin discoloring associated with aging or after injury.', 1, 4, NULL, NULL, NULL, '0-100', 'Hyperpigmentation', 90, '[{"name":"Sun","weight":10}]', 6, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (12, 2, 'How easily does your skin burn in the sun?', NULL, 8, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '0-100', 'Sun', 60, NULL, 6, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (13, 2, 'How often does your skin experience redness?', NULL, 9, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '0-100', 'Redness', 100, NULL, 6, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (14, 2, 'Halfway There! Do you want to save your progress?', NULL, 10, NULL, NULL, 'email', NULL, NULL, 4, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (15, 2, 'Which best describes your face?', NULL, 11, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '0-100', 'Lines', 100, '[{"name":"Age","weight":30}]', 6, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (16, 2, 'How firm is your skin?', NULL, 12, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '0-100', 'Firmness', 100, '[{"name":"Age","weight":20}]', 6, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (17, 2, 'Do you have enlarged pores?', NULL, 13, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '0-100', 'Pores', 100, NULL, 6, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (18, 2, 'Do you have blackheads?', NULL, 14, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '0-100', 'Blackheads', 100, NULL, 6, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (19, 2, 'Do you have any known allergies?', NULL, 15, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, NULL, 'Allergies', 100, NULL, 4, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (20, 2, 'Do you know if you have allergies to any of the following?', NULL, 16, NULL, NULL, NULL, NULL, NULL, 4, 'We’ll make sure to leave those out', NULL, '19|yes', NULL, NULL, NULL, NULL, 7, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (21, 3, 'Let’s adjust your cream to your geography. Enter your city below', NULL, 1, NULL, NULL, 'city', NULL, NULL, 4, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 8, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (22, 3, 'How often do you smoke?', NULL, 2, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '0-100', 'Pollution', 33, NULL, 6, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (23, 3, 'How would you describe your stress levels?', NULL, 3, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '0-100', 'Stress', 100, NULL, 6, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (24, 3, 'Which of these closest resembles your diet?', NULL, 4, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, NULL, 'Diet', 100, NULL, 4, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (25, 3, 'On average how many hours of sleep do you get a night?', NULL, 5, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '4-8', 'Sleep', 100, NULL, 6, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (26, 3, 'How many hours a day do you sit in front of a screen, ex phone, computer, tv etc.?', NULL, 6, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '0-6', 'Blue Light', 100, NULL, 6, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (27, 3, 'On average, how many glasses of water do you drink a day?', NULL, 7, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '0-100', 'Hydration', 15, NULL, 6, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (28, 3, 'How much makeup do you wear on a daily basis?', NULL, 8, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '0-100', 'Pollution', 33.33, NULL, 6, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (29, 3, 'On average, how many hours a week do you excercize?', NULL, 9, NULL, NULL, NULL, NULL, NULL, 4, NULL, NULL, NULL, '0-100', 'Oxygenation', 100, NULL, 6, '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (30, 2, 'Is your skin prone to Hypopigmentation?', NULL, 7, NULL, NULL, NULL, 'This is the likelihood of skin discoloring associated with aging or after injury.', 1, NULL, NULL, NULL, '', '0-100', 'Hypopigmentation', 100, NULL, 6, '2022-04-10 11:07:43', '2022-04-10 11:07:43'); +/*!40000 ALTER TABLE `question` ENABLE KEYS */; + +-- Dumping structure for table mkd.quiz +DROP TABLE IF EXISTS `quiz`; +CREATE TABLE IF NOT EXISTS `quiz` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(255) DEFAULT NULL, + `description` text DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.quiz: ~3 rows (approximately) +DELETE FROM `quiz`; +/*!40000 ALTER TABLE `quiz` DISABLE KEYS */; +INSERT INTO `quiz` (`id`, `name`, `description`, `created_at`, `updated_at`) VALUES + (1, 'The Basics', 'Let’s start by getting to know you.', '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (2, 'Your Skin', 'Let’s learn about your skin and it’s uniqueness.', '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (3, 'Your Environment', 'Almost done, let’s talk environment & lifestyle.', '2022-04-10 11:07:43', '2022-04-10 11:07:43'); +/*!40000 ALTER TABLE `quiz` ENABLE KEYS */; + +-- Dumping structure for table mkd.refer_log +DROP TABLE IF EXISTS `refer_log`; +CREATE TABLE IF NOT EXISTS `refer_log` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) DEFAULT NULL, + `referrer_user_id` int(11) DEFAULT NULL, + `type` int(11) DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.refer_log: ~0 rows (approximately) +DELETE FROM `refer_log`; +/*!40000 ALTER TABLE `refer_log` DISABLE KEYS */; +/*!40000 ALTER TABLE `refer_log` ENABLE KEYS */; + +-- Dumping structure for table mkd.result_profile +DROP TABLE IF EXISTS `result_profile`; +CREATE TABLE IF NOT EXISTS `result_profile` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `section_title` varchar(255) DEFAULT NULL, + `output_variable_list` text DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.result_profile: ~3 rows (approximately) +DELETE FROM `result_profile`; +/*!40000 ALTER TABLE `result_profile` DISABLE KEYS */; +INSERT INTO `result_profile` (`id`, `section_title`, `output_variable_list`, `created_at`, `updated_at`) VALUES + (1, 'Skin Sensitivity', '[6,7,13,11,10]', '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (2, 'Skin Characteristics', '[14,15,17,16,8]', '2022-04-10 11:07:44', '2022-04-10 11:07:44'), + (3, 'Environmental Factors', '[19,21,24,25]', '2022-04-10 11:07:44', '2022-04-10 11:07:44'); +/*!40000 ALTER TABLE `result_profile` ENABLE KEYS */; + +-- Dumping structure for table mkd.role +DROP TABLE IF EXISTS `role`; +CREATE TABLE IF NOT EXISTS `role` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(255) DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.role: ~2 rows (approximately) +DELETE FROM `role`; +/*!40000 ALTER TABLE `role` DISABLE KEYS */; +INSERT INTO `role` (`id`, `name`, `created_at`, `updated_at`) VALUES + (1, 'admin', '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (2, 'member', '2022-04-10 11:07:43', '2022-04-10 11:07:43'); +/*!40000 ALTER TABLE `role` ENABLE KEYS */; + +-- Dumping structure for table mkd.rule +DROP TABLE IF EXISTS `rule`; +CREATE TABLE IF NOT EXISTS `rule` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `output_variable_name` varchar(255) DEFAULT NULL, + `actives` text DEFAULT NULL, + `operator` int(11) DEFAULT NULL, + `compare_value` float DEFAULT NULL, + `min` float DEFAULT NULL, + `max` float DEFAULT NULL, + `action` int(11) DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.rule: ~1 rows (approximately) +DELETE FROM `rule`; +/*!40000 ALTER TABLE `rule` DISABLE KEYS */; +INSERT INTO `rule` (`id`, `output_variable_name`, `actives`, `operator`, `compare_value`, `min`, `max`, `action`, `created_at`, `updated_at`) VALUES + (1, 'Age', '["Camomile"]', 3, 30, NULL, NULL, 2, '2022-04-10 11:07:43', '2022-04-10 11:07:43'); +/*!40000 ALTER TABLE `rule` ENABLE KEYS */; + +-- Dumping structure for table mkd.setting +DROP TABLE IF EXISTS `setting`; +CREATE TABLE IF NOT EXISTS `setting` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `key` varchar(255) DEFAULT NULL, + `type` int(11) DEFAULT NULL, + `value` text DEFAULT NULL, + `maintenance` int(11) DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.setting: ~6 rows (approximately) +DELETE FROM `setting`; +/*!40000 ALTER TABLE `setting` DISABLE KEYS */; +INSERT INTO `setting` (`id`, `key`, `type`, `value`, `maintenance`, `created_at`, `updated_at`) VALUES + (1, 'site_name', 0, 'Createdby', NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (2, 'site_logo', 0, 'https://createdby.co/assets/img/logo.png', NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (3, 'maintenance', 1, '0', NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (4, 'version', 0, '1.0.0', NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (5, 'copyright', 0, 'Copyright © 2021 Createdby. All rights reserved.', NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'), + (6, 'license_key', 4, '4097fbd4f340955de76ca555c201b185cf9d6921d977301b05cdddeae4af54f924f0508cd0f7ca66', NULL, '2022-04-10 11:07:43', '2022-04-10 11:07:43'); +/*!40000 ALTER TABLE `setting` ENABLE KEYS */; + +-- Dumping structure for table mkd.sms +DROP TABLE IF EXISTS `sms`; +CREATE TABLE IF NOT EXISTS `sms` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `slug` varchar(255) DEFAULT NULL, + `tag` text DEFAULT NULL, + `content` text DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.sms: ~1 rows (approximately) +DELETE FROM `sms`; +/*!40000 ALTER TABLE `sms` DISABLE KEYS */; +INSERT INTO `sms` (`id`, `slug`, `tag`, `content`, `created_at`, `updated_at`) VALUES + (1, 'verify', 'code', 'Your verification # is {{{code}}}', '2022-04-10 11:07:43', '2022-04-10 11:07:43'); +/*!40000 ALTER TABLE `sms` ENABLE KEYS */; + +-- Dumping structure for table mkd.token +DROP TABLE IF EXISTS `token`; +CREATE TABLE IF NOT EXISTS `token` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `token` text DEFAULT NULL, + `data` text DEFAULT NULL, + `type` int(11) DEFAULT NULL, + `user_id` int(11) DEFAULT NULL, + `ttl` int(11) DEFAULT NULL, + `issue_at` datetime DEFAULT NULL, + `expire_at` datetime DEFAULT NULL, + `status` int(11) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.token: ~0 rows (approximately) +DELETE FROM `token`; +/*!40000 ALTER TABLE `token` DISABLE KEYS */; +/*!40000 ALTER TABLE `token` ENABLE KEYS */; + +-- Dumping structure for table mkd.user +DROP TABLE IF EXISTS `user`; +CREATE TABLE IF NOT EXISTS `user` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `role_id` int(11) DEFAULT NULL, + `profile_id` int(11) DEFAULT NULL, + `organization_id` int(11) DEFAULT NULL, + `first_name` varchar(255) DEFAULT NULL, + `last_name` varchar(255) DEFAULT NULL, + `phone` varchar(255) DEFAULT NULL, + `image` text DEFAULT NULL, + `refer` varchar(255) DEFAULT NULL, + `stripe_uid` varchar(255) DEFAULT NULL, + `paypal_uid` varchar(255) DEFAULT NULL, + `expire_at` date DEFAULT NULL, + `status` int(11) DEFAULT NULL, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + `user_id` int(11) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4; + +-- Dumping data for table mkd.user: ~2 rows (approximately) +DELETE FROM `user`; +/*!40000 ALTER TABLE `user` DISABLE KEYS */; +INSERT INTO `user` (`id`, `role_id`, `profile_id`, `organization_id`, `first_name`, `last_name`, `phone`, `image`, `refer`, `stripe_uid`, `paypal_uid`, `expire_at`, `status`, `created_at`, `updated_at`, `user_id`) VALUES + (1, 1, NULL, NULL, 'Admin', 'Admin', '12345678', '/image/profile.png', 'admin', NULL, NULL, NULL, 1, '2022-04-10 11:07:43', '2022-04-10 11:07:43', NULL), + (2, 2, NULL, NULL, 'Member', 'Member', '12345678', '/image/profile.png', 'member', NULL, NULL, NULL, 1, '2022-04-10 11:07:43', '2022-04-10 11:07:43', NULL); +/*!40000 ALTER TABLE `user` ENABLE KEYS */; + +/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; +/*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40111 SET SQL_NOTES=IFNULL(@OLD_SQL_NOTES, 1) */; diff --git a/models/active.js b/models/active.js new file mode 100644 index 0000000..bc2c2a7 --- /dev/null +++ b/models/active.js @@ -0,0 +1,117 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * active Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require("bcryptjs"); +const { Op } = require("sequelize"); +const { intersection } = require("lodash"); +const coreModel = require("./../core/models"); + +module.exports = (sequelize, DataTypes) => { + const Active = sequelize.define( + "active", + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + name: DataTypes.STRING, + handle: DataTypes.TEXT, + description: DataTypes.TEXT, + variables_scores: DataTypes.TEXT, + created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "active", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Active); + + Active._preCreateProcessing = function (data) { + return data; + }; + Active._postCreateProcessing = function (data) { + return data; + }; + Active._customCountingConditions = function (data) { + return data; + }; + + Active._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Active.allowFields(); + allowedFields.push(Active._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Active.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Active.associate = function (models) {}; + + Active.allowFields = function () { + return ["id", "name", "handle", "variables_scores", "description"]; + }; + + Active.labels = function () { + return ["ID", "Name", "Handle", "Variables scores", "Description"]; + }; + + Active.validationRules = function () { + return [ + ["id", "ID", ""], + ["name", "Name", "required"], + ["variables_scores", "Variables scores", ""], + ["description", "Description", ""], + ]; + }; + + Active.validationEditRules = function () { + return [ + ["id", "ID", ""], + ["name", "Name", "required"], + ["variables_scores", "Variables scores", ""], + ["description", "Description", ""], + ]; + }; + + // ex + Active.intersection = function (fields) { + if (fields) { + return intersection(["id", "name", "handle", "variables_scores", "description", "created_at", "updated_at"], Object.keys(fields)); + } else return []; + }; + + return Active; +}; diff --git a/models/activity_log.js b/models/activity_log.js new file mode 100644 index 0000000..3bdeb05 --- /dev/null +++ b/models/activity_log.js @@ -0,0 +1,133 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * activity_log Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require('bcryptjs'); +const { Op } = require("sequelize"); +const { intersection } = require('lodash'); +const coreModel = require('./../core/models'); + +module.exports = (sequelize, DataTypes) => { + const Activity_log = sequelize.define( + "activity_log", + { + + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + name: DataTypes.STRING, + action: DataTypes.STRING, + data: DataTypes.TEXT, +created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "activity_log", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Activity_log); + + Activity_log._preCreateProcessing = function (data) { + + return data; + }; + Activity_log._postCreateProcessing = function (data) { + + return data; + }; + Activity_log._customCountingConditions = function (data) { + + return data; + }; + + Activity_log._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Activity_log.allowFields(); + allowedFields.push(Activity_log._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Activity_log.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Activity_log.associate = function(models) { }; + + + + Activity_log.allowFields = function () { + return ['id','name','action','data',]; + }; + + Activity_log.labels = function () { + return ['ID','Name','Action','Data',]; + }; + + Activity_log.validationRules = function () { + return [ + ['id', 'ID', ''], + ['name', 'Name', ''], + ['action', 'Action', 'required'], + ['data', 'Data', 'required'], + ]; + }; + + Activity_log.validationEditRules = function () { + return [ + ['id', 'ID', ''], + ['name', 'Name', ''], + ['action', 'Action', 'required'], + ['data', 'Data', 'required'], + ]; + }; + + + + + + + // ex + Activity_log.intersection = function (fields) { + if (fields) { + return intersection( + [ + 'id','name','action','data','created_at','updated_at', + ], + Object.keys(fields), + ); + } else return []; + }; + + + return Activity_log; +}; diff --git a/models/admin_operation.js b/models/admin_operation.js new file mode 100644 index 0000000..86b4fd2 --- /dev/null +++ b/models/admin_operation.js @@ -0,0 +1,156 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * admin_operation Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require('bcryptjs'); +const { Op } = require("sequelize"); +const { intersection } = require('lodash'); +const coreModel = require('./../core/models'); + +module.exports = (sequelize, DataTypes) => { + const Admin_operation = sequelize.define( + "admin_operation", + { + user_id: DataTypes.INTEGER, + action: DataTypes.STRING, + detail: DataTypes.TEXT, + last_ip: DataTypes.STRING, + user_agent: DataTypes.STRING, +created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "admin_operation", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Admin_operation); + + Admin_operation._preCreateProcessing = function (data) { + + return data; + }; + Admin_operation._postCreateProcessing = function (data) { + + return data; + }; + Admin_operation._customCountingConditions = function (data) { + + return data; + }; + + Admin_operation._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Admin_operation.allowFields(); + allowedFields.push(Admin_operation._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Admin_operation.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Admin_operation.associate = function(models) { +Admin_operation.belongsTo(models.user, { + foreignKey: "user_id", + as: "user", + constraints: false, + }) }; + + + + Admin_operation.allowFields = function () { + return ['user_id','action','detail','last_ip','user_agent',]; + }; + + Admin_operation.labels = function () { + return ['User','Action','Detail','Last IP','User Agent',]; + }; + + Admin_operation.validationRules = function () { + return [ + ['user_id', 'User', 'required|integer'], + ['action', 'Action', 'required|max[50]'], + ['detail', 'Detail', 'required'], + ['last_ip', 'Last IP', 'required'], + ['user_agent', 'User Agent', 'required'], + ]; + }; + + Admin_operation.validationEditRules = function () { + return [ + ['user_id', 'User', ''], + ['action', 'Action', ''], + ['detail', 'Detail', ''], + ['last_ip', 'Last IP', ''], + ['user_agent', 'User Agent', ''], + ]; + }; + + + +Admin_operation.get_user_paginated = function(db, where = {}, ...rest) { + return Admin_operation.getPaginated(...rest, [{ + model: db.user, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "user", + }]) + } + + + Admin_operation.get_admin_operation_user = (id, db) => { + return Admin_operation.findByPk(id, + { + include: [ + { + model: db.user, + required: false, + as: "user", + } + ] + }); + }; + + // ex + Admin_operation.intersection = function (fields) { + if (fields) { + return intersection( + [ + 'user_id','action','detail','last_ip','user_agent','created_at','updated_at', + ], + Object.keys(fields), + ); + } else return []; + }; + + + return Admin_operation; +}; diff --git a/models/answer.js b/models/answer.js new file mode 100644 index 0000000..53f379e --- /dev/null +++ b/models/answer.js @@ -0,0 +1,214 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * answer Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require("bcryptjs"); +const { Op } = require("sequelize"); +const { intersection } = require("lodash"); +const coreModel = require("./../core/models"); + +module.exports = (sequelize, DataTypes) => { + const Answer = sequelize.define( + "answer", + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + question_id: DataTypes.INTEGER, + order: DataTypes.INTEGER, + answer: DataTypes.TEXT, + answer_value: DataTypes.FLOAT, + hide_answer: DataTypes.BOOLEAN, + explaination: DataTypes.TEXT, + image_id: DataTypes.TEXT, + response_header: DataTypes.TEXT, + response_body: DataTypes.TEXT, + response_arguments: DataTypes.TEXT, + black_list_actives: DataTypes.TEXT, + created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "answer", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Answer); + + Answer._preCreateProcessing = function (data) { + return data; + }; + Answer._postCreateProcessing = function (data) { + return data; + }; + Answer._customCountingConditions = function (data) { + return data; + }; + + Answer._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Answer.allowFields(); + allowedFields.push(Answer._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Answer.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Answer.associate = function (models) { + Answer.belongsTo(models.question, { + foreignKey: "question_id", + as: "question", + constraints: false, + }); + Answer.belongsTo(models.image, { + foreignKey: "image_id", + as: "image", + constraints: false, + }); + }; + + Answer.allowFields = function () { + return ["id", "question_id", "order", "answer", "answer_value", "hide_answer", "explaination", "image_id", "response_header", "response_body", "response_arguments", "black_list_actives"]; + }; + + Answer.labels = function () { + return ["ID", "Question ID", "Order", "Answer", "Answer value", "Hide answer", "Explaination", "Image ID", "Response header", "Response body", "Response arguments", "Black listed actives"]; + }; + + Answer.validationRules = function () { + return [ + ["id", "ID", ""], + ["question_id", "Question ID", "required"], + ["order", "Order", "required"], + ["answer", "Answer", "required"], + ["answer_value", "Answer value", ""], + ["hide_answer", "Hide answer", ""], + ["explaination", "Explaination", ""], + ["image_id", "Image ID", ""], + ["response_header", "Response header", ""], + ["response_body", "Response body", ""], + ["response_arguments", "Response arguments", ""], + ["black_list_actives", "Black listed actives", ""], + ]; + }; + + Answer.validationEditRules = function () { + return [ + ["id", "ID", ""], + ["question_id", "Question ID", "required"], + ["order", "Order", "required"], + ["answer", "Answer", "required"], + ["answer_value", "Answer value", ""], + ["hide_answer", "Hide answer", ""], + ["explaination", "Explaination", ""], + ["image_id", "Image ID", ""], + ["response_header", "Response header", ""], + ["response_body", "Response body", ""], + ["response_arguments", "Response arguments", ""], + ["black_list_actives", "Black listed actives", ""], + ]; + }; + + Answer.get_question_paginated = function (db, where = {}, ...rest) { + return Answer.getPaginated(...rest, [ + { + model: db.question, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "question", + }, + ]); + }; + + Answer.get_image_paginated = function (db, where = {}, ...rest) { + return Answer.getPaginated(...rest, [ + { + model: db.image, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "image", + }, + ]); + }; + + Answer.get_answer_question = (id, db) => { + return Answer.findByPk(id, { + include: [ + { + model: db.question, + required: false, + as: "question", + }, + ], + }); + }; + Answer.get_answer_image = (id, db) => { + return Answer.findByPk(id, { + include: [ + { + model: db.image, + required: false, + as: "image", + }, + ], + }); + }; + + // ex + Answer.intersection = function (fields) { + if (fields) { + return intersection( + [ + "id", + "question_id", + "order", + "answer", + "answer_value", + "hide_answer", + "explaination", + "image_id", + "response_header", + "response_body", + "response_arguments", + "black_list_actives", + "created_at", + "updated_at", + ], + Object.keys(fields) + ); + } else return []; + }; + + return Answer; +}; diff --git a/models/configuration.js b/models/configuration.js new file mode 100644 index 0000000..360715f --- /dev/null +++ b/models/configuration.js @@ -0,0 +1,116 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * configuration Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require("bcryptjs"); +const { Op } = require("sequelize"); +const { intersection } = require("lodash"); +const coreModel = require("./../core/models"); + +module.exports = (sequelize, DataTypes) => { + const Configuration = sequelize.define( + "configuration", + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + image_id: DataTypes.INTEGER, + created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "configuration", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Configuration); + + Configuration._preCreateProcessing = function (data) { + return data; + }; + Configuration._postCreateProcessing = function (data) { + return data; + }; + Configuration._customCountingConditions = function (data) { + return data; + }; + + Configuration._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Configuration.allowFields(); + allowedFields.push(Configuration._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Configuration.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Configuration.associate = function (models) { + Configuration.belongsTo(models.image, { + foreignKey: "image_id", + as: "image", + constraints: false, + }); + }; + + Configuration.allowFields = function () { + return ["id", "image_id"]; + }; + + Configuration.labels = function () { + return ["ID", "Image"]; + }; + + Configuration.validationRules = function () { + return [ + ["id", "ID", ""], + ["image_id", "Image", "required"], + ]; + }; + + Configuration.validationEditRules = function () { + return [ + ["id", "ID", ""], + ["image_id", "Image", "required"], + ]; + }; + + // ex + Configuration.intersection = function (fields) { + if (fields) { + return intersection(["id", "image_id", "created_at", "updated_at"], Object.keys(fields)); + } else return []; + }; + + return Configuration; +}; diff --git a/models/credential.js b/models/credential.js new file mode 100644 index 0000000..d6a8393 --- /dev/null +++ b/models/credential.js @@ -0,0 +1,208 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * credential Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require('bcryptjs'); +const { Op } = require("sequelize"); +const { intersection } = require('lodash'); +const coreModel = require('./../core/models'); + +module.exports = (sequelize, DataTypes) => { + const Credential = sequelize.define( + "credential", + { + + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + oauth: DataTypes.STRING, + email: DataTypes.STRING, + password: DataTypes.STRING, + user_id: DataTypes.INTEGER, + type: DataTypes.INTEGER, + verify: DataTypes.INTEGER, + status: DataTypes.INTEGER, + two_factor_authentication: DataTypes.INTEGER, + force_password_change: DataTypes.BOOLEAN, +created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "credential", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Credential); + + Credential._preCreateProcessing = function (data) { +if(!data.status) data.status = 1; +if(!data.two_factor_authentication) data.two_factor_authentication = 0; + return data; + }; + Credential._postCreateProcessing = function (data) { + + return data; + }; + Credential._customCountingConditions = function (data) { + + return data; + }; + + Credential._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Credential.allowFields(); + allowedFields.push(Credential._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Credential.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Credential.associate = function(models) { +Credential.belongsTo(models.user, { + foreignKey: "user_id", + as: "user", + constraints: false, + }) }; + + + Credential.verify_mapping = function (verify) { + const mapping = {"0":"Not verified","1":"Verified"} + + if (arguments.length === 0) return mapping; + else return mapping[verify]; + }; + + + Credential.status_mapping = function (status) { + const mapping = {"0":"Inactive","1":"Active","2":"Suspend"} + + if (arguments.length === 0) return mapping; + else return mapping[status]; + }; + + + Credential.type_mapping = function (type) { + const mapping = {"0":"normal","1":"facebook","2":"google","3":"twitter"} + + if (arguments.length === 0) return mapping; + else return mapping[type]; + }; + + + Credential.two_factor_authentication_mapping = function (two_factor_authentication) { + const mapping = {"0":"No","1":"Yes"} + + if (arguments.length === 0) return mapping; + else return mapping[two_factor_authentication]; + }; + + + Credential.allowFields = function () { + return ['id','oauth','email','password','user_id','type','verify','status','two_factor_authentication','force_password_change',]; + }; + + Credential.labels = function () { + return ['ID','ID','Email','Password','User','Type','Verified','Status','Two factor authentication','',]; + }; + + Credential.validationRules = function () { + return [ + ['id', 'ID', ''], + ['oauth', 'ID', ''], + ['email', 'Email', 'required|valid_email'], + ['password', 'Password', 'required'], + ['user_id', 'User', ''], + ['type', 'Type', 'required'], + ['verify', 'Verified', 'required'], + ['status', 'Status', 'required'], + ['two_factor_authentication', 'Two factor authentication', ''], + ['force_password_change', '', ''], + ]; + }; + + Credential.validationEditRules = function () { + return [ + ['id', 'ID', ''], + ['oauth', 'ID', ''], + ['email', 'Email', 'required|valid_email'], + ['password', 'Password', ''], + ['user_id', 'User', ''], + ['type', 'Type', 'required'], + ['verify', 'Verified', 'required'], + ['status', 'Status', 'required'], + ['two_factor_authentication', 'Two factor authentication', ''], + ['force_password_change', '', ''], + ]; + }; + + + +Credential.get_user_paginated = function(db, where = {}, ...rest) { + return Credential.getPaginated(...rest, [{ + model: db.user, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "user", + }]) + } + + + Credential.get_credential_user = (id, db) => { + return Credential.findByPk(id, + { + include: [ + { + model: db.user, + required: false, + as: "user", + } + ] + }); + }; + + // ex + Credential.intersection = function (fields) { + if (fields) { + return intersection( + [ + 'id','oauth','email','password','user_id','type','verify','status','two_factor_authentication','force_password_change','created_at','updated_at', + ], + Object.keys(fields), + ); + } else return []; + }; + + + return Credential; +}; diff --git a/models/email.js b/models/email.js new file mode 100644 index 0000000..c789ba3 --- /dev/null +++ b/models/email.js @@ -0,0 +1,135 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * email Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require('bcryptjs'); +const { Op } = require("sequelize"); +const { intersection } = require('lodash'); +const coreModel = require('./../core/models'); + +module.exports = (sequelize, DataTypes) => { + const Email = sequelize.define( + "email", + { + slug: DataTypes.STRING, + subject: DataTypes.TEXT, + tag: DataTypes.TEXT, + html: DataTypes.TEXT, +created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "email", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Email); + + Email._preCreateProcessing = function (data) { + + return data; + }; + Email._postCreateProcessing = function (data) { + + return data; + }; + Email._customCountingConditions = function (data) { + + return data; + }; + + Email._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Email.allowFields(); + allowedFields.push(Email._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Email.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Email.associate = function(models) { }; + + + Email.type_mapping = function (type) { + const mapping = {"0":"Forgot_token","1":"Access token","2":"Refresh_token","3":"Other","4":"Api Key","5":"Api Secret","6":"Verify"} + + if (arguments.length === 0) return mapping; + else return mapping[type]; + }; + + + Email.allowFields = function () { + return ['slug','subject','tag','html',]; + }; + + Email.labels = function () { + return ['Email Type','Subject','Replacement Tags','Email Body',]; + }; + + Email.validationRules = function () { + return [ + ['slug', 'Email Type', 'required|is_unique[email.slug]'], + ['subject', 'Subject', 'required'], + ['tag', 'Replacement Tags', 'required'], + ['html', 'Email Body', 'required'], + ]; + }; + + Email.validationEditRules = function () { + return [ + ['slug', 'Email Type', ''], + ['subject', 'Subject', 'required'], + ['tag', 'Replacement Tags', ''], + ['html', 'Email Body', 'required'], + ]; + }; + + + + + + + // ex + Email.intersection = function (fields) { + if (fields) { + return intersection( + [ + 'slug','subject','tag','html','created_at','updated_at', + ], + Object.keys(fields), + ); + } else return []; + }; + + + return Email; +}; diff --git a/models/image.js b/models/image.js new file mode 100644 index 0000000..b5d1786 --- /dev/null +++ b/models/image.js @@ -0,0 +1,199 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * image Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require("bcryptjs"); +const { Op } = require("sequelize"); +const { intersection } = require("lodash"); +const coreModel = require("./../core/models"); + +module.exports = (sequelize, DataTypes) => { + const Image = sequelize.define( + "image", + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + url: DataTypes.TEXT, + caption: DataTypes.TEXT, + user_id: DataTypes.INTEGER, + width: DataTypes.INTEGER, + height: DataTypes.INTEGER, + mobile_width: DataTypes.INTEGER, + mobile_height: DataTypes.INTEGER, + upload_type: DataTypes.INTEGER, + created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "image", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Image); + + Image._preCreateProcessing = function (data) { + return data; + }; + Image._postCreateProcessing = function (data) { + return data; + }; + Image._customCountingConditions = function (data) { + return data; + }; + + Image._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Image.allowFields(); + allowedFields.push(Image._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Image.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Image.associate = function (models) { + Image.belongsTo(models.user, { + foreignKey: "user_id", + as: "user", + constraints: false, + }); + Image.hasOne(models.configuration, { + foreignKey: "image_id", + as: "configuration", + constraints: false, + }); + Image.hasMany(models.answer, { + foreignKey: "image_id", + as: "answers", + constraints: false, + }); + }; + + Image.upload_type_mapping = function (upload_type) { + const mapping = { 0: "Server Hosted", 1: "External Link", 2: "S3", 3: "Cloudinary", 4: "File", 5: "External File", 6: "Local Hosted" }; + + if (arguments.length === 0) return mapping; + else return mapping[upload_type]; + }; + + Image.allowFields = function () { + return ["image_id", "id", "url", "caption", "user_id", "width", "height", "mobile_width", "mobile_height", "upload_type"]; + }; + + Image.labels = function () { + return ["ID", "URL", "Caption", "User", "Width", "Height", "Mobile width", "Mobile height", "Upload Type"]; + }; + + Image.validationRules = function () { + return [ + ["id", "ID", ""], + ["url", "URL", "required"], + ["caption", "Caption", ""], + ["user_id", "User", ""], + ["width", "Width", ""], + ["height", "Height", ""], + ["mobile_width", "Mobile width", ""], + ["mobile_height", "Mobile height", ""], + ["upload_type", "Upload Type", ""], + ]; + }; + + Image.validationEditRules = function () { + return [ + ["id", "ID", ""], + ["url", "URL", "required"], + ["caption", "Caption", ""], + ["user_id", "User", ""], + ["width", "Width", ""], + ["height", "Height", ""], + ["mobile_width", "Mobile width", ""], + ["mobile_height", "Mobile height", ""], + ["upload_type", "Upload Type", ""], + ]; + }; + + Image.get_user_paginated = function (db, where = {}, ...rest) { + return Image.getPaginated(...rest, [ + { + model: db.user, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "user", + }, + ]); + }; + + Image.get_answer_paginated = function (db, where = {}, ...rest) { + return Image.getPaginated(...rest, [ + { + model: db.answer, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "answers", + }, + ]); + }; + + Image.get_image_user = (id, db) => { + return Image.findByPk(id, { + include: [ + { + model: db.user, + required: false, + as: "user", + }, + ], + }); + }; + Image.get_image_answer = (id, db) => { + return Image.findByPk(id, { + include: [ + { + model: db.answer, + required: false, + as: "answers", + }, + ], + }); + }; + + // ex + Image.intersection = function (fields) { + if (fields) { + return intersection(["id", "url", "caption", "user_id", "width", "height", "mobile_width", "mobile_height", "upload_type", "created_at", "updated_at"], Object.keys(fields)); + } else return []; + }; + + return Image; +}; diff --git a/models/index.js b/models/index.js new file mode 100644 index 0000000..59f86f1 --- /dev/null +++ b/models/index.js @@ -0,0 +1,61 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2020*/ +/** + * Sequelize File + * @copyright 2020 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const fs = require('fs'); +const path = require('path'); +let Sequelize = require('sequelize'); +const basename = path.basename(__filename); +const dotenv = require('dotenv'); +dotenv.config(); + +let db = {}; + +let sequelize = new Sequelize(process.env.DB_DATABASE, process.env.DB_USERNAME, process.env.DB_PASSWORD, { + dialect: process.env.DB_ADAPTER, + username: process.env.DB_USERNAME, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, + host: process.env.DB_HOSTNAME, + port: process.env.DB_PORT, + logging: console.log, + timezone: '-04:00', + pool: { + maxConnections: 1, + minConnections: 0, + maxIdleTime: 100, + }, + define: { + timestamps: false, + underscoredAll: true, + underscored: true, + }, +}); + +// sequelize.sync({ force: true }); + +fs.readdirSync(__dirname) + .filter((file) => { + return file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js'; + }) + .forEach((file) => { + var model = sequelize['import'](path.join(__dirname, file)); + db[model.name] = model; + }); + +Object.keys(db).forEach((modelName) => { + if (db[modelName].associate) { + db[modelName].associate(db); + } +}); + +db.sequelize = sequelize; +db.Sequelize = Sequelize; + +module.exports = db; diff --git a/models/member_operation.js b/models/member_operation.js new file mode 100644 index 0000000..b853592 --- /dev/null +++ b/models/member_operation.js @@ -0,0 +1,163 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * member_operation Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require('bcryptjs'); +const { Op } = require("sequelize"); +const { intersection } = require('lodash'); +const coreModel = require('./../core/models'); + +module.exports = (sequelize, DataTypes) => { + const Member_operation = sequelize.define( + "member_operation", + { + action: DataTypes.STRING, + detail: DataTypes.TEXT, + last_ip: DataTypes.STRING, + user_agent: DataTypes.STRING, + status: DataTypes.INTEGER, +created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "member_operation", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Member_operation); + + Member_operation._preCreateProcessing = function (data) { +if(!data.status) data.status = 1; + return data; + }; + Member_operation._postCreateProcessing = function (data) { + + return data; + }; + Member_operation._customCountingConditions = function (data) { + + return data; + }; + + Member_operation._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Member_operation.allowFields(); + allowedFields.push(Member_operation._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Member_operation.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Member_operation.associate = function(models) { +Member_operation.belongsTo(models.user, { + foreignKey: "user_id", + as: "user", + constraints: false, + }) }; + + + Member_operation.status_mapping = function (status) { + const mapping = {"0":"Inactive","1":"Active"} + + if (arguments.length === 0) return mapping; + else return mapping[status]; + }; + + + Member_operation.allowFields = function () { + return ["user_id",'action','detail','last_ip','user_agent','status',]; + }; + + Member_operation.labels = function () { + return ['Action','Detail','Last IP','User Agent','Status',]; + }; + + Member_operation.validationRules = function () { + return [ + ['action', 'Action', 'required|max[50]'], + ['detail', 'Detail', 'required'], + ['last_ip', 'Last IP', 'required'], + ['user_agent', 'User Agent', 'required'], + ['status', 'Status', 'required|integer'], + ]; + }; + + Member_operation.validationEditRules = function () { + return [ + ['action', 'Action', ''], + ['detail', 'Detail', ''], + ['last_ip', 'Last IP', ''], + ['user_agent', 'User Agent', ''], + ['status', 'Status', 'required|integer'], + ]; + }; + + + +Member_operation.get_user_paginated = function(db, where = {}, ...rest) { + return Member_operation.getPaginated(...rest, [{ + model: db.user, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "user", + }]) + } + + + Member_operation.get_member_operation_user = (id, db) => { + return Member_operation.findByPk(id, + { + include: [ + { + model: db.user, + required: false, + as: "user", + } + ] + }); + }; + + // ex + Member_operation.intersection = function (fields) { + if (fields) { + return intersection( + [ + 'action','detail','last_ip','user_agent','status','created_at','updated_at', + ], + Object.keys(fields), + ); + } else return []; + }; + + + return Member_operation; +}; diff --git a/models/order.js b/models/order.js new file mode 100644 index 0000000..9165db8 --- /dev/null +++ b/models/order.js @@ -0,0 +1,143 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * order Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require("bcryptjs"); +const { Op } = require("sequelize"); +const { intersection } = require("lodash"); +const coreModel = require("./../core/models"); + +module.exports = (sequelize, DataTypes) => { + const Order = sequelize.define( + "order", + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + webhook_id: { + type: DataTypes.STRING, + unique: true, + }, + shopify_id: { + type: DataTypes.STRING, + unique: true, + }, + event: DataTypes.TEXT, + customer_shopify_id: DataTypes.STRING, + customer: DataTypes.TEXT, + answers: DataTypes.TEXT, + profile: DataTypes.TEXT, + actives: DataTypes.TEXT, + items: DataTypes.TEXT, + financial_status: DataTypes.STRING, + fulfillment_status: DataTypes.STRING, + created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "order", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Order); + + Order._preCreateProcessing = function (data) { + return data; + }; + Order._postCreateProcessing = function (data) { + return data; + }; + Order._customCountingConditions = function (data) { + return data; + }; + + Order._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Order.allowFields(); + allowedFields.push(Order._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Order.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Order.associate = function (models) {}; + + Order.allowFields = function () { + return ["id", "webhook_id", "shopify_id", "event", "profile", "actives", "customer_shopify_id", "customer", "answers", "items", "financial_status", "fulfillment_status"]; + }; + + Order.labels = function () { + return ["ID", "Webhook Id", "Order shopify id", "Event", "Profile", "Actives", "Customer", "Customer", "Answers", "Items", "Financial status", "Fulfillment status"]; + }; + + Order.validationRules = function () { + return [ + ["id", "ID", ""], + ["shopify_id", "Order shopify id", ""], + ["event", "Event", ""], + ["customer_shopify_id", "Customer", ""], + ["customer", "Customer", ""], + ["answers", "Answers", ""], + ["items", "Items", ""], + ["financial_status", "Financial status", ""], + ["fulfillment_status", "Fulfillment status", ""], + ]; + }; + + Order.validationEditRules = function () { + return [ + ["id", "ID", ""], + ["shopify_id", "Order shopify id", ""], + ["event", "Event", ""], + ["customer_shopify_id", "Customer", ""], + ["customer", "Customer", ""], + ["answers", "Answers", ""], + ["items", "Items", ""], + ["financial_status", "Financial status", ""], + ["fulfillment_status", "Fulfillment status", ""], + ]; + }; + + // ex + Order.intersection = function (fields) { + if (fields) { + return intersection( + ["id", "webhook_id", "shopify_id", "event", "customer_shopify_id", "profile", "actives", "customer", "answers", "items", "financial_status", "fulfillment_status", "created_at", "updated_at"], + Object.keys(fields) + ); + } else return []; + }; + + return Order; +}; diff --git a/models/output_variable.js b/models/output_variable.js new file mode 100644 index 0000000..db77999 --- /dev/null +++ b/models/output_variable.js @@ -0,0 +1,119 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * output_variable Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require("bcryptjs"); +const { Op } = require("sequelize"); +const { intersection } = require("lodash"); +const coreModel = require("./../core/models"); + +module.exports = (sequelize, DataTypes) => { + const Output_variable = sequelize.define( + "output_variable", + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + name: DataTypes.STRING, + priority: DataTypes.FLOAT, + active_list: DataTypes.TEXT, + ranges_response: DataTypes.TEXT, + created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "output_variable", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Output_variable); + + Output_variable._preCreateProcessing = function (data) { + return data; + }; + Output_variable._postCreateProcessing = function (data) { + return data; + }; + Output_variable._customCountingConditions = function (data) { + return data; + }; + + Output_variable._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Output_variable.allowFields(); + allowedFields.push(Output_variable._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Output_variable.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Output_variable.associate = function (models) {}; + + Output_variable.allowFields = function () { + return ["id", "name", "priority", "active_list", "ranges_response"]; + }; + + Output_variable.labels = function () { + return ["ID", "Name", "Priority", "Actives list", "Ranges responses"]; + }; + + Output_variable.validationRules = function () { + return [ + ["id", "ID", ""], + ["name", "Name", "required"], + ["priority", "Priority", "required"], + ["active_list", "Actives list", "required"], + ["ranges_response", "Ranges responses", "required"], + ]; + }; + + Output_variable.validationEditRules = function () { + return [ + ["id", "ID", ""], + ["name", "Name", "required"], + ["priority", "Priority", "required"], + ["active_list", "Actives list", "required"], + ["ranges_response", "Ranges responses", "required"], + ]; + }; + + // ex + Output_variable.intersection = function (fields) { + if (fields) { + return intersection(["id", "name", "priority", "active_list", "ranges_response", "created_at", "updated_at"], Object.keys(fields)); + } else return []; + }; + + return Output_variable; +}; diff --git a/models/question.js b/models/question.js new file mode 100644 index 0000000..d4dfbe6 --- /dev/null +++ b/models/question.js @@ -0,0 +1,304 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * question Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require("bcryptjs"); +const { Op } = require("sequelize"); +const { intersection } = require("lodash"); +const coreModel = require("./../core/models"); + +module.exports = (sequelize, DataTypes) => { + const Question = sequelize.define( + "question", + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + quiz_id: DataTypes.INTEGER, + question: DataTypes.TEXT, + question_arguments: DataTypes.TEXT, + order: DataTypes.INTEGER, + image_width: DataTypes.FLOAT, + image_height: DataTypes.FLOAT, + placeholder: DataTypes.STRING, + note: DataTypes.TEXT, + note_type: DataTypes.INTEGER, + target: DataTypes.INTEGER, + response: DataTypes.TEXT, + save_response_into: DataTypes.STRING, + depends_on: DataTypes.STRING, + slider_range: DataTypes.STRING, + output_variable_name: DataTypes.STRING, + weight: DataTypes.FLOAT, + extra_output_variable: DataTypes.TEXT, + type: DataTypes.INTEGER, + created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "question", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Question); + + Question._preCreateProcessing = function (data) { + return data; + }; + Question._postCreateProcessing = function (data) { + return data; + }; + Question._customCountingConditions = function (data) { + return data; + }; + + Question._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Question.allowFields(); + allowedFields.push(Question._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Question.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Question.associate = function (models) { + Question.belongsTo(models.quiz, { + foreignKey: "quiz_id", + as: "quiz", + constraints: false, + }); + Question.hasMany(models.answer, { + foreignKey: "question_id", + as: "answers", + constraints: false, + }); + }; + + Question.type_mapping = function (type) { + const mapping = { 1: "text", 2: "number", 3: "date", 4: "mcq", 5: "mcqi", 6: "slide", 7: "selection", 8: "geolocation" }; + + if (arguments.length === 0) return mapping; + else return mapping[type]; + }; + + Question.target_mapping = function (target) { + const mapping = { 1: "female", 2: "male", 3: "non-binary", 4: "all" }; + + if (arguments.length === 0) return mapping; + else return mapping[target]; + }; + + Question.note_type_mapping = function (note_type) { + const mapping = { 1: "Note", 2: "Scientific note" }; + + if (arguments.length === 0) return mapping; + else return mapping[note_type]; + }; + + Question.allowFields = function () { + return [ + "question_id", + "id", + "quiz_id", + "question", + "question_arguments", + "order", + "image_width", + "image_height", + "placeholder", + "note", + "note_type", + "target", + "response", + "save_response_into", + "depends_on", + "slider_range", + "output_variable_name", + "weight", + "extra_output_variable", + "type", + ]; + }; + + Question.labels = function () { + return [ + "ID", + "Quiz ID", + "Question", + "Question arguments", + "Order", + "Image width", + "Image height", + "Placeholder", + "Note", + "Note type", + "Target", + "Response", + "Save response", + "Depends on question", + "Slider range", + "Output variable", + "weight", + "Extra output variables", + "Type", + ]; + }; + + Question.validationRules = function () { + return [ + ["id", "ID", ""], + ["quiz_id", "Quiz ID", "required"], + ["question", "Question", "required"], + ["question_arguments", "Question arguments", ""], + ["order", "Order", "required"], + ["image_width", "Image width", "required"], + ["image_height", "Image height", "required"], + ["placeholder", "Placeholder", ""], + ["note", "Note", ""], + ["note_type", "Note type", ""], + ["target", "Target", ""], + ["response", "Response", ""], + ["save_response_into", "Save response", ""], + ["depends_on", "Depends on question", ""], + ["slider_range", "Slider range", ""], + ["output_variable_name", "Output variable", "required"], + ["weight", "weight", "required"], + ["extra_output_variable", "Extra output variables", ""], + ["type", "Type", "required"], + ]; + }; + + Question.validationEditRules = function () { + return [ + ["id", "ID", ""], + ["quiz_id", "Quiz ID", "required"], + ["question", "Question", "required"], + ["question_arguments", "Question arguments", ""], + ["order", "Order", "required"], + ["image_width", "Image width", "required"], + ["image_height", "Image height", "required"], + ["placeholder", "Placeholder", ""], + ["note", "Note", ""], + ["note_type", "Note type", ""], + ["target", "Target", ""], + ["response", "Response", ""], + ["save_response_into", "Save response", ""], + ["depends_on", "Depends on question", ""], + ["slider_range", "Slider range", ""], + ["output_variable_name", "Output variable", "required"], + ["weight", "weight", "required"], + ["extra_output_variable", "Extra output variables", ""], + ["type", "Type", "required"], + ]; + }; + + Question.get_quiz_paginated = function (db, where = {}, ...rest) { + return Question.getPaginated(...rest, [ + { + model: db.quiz, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "quiz", + }, + ]); + }; + + Question.get_answer_paginated = function (db, where = {}, ...rest) { + return Question.getPaginated(...rest, [ + { + model: db.answer, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "answers", + }, + ]); + }; + + Question.get_question_quiz = (id, db) => { + return Question.findByPk(id, { + include: [ + { + model: db.quiz, + required: false, + as: "quiz", + }, + ], + }); + }; + Question.get_question_answer = (id, db) => { + return Question.findByPk(id, { + include: [ + { + model: db.answer, + required: false, + as: "answers", + }, + ], + }); + }; + + // ex + Question.intersection = function (fields) { + if (fields) { + return intersection( + [ + "id", + "quiz_id", + "question", + "question_arguments", + "order", + "image_width", + "image_height", + "placeholder", + "note", + "note_type", + "target", + "response", + "save_response_into", + "depends_on", + "slider_range", + "output_variable_name", + "weight", + "extra_output_variable", + "type", + "created_at", + "updated_at", + ], + Object.keys(fields) + ); + } else return []; + }; + + return Question; +}; diff --git a/models/quiz.js b/models/quiz.js new file mode 100644 index 0000000..7e9eaf2 --- /dev/null +++ b/models/quiz.js @@ -0,0 +1,155 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * quiz Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require('bcryptjs'); +const { Op } = require("sequelize"); +const { intersection } = require('lodash'); +const coreModel = require('./../core/models'); + +module.exports = (sequelize, DataTypes) => { + const Quiz = sequelize.define( + "quiz", + { + + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + name: DataTypes.STRING, + description: DataTypes.TEXT, +created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "quiz", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Quiz); + + Quiz._preCreateProcessing = function (data) { + + return data; + }; + Quiz._postCreateProcessing = function (data) { + + return data; + }; + Quiz._customCountingConditions = function (data) { + + return data; + }; + + Quiz._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Quiz.allowFields(); + allowedFields.push(Quiz._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Quiz.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Quiz.associate = function(models) { +Quiz.hasMany(models.question, { + foreignKey: "quiz_id", + as: "questions", + constraints: false, + }) }; + + + + Quiz.allowFields = function () { + return ["quiz_id",'id','name','description',]; + }; + + Quiz.labels = function () { + return ['ID','Name','Description',]; + }; + + Quiz.validationRules = function () { + return [ + ['id', 'ID', ''], + ['name', 'Name', 'required'], + ['description', 'Description', ''], + ]; + }; + + Quiz.validationEditRules = function () { + return [ + ['id', 'ID', ''], + ['name', 'Name', 'required'], + ['description', 'Description', ''], + ]; + }; + + + +Quiz.get_question_paginated = function(db, where = {}, ...rest) { + return Quiz.getPaginated(...rest, [{ + model: db.question, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "questions", + }]) + } + + + Quiz.get_quiz_question = (id, db) => { + return Quiz.findByPk(id, + { + include: [ + { + model: db.question, + required: false, + as: "questions", + } + ] + }); + }; + + // ex + Quiz.intersection = function (fields) { + if (fields) { + return intersection( + [ + 'id','name','description','created_at','updated_at', + ], + Object.keys(fields), + ); + } else return []; + }; + + + return Quiz; +}; diff --git a/models/refer_log.js b/models/refer_log.js new file mode 100644 index 0000000..b5bf808 --- /dev/null +++ b/models/refer_log.js @@ -0,0 +1,165 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * refer_log Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require('bcryptjs'); +const { Op } = require("sequelize"); +const { intersection } = require('lodash'); +const coreModel = require('./../core/models'); + +module.exports = (sequelize, DataTypes) => { + const Refer_log = sequelize.define( + "refer_log", + { + + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + user_id: DataTypes.INTEGER, + referrer_user_id: DataTypes.INTEGER, + type: DataTypes.INTEGER, +created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "refer_log", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Refer_log); + + Refer_log._preCreateProcessing = function (data) { + + return data; + }; + Refer_log._postCreateProcessing = function (data) { + + return data; + }; + Refer_log._customCountingConditions = function (data) { + + return data; + }; + + Refer_log._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Refer_log.allowFields(); + allowedFields.push(Refer_log._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Refer_log.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Refer_log.associate = function(models) { +Refer_log.belongsTo(models.user, { + foreignKey: "user_id", + as: "user", + constraints: false, + }) }; + + + Refer_log.type_mapping = function (type) { + const mapping = {"0":"user"} + + if (arguments.length === 0) return mapping; + else return mapping[type]; + }; + + + Refer_log.allowFields = function () { + return ['id','user_id','referrer_user_id','type',]; + }; + + Refer_log.labels = function () { + return ['ID','Referree User','Referrer User','Type',]; + }; + + Refer_log.validationRules = function () { + return [ + ['id', 'ID', ''], + ['user_id', 'Referree User', 'required|integer'], + ['referrer_user_id', 'Referrer User', 'required|integer'], + ['type', 'Type', 'required|integer'], + ]; + }; + + Refer_log.validationEditRules = function () { + return [ + ['id', 'ID', ''], + ['user_id', 'Referree User', ''], + ['referrer_user_id', 'Referrer User', ''], + ['type', 'Type', 'required|integer'], + ]; + }; + + + +Refer_log.get_user_paginated = function(db, where = {}, ...rest) { + return Refer_log.getPaginated(...rest, [{ + model: db.user, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "user", + }]) + } + + + Refer_log.get_refer_log_user = (id, db) => { + return Refer_log.findByPk(id, + { + include: [ + { + model: db.user, + required: false, + as: "user", + } + ] + }); + }; + + // ex + Refer_log.intersection = function (fields) { + if (fields) { + return intersection( + [ + 'id','user_id','referrer_user_id','type','created_at','updated_at', + ], + Object.keys(fields), + ); + } else return []; + }; + + + return Refer_log; +}; diff --git a/models/result_profile.js b/models/result_profile.js new file mode 100644 index 0000000..f91112b --- /dev/null +++ b/models/result_profile.js @@ -0,0 +1,113 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * result_profile Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require("bcryptjs"); +const { Op } = require("sequelize"); +const { intersection } = require("lodash"); +const coreModel = require("./../core/models"); + +module.exports = (sequelize, DataTypes) => { + const Result_profile = sequelize.define( + "result_profile", + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + section_title: DataTypes.STRING, + output_variable_list: DataTypes.TEXT, + created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "result_profile", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Result_profile); + + Result_profile._preCreateProcessing = function (data) { + return data; + }; + Result_profile._postCreateProcessing = function (data) { + return data; + }; + Result_profile._customCountingConditions = function (data) { + return data; + }; + + Result_profile._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Result_profile.allowFields(); + allowedFields.push(Result_profile._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Result_profile.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Result_profile.associate = function (models) {}; + + Result_profile.allowFields = function () { + return ["id", "section_title", "output_variable_list"]; + }; + + Result_profile.labels = function () { + return ["ID", "Section title", "Variables List"]; + }; + + Result_profile.validationRules = function () { + return [ + ["id", "ID", ""], + ["section_title", "Section title", ""], + ["output_variable_list", "Variables List", ""], + ]; + }; + + Result_profile.validationEditRules = function () { + return [ + ["id", "ID", ""], + ["section_title", "Section title", ""], + ["output_variable_list", "Variables List", ""], + ]; + }; + + // ex + Result_profile.intersection = function (fields) { + if (fields) { + return intersection(["id", "section_title", "output_variable_list", "created_at", "updated_at"], Object.keys(fields)); + } else return []; + }; + + return Result_profile; +}; diff --git a/models/role.js b/models/role.js new file mode 100644 index 0000000..b901380 --- /dev/null +++ b/models/role.js @@ -0,0 +1,152 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * role Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require('bcryptjs'); +const { Op } = require("sequelize"); +const { intersection } = require('lodash'); +const coreModel = require('./../core/models'); + +module.exports = (sequelize, DataTypes) => { + const Role = sequelize.define( + "role", + { + + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + name: DataTypes.STRING, +created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "role", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Role); + + Role._preCreateProcessing = function (data) { + + return data; + }; + Role._postCreateProcessing = function (data) { + + return data; + }; + Role._customCountingConditions = function (data) { + + return data; + }; + + Role._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Role.allowFields(); + allowedFields.push(Role._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Role.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Role.associate = function(models) { +Role.hasMany(models.user, { + foreignKey: "user_id", + as: "users", + constraints: false, + }) }; + + + + Role.allowFields = function () { + return ["user_id",'id','name',]; + }; + + Role.labels = function () { + return ['ID','Role Name',]; + }; + + Role.validationRules = function () { + return [ + ['id', 'ID', ''], + ['name', 'Role Name', 'required'], + ]; + }; + + Role.validationEditRules = function () { + return [ + ['id', 'ID', ''], + ['name', 'Role Name', 'required'], + ]; + }; + + + +Role.get_user_paginated = function(db, where = {}, ...rest) { + return Role.getPaginated(...rest, [{ + model: db.user, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "users", + }]) + } + + + Role.get_role_user = (id, db) => { + return Role.findByPk(id, + { + include: [ + { + model: db.user, + required: false, + as: "users", + } + ] + }); + }; + + // ex + Role.intersection = function (fields) { + if (fields) { + return intersection( + [ + 'id','name','created_at','updated_at', + ], + Object.keys(fields), + ); + } else return []; + }; + + + return Role; +}; diff --git a/models/rule.js b/models/rule.js new file mode 100644 index 0000000..ccb41c0 --- /dev/null +++ b/models/rule.js @@ -0,0 +1,142 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * rule Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require("bcryptjs"); +const { Op } = require("sequelize"); +const { intersection } = require("lodash"); +const coreModel = require("./../core/models"); + +module.exports = (sequelize, DataTypes) => { + const Rule = sequelize.define( + "rule", + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + output_variable_name: DataTypes.STRING, + actives: DataTypes.TEXT, + operator: DataTypes.INTEGER, + compare_value: DataTypes.FLOAT, + min: DataTypes.FLOAT, + max: DataTypes.FLOAT, + action: DataTypes.INTEGER, + created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "rule", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Rule); + + Rule._preCreateProcessing = function (data) { + return data; + }; + Rule._postCreateProcessing = function (data) { + return data; + }; + Rule._customCountingConditions = function (data) { + return data; + }; + + Rule._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Rule.allowFields(); + allowedFields.push(Rule._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Rule.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Rule.associate = function (models) {}; + + Rule.operator_mapping = function (operator) { + const mapping = { 0: "=:equal", 1: "<:less than", 2: "<=:less than or equal", 3: ">:greater than", 4: ">=:greater than or equal", 5: "!=:not equal", 6: "in:between" }; + + if (arguments.length === 0) return mapping; + else return mapping[operator]; + }; + + Rule.action_mapping = function (action) { + const mapping = { 1: "add", 2: "remove" }; + + if (arguments.length === 0) return mapping; + else return mapping[action]; + }; + + Rule.allowFields = function () { + return ["id", "output_variable_name", "actives", "operator", "compare_value", "min", "max", "action"]; + }; + + Rule.labels = function () { + return ["ID", "Output variable", "actives", "Condition operator", "Compare value", "Between Min", "Between Max", "Action"]; + }; + + Rule.validationRules = function () { + return [ + ["id", "ID", ""], + ["output_variable_name", "Output variable", "required"], + ["actives", "actives", "required"], + ["operator", "Condition operator", "required"], + ["compare_value", "Compare value", "required"], + ["min", "Between Min", ""], + ["max", "Between Max", ""], + ["action", "Action", "required"], + ]; + }; + + Rule.validationEditRules = function () { + return [ + ["id", "ID", ""], + ["output_variable_name", "Output variable", "required"], + ["actives", "actives", "required"], + ["operator", "Condition operator", "required"], + ["compare_value", "Compare value", "required"], + ["min", "Between Min", ""], + ["max", "Between Max", ""], + ["action", "Action", "required"], + ]; + }; + + // ex + Rule.intersection = function (fields) { + if (fields) { + return intersection(["id", "output_variable_name", "actives", "operator", "compare_value", "min", "max", "action", "created_at", "updated_at"], Object.keys(fields)); + } else return []; + }; + + return Rule; +}; diff --git a/models/setting.js b/models/setting.js new file mode 100644 index 0000000..d600590 --- /dev/null +++ b/models/setting.js @@ -0,0 +1,151 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * setting Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require('bcryptjs'); +const { Op } = require("sequelize"); +const { intersection } = require('lodash'); +const coreModel = require('./../core/models'); + +module.exports = (sequelize, DataTypes) => { + const Setting = sequelize.define( + "setting", + { + + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + key: DataTypes.STRING, + type: DataTypes.INTEGER, + value: DataTypes.TEXT, + maintenance: DataTypes.INTEGER, +created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "setting", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Setting); + + Setting._preCreateProcessing = function (data) { + + return data; + }; + Setting._postCreateProcessing = function (data) { + + return data; + }; + Setting._customCountingConditions = function (data) { + + return data; + }; + + Setting._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Setting.allowFields(); + allowedFields.push(Setting._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Setting.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Setting.associate = function(models) { }; + + + Setting.type_mapping = function (type) { + const mapping = {"0":"text","1":"select","2":"number","3":"image","4":"read_only"} + + if (arguments.length === 0) return mapping; + else return mapping[type]; + }; + + + Setting.maintenance_mapping = function (maintenance) { + const mapping = {"0":"No","1":"Yes"} + + if (arguments.length === 0) return mapping; + else return mapping[maintenance]; + }; + + + Setting.allowFields = function () { + return ['id','key','type','value','maintenance',]; + }; + + Setting.labels = function () { + return ['ID','Setting Field','Setting Type','Setting Value','Setting Type',]; + }; + + Setting.validationRules = function () { + return [ + ['id', 'ID', ''], + ['key', 'Setting Field', 'required'], + ['type', 'Setting Type', 'required'], + ['value', 'Setting Value', 'required'], + ['maintenance', 'Setting Type', 'required'], + ]; + }; + + Setting.validationEditRules = function () { + return [ + ['id', 'ID', ''], + ['key', 'Setting Field', ''], + ['type', 'Setting Type', ''], + ['value', 'Setting Value', 'required'], + ['maintenance', 'Setting Type', ''], + ]; + }; + + + + + + + // ex + Setting.intersection = function (fields) { + if (fields) { + return intersection( + [ + 'id','key','type','value','maintenance','created_at','updated_at', + ], + Object.keys(fields), + ); + } else return []; + }; + + + return Setting; +}; diff --git a/models/sms.js b/models/sms.js new file mode 100644 index 0000000..3f9c731 --- /dev/null +++ b/models/sms.js @@ -0,0 +1,125 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * sms Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require('bcryptjs'); +const { Op } = require("sequelize"); +const { intersection } = require('lodash'); +const coreModel = require('./../core/models'); + +module.exports = (sequelize, DataTypes) => { + const Sms = sequelize.define( + "sms", + { + slug: DataTypes.STRING, + tag: DataTypes.TEXT, + content: DataTypes.TEXT, +created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "sms", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Sms); + + Sms._preCreateProcessing = function (data) { + + return data; + }; + Sms._postCreateProcessing = function (data) { + + return data; + }; + Sms._customCountingConditions = function (data) { + + return data; + }; + + Sms._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Sms.allowFields(); + allowedFields.push(Sms._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Sms.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Sms.associate = function(models) { }; + + + + Sms.allowFields = function () { + return ['slug','tag','content',]; + }; + + Sms.labels = function () { + return ['SMS Slug','Replacement Tags','SMS Body',]; + }; + + Sms.validationRules = function () { + return [ + ['slug', 'SMS Slug', 'required|is_unique[sms.slug]'], + ['tag', 'Replacement Tags', 'required'], + ['content', 'SMS Body', 'required'], + ]; + }; + + Sms.validationEditRules = function () { + return [ + ['slug', 'SMS Slug', ''], + ['tag', 'Replacement Tags', ''], + ['content', 'SMS Body', 'required'], + ]; + }; + + + + + + + // ex + Sms.intersection = function (fields) { + if (fields) { + return intersection( + [ + 'slug','tag','content','created_at','updated_at', + ], + Object.keys(fields), + ); + } else return []; + }; + + + return Sms; +}; diff --git a/models/token.js b/models/token.js new file mode 100644 index 0000000..32fd287 --- /dev/null +++ b/models/token.js @@ -0,0 +1,187 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * token Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require('bcryptjs'); +const { Op } = require("sequelize"); +const { intersection } = require('lodash'); +const coreModel = require('./../core/models'); + +module.exports = (sequelize, DataTypes) => { + const Token = sequelize.define( + "token", + { + + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + token: DataTypes.TEXT, + data: DataTypes.TEXT, + type: DataTypes.INTEGER, + user_id: DataTypes.INTEGER, + ttl: DataTypes.INTEGER, + issue_at: DataTypes.DATE, + expire_at: DataTypes.DATE, + status: DataTypes.INTEGER, + + }, + { + timestamps: false, + freezeTableName: true, + tableName: "token", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, Token); + + Token._preCreateProcessing = function (data) { +if(!data.status) data.status = 1; + return data; + }; + Token._postCreateProcessing = function (data) { + + return data; + }; + Token._customCountingConditions = function (data) { + + return data; + }; + + Token._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = Token.allowFields(); + allowedFields.push(Token._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + Token.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + Token.associate = function(models) { +Token.belongsTo(models.user, { + foreignKey: "user_id", + as: "user", + constraints: false, + }) }; + + + Token.status_mapping = function (status) { + const mapping = {"0":"Inactive","1":"Active"} + + if (arguments.length === 0) return mapping; + else return mapping[status]; + }; + + + Token.type_mapping = function (type) { + const mapping = {"0":"Forgot_token","1":"Access token","2":"Refresh_token","3":"Other","4":"Api Key","5":"Api Secret","6":"Verify"} + + if (arguments.length === 0) return mapping; + else return mapping[type]; + }; + + + Token.allowFields = function () { + return ['id','token','data','type','user_id','ttl','issue_at','expire_at','status',]; + }; + + Token.labels = function () { + return ['ID','Token','Data','Token Type','User','Time To Live','Issue at','Expire at','Status',]; + }; + + Token.validationRules = function () { + return [ + ['id', 'ID', ''], + ['token', 'Token', 'required'], + ['data', 'Data', 'required'], + ['type', 'Token Type', 'required|integer'], + ['user_id', 'User', 'required|integer'], + ['ttl', 'Time To Live', 'required|integer'], + ['issue_at', 'Issue at', 'required'], + ['expire_at', 'Expire at', 'required'], + ['status', 'Status', 'required|integer'], + ]; + }; + + Token.validationEditRules = function () { + return [ + ['id', 'ID', ''], + ['token', 'Token', 'required'], + ['data', 'Data', 'required'], + ['type', 'Token Type', 'required|integer'], + ['user_id', 'User', 'required|integer'], + ['ttl', 'Time To Live', 'required|integer'], + ['issue_at', 'Issue at', 'required'], + ['expire_at', 'Expire at', 'required'], + ['status', 'Status', 'required|integer'], + ]; + }; + + + +Token.get_user_paginated = function(db, where = {}, ...rest) { + return Token.getPaginated(...rest, [{ + model: db.user, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "user", + }]) + } + + + Token.get_token_user = (id, db) => { + return Token.findByPk(id, + { + include: [ + { + model: db.user, + required: false, + as: "user", + } + ] + }); + }; + + // ex + Token.intersection = function (fields) { + if (fields) { + return intersection( + [ + 'id','token','data','type','user_id','ttl','issue_at','expire_at','status','created_at','updated_at', + ], + Object.keys(fields), + ); + } else return []; + }; + + + return Token; +}; diff --git a/models/user.js b/models/user.js new file mode 100644 index 0000000..3aea7a1 --- /dev/null +++ b/models/user.js @@ -0,0 +1,357 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * user Model + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const moment = require("moment"); +const bcrypt = require('bcryptjs'); +const { Op } = require("sequelize"); +const { intersection } = require('lodash'); +const coreModel = require('./../core/models'); + +module.exports = (sequelize, DataTypes) => { + const User = sequelize.define( + "user", + { + + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + role_id: DataTypes.INTEGER, + profile_id: DataTypes.INTEGER, + organization_id: DataTypes.INTEGER, + first_name: DataTypes.STRING, + last_name: DataTypes.STRING, + phone: DataTypes.STRING, + image: DataTypes.TEXT, + refer: DataTypes.STRING, + stripe_uid: DataTypes.STRING, + paypal_uid: DataTypes.STRING, + expire_at: DataTypes.DATEONLY, + status: DataTypes.INTEGER, +created_at: DataTypes.DATEONLY, + updated_at: DataTypes.DATE, + }, + { + timestamps: true, + freezeTableName: true, + tableName: "user", + }, + { + underscoredAll: false, + underscored: false, + } + ); + + coreModel.call(this, User); + + User._preCreateProcessing = function (data) { +if(!data.image) data.image = "/image/profile.png"; +if(!data.refer) data.refer = Math.round(Math.random() * 1000000000000,0); +if(!data.status) data.status = 1; +if(!data.verify) data.verify = 0; +if(!data.type) + { + data.type = 'n'; + } + return data; + }; + User._postCreateProcessing = function (data) { +if(data.password && data.password.length < 1) + { + delete data.password; + } +if(data.image && data.image.length < 1) + { + delete data.image; + } + + return data; + }; + User._customCountingConditions = function (data) { + + return data; + }; + + User._filterAllowKeys = function (data) { + let cleanData = {}; + let allowedFields = User.allowFields(); + allowedFields.push(User._primaryKey()); + + for (const key in data) { + if (allowedFields.includes(key)) { + cleanData[key] = data[key]; + } + } + return cleanData; + }; + + User.timeDefaultMapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0".i : i; + let min = j < 10 ? "0".j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + User.associate = function(models) { +User.belongsTo(models.role, { + foreignKey: "role_id", + as: "role", + constraints: false, + }) +User.hasOne(models.credential, { + foreignKey: "user_id", + as: "credential", + constraints: false, + }) +User.hasMany(models.refer_log, { + foreignKey: "user_id", + as: "refer_logs", + constraints: false, + }) +User.hasMany(models.member_operation, { + foreignKey: "user_id", + as: "member_operations", + constraints: false, + }) +User.hasMany(models.admin_operation, { + foreignKey: "user_id", + as: "admin_operations", + constraints: false, + }) +User.hasMany(models.token, { + foreignKey: "user_id", + as: "tokens", + constraints: false, + }) +User.hasMany(models.image, { + foreignKey: "user_id", + as: "images", + constraints: false, + }) }; + + + User.status_mapping = function (status) { + const mapping = {"0":"Inactive","1":"Active","2":"Suspend"} + + if (arguments.length === 0) return mapping; + else return mapping[status]; + }; + + + User.allowFields = function () { + return ["user_id","user_id","user_id","user_id","user_id","user_id",'id','role_id','profile_id','organization_id','first_name','last_name','phone','image','refer','stripe_uid','paypal_uid','expire_at','status',]; + }; + + User.labels = function () { + return ['ID','Role ID','Profile ID','Organization ID','First Name','Last Name','Phone #','Image','Refer Code','Stripe ID','PayPal ID','Expire At','Status',]; + }; + + User.validationRules = function () { + return [ + ['id', 'ID', ''], + ['role_id', 'Role ID', ''], + ['profile_id', 'Profile ID', ''], + ['organization_id', 'Organization ID', ''], + ['first_name', 'First Name', 'required'], + ['last_name', 'Last Name', 'required'], + ['phone', 'Phone #', ''], + ['image', 'Image', ''], + ['refer', 'Refer Code', ''], + ['stripe_uid', 'Stripe ID', ''], + ['paypal_uid', 'PayPal ID', ''], + ['expire_at', 'Expire At', ''], + ['status', 'Status', 'required'], + ]; + }; + + User.validationEditRules = function () { + return [ + ['id', 'ID', ''], + ['role_id', 'Role ID', ''], + ['profile_id', 'Profile ID', ''], + ['organization_id', 'Organization ID', ''], + ['first_name', 'First Name', ''], + ['last_name', 'Last Name', ''], + ['phone', 'Phone #', ''], + ['image', 'Image', ''], + ['refer', 'Refer Code', ''], + ['stripe_uid', 'Stripe ID', ''], + ['paypal_uid', 'PayPal ID', ''], + ['expire_at', 'Expire At', ''], + ['status', 'Status', ''], + ]; + }; + + + +User.get_role_paginated = function(db, where = {}, ...rest) { + return User.getPaginated(...rest, [{ + model: db.role, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "role", + }]) + } + +User.get_credential_paginated = function(db, where = {}, ...rest) { + return User.getPaginated(...rest, [{ + model: db.credential, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "credential", + }]) + } + +User.get_refer_log_paginated = function(db, where = {}, ...rest) { + return User.getPaginated(...rest, [{ + model: db.refer_log, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "refer_logs", + }]) + } + +User.get_member_operation_paginated = function(db, where = {}, ...rest) { + return User.getPaginated(...rest, [{ + model: db.member_operation, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "member_operations", + }]) + } + +User.get_admin_operation_paginated = function(db, where = {}, ...rest) { + return User.getPaginated(...rest, [{ + model: db.admin_operation, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "admin_operations", + }]) + } + +User.get_token_paginated = function(db, where = {}, ...rest) { + return User.getPaginated(...rest, [{ + model: db.token, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "tokens", + }]) + } + +User.get_image_paginated = function(db, where = {}, ...rest) { + return User.getPaginated(...rest, [{ + model: db.image, + where: where, + required: Object.keys(where).length > 0 ? true : false, + as: "images", + }]) + } + + + User.get_user_role = (id, db) => { + return User.findByPk(id, + { + include: [ + { + model: db.role, + required: false, + as: "role", + } + ] + }); + };User.get_user_credential = (id, db) => { + return User.findByPk(id, + { + include: [ + { + model: db.credential, + required: false, + as: "credential", + } + ] + }); + };User.get_user_refer_log = (id, db) => { + return User.findByPk(id, + { + include: [ + { + model: db.refer_log, + required: false, + as: "refer_logs", + } + ] + }); + };User.get_user_member_operation = (id, db) => { + return User.findByPk(id, + { + include: [ + { + model: db.member_operation, + required: false, + as: "member_operations", + } + ] + }); + };User.get_user_admin_operation = (id, db) => { + return User.findByPk(id, + { + include: [ + { + model: db.admin_operation, + required: false, + as: "admin_operations", + } + ] + }); + };User.get_user_token = (id, db) => { + return User.findByPk(id, + { + include: [ + { + model: db.token, + required: false, + as: "tokens", + } + ] + }); + };User.get_user_image = (id, db) => { + return User.findByPk(id, + { + include: [ + { + model: db.image, + required: false, + as: "images", + } + ] + }); + }; + + // ex + User.intersection = function (fields) { + if (fields) { + return intersection( + [ + 'id','role_id','profile_id','organization_id','first_name','last_name','phone','image','refer','stripe_uid','paypal_uid','expire_at','status','created_at','updated_at', + ], + Object.keys(fields), + ); + } else return []; + }; + + + return User; +}; diff --git a/name_centered.png b/name_centered.png new file mode 100644 index 0000000..db0f851 Binary files /dev/null and b/name_centered.png differ diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..dd1d3ba --- /dev/null +++ b/package-lock.json @@ -0,0 +1,20530 @@ +{ + "name": "node_code_builder", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "node_code_builder", + "version": "1.0.0", + "license": "Private", + "dependencies": { + "apollo-server-express": "^2.11.0", + "aws-sdk": "^2.860.0", + "aws-serverless-express": "^3.3.7", + "axios": "^0.19.2", + "bcryptjs": "^2.4.3", + "body-parser": "^1.19.0", + "bootstrap-select": "^1.13.18", + "browserify": "^17.0.0", + "child_process": "^1.0.2", + "claudia": "^5.12.0", + "connect-flash": "^0.1.1", + "cookie-parser": "~1.4.4", + "cors": "^2.8.5", + "dotenv": "^8.2.0", + "eta": "^1.12", + "express": "^4.17.1", + "express-ip": "^1.0.4", + "express-session": "^1.17.1", + "fast-csv": "^4.3.6", + "firebase-admin": "^8.12.1", + "fs-extra": "^9.1.0", + "graphql-fields": "^2.0.3", + "helmet": "^3.19.0", + "html-pdf-node": "^1.0.7", + "image-size": "^1.0.0", + "jju": "^1.4.0", + "json-2-csv": "^3.11.0", + "json-to-csv": "^1.0.0", + "jsonwebtoken": "^8.5.1", + "lodash": "^4.17.21", + "mime-types": "^2.1.29", + "minify": "^7.0.1", + "moment": "^2.26.0", + "morgan": "~1.9.1", + "multer": "^1.4.2", + "multer-s3": "^2.9.0", + "mysql2": "^2.1.0", + "nanoid": "^3.1.20", + "node-input-validator": "^4.3.2", + "nodemailer": "^6.4.11", + "package-merge": "^0.1.2", + "qrcode": "^1.5.0", + "quagga": "^0.12.1", + "querystring": "^0.2.0", + "sanitize-html": "^2.4.0", + "semver-set": "^0.1.2", + "sequelize": "^5.21.3", + "stripe": "^8.138.0", + "twilio": "^3.41.1", + "uppload": "^3.2.1", + "winston": "^3.3.3" + } + }, + "node_modules/@apollo/protobufjs": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.0.4.tgz", + "integrity": "sha512-EE3zx+/D/wur/JiLp6VCiw1iYdyy1lCJMf8CGPkLeDt5QJrN4N8tKFx33Ah4V30AUQzMk7Uz4IXKZ1LOj124gA==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.0", + "@types/node": "^10.1.0", + "long": "^4.0.0" + }, + "bin": { + "apollo-pbjs": "bin/pbjs", + "apollo-pbts": "bin/pbts" + } + }, + "node_modules/@apollo/protobufjs/node_modules/@types/node": { + "version": "10.17.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.26.tgz", + "integrity": "sha512-myMwkO2Cr82kirHY8uknNRHEVtn0wV3DTQfkrjx17jmkstDRZ24gNUdl8AHXVyVclTYI/bNjgTPTAWvWLqXqkw==" + }, + "node_modules/@apollographql/apollo-tools": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.4.8.tgz", + "integrity": "sha512-W2+HB8Y7ifowcf3YyPHgDI05izyRtOeZ4MqIr7LbTArtmJ0ZHULWpn84SGMW7NAvTV1tFExpHlveHhnXuJfuGA==", + "dependencies": { + "apollo-env": "^0.6.5" + }, + "engines": { + "node": ">=8", + "npm": ">=6" + } + }, + "node_modules/@apollographql/graphql-playground-html": { + "version": "1.6.26", + "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.26.tgz", + "integrity": "sha512-XAwXOIab51QyhBxnxySdK3nuMEUohhDsHQ5Rbco/V1vjlP75zZ0ZLHD9dTpXTN8uxKxopb2lUvJTq+M4g2Q0HQ==", + "dependencies": { + "xss": "^1.0.6" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", + "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "node_modules/@fast-csv/format": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@fast-csv/format/-/format-4.3.5.tgz", + "integrity": "sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==", + "dependencies": { + "@types/node": "^14.0.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.isboolean": "^3.0.3", + "lodash.isequal": "^4.5.0", + "lodash.isfunction": "^3.0.9", + "lodash.isnil": "^4.0.0" + } + }, + "node_modules/@fast-csv/parse": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/@fast-csv/parse/-/parse-4.3.6.tgz", + "integrity": "sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==", + "dependencies": { + "@types/node": "^14.0.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.groupby": "^4.6.0", + "lodash.isfunction": "^3.0.9", + "lodash.isnil": "^4.0.0", + "lodash.isundefined": "^3.0.1", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/@firebase/app-types": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.6.1.tgz", + "integrity": "sha512-L/ZnJRAq7F++utfuoTKX4CLBG5YR7tFO3PLzG1/oXXKEezJ0kRL3CMRoueBEmTCzVb/6SIs2Qlaw++uDgi5Xyg==" + }, + "node_modules/@firebase/auth-interop-types": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.5.tgz", + "integrity": "sha512-88h74TMQ6wXChPA6h9Q3E1Jg6TkTHep2+k63OWg3s0ozyGVMeY+TTOti7PFPzq5RhszQPQOoCi59es4MaRvgCw==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "0.x" + } + }, + "node_modules/@firebase/component": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.15.tgz", + "integrity": "sha512-HqFb1qQl1vtlUMIzPM15plNz27jqM8DWjuQQuGeDfG+4iRRflwKfgNw1BOyoP4kQ8vOBCL7t/71yPXSomNdJdQ==", + "dependencies": { + "@firebase/util": "0.2.50", + "tslib": "^1.11.1" + } + }, + "node_modules/@firebase/database": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.6.tgz", + "integrity": "sha512-TqUJOaCATF/h3wpqhPT9Fz1nZI6gBv/M2pHZztUjX4A9o9Bq93NyqUurYiZnGB7zpSkEADFCVT4f0VBrWdHlNw==", + "dependencies": { + "@firebase/auth-interop-types": "0.1.5", + "@firebase/component": "0.1.15", + "@firebase/database-types": "0.5.1", + "@firebase/logger": "0.2.5", + "@firebase/util": "0.2.50", + "faye-websocket": "0.11.3", + "tslib": "^1.11.1" + } + }, + "node_modules/@firebase/database-types": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.5.1.tgz", + "integrity": "sha512-onQxom1ZBYBJ648w/VNRzUewovEDAH7lvnrrpCd69ukkyrMk6rGEO/PQ9BcNEbhlNtukpsqRS0oNOFlHs0FaSA==", + "dependencies": { + "@firebase/app-types": "0.6.1" + } + }, + "node_modules/@firebase/logger": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.5.tgz", + "integrity": "sha512-qqw3m0tWs/qrg7axTZG/QZq24DIMdSY6dGoWuBn08ddq7+GLF5HiqkRj71XznYeUUbfRq5W9C/PSFnN4JxX+WA==" + }, + "node_modules/@firebase/util": { + "version": "0.2.50", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.50.tgz", + "integrity": "sha512-vFE6+Jfc25u0ViSpFxxq0q5s+XmuJ/y7CL3ud79RQe+WLFFg+j0eH1t23k0yNSG9vZNM7h3uHRIXbV97sYLAyw==", + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@google-cloud/common": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-2.4.0.tgz", + "integrity": "sha512-zWFjBS35eI9leAHhjfeOYlK5Plcuj/77EzstnrJIZbKgF/nkqjcQuGiMCpzCwOfPyUbz8ZaEOYgbHa759AKbjg==", + "optional": true, + "dependencies": { + "@google-cloud/projectify": "^1.0.0", + "@google-cloud/promisify": "^1.0.0", + "arrify": "^2.0.0", + "duplexify": "^3.6.0", + "ent": "^2.2.0", + "extend": "^3.0.2", + "google-auth-library": "^5.5.0", + "retry-request": "^4.0.0", + "teeny-request": "^6.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/@google-cloud/common/node_modules/gcp-metadata": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-3.5.0.tgz", + "integrity": "sha512-ZQf+DLZ5aKcRpLzYUyBS3yo3N0JSa82lNDO8rj3nMSlovLcz2riKFBsYgDzeXcv75oo5eqB2lx+B14UvPoCRnA==", + "optional": true, + "dependencies": { + "gaxios": "^2.1.0", + "json-bigint": "^0.3.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/@google-cloud/common/node_modules/google-auth-library": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-5.10.1.tgz", + "integrity": "sha512-rOlaok5vlpV9rSiUu5EpR0vVpc+PhN62oF4RyX/6++DG1VsaulAFEMlDYBLjJDDPI6OcNOCGAKy9UVB/3NIDXg==", + "optional": true, + "dependencies": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^2.1.0", + "gcp-metadata": "^3.4.0", + "gtoken": "^4.1.0", + "jws": "^4.0.0", + "lru-cache": "^5.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/@google-cloud/common/node_modules/google-p12-pem": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.4.tgz", + "integrity": "sha512-S4blHBQWZRnEW44OcR7TL9WR+QCqByRvhNDZ/uuQfpxywfupikf/miba8js1jZi6ZOGv5slgSuoshCWh6EMDzg==", + "optional": true, + "dependencies": { + "node-forge": "^0.9.0" + }, + "bin": { + "gp12-pem": "build/src/bin/gp12-pem.js" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/@google-cloud/common/node_modules/gtoken": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.4.tgz", + "integrity": "sha512-VxirzD0SWoFUo5p8RDP8Jt2AGyOmyYcT/pOUgDKJCK+iSw0TMqwrVfY37RXTNmoKwrzmDHSk0GMT9FsgVmnVSA==", + "optional": true, + "dependencies": { + "gaxios": "^2.1.0", + "google-p12-pem": "^2.0.0", + "jws": "^4.0.0", + "mime": "^2.2.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/@google-cloud/common/node_modules/json-bigint": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.1.tgz", + "integrity": "sha512-DGWnSzmusIreWlEupsUelHrhwmPPE+FiQvg+drKfk2p+bdEYa5mp4PJ8JsCWqae0M2jQNb0HPvnwvf1qOTThzQ==", + "optional": true, + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/@google-cloud/common/node_modules/mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@google-cloud/common/node_modules/node-forge": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.2.tgz", + "integrity": "sha512-naKSScof4Wn+aoHU6HBsifh92Zeicm1GDQKd1vp3Y/kOi8ub0DozCa9KpvYNCXslFHYRmLNiqRopGdTGwNLpNw==", + "optional": true, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/@google-cloud/firestore": { + "version": "3.8.6", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-3.8.6.tgz", + "integrity": "sha512-ox80NbrM1MLJgvAAUd1quFLx/ie/nSjrk1PtscSicpoYDlKb9e6j7pHrVpbopBMyliyfNl3tLJWaDh+x+uCXqw==", + "optional": true, + "dependencies": { + "deep-equal": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^1.15.3", + "readable-stream": "^3.4.0", + "through2": "^3.0.0" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@google-cloud/paginator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-2.0.3.tgz", + "integrity": "sha512-kp/pkb2p/p0d8/SKUu4mOq8+HGwF8NPzHWkj+VKrIPQPyMRw8deZtrO/OcSiy9C/7bpfU5Txah5ltUNfPkgEXg==", + "optional": true, + "dependencies": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/@google-cloud/projectify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-1.0.4.tgz", + "integrity": "sha512-ZdzQUN02eRsmTKfBj9FDL0KNDIFNjBn/d6tHQmA/+FImH5DO6ZV8E7FzxMgAUiVAUq41RFAkb25p1oHOZ8psfg==", + "optional": true, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/@google-cloud/promisify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-1.0.4.tgz", + "integrity": "sha512-VccZDcOql77obTnFh0TbNED/6ZbbmHDf8UMNnzO1d5g9V0Htfm4k5cllY8P1tJsRKC3zWYGRLaViiupcgVjBoQ==", + "optional": true, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/@google-cloud/storage": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-4.7.0.tgz", + "integrity": "sha512-f0guAlbeg7Z0m3gKjCfBCu7FG9qS3M3oL5OQQxlvGoPtK7/qg3+W+KQV73O2/sbuS54n0Kh2mvT5K2FWzF5vVQ==", + "optional": true, + "dependencies": { + "@google-cloud/common": "^2.1.1", + "@google-cloud/paginator": "^2.0.0", + "@google-cloud/promisify": "^1.0.0", + "arrify": "^2.0.0", + "compressible": "^2.0.12", + "concat-stream": "^2.0.0", + "date-and-time": "^0.13.0", + "duplexify": "^3.5.0", + "extend": "^3.0.2", + "gaxios": "^3.0.0", + "gcs-resumable-upload": "^2.2.4", + "hash-stream-validation": "^0.2.2", + "mime": "^2.2.0", + "mime-types": "^2.0.8", + "onetime": "^5.1.0", + "p-limit": "^2.2.0", + "pumpify": "^2.0.0", + "readable-stream": "^3.4.0", + "snakeize": "^0.1.0", + "stream-events": "^1.0.1", + "through2": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/@google-cloud/storage/node_modules/gaxios": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-3.0.3.tgz", + "integrity": "sha512-PkzQludeIFhd535/yucALT/Wxyj/y2zLyrMwPcJmnLHDugmV49NvAi/vb+VUq/eWztATZCNcb8ue+ywPG+oLuw==", + "optional": true, + "dependencies": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.3.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@google-cloud/storage/node_modules/mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.0.5.tgz", + "integrity": "sha512-Hm+xOiqAhcpT9RYM8lc15dbQD7aQurM7ZU8ulmulepiPlN7iwBXXwP3vSBUimoFoApRqz7pSIisXU8pZaCB4og==", + "optional": true, + "dependencies": { + "semver": "^6.2.0" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + }, + "peerDependencies": { + "google-auth-library": "5.x || 6.x" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.4.tgz", + "integrity": "sha512-HTM4QpI9B2XFkPz7pjwMyMgZchJ93TVkL3kWPW8GDMDKYxsMnmf4w2TNMJK7+KNiYHS5cJrCEAFlF+AwtXWVPA==", + "optional": true, + "dependencies": { + "lodash.camelcase": "^4.3.0", + "protobufjs": "^6.8.6" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, + "node_modules/@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@tokenizer/token": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz", + "integrity": "sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w==" + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", + "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-P1bffQfhD3O4LW0ioENXUhZ9OIa0Zn+P7M+pWgkCKaT53wVLSq0mrKksCID/FGHpFhRSxRGhgrQmfhRuzwtKdg==" + }, + "node_modules/@types/cookies": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.4.tgz", + "integrity": "sha512-oTGtMzZZAVuEjTwCjIh8T8FrC8n/uwy+PG0yTvQcdZ7etoel7C7/3MSd7qrukENTgQtotG7gvBlBojuVs7X5rw==", + "dependencies": { + "@types/connect": "*", + "@types/express": "*", + "@types/keygrip": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-invOmosX0DqbpA+cE2yoHGUlF/blyf7nB0OGYBBiH27crcVm5NmFaZkLP4Ta1hGaesckCi5lVLlydNJCxkTOSg==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz", + "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==" + }, + "node_modules/@types/express": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.4.tgz", + "integrity": "sha512-DO1L53rGqIDUEvOjJKmbMEQ5Z+BM2cIEPy/eV3En+s166Gz+FeuzRerxcab757u/U4v4XF4RYrZPmqKa+aY/2w==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "*", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.8.tgz", + "integrity": "sha512-1SJZ+R3Q/7mLkOD9ewCBDYD2k0WyZQtWYqF/2VvoNN2/uhI49J9CDN4OAm+wGMA0DbArA4ef27xl4+JwMtGggw==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/fs-capacitor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz", + "integrity": "sha512-FKVPOCFbhCvZxpVAMhdBdTfVfXUpsh15wFHgqOKxh9N9vzWZVuWCSijZ5T4U34XYNnuj2oduh6xcs1i+LPI+BQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.1.tgz", + "integrity": "sha512-TcUlBem321DFQzBNuz8p0CLLKp0VvF/XH9E4KHNmgwyp4E3AfgI5cjiIVZWlbfThBop2qxFIh4+LeY6hVWWZ2w==", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/graphql-upload": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@types/graphql-upload/-/graphql-upload-8.0.3.tgz", + "integrity": "sha512-hmLg9pCU/GmxBscg8GCr1vmSoEmbItNNxdD5YH2TJkXm//8atjwuprB+xJBK714JG1dkxbbhp5RHX+Pz1KsCMA==", + "dependencies": { + "@types/express": "*", + "@types/fs-capacitor": "*", + "@types/koa": "*", + "graphql": "^14.5.3" + } + }, + "node_modules/@types/http-assert": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz", + "integrity": "sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ==" + }, + "node_modules/@types/keygrip": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", + "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==" + }, + "node_modules/@types/koa": { + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.11.3.tgz", + "integrity": "sha512-ABxVkrNWa4O/Jp24EYI/hRNqEVRlhB9g09p48neQp4m3xL1TJtdWk2NyNQSMCU45ejeELMQZBYyfstyVvO2H3Q==", + "dependencies": { + "@types/accepts": "*", + "@types/content-disposition": "*", + "@types/cookies": "*", + "@types/http-assert": "*", + "@types/keygrip": "*", + "@types/koa-compose": "*", + "@types/node": "*" + } + }, + "node_modules/@types/koa-compose": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", + "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", + "dependencies": { + "@types/koa": "*" + } + }, + "node_modules/@types/long": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", + "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + }, + "node_modules/@types/mime": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.2.tgz", + "integrity": "sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q==" + }, + "node_modules/@types/node": { + "version": "14.0.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.14.tgz", + "integrity": "sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ==" + }, + "node_modules/@types/node-fetch": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", + "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "node_modules/@types/qs": { + "version": "6.9.3", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz", + "integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" + }, + "node_modules/@types/readable-stream": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.9.tgz", + "integrity": "sha512-sqsgQqFT7HmQz/V5jH1O0fvQQnXAJO46Gg9LRO/JPfjmVmGUlcx831TZZO3Y3HtWhIkzf3kTsNT0Z0kzIhIvZw==", + "dependencies": { + "@types/node": "*", + "safe-buffer": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.4.tgz", + "integrity": "sha512-jTDt0o/YbpNwZbQmE/+2e+lfjJEJJR0I3OFaKQKPWkASkCoW3i6fsUnqudSMcNAfbtmADGu8f4MV4q+GqULmug==", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/mime": "*" + } + }, + "node_modules/@types/ws": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.2.6.tgz", + "integrity": "sha512-Q07IrQUSNpr+cXU4E4LtkSIBPie5GLZyyMC1QtQYRLWz701+XcoVygGUZgvLqElq1nU4ICldMYPnexlBsg3dqQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yauzl": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz", + "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@wry/equality": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.1.11.tgz", + "integrity": "sha512-mwEVBDUVODlsQQ5dfuLUS5/Tf7jqUKyhKYHmVi4fPB6bDMOfWvUPJmKgS1Z7Za/sOI3vzWt4+O7yCiL/70MogA==", + "dependencies": { + "tslib": "^1.9.3" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "optional": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz", + "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "optional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansi-styles/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ansi-styles/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "node_modules/apollo-cache-control": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.11.1.tgz", + "integrity": "sha512-6iHa8TkcKt4rx5SKRzDNjUIpCQX+7/FlZwD7vRh9JDnM4VH8SWhpj8fUR3CiEY8Kuc4ChXnOY8bCcMju5KPnIQ==", + "deprecated": "The functionality provided by the `apollo-cache-control` package is built in to `apollo-server-core` starting with Apollo Server 3. See https://www.apollographql.com/docs/apollo-server/migration/#cachecontrol for details.", + "dependencies": { + "apollo-server-env": "^2.4.5", + "apollo-server-plugin-base": "^0.9.1" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependencies": { + "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" + } + }, + "node_modules/apollo-datasource": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.7.2.tgz", + "integrity": "sha512-ibnW+s4BMp4K2AgzLEtvzkjg7dJgCaw9M5b5N0YKNmeRZRnl/I/qBTQae648FsRKgMwTbRQIvBhQ0URUFAqFOw==", + "dependencies": { + "apollo-server-caching": "^0.5.2", + "apollo-server-env": "^2.4.5" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/apollo-engine-reporting": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/apollo-engine-reporting/-/apollo-engine-reporting-2.2.1.tgz", + "integrity": "sha512-HPwf70p4VbxKEagHYWTwldqfYNekBE33BXcryHI9owxMm5B8/vutQfx67+4Bf351kOpndCG9I91aOiFBfC2/iQ==", + "dependencies": { + "apollo-engine-reporting-protobuf": "^0.5.2", + "apollo-graphql": "^0.4.0", + "apollo-server-caching": "^0.5.2", + "apollo-server-env": "^2.4.5", + "apollo-server-errors": "^2.4.2", + "apollo-server-plugin-base": "^0.9.1", + "apollo-server-types": "^0.5.1", + "async-retry": "^1.2.1", + "uuid": "^8.0.0" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependencies": { + "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" + } + }, + "node_modules/apollo-engine-reporting-protobuf": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.5.2.tgz", + "integrity": "sha512-4wm9FR3B7UvJxcK/69rOiS5CAJPEYKufeRWb257ZLfX7NGFTMqvbc1hu4q8Ch7swB26rTpkzfsftLED9DqH9qg==", + "dependencies": { + "@apollo/protobufjs": "^1.0.3" + } + }, + "node_modules/apollo-env": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/apollo-env/-/apollo-env-0.6.5.tgz", + "integrity": "sha512-jeBUVsGymeTHYWp3me0R2CZRZrFeuSZeICZHCeRflHTfnQtlmbSXdy5E0pOyRM9CU4JfQkKDC98S1YglQj7Bzg==", + "dependencies": { + "@types/node-fetch": "2.5.7", + "core-js": "^3.0.1", + "node-fetch": "^2.2.0", + "sha.js": "^2.4.11" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/apollo-graphql": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.4.5.tgz", + "integrity": "sha512-0qa7UOoq7E71kBYE7idi6mNQhHLVdMEDInWk6TNw3KsSWZE2/I68gARP84Mj+paFTO5NYuw1Dht66PVX76Cc2w==", + "dependencies": { + "apollo-env": "^0.6.5", + "lodash.sortby": "^4.7.0" + }, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "graphql": "^14.2.1" + } + }, + "node_modules/apollo-link": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.14.tgz", + "integrity": "sha512-p67CMEFP7kOG1JZ0ZkYZwRDa369w5PIjtMjvrQd/HnIV8FRsHRqLqK+oAZQnFa1DDdZtOtHTi+aMIW6EatC2jg==", + "dependencies": { + "apollo-utilities": "^1.3.0", + "ts-invariant": "^0.4.0", + "tslib": "^1.9.3", + "zen-observable-ts": "^0.8.21" + }, + "peerDependencies": { + "graphql": "^0.11.3 || ^0.12.3 || ^0.13.0 || ^14.0.0 || ^15.0.0" + } + }, + "node_modules/apollo-server-caching": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.2.tgz", + "integrity": "sha512-HUcP3TlgRsuGgeTOn8QMbkdx0hLPXyEJehZIPrcof0ATz7j7aTPA4at7gaiFHCo8gk07DaWYGB3PFgjboXRcWQ==", + "dependencies": { + "lru-cache": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/apollo-server-core": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.15.1.tgz", + "integrity": "sha512-ZRSK3uVPS6YkIV3brm2CjzVphg6NHY0PRhFojZD8BjoQlGo3+pPRP1IHFDvC3UzybGWfyCelcfF4YiVqh4GJHw==", + "dependencies": { + "@apollographql/apollo-tools": "^0.4.3", + "@apollographql/graphql-playground-html": "1.6.26", + "@types/graphql-upload": "^8.0.0", + "@types/ws": "^7.0.0", + "apollo-cache-control": "^0.11.1", + "apollo-datasource": "^0.7.2", + "apollo-engine-reporting": "^2.2.1", + "apollo-server-caching": "^0.5.2", + "apollo-server-env": "^2.4.5", + "apollo-server-errors": "^2.4.2", + "apollo-server-plugin-base": "^0.9.1", + "apollo-server-types": "^0.5.1", + "apollo-tracing": "^0.11.1", + "fast-json-stable-stringify": "^2.0.0", + "graphql-extensions": "^0.12.4", + "graphql-tag": "^2.9.2", + "graphql-tools": "^4.0.0", + "graphql-upload": "^8.0.2", + "loglevel": "^1.6.7", + "sha.js": "^2.4.11", + "subscriptions-transport-ws": "^0.9.11", + "ws": "^6.0.0" + }, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" + } + }, + "node_modules/apollo-server-env": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.5.tgz", + "integrity": "sha512-nfNhmGPzbq3xCEWT8eRpoHXIPNcNy3QcEoBlzVMjeglrBGryLG2LXwBSPnVmTRRrzUYugX0ULBtgE3rBFNoUgA==", + "dependencies": { + "node-fetch": "^2.1.2", + "util.promisify": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/apollo-server-errors": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.4.2.tgz", + "integrity": "sha512-FeGxW3Batn6sUtX3OVVUm7o56EgjxDlmgpTLNyWcLb0j6P8mw9oLNyAm3B+deHA4KNdNHO5BmHS2g1SJYjqPCQ==", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" + } + }, + "node_modules/apollo-server-express": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.15.1.tgz", + "integrity": "sha512-anNb9HJo+KTpgvUqiPOjEl4wPq8y8NmWaIUz/QqPZlhIEDdf7wd/kQo3Sdbov++7J9JNJx6Ownnvw+wxfogUgA==", + "dependencies": { + "@apollographql/graphql-playground-html": "1.6.26", + "@types/accepts": "^1.3.5", + "@types/body-parser": "1.19.0", + "@types/cors": "^2.8.4", + "@types/express": "4.17.4", + "accepts": "^1.3.5", + "apollo-server-core": "^2.15.1", + "apollo-server-types": "^0.5.1", + "body-parser": "^1.18.3", + "cors": "^2.8.4", + "express": "^4.17.1", + "graphql-subscriptions": "^1.0.0", + "graphql-tools": "^4.0.0", + "parseurl": "^1.3.2", + "subscriptions-transport-ws": "^0.9.16", + "type-is": "^1.6.16" + }, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" + } + }, + "node_modules/apollo-server-plugin-base": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.9.1.tgz", + "integrity": "sha512-kvrX4Z3FdpjrZdHkyl5iY2A1Wvp4b6KQp00DeZqss7GyyKNUBKr80/7RQgBLEw7EWM7WB19j459xM/TjvW0FKQ==", + "dependencies": { + "apollo-server-types": "^0.5.1" + }, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" + } + }, + "node_modules/apollo-server-types": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.5.1.tgz", + "integrity": "sha512-my2cPw+DAb2qVnIuBcsRKGyS28uIc2vjFxa1NpRoJZe9gK0BWUBk7wzXnIzWy3HZ5Er11e/40MPTUesNfMYNVA==", + "dependencies": { + "apollo-engine-reporting-protobuf": "^0.5.2", + "apollo-server-caching": "^0.5.2", + "apollo-server-env": "^2.4.5" + }, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" + } + }, + "node_modules/apollo-tracing": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.11.1.tgz", + "integrity": "sha512-l7g+uILw7v32GA46IRXIx5XXbZhFI96BhSqrGK9yyvfq+NMcvVZrj3kIhRImPGhAjMdV+5biA/jztabElAbDjg==", + "deprecated": "The `apollo-tracing` package is no longer part of Apollo Server 3. See https://www.apollographql.com/docs/apollo-server/migration/#tracing for details", + "dependencies": { + "apollo-server-env": "^2.4.5", + "apollo-server-plugin-base": "^0.9.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" + } + }, + "node_modules/apollo-utilities": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.3.4.tgz", + "integrity": "sha512-pk2hiWrCXMAy2fRPwEyhvka+mqwzeP60Jr1tRYi5xru+3ko94HI9o6lK0CT33/w4RDlxWchmdhDCrvdr+pHCig==", + "dependencies": { + "@wry/equality": "^0.1.2", + "fast-json-stable-stringify": "^2.0.0", + "ts-invariant": "^0.4.0", + "tslib": "^1.10.0" + }, + "peerDependencies": { + "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, + "node_modules/archive-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", + "integrity": "sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA=", + "dependencies": { + "file-type": "^4.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/archive-type/node_modules/file-type": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", + "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=", + "engines": { + "node": ">=4" + } + }, + "node_modules/array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dependencies": { + "object-assign": "^4.1.1", + "util": "0.10.3" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assert/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "node_modules/assert/node_modules/util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dependencies": { + "inherits": "2.0.1" + } + }, + "node_modules/async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "node_modules/async-retry": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.1.tgz", + "integrity": "sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA==", + "dependencies": { + "retry": "0.12.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz", + "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==", + "dependencies": { + "array-filter": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sdk": { + "version": "2.860.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.860.0.tgz", + "integrity": "sha512-BUBWw28PNDhRDnPEnXiPEvgTWD8Iyq5pl9lk/WhXC/vkACJ3aUVe+sicezI1/JQRjLrO3R6w7X20YknVWfAibA==", + "dependencies": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/aws-sdk/node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/aws-sdk/node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/aws-sdk/node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/aws-sdk/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/aws-sdk/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "node_modules/aws-sdk/node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/aws-sdk/node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/aws-serverless-express": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/aws-serverless-express/-/aws-serverless-express-3.3.8.tgz", + "integrity": "sha512-2TQdF5EhxnAtGeEi+wSi2M3xCfpiemuImnpU7HKih3onH0izJ/G2tkM+gwcGHZEsW/gLWFl/JjQAYGa3fILfvw==", + "dependencies": { + "binary-case": "^1.0.0", + "type-is": "^1.6.16" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, + "node_modules/axios": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", + "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "deprecated": "Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410", + "dependencies": { + "follow-redirects": "1.5.10" + } + }, + "node_modules/backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/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==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/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==" + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + }, + "node_modules/bignumber.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/binary-case/-/binary-case-1.1.4.tgz", + "integrity": "sha512-9Kq8m6NZTAgy05Ryuh7U3Qc4/ujLQU1AZ5vMw4cr3igTdi5itZC6kCNrRr2X8NzPiDn2oUIFTfa71DKMnue/Zg==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "node_modules/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dependencies": { + "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" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/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==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/body-parser/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/body-parser/node_modules/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==", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/bootstrap-select": { + "version": "1.13.18", + "resolved": "https://registry.npmjs.org/bootstrap-select/-/bootstrap-select-1.13.18.tgz", + "integrity": "sha512-V1IzK4rxBq5FrJtkzSH6RmFLFBsjx50byFbfAf8jYyXROWs7ZpprGjdHeoyq2HSsHyjJhMMwjsQhRoYAfxCGow==", + "peerDependencies": { + "bootstrap": ">=3.0.0", + "jquery": "1.9.1 - 3" + } + }, + "node_modules/bowser": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.9.0.tgz", + "integrity": "sha512-2ld76tuLBNFekRgmJfT2+3j5MIrP6bFict8WAIT3beq+srz1gcKNAdNKMqHqauQt63NmAa88HfP1/Ypa9Er3HA==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "node_modules/browser-pack": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", + "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", + "dependencies": { + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "JSONStream": "^1.0.3", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + }, + "bin": { + "browser-pack": "bin/cmd.js" + } + }, + "node_modules/browser-pack/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/browser-pack/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/browser-pack/node_modules/readable-stream/node_modules/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==" + }, + "node_modules/browser-pack/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "dependencies": { + "resolve": "^1.17.0" + } + }, + "node_modules/browserify": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz", + "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==", + "dependencies": { + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^2.0.0", + "browserify-zlib": "~0.2.0", + "buffer": "~5.2.1", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.1", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^3.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.2.1", + "JSONStream": "^1.0.3", + "labeled-stream-splicer": "^2.0.0", + "mkdirp-classic": "^0.5.2", + "module-deps": "^6.2.3", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "^1.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum-object": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^3.0.0", + "stream-http": "^3.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.12.0", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + }, + "bin": { + "browserify": "bin/cmd.js" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/browserify/node_modules/buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/browserify/node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/browserify/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/browserify/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/browserify/node_modules/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==" + }, + "node_modules/browserify/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "engines": { + "node": "*" + } + }, + "node_modules/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=" + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "node_modules/busboy": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz", + "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==", + "dependencies": { + "dicer": "0.3.0" + }, + "engines": { + "node": ">=4.5.0" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "dependencies": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "engines": { + "node": ">=4" + } + }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cached-path-relative": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", + "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==" + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camel-case/node_modules/tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", + "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + }, + "node_modules/cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", + "dependencies": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + }, + "bin": { + "cdl": "bin/cdl.js" + } + }, + "node_modules/cartesian-product": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cartesian-product/-/cartesian-product-2.1.2.tgz", + "integrity": "sha1-yahGLFSrGaDF/TIZKSLiOatMpP0=" + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "node_modules/child_process": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz", + "integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o=" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/claudia": { + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/claudia/-/claudia-5.12.0.tgz", + "integrity": "sha512-ukgOGUNeIaU23xQB5r41AqGPAcq8bBd5LGz4Q880aRgGSW6VGHVMD/srsZcWM6mP4XKSmaofHzmJfoIXSmlJFg==", + "hasShrinkwrap": true, + "dependencies": { + "archiver": "^3.0.0", + "aws-sdk": "^2.599.0", + "fs-extra": "^6.0.1", + "glob": "^7.1.2", + "gunzip-maybe": "^1.4.0", + "https-proxy-agent": "^3.0.0", + "minimal-request-promise": "^1.1.0", + "minimist": "^1.2.0", + "oh-no-i-insist": "^1.1.1", + "sequential-promise-map": "^1.0.0", + "tar-fs": "^1.14.0", + "uuid": "^2.0.1", + "which": "^1.3.1" + }, + "bin": { + "claudia": "bin/cmd.js" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/claudia/node_modules/@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "extraneous": true, + "dependencies": { + "@babel/highlight": "^7.0.0" + } + }, + "node_modules/claudia/node_modules/@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "extraneous": true, + "dependencies": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "node_modules/claudia/node_modules/acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "extraneous": true + }, + "node_modules/claudia/node_modules/acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "extraneous": true + }, + "node_modules/claudia/node_modules/agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dependencies": { + "es6-promisify": "^5.0.0" + } + }, + "node_modules/claudia/node_modules/ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "extraneous": true, + "dependencies": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/claudia/node_modules/ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "extraneous": true + }, + "node_modules/claudia/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "extraneous": true + }, + "node_modules/claudia/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "extraneous": true, + "dependencies": { + "color-convert": "^1.9.0" + } + }, + "node_modules/claudia/node_modules/archiver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-3.0.0.tgz", + "integrity": "sha512-5QeR6Xc5hSA9X1rbQfcuQ6VZuUXOaEdB65Dhmk9duuRJHYif/ZyJfuyJqsQrj34PFjU5emv5/MmfgA8un06onw==", + "dependencies": { + "archiver-utils": "^2.0.0", + "async": "^2.0.0", + "buffer-crc32": "^0.2.1", + "glob": "^7.0.0", + "readable-stream": "^2.0.0", + "tar-stream": "^1.5.0", + "zip-stream": "^2.0.1" + } + }, + "node_modules/claudia/node_modules/archiver-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.0.0.tgz", + "integrity": "sha512-JRBgcVvDX4Mwu2RBF8bBaHcQCSxab7afsxAPYDQ5W+19quIPP5CfKE7Ql+UHs9wYvwsaNR8oDuhtf5iqrKmzww==", + "dependencies": { + "glob": "^7.0.0", + "graceful-fs": "^4.1.0", + "lazystream": "^1.0.0", + "lodash.assign": "^4.2.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.toarray": "^4.4.0", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + } + }, + "node_modules/claudia/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "extraneous": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/claudia/node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "extraneous": true + }, + "node_modules/claudia/node_modules/async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dependencies": { + "lodash": "^4.17.11" + } + }, + "node_modules/claudia/node_modules/aws-sdk": { + "version": "2.599.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.599.0.tgz", + "integrity": "sha512-7yTXnV5SC9W6m+STbziPd1ZNVh9fTtEZ7Mm0rMqEDm/B2fJBa5xd45TwWG8JvS40X5+9jUBykiWdCuVBBx82rg==", + "dependencies": { + "buffer": "4.9.1", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + } + }, + "node_modules/claudia/node_modules/aws-sdk/node_modules/buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/claudia/node_modules/aws-sdk/node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/claudia/node_modules/aws-sdk/node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "node_modules/claudia/node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "node_modules/claudia/node_modules/base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha1-yrHmEY8FEJXli1KBrqjBzSK/wOM=" + }, + "node_modules/claudia/node_modules/bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha1-oWCRFxcQPAdBDO9j71Gzl8Alr5w=", + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/claudia/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/claudia/node_modules/browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dependencies": { + "pako": "~0.2.0" + } + }, + "node_modules/claudia/node_modules/buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/claudia/node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha1-iQ3ZDZI6hz4I4Q5f1RpX5bfM4Ow=", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/claudia/node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha1-vX3CauKXLQ7aJTvgYdupkjScGfA=" + }, + "node_modules/claudia/node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "node_modules/claudia/node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "node_modules/claudia/node_modules/buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha1-h/yqOimDWOCt5uRCz86EB0DRrQQ=" + }, + "node_modules/claudia/node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "extraneous": true + }, + "node_modules/claudia/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "extraneous": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "node_modules/claudia/node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "extraneous": true + }, + "node_modules/claudia/node_modules/chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "node_modules/claudia/node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "extraneous": true, + "dependencies": { + "restore-cursor": "^2.0.0" + } + }, + "node_modules/claudia/node_modules/cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "extraneous": true + }, + "node_modules/claudia/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "extraneous": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/claudia/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "extraneous": true + }, + "node_modules/claudia/node_modules/colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "extraneous": true + }, + "node_modules/claudia/node_modules/commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "extraneous": true, + "dependencies": { + "graceful-readlink": ">= 1.0.0" + } + }, + "node_modules/claudia/node_modules/compress-commons": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", + "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", + "dependencies": { + "buffer-crc32": "^0.2.1", + "crc32-stream": "^2.0.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + } + }, + "node_modules/claudia/node_modules/compress-commons/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dependencies": { + "remove-trailing-separator": "^1.0.1" + } + }, + "node_modules/claudia/node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/claudia/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/claudia/node_modules/crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dependencies": { + "buffer": "^5.1.0" + } + }, + "node_modules/claudia/node_modules/crc32-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", + "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", + "dependencies": { + "crc": "^3.4.4", + "readable-stream": "^2.0.0" + } + }, + "node_modules/claudia/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "extraneous": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/claudia/node_modules/cross-spawn/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "extraneous": true + }, + "node_modules/claudia/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/claudia/node_modules/decompress": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz", + "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", + "extraneous": true, + "dependencies": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + } + }, + "node_modules/claudia/node_modules/decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "extraneous": true, + "dependencies": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + } + }, + "node_modules/claudia/node_modules/decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "extraneous": true, + "dependencies": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + } + }, + "node_modules/claudia/node_modules/decompress-tarbz2/node_modules/file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", + "extraneous": true + }, + "node_modules/claudia/node_modules/decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "extraneous": true, + "dependencies": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + } + }, + "node_modules/claudia/node_modules/decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "extraneous": true, + "dependencies": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + } + }, + "node_modules/claudia/node_modules/decompress-unzip/node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "extraneous": true + }, + "node_modules/claudia/node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "extraneous": true + }, + "node_modules/claudia/node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "extraneous": true, + "dependencies": { + "esutils": "^2.0.2" + } + }, + "node_modules/claudia/node_modules/dotenv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-2.0.0.tgz", + "integrity": "sha1-vXWcNXqqcDZeAclrewvsCKbg2Uk=", + "extraneous": true + }, + "node_modules/claudia/node_modules/duplexify": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", + "integrity": "sha1-WSkD9dgLONA3IgVBJk1poZj7NBA=", + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/claudia/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "extraneous": true + }, + "node_modules/claudia/node_modules/end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/claudia/node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "node_modules/claudia/node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dependencies": { + "es6-promise": "^4.0.3" + } + }, + "node_modules/claudia/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "extraneous": true + }, + "node_modules/claudia/node_modules/eslint": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.5.1.tgz", + "integrity": "sha512-32h99BoLYStT1iq1v2P9uwpyznQ4M2jRiFB6acitKz52Gqn+vPaMDUTB1bYi1WN4Nquj2w+t+bimYUG83DC55A==", + "extraneous": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.2", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.4.1", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + } + }, + "node_modules/claudia/node_modules/eslint-config-crockford": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-crockford/-/eslint-config-crockford-0.2.0.tgz", + "integrity": "sha1-5tpfbqfH4HzOdnGeeNo/OHxnqlU=", + "extraneous": true + }, + "node_modules/claudia/node_modules/eslint-config-defaults": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-defaults/-/eslint-config-defaults-9.0.0.tgz", + "integrity": "sha1-oJCtwTspNeP0OzzQSKknAWVOWtU=", + "extraneous": true + }, + "node_modules/claudia/node_modules/eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "extraneous": true, + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "node_modules/claudia/node_modules/eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "extraneous": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "node_modules/claudia/node_modules/eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "extraneous": true + }, + "node_modules/claudia/node_modules/eslint/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "extraneous": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/claudia/node_modules/espree": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "extraneous": true, + "dependencies": { + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "node_modules/claudia/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "extraneous": true + }, + "node_modules/claudia/node_modules/esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "extraneous": true, + "dependencies": { + "estraverse": "^4.0.0" + } + }, + "node_modules/claudia/node_modules/esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "extraneous": true, + "dependencies": { + "estraverse": "^4.1.0" + } + }, + "node_modules/claudia/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "extraneous": true + }, + "node_modules/claudia/node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "extraneous": true + }, + "node_modules/claudia/node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "node_modules/claudia/node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "extraneous": true + }, + "node_modules/claudia/node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "extraneous": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "node_modules/claudia/node_modules/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=", + "extraneous": true + }, + "node_modules/claudia/node_modules/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=", + "extraneous": true + }, + "node_modules/claudia/node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "extraneous": true + }, + "node_modules/claudia/node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "extraneous": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/claudia/node_modules/figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "extraneous": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + } + }, + "node_modules/claudia/node_modules/file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "extraneous": true, + "dependencies": { + "flat-cache": "^2.0.1" + } + }, + "node_modules/claudia/node_modules/file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", + "extraneous": true + }, + "node_modules/claudia/node_modules/flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "extraneous": true, + "dependencies": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "node_modules/claudia/node_modules/flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "extraneous": true + }, + "node_modules/claudia/node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha1-a+Dem+mYzhavivwkSXue6bfM2a0=" + }, + "node_modules/claudia/node_modules/fs-extra": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", + "integrity": "sha1-irwSj3lG4xATXdyTuYvdtBDno0s=", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/claudia/node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/claudia/node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "extraneous": true + }, + "node_modules/claudia/node_modules/get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "extraneous": true, + "dependencies": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "node_modules/claudia/node_modules/glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "node_modules/claudia/node_modules/glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "extraneous": true, + "dependencies": { + "is-glob": "^4.0.1" + } + }, + "node_modules/claudia/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "extraneous": true + }, + "node_modules/claudia/node_modules/graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "node_modules/claudia/node_modules/graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "extraneous": true + }, + "node_modules/claudia/node_modules/gunzip-maybe": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.1.tgz", + "integrity": "sha1-Occu2J0bSbpwjhh3ZQBIiQKlICc=", + "dependencies": { + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + } + }, + "node_modules/claudia/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "extraneous": true + }, + "node_modules/claudia/node_modules/https-proxy-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.0.tgz", + "integrity": "sha512-y4jAxNEihqvBI5F3SaO2rtsjIOnnNA8sEbuiP+UhJZJHeM2NRm6c09ax2tgqme+SgUUvjao2fJXF4h3D6Cb2HQ==", + "dependencies": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + }, + "node_modules/claudia/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "extraneous": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "node_modules/claudia/node_modules/ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha1-UL8k5bnIu5ivSWTJQc2wkY2ntgs=" + }, + "node_modules/claudia/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "extraneous": true + }, + "node_modules/claudia/node_modules/import-fresh": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", + "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", + "extraneous": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "node_modules/claudia/node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "extraneous": true + }, + "node_modules/claudia/node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/claudia/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/claudia/node_modules/inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "extraneous": true, + "dependencies": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + } + }, + "node_modules/claudia/node_modules/is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha1-yGKQHDwWH7CdrHzcfnhPgOmPLxQ=" + }, + "node_modules/claudia/node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "extraneous": true + }, + "node_modules/claudia/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "extraneous": true + }, + "node_modules/claudia/node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "extraneous": true, + "dependencies": { + "is-extglob": "^2.1.1" + } + }, + "node_modules/claudia/node_modules/is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=" + }, + "node_modules/claudia/node_modules/is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", + "extraneous": true + }, + "node_modules/claudia/node_modules/is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "extraneous": true + }, + "node_modules/claudia/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "extraneous": true + }, + "node_modules/claudia/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/claudia/node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "node_modules/claudia/node_modules/jasmine": { + "version": "2.99.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.99.0.tgz", + "integrity": "sha1-jKctEC5jm4Z8ZImFbg4YqceqQrc=", + "extraneous": true, + "dependencies": { + "exit": "^0.1.2", + "glob": "^7.0.6", + "jasmine-core": "~2.99.0" + } + }, + "node_modules/claudia/node_modules/jasmine-core": { + "version": "2.99.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz", + "integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=", + "extraneous": true + }, + "node_modules/claudia/node_modules/jasmine-spec-reporter": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-2.7.0.tgz", + "integrity": "sha1-QpB/+ImVKhKcCvwpKeGV9OdMmP8=", + "extraneous": true, + "dependencies": { + "colors": "1.1.2" + } + }, + "node_modules/claudia/node_modules/jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, + "node_modules/claudia/node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "extraneous": true + }, + "node_modules/claudia/node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "extraneous": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "node_modules/claudia/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "extraneous": true + }, + "node_modules/claudia/node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "extraneous": true + }, + "node_modules/claudia/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/claudia/node_modules/lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dependencies": { + "readable-stream": "^2.0.5" + } + }, + "node_modules/claudia/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "extraneous": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "node_modules/claudia/node_modules/lodash": { + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz", + "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==" + }, + "node_modules/claudia/node_modules/lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + }, + "node_modules/claudia/node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + }, + "node_modules/claudia/node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" + }, + "node_modules/claudia/node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + }, + "node_modules/claudia/node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "node_modules/claudia/node_modules/lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" + }, + "node_modules/claudia/node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" + }, + "node_modules/claudia/node_modules/make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "extraneous": true, + "dependencies": { + "pify": "^3.0.0" + } + }, + "node_modules/claudia/node_modules/make-dir/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "extraneous": true + }, + "node_modules/claudia/node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "extraneous": true + }, + "node_modules/claudia/node_modules/minimal-request-promise": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/minimal-request-promise/-/minimal-request-promise-1.5.0.tgz", + "integrity": "sha1-YPXX9VtAJtGXB04uFVYm1MxcLrw=" + }, + "node_modules/claudia/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dependencies": { + "brace-expansion": "^1.1.7" + } + }, + "node_modules/claudia/node_modules/minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "node_modules/claudia/node_modules/mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dependencies": { + "minimist": "0.0.8" + } + }, + "node_modules/claudia/node_modules/mkdirp/node_modules/minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "node_modules/claudia/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/claudia/node_modules/mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "extraneous": true + }, + "node_modules/claudia/node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "extraneous": true + }, + "node_modules/claudia/node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "extraneous": true + }, + "node_modules/claudia/node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "node_modules/claudia/node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "extraneous": true + }, + "node_modules/claudia/node_modules/oh-no-i-insist": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/oh-no-i-insist/-/oh-no-i-insist-1.1.1.tgz", + "integrity": "sha1-r28S4tQzZoObrkX4yHC5dqEe7jU=" + }, + "node_modules/claudia/node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/claudia/node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "extraneous": true, + "dependencies": { + "mimic-fn": "^1.0.0" + } + }, + "node_modules/claudia/node_modules/optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "extraneous": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "node_modules/claudia/node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "extraneous": true + }, + "node_modules/claudia/node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=" + }, + "node_modules/claudia/node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "extraneous": true, + "dependencies": { + "callsites": "^3.0.0" + } + }, + "node_modules/claudia/node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "node_modules/claudia/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "extraneous": true + }, + "node_modules/claudia/node_modules/peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha1-OzXYS3zLvSYv/zHcENpWhW6tbWc=", + "dependencies": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } + }, + "node_modules/claudia/node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "extraneous": true + }, + "node_modules/claudia/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "extraneous": true + }, + "node_modules/claudia/node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "extraneous": true + }, + "node_modules/claudia/node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "extraneous": true, + "dependencies": { + "pinkie": "^2.0.0" + } + }, + "node_modules/claudia/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "extraneous": true + }, + "node_modules/claudia/node_modules/process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=" + }, + "node_modules/claudia/node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "extraneous": true + }, + "node_modules/claudia/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/claudia/node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4=", + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/claudia/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "node_modules/claudia/node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "node_modules/claudia/node_modules/readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/claudia/node_modules/regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "extraneous": true + }, + "node_modules/claudia/node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "node_modules/claudia/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "extraneous": true + }, + "node_modules/claudia/node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "extraneous": true, + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/claudia/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "extraneous": true, + "dependencies": { + "glob": "^7.1.3" + } + }, + "node_modules/claudia/node_modules/rimraf/node_modules/glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "extraneous": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "node_modules/claudia/node_modules/run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "extraneous": true, + "dependencies": { + "is-promise": "^2.1.0" + } + }, + "node_modules/claudia/node_modules/rxjs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", + "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", + "extraneous": true, + "dependencies": { + "tslib": "^1.9.0" + } + }, + "node_modules/claudia/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" + }, + "node_modules/claudia/node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "extraneous": true + }, + "node_modules/claudia/node_modules/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "node_modules/claudia/node_modules/seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "extraneous": true, + "dependencies": { + "commander": "~2.8.1" + } + }, + "node_modules/claudia/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "extraneous": true + }, + "node_modules/claudia/node_modules/sequential-promise-map": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/sequential-promise-map/-/sequential-promise-map-1.0.4.tgz", + "integrity": "sha1-6+SlyPmF5yDcjyBVVFp2x4xFGwU=" + }, + "node_modules/claudia/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "extraneous": true, + "dependencies": { + "shebang-regex": "^1.0.0" + } + }, + "node_modules/claudia/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "extraneous": true + }, + "node_modules/claudia/node_modules/signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "extraneous": true + }, + "node_modules/claudia/node_modules/slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "extraneous": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "node_modules/claudia/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "extraneous": true + }, + "node_modules/claudia/node_modules/stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, + "node_modules/claudia/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/claudia/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "extraneous": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "node_modules/claudia/node_modules/string-width/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "extraneous": true, + "dependencies": { + "ansi-regex": "^3.0.0" + } + }, + "node_modules/claudia/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "extraneous": true, + "dependencies": { + "ansi-regex": "^4.1.0" + } + }, + "node_modules/claudia/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "extraneous": true + }, + "node_modules/claudia/node_modules/strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "extraneous": true, + "dependencies": { + "is-natural-number": "^4.0.1" + } + }, + "node_modules/claudia/node_modules/strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "extraneous": true + }, + "node_modules/claudia/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "extraneous": true, + "dependencies": { + "has-flag": "^3.0.0" + } + }, + "node_modules/claudia/node_modules/table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "extraneous": true, + "dependencies": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } + }, + "node_modules/claudia/node_modules/table/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "extraneous": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "node_modules/claudia/node_modules/tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha1-lmpiiEHaLEAQQGqCFny9Xgxy1Qk=", + "dependencies": { + "chownr": "^1.0.1", + "mkdirp": "^0.5.1", + "pump": "^1.0.0", + "tar-stream": "^1.1.2" + } + }, + "node_modules/claudia/node_modules/tar-fs/node_modules/pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha1-Xf6DEcM7v2/BgmH580cCxHwIqVQ=", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/claudia/node_modules/tar-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", + "integrity": "sha1-+E7xaWJp1iI8pI9uHu7eP36B85U=", + "dependencies": { + "bl": "^1.0.0", + "buffer-alloc": "^1.1.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.0", + "xtend": "^4.0.0" + } + }, + "node_modules/claudia/node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "extraneous": true + }, + "node_modules/claudia/node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "extraneous": true + }, + "node_modules/claudia/node_modules/through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dependencies": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "node_modules/claudia/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "extraneous": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + } + }, + "node_modules/claudia/node_modules/to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha1-STvUj2LXxD/N7TE6A9ytsuEhOoA=" + }, + "node_modules/claudia/node_modules/tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "extraneous": true + }, + "node_modules/claudia/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "extraneous": true, + "dependencies": { + "prelude-ls": "~1.1.2" + } + }, + "node_modules/claudia/node_modules/unbzip2-stream": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", + "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", + "extraneous": true, + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/claudia/node_modules/unbzip2-stream/node_modules/buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "extraneous": true, + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/claudia/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=" + }, + "node_modules/claudia/node_modules/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==", + "extraneous": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/claudia/node_modules/uri-js/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "extraneous": true + }, + "node_modules/claudia/node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/claudia/node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/claudia/node_modules/uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=" + }, + "node_modules/claudia/node_modules/v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "extraneous": true + }, + "node_modules/claudia/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=", + "dependencies": { + "isexe": "^2.0.0" + } + }, + "node_modules/claudia/node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "extraneous": true + }, + "node_modules/claudia/node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/claudia/node_modules/write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "extraneous": true, + "dependencies": { + "mkdirp": "^0.5.1" + } + }, + "node_modules/claudia/node_modules/xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "node_modules/claudia/node_modules/xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "node_modules/claudia/node_modules/xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "node_modules/claudia/node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "extraneous": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/claudia/node_modules/zip-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.0.1.tgz", + "integrity": "sha512-c+eUhhkDpaK87G/py74wvWLtz2kzMPNCCkUApkun50ssE0oQliIQzWpTnwjB+MTKVIf2tGzIgHyqW/Y+W77ecQ==", + "dependencies": { + "archiver-utils": "^2.0.0", + "compress-commons": "^1.2.0", + "readable-stream": "^2.0.0" + } + }, + "node_modules/clean-css": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.1.0.tgz", + "integrity": "sha512-98ALLW4NOhZpvUEoSc2dJO23xE4S4SXc4mLieCVFGo8DNLTFQ3gzi7msW1lqSYJeGZSF5r5+W3KF6cEnkILnFQ==", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/cli-table": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.6.tgz", + "integrity": "sha512-ZkNZbnZjKERTY5NwC2SeMeLeifSPq/pubeRoTpdr3WchLlnZg6hEgvHkK5zL7KNFdd9PmHN8lxrENUwI3cE8vQ==", + "dependencies": { + "colors": "1.0.3" + }, + "engines": { + "node": ">= 0.2.0" + } + }, + "node_modules/cli-table/node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/cls-bluebird": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz", + "integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=", + "dependencies": { + "is-bluebird": "^1.0.2", + "shimmer": "^1.1.0" + } + }, + "node_modules/color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "dependencies": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/color-string": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz", + "integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==" + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/colorspace": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", + "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", + "dependencies": { + "color": "3.0.x", + "text-hex": "1.0.x" + } + }, + "node_modules/combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "dependencies": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + } + }, + "node_modules/combine-source-map/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "optional": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "optional": true, + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "optional": true, + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/connect-flash": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", + "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/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==" + }, + "node_modules/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==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=" + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz", + "integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==", + "dependencies": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/core-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/cropperjs": { + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.5.11.tgz", + "integrity": "sha512-SJUeBBhtNBnnn+UrLKluhFRIXLJn7XFPv8QN1j49X5t+BIMwkgvDev541f96bmu8Xe0TgCx3gON22KmY/VddaA==" + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/css-b64-images": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/css-b64-images/-/css-b64-images-0.2.5.tgz", + "integrity": "sha1-QgBdgyBLK0pdk7axpWRBM7WSegI=", + "bin": { + "css-b64-images": "bin/css-b64-images" + }, + "engines": { + "node": "*" + } + }, + "node_modules/cssfilter": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", + "integrity": "sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=" + }, + "node_modules/cwise-compiler": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cwise-compiler/-/cwise-compiler-1.1.3.tgz", + "integrity": "sha1-9NZnQQ6FDToxOn0tt7HlBbsDTMU=", + "dependencies": { + "uniq": "^1.0.0" + } + }, + "node_modules/dash-ast": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", + "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dasherize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz", + "integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg=" + }, + "node_modules/data-uri-to-buffer": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-0.0.3.tgz", + "integrity": "sha1-GK6XmmoMqZSwYlhTkW0mYruuCxo=" + }, + "node_modules/date-and-time": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-0.13.1.tgz", + "integrity": "sha512-/Uge9DJAT+s+oAcDxtBhyR8+sKjUnZbYmyhbmWjTHNtX7B7oWD8YyYdeXcBRbwSj6hVvj+IQegJam7m7czhbFw==", + "optional": true + }, + "node_modules/dayjs": { + "version": "1.8.29", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.29.tgz", + "integrity": "sha512-Vm6teig8ZWK7rH/lxzVGxZJCljPdmUr6q/3f4fr5F0VWNGVkZEjZOQJsAN8hUHUqn+NK4XHNEpJZS1MwLyDcLw==" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", + "dependencies": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "dependencies": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tar/node_modules/bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/decompress-tar/node_modules/file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tar/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-tar/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/decompress-tar/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/decompress-tar/node_modules/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==" + }, + "node_modules/decompress-tar/node_modules/tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dependencies": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "dependencies": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tarbz2/node_modules/file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tarbz2/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "dependencies": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-targz/node_modules/file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-targz/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "dependencies": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-unzip/node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-unzip/node_modules/get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "dependencies": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-unzip/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress/node_modules/make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress/node_modules/make-dir/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deeks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/deeks/-/deeks-2.3.0.tgz", + "integrity": "sha512-mrNI+TSdnK5s2Gal4Fv3/RGcrYGtB4NC3tTXU1hu74tYsG9JS6SzNKLD8doq6UWsglouGwC86kXqB1pdO+9hyA==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/deep-equal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.3.tgz", + "integrity": "sha512-Spqdl4H+ky45I9ByyJtXteOm9CaIrPmnIPmOhrkKGNYWeDgCvJ8jNYVCTjChxW4FqGuZnLHADc8EKRMX6+CgvA==", + "optional": true, + "dependencies": { + "es-abstract": "^1.17.5", + "es-get-iterator": "^1.1.0", + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.2", + "is-regex": "^1.0.5", + "isarray": "^2.0.5", + "object-is": "^1.1.2", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.2", + "which-boxed-primitive": "^1.0.1", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denque": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", + "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/deprecated-decorator": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz", + "integrity": "sha1-AJZjF7ehL+kvPMgx91g68ym4bDc=" + }, + "node_modules/deps-sort": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz", + "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==", + "dependencies": { + "JSONStream": "^1.0.3", + "shasum-object": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + }, + "bin": { + "deps-sort": "bin/cmd.js" + } + }, + "node_modules/deps-sort/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/deps-sort/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/deps-sort/node_modules/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==" + }, + "node_modules/deps-sort/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/detective": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", + "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", + "dependencies": { + "acorn-node": "^1.6.1", + "defined": "^1.0.0", + "minimist": "^1.1.1" + }, + "bin": { + "detective": "bin/detective.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/devtools-protocol": { + "version": "0.0.818844", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.818844.tgz", + "integrity": "sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg==" + }, + "node_modules/dicer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", + "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", + "dependencies": { + "streamsearch": "0.1.2" + }, + "engines": { + "node": ">=4.5.0" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/dijkstrajs": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.2.tgz", + "integrity": "sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==" + }, + "node_modules/doc-path": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/doc-path/-/doc-path-2.3.0.tgz", + "integrity": "sha512-RMZA8AXl0I78jI9odw0kFzOfQvBcCFLI6/ZtOs9PwogcL4DHc+sCUZQ34fkealJyqErJryYODVBOtO2IzU/CSw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz", + "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz", + "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/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==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-case/node_modules/tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + }, + "node_modules/dot-prop": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", + "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", + "optional": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/dottie": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", + "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" + }, + "node_modules/download": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/download/-/download-8.0.0.tgz", + "integrity": "sha512-ASRY5QhDk7FK+XrQtQyvhpDKanLluEEQtWl/J7Lxuf/b+i8RYh997QeXvL85xitrmRKVlx9c7eTrcRdq2GS4eA==", + "dependencies": { + "archive-type": "^4.0.0", + "content-disposition": "^0.5.2", + "decompress": "^4.2.1", + "ext-name": "^5.0.0", + "file-type": "^11.1.0", + "filenamify": "^3.0.0", + "get-stream": "^4.1.0", + "got": "^8.3.1", + "make-dir": "^2.1.0", + "p-event": "^2.1.0", + "pify": "^4.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/download/node_modules/file-type": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-11.1.0.tgz", + "integrity": "sha512-rM0UO7Qm9K7TWTtA6AShI/t7H5BPjDeGVDaNyg9BjHAj3PysKy7+8C8D137R88jnR3rFJZQB/tFgydl5sN5m7g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/download/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/download/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/download/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/duplexer2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexer2/node_modules/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==" + }, + "node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "optional": true, + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "optional": true + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "optional": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexify/node_modules/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==", + "optional": true + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/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==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, + "node_modules/encode-utf8": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", + "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "optional": true + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", + "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", + "optional": true, + "dependencies": { + "es-abstract": "^1.17.4", + "has-symbols": "^1.0.1", + "is-arguments": "^1.0.4", + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eta": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/eta/-/eta-1.12.1.tgz", + "integrity": "sha512-H8npoci2J/7XiPnVcCVulBSPsTNGvGaINyMjQDU8AFqp9LGsEYS88g2CiU+d01Sg44WtX7o4nb8wUJ9vnI+tiA==", + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "url": "https://github.com/eta-dev/eta?sponsor=1" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dependencies": { + "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" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-ip": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/express-ip/-/express-ip-1.0.4.tgz", + "integrity": "sha512-PP9s2kg1+GHhJGtRqwoVHkBHi8glbL5wXXSj2p2+3qcxUNALwXoNhjtY2eLuNchcnWPkmJGyZcqAWUUpd9ecpA==", + "dependencies": { + "geoip-lite": "^1.2.2" + } + }, + "node_modules/express-session": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz", + "integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==", + "dependencies": { + "cookie": "0.4.0", + "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.2.0", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express-session/node_modules/safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "node_modules/express/node_modules/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==" + }, + "node_modules/express/node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "dependencies": { + "mime-db": "^1.28.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "dependencies": { + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extract-zip/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/extract-zip/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-csv": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/fast-csv/-/fast-csv-4.3.6.tgz", + "integrity": "sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==", + "dependencies": { + "@fast-csv/format": "4.3.5", + "@fast-csv/parse": "4.3.6" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" + }, + "node_modules/fast-text-encoding": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", + "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==", + "optional": true + }, + "node_modules/faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/feature-policy": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/feature-policy/-/feature-policy-0.3.0.tgz", + "integrity": "sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/fecha": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", + "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==" + }, + "node_modules/file-type": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.2.0.tgz", + "integrity": "sha512-1Wwww3mmZCMmLjBfslCluwt2mxH80GsAXYrvPnfQ42G1EGWag336kB1iyCgyn7UXiKY3cJrNykXPrCwA7xb5Ag==", + "dependencies": { + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.0.3", + "token-types": "^2.0.0", + "typedarray-to-buffer": "^3.1.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-3.0.0.tgz", + "integrity": "sha512-5EFZ//MsvJgXjBAFJ+Bh2YaCTRF/VP1YOmGrgt+KJ4SFRLjI87EIdwLLuT6wQX0I4F9W41xutobzczjsOKlI/g==", + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "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" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/firebase-admin": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-8.13.0.tgz", + "integrity": "sha512-krXj5ncWMJBhCpXSn9UFY6zmDWjFjqgx+1e9ATXKFYndEjmKtNBuJzqdrAdDh7aTUR7X6+0TPx4Hbc08kd0lwQ==", + "dependencies": { + "@firebase/database": "^0.6.0", + "@types/node": "^8.10.59", + "dicer": "^0.3.0", + "jsonwebtoken": "^8.5.1", + "node-forge": "^0.7.6" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + }, + "optionalDependencies": { + "@google-cloud/firestore": "^3.0.0", + "@google-cloud/storage": "^4.1.2" + } + }, + "node_modules/firebase-admin/node_modules/@types/node": { + "version": "8.10.61", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.61.tgz", + "integrity": "sha512-l+zSbvT8TPRaCxL1l9cwHCb0tSqGAGcjPJFItGGYat5oCTiq1uQQKYg5m7AF1mgnEBzFXGLJ2LRmNjtreRX76Q==" + }, + "node_modules/flat": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", + "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "dependencies": { + "is-buffer": "~2.0.3" + }, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat/node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=4" + } + }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, + "node_modules/focus-trap": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-5.1.0.tgz", + "integrity": "sha512-CkB/nrO55069QAUjWFBpX6oc+9V90Qhgpe6fBWApzruMq5gnlh90Oo7iSSDK7pKiV5ugG6OY2AXM5mxcmL3lwQ==", + "dependencies": { + "tabbable": "^4.0.0", + "xtend": "^4.0.1" + } + }, + "node_modules/follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "dependencies": { + "debug": "=3.1.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/follow-redirects/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", + "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/from2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/from2/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/from2/node_modules/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==" + }, + "node_modules/fs-capacitor": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-2.0.4.tgz", + "integrity": "sha512-8S4f4WsCryNw2mJJchi46YgB6CR5Ze+4L1h8ewl9tEpL4SJ3ZO+c/bS4BWhB8bK+O3TMqhuZarTitd0S0eh2pA==", + "engines": { + "node": ">=8.5" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "optional": true + }, + "node_modules/gaxios": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-2.3.4.tgz", + "integrity": "sha512-US8UMj8C5pRnao3Zykc4AAVr+cffoNKRTg9Rsf2GiuZCW69vgJj38VK2PzlPuQU73FZ/nTk9/Av6/JGcE1N9vA==", + "optional": true, + "dependencies": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.3.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/gcs-resumable-upload": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-2.3.3.tgz", + "integrity": "sha512-sf896I5CC/1AxeaGfSFg3vKMjUq/r+A3bscmVzZm10CElyRanN0XwPu/MxeIO4LSP+9uF6yKzXvNsaTsMXUG6Q==", + "optional": true, + "dependencies": { + "abort-controller": "^3.0.0", + "configstore": "^5.0.0", + "gaxios": "^2.0.0", + "google-auth-library": "^5.0.0", + "pumpify": "^2.0.0", + "stream-events": "^1.0.4" + }, + "bin": { + "gcs-upload": "build/src/cli.js" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/gcs-resumable-upload/node_modules/gcp-metadata": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-3.5.0.tgz", + "integrity": "sha512-ZQf+DLZ5aKcRpLzYUyBS3yo3N0JSa82lNDO8rj3nMSlovLcz2riKFBsYgDzeXcv75oo5eqB2lx+B14UvPoCRnA==", + "optional": true, + "dependencies": { + "gaxios": "^2.1.0", + "json-bigint": "^0.3.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/gcs-resumable-upload/node_modules/google-auth-library": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-5.10.1.tgz", + "integrity": "sha512-rOlaok5vlpV9rSiUu5EpR0vVpc+PhN62oF4RyX/6++DG1VsaulAFEMlDYBLjJDDPI6OcNOCGAKy9UVB/3NIDXg==", + "optional": true, + "dependencies": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^2.1.0", + "gcp-metadata": "^3.4.0", + "gtoken": "^4.1.0", + "jws": "^4.0.0", + "lru-cache": "^5.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/gcs-resumable-upload/node_modules/google-p12-pem": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.4.tgz", + "integrity": "sha512-S4blHBQWZRnEW44OcR7TL9WR+QCqByRvhNDZ/uuQfpxywfupikf/miba8js1jZi6ZOGv5slgSuoshCWh6EMDzg==", + "optional": true, + "dependencies": { + "node-forge": "^0.9.0" + }, + "bin": { + "gp12-pem": "build/src/bin/gp12-pem.js" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/gcs-resumable-upload/node_modules/gtoken": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.4.tgz", + "integrity": "sha512-VxirzD0SWoFUo5p8RDP8Jt2AGyOmyYcT/pOUgDKJCK+iSw0TMqwrVfY37RXTNmoKwrzmDHSk0GMT9FsgVmnVSA==", + "optional": true, + "dependencies": { + "gaxios": "^2.1.0", + "google-p12-pem": "^2.0.0", + "jws": "^4.0.0", + "mime": "^2.2.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/gcs-resumable-upload/node_modules/json-bigint": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.1.tgz", + "integrity": "sha512-DGWnSzmusIreWlEupsUelHrhwmPPE+FiQvg+drKfk2p+bdEYa5mp4PJ8JsCWqae0M2jQNb0HPvnwvf1qOTThzQ==", + "optional": true, + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/gcs-resumable-upload/node_modules/mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/gcs-resumable-upload/node_modules/node-forge": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.2.tgz", + "integrity": "sha512-naKSScof4Wn+aoHU6HBsifh92Zeicm1GDQKd1vp3Y/kOi8ub0DozCa9KpvYNCXslFHYRmLNiqRopGdTGwNLpNw==", + "optional": true, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/geoip-lite": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/geoip-lite/-/geoip-lite-1.4.2.tgz", + "integrity": "sha512-1rUNqar68+ldSSlSMdpLZPAM+NRokIDzB2lpQFRHSOaDVqtmy25jTAWe0lM2GqWFeaA35RiLhF8GF0vvL+qOKA==", + "dependencies": { + "async": "^2.1.1", + "colors": "^1.1.2", + "iconv-lite": "^0.4.13", + "ip-address": "^5.8.9", + "lazy": "^1.0.11", + "rimraf": "^2.5.2", + "yauzl": "^2.9.2" + }, + "engines": { + "node": ">=5.10.0" + } + }, + "node_modules/geoip-lite/node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/geoip-lite/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/get-assigned-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-pixels": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/get-pixels/-/get-pixels-3.3.2.tgz", + "integrity": "sha512-6ar+8yPxRd1pskEcl2GSEu1La0+xYRjjnkby6AYiRDDwZ0tJbPQmHnSeH9fGLskT8kvR0OukVgtZLcsENF9YKQ==", + "dependencies": { + "data-uri-to-buffer": "0.0.3", + "jpeg-js": "^0.3.2", + "mime-types": "^2.0.1", + "ndarray": "^1.0.13", + "ndarray-pack": "^1.1.1", + "node-bitmap": "0.0.1", + "omggif": "^1.0.5", + "parse-data-uri": "^0.2.0", + "pngjs": "^3.3.3", + "request": "^2.44.0", + "through": "^2.3.4" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/gl-mat2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gl-mat2/-/gl-mat2-1.0.1.tgz", + "integrity": "sha1-FCUFcwpcL+Hp8l2ezj0NbMJxCjA=" + }, + "node_modules/gl-vec2": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/gl-vec2/-/gl-vec2-1.3.0.tgz", + "integrity": "sha512-YiqaAuNsheWmUV0Sa8k94kBB0D6RWjwZztyO+trEYS8KzJ6OQB/4686gdrf59wld4hHFIvaxynO3nRxpk1Ij/A==" + }, + "node_modules/gl-vec3": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gl-vec3/-/gl-vec3-1.1.3.tgz", + "integrity": "sha512-jduKUqT0SGH02l8Yl+mV1yVsDfYgQAJyXGxkJQGyxPLHRiW25DwVIRPt6uvhrEMHftJfqhqKthRcyZqNEl9Xdw==" + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/google-gax": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-1.15.3.tgz", + "integrity": "sha512-3JKJCRumNm3x2EksUTw4P1Rad43FTpqrtW9jzpf3xSMYXx+ogaqTM1vGo7VixHB4xkAyATXVIa3OcNSh8H9zsQ==", + "optional": true, + "dependencies": { + "@grpc/grpc-js": "~1.0.3", + "@grpc/proto-loader": "^0.5.1", + "@types/fs-extra": "^8.0.1", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^3.6.0", + "google-auth-library": "^5.0.0", + "is-stream-ended": "^0.1.4", + "lodash.at": "^4.6.0", + "lodash.has": "^4.5.2", + "node-fetch": "^2.6.0", + "protobufjs": "^6.8.9", + "retry-request": "^4.0.0", + "semver": "^6.0.0", + "walkdir": "^0.4.0" + }, + "bin": { + "compileProtos": "build/tools/compileProtos.js" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/google-gax/node_modules/gcp-metadata": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-3.5.0.tgz", + "integrity": "sha512-ZQf+DLZ5aKcRpLzYUyBS3yo3N0JSa82lNDO8rj3nMSlovLcz2riKFBsYgDzeXcv75oo5eqB2lx+B14UvPoCRnA==", + "optional": true, + "dependencies": { + "gaxios": "^2.1.0", + "json-bigint": "^0.3.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/google-gax/node_modules/google-auth-library": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-5.10.1.tgz", + "integrity": "sha512-rOlaok5vlpV9rSiUu5EpR0vVpc+PhN62oF4RyX/6++DG1VsaulAFEMlDYBLjJDDPI6OcNOCGAKy9UVB/3NIDXg==", + "optional": true, + "dependencies": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^2.1.0", + "gcp-metadata": "^3.4.0", + "gtoken": "^4.1.0", + "jws": "^4.0.0", + "lru-cache": "^5.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/google-gax/node_modules/google-p12-pem": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.4.tgz", + "integrity": "sha512-S4blHBQWZRnEW44OcR7TL9WR+QCqByRvhNDZ/uuQfpxywfupikf/miba8js1jZi6ZOGv5slgSuoshCWh6EMDzg==", + "optional": true, + "dependencies": { + "node-forge": "^0.9.0" + }, + "bin": { + "gp12-pem": "build/src/bin/gp12-pem.js" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/google-gax/node_modules/gtoken": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.4.tgz", + "integrity": "sha512-VxirzD0SWoFUo5p8RDP8Jt2AGyOmyYcT/pOUgDKJCK+iSw0TMqwrVfY37RXTNmoKwrzmDHSk0GMT9FsgVmnVSA==", + "optional": true, + "dependencies": { + "gaxios": "^2.1.0", + "google-p12-pem": "^2.0.0", + "jws": "^4.0.0", + "mime": "^2.2.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/google-gax/node_modules/json-bigint": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.1.tgz", + "integrity": "sha512-DGWnSzmusIreWlEupsUelHrhwmPPE+FiQvg+drKfk2p+bdEYa5mp4PJ8JsCWqae0M2jQNb0HPvnwvf1qOTThzQ==", + "optional": true, + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/google-gax/node_modules/mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/google-gax/node_modules/node-forge": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.2.tgz", + "integrity": "sha512-naKSScof4Wn+aoHU6HBsifh92Zeicm1GDQKd1vp3Y/kOi8ub0DozCa9KpvYNCXslFHYRmLNiqRopGdTGwNLpNw==", + "optional": true, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/got": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", + "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "dependencies": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/got/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "engines": { + "node": ">=4" + } + }, + "node_modules/got/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + }, + "node_modules/graphql": { + "version": "14.6.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.6.0.tgz", + "integrity": "sha512-VKzfvHEKybTKjQVpTFrA5yUq2S9ihcZvfJAtsDBBCuV6wauPu1xl/f9ehgVf0FcEJJs4vz6ysb/ZMkGigQZseg==", + "dependencies": { + "iterall": "^1.2.2" + }, + "engines": { + "node": ">= 6.x" + } + }, + "node_modules/graphql-extensions": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.12.4.tgz", + "integrity": "sha512-GnR4LiWk3s2bGOqIh6V1JgnSXw2RCH4NOgbCFEWvB6JqWHXTlXnLZ8bRSkCiD4pltv7RHUPWqN/sGh8R6Ae/ag==", + "deprecated": "The `graphql-extensions` API has been removed from Apollo Server 3. Use the plugin API instead: https://www.apollographql.com/docs/apollo-server/integrations/plugins/", + "dependencies": { + "@apollographql/apollo-tools": "^0.4.3", + "apollo-server-env": "^2.4.5", + "apollo-server-types": "^0.5.1" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependencies": { + "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" + } + }, + "node_modules/graphql-fields": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/graphql-fields/-/graphql-fields-2.0.3.tgz", + "integrity": "sha512-x3VE5lUcR4XCOxPIqaO4CE+bTK8u6gVouOdpQX9+EKHr+scqtK5Pp/l8nIGqIpN1TUlkKE6jDCCycm/WtLRAwA==" + }, + "node_modules/graphql-subscriptions": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-1.1.0.tgz", + "integrity": "sha512-6WzlBFC0lWmXJbIVE8OgFgXIP4RJi3OQgTPa0DVMsDXdpRDjTsM1K9wfl5HSYX7R87QAGlvcv2Y4BIZa/ItonA==", + "dependencies": { + "iterall": "^1.2.1" + }, + "peerDependencies": { + "graphql": "^0.10.5 || ^0.11.3 || ^0.12.0 || ^0.13.0 || ^14.0.0" + } + }, + "node_modules/graphql-tag": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.10.3.tgz", + "integrity": "sha512-4FOv3ZKfA4WdOKJeHdz6B3F/vxBLSgmBcGeAFPf4n1F64ltJUvOOerNj0rsJxONQGdhUMynQIvd6LzB+1J5oKA==", + "peerDependencies": { + "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0" + } + }, + "node_modules/graphql-tools": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-4.0.8.tgz", + "integrity": "sha512-MW+ioleBrwhRjalKjYaLQbr+920pHBgy9vM/n47sswtns8+96sRn5M/G+J1eu7IMeKWiN/9p6tmwCHU7552VJg==", + "deprecated": "This package has been deprecated and now it only exports makeExecutableSchema.\\nAnd it will no longer receive updates.\\nWe recommend you to migrate to scoped packages such as @graphql-tools/schema, @graphql-tools/utils and etc.\\nCheck out https://www.graphql-tools.com to learn what package you should use instead", + "dependencies": { + "apollo-link": "^1.2.14", + "apollo-utilities": "^1.0.1", + "deprecated-decorator": "^0.1.6", + "iterall": "^1.1.3", + "uuid": "^3.1.0" + }, + "peerDependencies": { + "graphql": "^0.13.0 || ^14.0.0 || ^15.0.0" + } + }, + "node_modules/graphql-tools/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/graphql-upload": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-8.1.0.tgz", + "integrity": "sha512-U2OiDI5VxYmzRKw0Z2dmfk0zkqMRaecH9Smh1U277gVgVe9Qn+18xqf4skwr4YJszGIh7iQDZ57+5ygOK9sM/Q==", + "dependencies": { + "busboy": "^0.3.1", + "fs-capacitor": "^2.0.4", + "http-errors": "^1.7.3", + "object-path": "^0.11.4" + }, + "engines": { + "node": ">=8.5" + }, + "peerDependencies": { + "graphql": "0.13.1 - 14" + } + }, + "node_modules/handlebars": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "engines": { + "node": "*" + } + }, + "node_modules/has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "dependencies": { + "has-symbol-support-x": "^1.4.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag/node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-stream-validation": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.3.tgz", + "integrity": "sha512-OEohGLoUOh+bwsIpHpdvhIXFyRGjeLqJbT8Yc5QTZPbRM7LKywagTQxnX/6mghLDOrD9YGz88hy5mLN2eKflYQ==", + "optional": true, + "dependencies": { + "through2": "^2.0.0" + } + }, + "node_modules/hash-stream-validation/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "optional": true + }, + "node_modules/hash-stream-validation/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "optional": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hash-stream-validation/node_modules/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==", + "optional": true + }, + "node_modules/hash-stream-validation/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "optional": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/helmet": { + "version": "3.23.3", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.23.3.tgz", + "integrity": "sha512-U3MeYdzPJQhtvqAVBPntVgAvNSOJyagwZwyKsFdyRa8TV3pOKVFljalPOCxbw5Wwf2kncGhmP0qHjyazIdNdSA==", + "dependencies": { + "depd": "2.0.0", + "dont-sniff-mimetype": "1.1.0", + "feature-policy": "0.3.0", + "helmet-crossdomain": "0.4.0", + "helmet-csp": "2.10.0", + "hide-powered-by": "1.1.0", + "hpkp": "2.0.0", + "hsts": "2.2.0", + "nocache": "2.1.0", + "referrer-policy": "1.2.0", + "x-xss-protection": "1.3.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/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==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/helmet-csp": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.10.0.tgz", + "integrity": "sha512-Rz953ZNEFk8sT2XvewXkYN0Ho4GEZdjAZy4stjiEQV3eN7GDxg1QKmYggH7otDyIA7uGA6XnUMVSgeJwbR5X+w==", + "dependencies": { + "bowser": "2.9.0", + "camelize": "1.0.0", + "content-security-policy-builder": "2.1.0", + "dasherize": "2.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/helmet/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/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==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/hpkp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz", + "integrity": "sha1-EOFCJk52IVpdMMROxD3mTe5tFnI=" + }, + "node_modules/hsts": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.2.0.tgz", + "integrity": "sha512-ToaTnQ2TbJkochoVcdXYm4HOCliNozlviNsg+X2XQLQvZNI/kCHR9rZxVYpJB3UPcHz80PgxRyWQ7PdU1r+VBQ==", + "dependencies": { + "depd": "2.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/hsts/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==" + }, + "node_modules/html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "dependencies": { + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/html-minifier-terser/node_modules/clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/html-minifier-terser/node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/html-minifier-terser/node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/html-pdf-node": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/html-pdf-node/-/html-pdf-node-1.0.7.tgz", + "integrity": "sha512-fBvV3/+GxqEuyZuYGPou9aKEP84VbN/1wmL1ujF1UsLSy10srESfQelbOrSgJkOHs23yPfUG9uGMajat6+1UfQ==", + "dependencies": { + "bluebird": "^3.7.2", + "handlebars": "^4.7.6", + "puppeteer": "^5.1.0" + } + }, + "node_modules/htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" + }, + "node_modules/http-errors": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", + "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.2.tgz", + "integrity": "sha512-opCO9ASqg5Wy2FNo7A0sxy71yGbbkJJXLdgMK04Tcypw9jr2MgWbyubb0+WdmDmGnFflO7fRbqbaihh/ENDlRQ==" + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "optional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/http-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "optional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/image-size": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.0.tgz", + "integrity": "sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw==", + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "optional": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", + "engines": [ + "node >= 0.4.0" + ] + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "dependencies": { + "source-map": "~0.5.3" + } + }, + "node_modules/inline-source-map/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/insert-module-globals": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz", + "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==", + "dependencies": { + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "JSONStream": "^1.0.3", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + }, + "bin": { + "insert-module-globals": "bin/cmd.js" + } + }, + "node_modules/insert-module-globals/node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/insert-module-globals/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/insert-module-globals/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/insert-module-globals/node_modules/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==" + }, + "node_modules/insert-module-globals/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", + "dependencies": { + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/iota-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz", + "integrity": "sha1-ge9X/l0FgUzVjCSDYyqZwwoOgIc=" + }, + "node_modules/ip-address": { + "version": "5.9.4", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-5.9.4.tgz", + "integrity": "sha512-dHkI3/YNJq4b/qQaz+c8LuarD3pY24JqZWfjB8aZx1gtpc2MDILu9L9jpZe1sHpzo/yWFweQVn+U//FhazUxmw==", + "dependencies": { + "jsbn": "1.1.0", + "lodash": "^4.17.15", + "sprintf-js": "1.1.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ip-address/node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha1-sBMHyym2GKHtJux56RH4A8TaAEA=" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, + "node_modules/is-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.0.tgz", + "integrity": "sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g==", + "optional": true + }, + "node_modules/is-bluebird": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz", + "integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-boolean-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.1.tgz", + "integrity": "sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==", + "optional": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", + "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz", + "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", + "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" + }, + "node_modules/is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "optional": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, + "node_modules/is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", + "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", + "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream-ended": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", + "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==", + "optional": true + }, + "node_modules/is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "optional": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-svg": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", + "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", + "dependencies": { + "html-comment-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.3.tgz", + "integrity": "sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ==", + "dependencies": { + "available-typed-arrays": "^1.0.0", + "es-abstract": "^1.17.4", + "foreach": "^2.0.5", + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz", + "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw==", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "optional": true + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "node_modules/isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "dependencies": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/iterall": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", + "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==" + }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=" + }, + "node_modules/jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/jpeg-js": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.7.tgz", + "integrity": "sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ==" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "node_modules/json-2-csv": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/json-2-csv/-/json-2-csv-3.11.0.tgz", + "integrity": "sha512-sElSEXF0ukJAnzmwVn839tPuzOvcl1GZi6d/ne9n1/6dI4/9Q/xCuBsDD3coWLGv5FYWRxCz9BtYa6P54VRjMQ==", + "dependencies": { + "deeks": "2.3.0", + "doc-path": "2.3.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "node_modules/json-to-csv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-to-csv/-/json-to-csv-1.0.0.tgz", + "integrity": "sha1-RkC/ffkwwOu6atE9EqbULTt+ohM=", + "dependencies": { + "json2csv": "^3.4.2", + "ramda": "^0.21.0" + } + }, + "node_modules/json2csv": { + "version": "3.11.5", + "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-3.11.5.tgz", + "integrity": "sha512-ORsw84BuRKMLxfI+HFZuvxRDnsJps53D5fIGr6tLn4ZY+ymcG8XU00E+JJ2wfAiHx5w2QRNmOLE8xHiGAeSfuQ==", + "dependencies": { + "cli-table": "^0.3.1", + "commander": "^2.8.1", + "debug": "^3.1.0", + "flat": "^4.0.0", + "lodash.clonedeep": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.get": "^4.4.0", + "lodash.set": "^4.3.0", + "lodash.uniq": "^4.5.0", + "path-is-absolute": "^1.0.0" + }, + "bin": { + "json2csv": "bin/json2csv.js" + } + }, + "node_modules/json2csv/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/json2csv/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "dependencies": { + "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" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, + "node_modules/jsonwebtoken/node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "optional": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "optional": true, + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/klona": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz", + "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, + "node_modules/labeled-stream-splicer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", + "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", + "dependencies": { + "inherits": "^2.0.1", + "stream-splicer": "^2.0.0" + } + }, + "node_modules/lazy": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", + "integrity": "sha1-2qBoIGKCVCwIgojpdcKXwa53tpA=", + "engines": { + "node": ">=0.2.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.at": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.at/-/lodash.at-4.6.0.tgz", + "integrity": "sha1-k83OZk8KGZTqM9181A4jr9EbD/g=", + "optional": true + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "optional": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "node_modules/lodash.groupby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", + "integrity": "sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E=" + }, + "node_modules/lodash.has": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", + "integrity": "sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI=" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "node_modules/lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "node_modules/lodash.isnil": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", + "integrity": "sha1-SeKM1VkBNFjIFMVHnTxmOiG/qmw=" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "node_modules/lodash.isundefined": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", + "integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=" + }, + "node_modules/lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, + "node_modules/lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + }, + "node_modules/logform": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", + "integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==", + "dependencies": { + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "triple-beam": "^1.3.0" + } + }, + "node_modules/logform/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/loglevel": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz", + "integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA==", + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-loglevel?utm_medium=referral&utm_source=npm_fund" + } + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lower-case/node_modules/tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "optional": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.29", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", + "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "dependencies": { + "mime-db": "1.46.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/minify": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/minify/-/minify-7.0.1.tgz", + "integrity": "sha512-U3CjnPKRjPu3DxZX7NsB833r2ijbw9af3fHsaChn6o7BHKvaT/zxYDQ8Q/3W7VFXGDrnkAx6XBx3ggEf5KJm7A==", + "dependencies": { + "clean-css": "^5.0.1", + "css-b64-images": "~0.2.5", + "debug": "^4.1.0", + "html-minifier-terser": "^5.1.1", + "terser": "^5.3.2", + "try-to-catch": "^3.0.0" + }, + "bin": { + "minify": "bin/minify.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/minify/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/minify/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "node_modules/mitt": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz", + "integrity": "sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==" + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/module-deps": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz", + "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==", + "dependencies": { + "browser-resolve": "^2.0.0", + "cached-path-relative": "^1.0.2", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.2.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "JSONStream": "^1.0.3", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + }, + "bin": { + "module-deps": "bin/cmd.js" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/module-deps/node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/module-deps/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/module-deps/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/module-deps/node_modules/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==" + }, + "node_modules/module-deps/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.31", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", + "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", + "dependencies": { + "moment": ">= 2.9.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/morgan": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", + "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", + "dependencies": { + "basic-auth": "~2.0.0", + "debug": "2.6.9", + "depd": "~1.1.2", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/multer": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.2.tgz", + "integrity": "sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/multer-s3": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/multer-s3/-/multer-s3-2.9.0.tgz", + "integrity": "sha512-qLF8pCD5HhXLLd954q49B63x3bk6Fe0jqD3eM0FVcGtqhiSVuTrchEDAo0mnO5pc34cMuX/CVCCbPkGTjX2xUA==", + "dependencies": { + "file-type": "^3.3.0", + "is-svg": "^2.1.0", + "run-parallel": "^1.1.6" + } + }, + "node_modules/multer-s3/node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/multer/node_modules/busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "dependencies": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/multer/node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/multer/node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/multer/node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/multer/node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/multer/node_modules/dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "dependencies": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/multer/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "node_modules/multer/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/multer/node_modules/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==" + }, + "node_modules/multer/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "node_modules/mysql2": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.1.0.tgz", + "integrity": "sha512-9kGVyi930rG2KaHrz3sHwtc6K+GY9d8wWk1XRSYxQiunvGcn4DwuZxOwmK11ftuhhwrYDwGx9Ta4VBwznJn36A==", + "dependencies": { + "cardinal": "^2.1.1", + "denque": "^1.4.1", + "generate-function": "^2.3.1", + "iconv-lite": "^0.5.0", + "long": "^4.0.0", + "lru-cache": "^5.1.1", + "named-placeholders": "^1.1.2", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.1" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/mysql2/node_modules/iconv-lite": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", + "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", + "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", + "dependencies": { + "lru-cache": "^4.1.3" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/named-placeholders/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "node_modules/nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/ndarray": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.19.tgz", + "integrity": "sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ==", + "dependencies": { + "iota-array": "^1.0.0", + "is-buffer": "^1.0.2" + } + }, + "node_modules/ndarray-linear-interpolate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ndarray-linear-interpolate/-/ndarray-linear-interpolate-1.0.0.tgz", + "integrity": "sha1-eLySuFuavBW25n7mWCj54hN65ys=" + }, + "node_modules/ndarray-pack": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ndarray-pack/-/ndarray-pack-1.2.1.tgz", + "integrity": "sha1-jK6+qqJNXs9w/4YCBjeXfajuWFo=", + "dependencies": { + "cwise-compiler": "^1.1.2", + "ndarray": "^1.0.13" + } + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/no-case/node_modules/tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + }, + "node_modules/nocache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz", + "integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/node-bitmap": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/node-bitmap/-/node-bitmap-0.0.1.tgz", + "integrity": "sha1-GA6scAPgxwdhjvMTaPYvhLKmkJE=", + "engines": { + "node": ">=v0.6.5" + } + }, + "node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/node-forge": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz", + "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==", + "engines": { + "node": "*" + } + }, + "node_modules/node-input-validator": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/node-input-validator/-/node-input-validator-4.3.3.tgz", + "integrity": "sha512-yzMvEMjnFxGocb1u/Zdb9L0SsLd6b/+fEVfAMoHbG7RHXWN8AsAs3xi45flphef1dvXNFMFjVVo0/lZXYXoG4g==", + "dependencies": { + "file-type": "^16.2.0", + "image-size": "^0.8.3", + "lodash.has": "^4.5.2", + "mime-types": "^2.1.28", + "moment": "^2.29.1", + "read-chunk": "^3.2.0", + "validator": "^13.5.2" + }, + "engines": { + "node": ">=8.16" + } + }, + "node_modules/node-input-validator/node_modules/image-size": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.8.3.tgz", + "integrity": "sha512-SMtq1AJ+aqHB45c3FsB4ERK0UCiA2d3H1uq8s+8T0Pf8A3W4teyBQyaFaktH6xvZqh+npwlKU7i4fJo0r7TYTg==", + "dependencies": { + "queue": "6.0.1" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/node-input-validator/node_modules/queue": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.1.tgz", + "integrity": "sha512-AJBQabRCCNr9ANq8v77RJEv73DPbn55cdTb+Giq4X0AVnNVZvMHlYp7XlQiN+1npCZj1DuSmaA2hYVUUDgxFDg==", + "dependencies": { + "inherits": "~2.0.3" + } + }, + "node_modules/node-input-validator/node_modules/validator": { + "version": "13.5.2", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.5.2.tgz", + "integrity": "sha512-mD45p0rvHVBlY2Zuy3F3ESIe1h5X58GPfAtslBjY7EtTqGquZTj+VX/J4RnHWN8FKq0C9WRVt1oWAcytWRuYLQ==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/nodemailer": { + "version": "6.4.11", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.11.tgz", + "integrity": "sha512-BVZBDi+aJV4O38rxsUh164Dk1NCqgh6Cm0rQSb9SK/DHGll/DrCMnycVDD7msJgZCnmVa8ASo8EZzR7jsgTukQ==", + "hasInstallScript": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "dependencies": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", + "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", + "optional": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-path": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", + "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dependencies": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/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==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dependencies": { + "fn.name": "1.x.x" + } + }, + "node_modules/onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "optional": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, + "node_modules/p-cancelable": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-event": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz", + "integrity": "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==", + "dependencies": { + "p-timeout": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-merge": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/package-merge/-/package-merge-0.1.2.tgz", + "integrity": "sha1-wng55RHV2AlOmjb/zFRmzCfWazw=", + "dependencies": { + "jju": "^1.2.0", + "semver": "^4.3.6", + "semver-set": "^0.1.1" + } + }, + "node_modules/package-merge/node_modules/semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/param-case/node_modules/tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + }, + "node_modules/parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dependencies": { + "path-platform": "~0.11.15" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/parse-data-uri": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/parse-data-uri/-/parse-data-uri-0.2.0.tgz", + "integrity": "sha1-vwTYUd1ch7CrI45dAazklLYEtMk=", + "dependencies": { + "data-uri-to-buffer": "0.0.3" + } + }, + "node_modules/parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha1-8r0iH2zJcKk42IVWq8WJyqqiveE=" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/pascal-case/node_modules/tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/peek-readable": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-3.1.3.tgz", + "integrity": "sha512-mpAcysyRJxmICBcBa5IXH7SZPvWkcghm6Fk8RekoS3v+BpbSzlZzuWbMx+GXrlUwESi9qHar4nVEZNMKylIHvg==", + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pop-iterate": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pop-iterate/-/pop-iterate-1.0.1.tgz", + "integrity": "sha1-zqz9q0q/NT16DyqqLB/Hs/lBO6M=" + }, + "node_modules/postcss": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.5.tgz", + "integrity": "sha512-NxTuJocUhYGsMiMFHDUkmjSKT3EdH4/WbGF6GCi1NDGk+vbcUTun4fpbOqaPtD8IIsztA2ilZm2DhYCuyN58gA==", + "dependencies": { + "colorette": "^1.2.2", + "nanoid": "^3.1.23", + "source-map-js": "^0.6.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "engines": { + "node": ">=4" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/protobufjs": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.9.0.tgz", + "integrity": "sha512-LlGVfEWDXoI/STstRDdZZKb/qusoAWUnmLg9R8OLSO473mBLWHowx8clbX5/+mKDEI+v7GzjoK9tRPZMMcoTrg==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": "^13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/protobufjs/node_modules/@types/node": { + "version": "13.13.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.12.tgz", + "integrity": "sha512-zWz/8NEPxoXNT9YyF2osqyA9WjssZukYpgI4UYZpOjcyqwIUqWGkcCionaEb9Ki+FULyPyvNFpg/329Kd2/pbw==", + "optional": true + }, + "node_modules/proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dependencies": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", + "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", + "optional": true, + "dependencies": { + "duplexify": "^4.1.1", + "inherits": "^2.0.3", + "pump": "^3.0.0" + } + }, + "node_modules/pumpify/node_modules/duplexify": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.1.tgz", + "integrity": "sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==", + "optional": true, + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "node_modules/puppeteer": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-5.5.0.tgz", + "integrity": "sha512-OM8ZvTXAhfgFA7wBIIGlPQzvyEETzDjeRa4mZRCRHxYL+GNH5WAuYUQdja3rpWZvkX/JKqmuVgbsxDNsDFjMEg==", + "deprecated": "Version no longer supported. Upgrade to @latest", + "hasInstallScript": true, + "dependencies": { + "debug": "^4.1.0", + "devtools-protocol": "0.0.818844", + "extract-zip": "^2.0.0", + "https-proxy-agent": "^4.0.0", + "node-fetch": "^2.6.1", + "pkg-dir": "^4.2.0", + "progress": "^2.0.1", + "proxy-from-env": "^1.0.0", + "rimraf": "^3.0.2", + "tar-fs": "^2.0.0", + "unbzip2-stream": "^1.3.3", + "ws": "^7.2.3" + }, + "engines": { + "node": ">=10.18.1" + } + }, + "node_modules/puppeteer/node_modules/agent-base": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/puppeteer/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/puppeteer/node_modules/https-proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "dependencies": { + "agent-base": "5", + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/puppeteer/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/puppeteer/node_modules/ws": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz", + "integrity": "sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/q": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/q/-/q-2.0.3.tgz", + "integrity": "sha1-dbjbAlWhpa+C9Yw/Oqoe/sfQ0TQ=", + "dependencies": { + "asap": "^2.0.0", + "pop-iterate": "^1.0.1", + "weak-map": "^1.0.5" + } + }, + "node_modules/qrcode": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.0.tgz", + "integrity": "sha512-9MgRpgVc+/+47dFvQeD6U2s0Z92EsKzcHogtum4QB+UNd025WOJSHvn/hjk9xmzj7Stj95CyUAs31mrjxliEsQ==", + "dependencies": { + "dijkstrajs": "^1.0.1", + "encode-utf8": "^1.0.3", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/qrcode/node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/quagga": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/quagga/-/quagga-0.12.1.tgz", + "integrity": "sha1-b0jFbtmS3F/euQ2+5wacLhzd6Lc=", + "dependencies": { + "get-pixels": "^3.2.3", + "gl-mat2": "^1.0.0", + "gl-vec2": "^1.0.0", + "gl-vec3": "^1.0.3", + "lodash": "^4.17.4", + "ndarray": "^1.0.18", + "ndarray-linear-interpolate": "^1.0.0" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dependencies": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", + "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==" + }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "dependencies": { + "inherits": "~2.0.3" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.2.tgz", + "integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ramda": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.21.0.tgz", + "integrity": "sha1-oAGr7bP/YQd9T/HVd9RN536NCjU=" + }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/read-chunk": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-3.2.0.tgz", + "integrity": "sha512-CEjy9LCzhmD7nUpJ1oVOE6s/hBkejlcJEgLQHVnQznOSilOPb+kpKktlLfFDK3/WP43+F80xkUTM2VOkYoSYvQ==", + "dependencies": { + "pify": "^4.0.1", + "with-open-file": "^0.1.6" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/read-only-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/read-only-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/read-only-stream/node_modules/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==" + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readable-web-to-node-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.1.tgz", + "integrity": "sha512-4zDC6CvjUyusN7V0QLsXVB7pJCD9+vtrM9bYDRv6uBQ+SKfx36rp5AFNPRgh9auKRul/a1iFZJYXcCbwRL+SaA==", + "dependencies": { + "@types/readable-stream": "^2.3.9", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", + "dependencies": { + "esprima": "~4.0.0" + } + }, + "node_modules/referrer-policy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.2.0.tgz", + "integrity": "sha512-LgQJIuS6nAy1Jd88DCQRemyE3mS+ispwlqMk3b0yjZ257fI1v9c+/p6SD5gP5FGyXUIgrNOAfmyioHwZtYv2VA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "optional": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "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.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "engines": { + "node": ">= 4" + } + }, + "node_modules/retry-as-promised": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", + "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", + "dependencies": { + "any-promise": "^1.3.0" + } + }, + "node_modules/retry-request": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.1.1.tgz", + "integrity": "sha512-BINDzVtLI2BDukjWmjAIRZ0oglnCAkpP2vQjM3jdLhmT62h0xnQgciPwBRDAvHqpkPT2Wo1XuUyLyn6nbGrZQQ==", + "optional": true, + "dependencies": { + "debug": "^4.1.1", + "through2": "^3.0.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/retry-request/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "optional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/retry-request/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/rootpath": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/rootpath/-/rootpath-0.1.2.tgz", + "integrity": "sha1-Wzeah9ypBum5HWkKWZQ5vvJn6ms=" + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sanitize-html": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.4.0.tgz", + "integrity": "sha512-Y1OgkUiTPMqwZNRLPERSEi39iOebn2XJLbeiGOBhaJD/yLqtLGu6GE5w7evx177LeGgSE+4p4e107LMiydOf6A==", + "dependencies": { + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^6.0.0", + "is-plain-object": "^5.0.0", + "klona": "^2.0.3", + "parse-srcset": "^1.0.2", + "postcss": "^8.0.2" + } + }, + "node_modules/sanitize-html/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "node_modules/scmp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz", + "integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==" + }, + "node_modules/seek-bzip": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", + "dependencies": { + "commander": "^2.8.1" + }, + "bin": { + "seek-bunzip": "bin/seek-bunzip", + "seek-table": "bin/seek-bzip-table" + } + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-set": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/semver-set/-/semver-set-0.1.2.tgz", + "integrity": "sha512-ds4+upjcYVTChXvPjO9x+9Xsqp/r9FCNAFmXqPZcpxf80IpD+T3AR1zVnTu6rpVm3q8J+RFTfm7kLI40E3bHPw==", + "dependencies": { + "cartesian-product": "^2.1.2", + "invariant": "^2.1.0", + "lodash": "^3.9.3", + "semver": "^4.3.6" + } + }, + "node_modules/semver-set/node_modules/lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + }, + "node_modules/semver-set/node_modules/semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dependencies": { + "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" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/send/node_modules/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==" + }, + "node_modules/send/node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" + }, + "node_modules/sequelize": { + "version": "5.22.3", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.22.3.tgz", + "integrity": "sha512-+nxf4TzdrB+PRmoWhR05TP9ukLAurK7qtKcIFv5Vhxm5Z9v+d2PcTT6Ea3YAoIQVkZ47QlT9XWAIUevMT/3l8Q==", + "deprecated": "Please update to v6 or higher! A migration guide can be found here: https://sequelize.org/v6/manual/upgrade-to-v6.html", + "dependencies": { + "bluebird": "^3.5.0", + "cls-bluebird": "^2.1.0", + "debug": "^4.1.1", + "dottie": "^2.0.0", + "inflection": "1.12.0", + "lodash": "^4.17.15", + "moment": "^2.24.0", + "moment-timezone": "^0.5.21", + "retry-as-promised": "^3.2.0", + "semver": "^6.3.0", + "sequelize-pool": "^2.3.0", + "toposort-class": "^1.0.1", + "uuid": "^3.3.3", + "validator": "^10.11.0", + "wkx": "^0.4.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/sequelize-pool": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-2.3.0.tgz", + "integrity": "sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA==", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/sequelize/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/sequelize/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/sequelize/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/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==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shasum-object": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz", + "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==", + "dependencies": { + "fast-safe-stringify": "^2.0.7" + } + }, + "node_modules/shell-quote": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", + "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" + }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + }, + "node_modules/side-channel": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz", + "integrity": "sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==", + "optional": true, + "dependencies": { + "es-abstract": "^1.17.0-next.1", + "object-inspect": "^1.7.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "optional": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/snakeize": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz", + "integrity": "sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=", + "optional": true + }, + "node_modules/sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", + "dependencies": { + "sort-keys": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-keys-length/node_modules/sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", + "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + }, + "node_modules/sqlstring": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.2.tgz", + "integrity": "sha512-vF4ZbYdKS8OnoJAWBmMxCQDkiEBkGQYU7UZPtL8flbDRSNkhaXvRJ279ZtI6M+zDaQovVU4tuRgzK5fVhvFAhg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "engines": { + "node": "*" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dependencies": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-combiner2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/stream-combiner2/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/stream-combiner2/node_modules/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==" + }, + "node_modules/stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "optional": true, + "dependencies": { + "stubs": "^3.0.0" + } + }, + "node_modules/stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "optional": true + }, + "node_modules/stream-splicer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", + "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-splicer/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/stream-splicer/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/stream-splicer/node_modules/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==" + }, + "node_modules/streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/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==" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "dependencies": { + "is-natural-number": "^4.0.1" + } + }, + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stripe": { + "version": "8.138.0", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-8.138.0.tgz", + "integrity": "sha512-Cr+jzcacXOlL1Wrd7xxcE9nk9OBF0l73Z/oCAlBHXldtRr2FRflg/2h4g4Na3LTlcLRYtx+jnKs64/WPOqmpsA==", + "dependencies": { + "@types/node": ">=8.1.0", + "qs": "^6.6.0" + }, + "engines": { + "node": "^8.1 || >=10.*" + } + }, + "node_modules/strtok3": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.0.8.tgz", + "integrity": "sha512-QLgv+oiXwXgCgp2PdPPa+Jpp4D9imK9e/0BsyfeFMr6QL6wMVqoVn9+OXQ9I7MZbmUzN6lmitTJ09uwS2OmGcw==", + "dependencies": { + "@tokenizer/token": "^0.1.1", + "@types/debug": "^4.1.5", + "peek-readable": "^3.1.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", + "optional": true + }, + "node_modules/subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dependencies": { + "minimist": "^1.1.0" + } + }, + "node_modules/subscriptions-transport-ws": { + "version": "0.9.16", + "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.16.tgz", + "integrity": "sha512-pQdoU7nC+EpStXnCfh/+ho0zE0Z+ma+i7xvj7bkXKb1dvYHSZxgRPaU6spRP+Bjzow67c/rRDoix5RT0uU9omw==", + "dependencies": { + "backo2": "^1.0.2", + "eventemitter3": "^3.1.0", + "iterall": "^1.2.1", + "symbol-observable": "^1.0.4", + "ws": "^5.2.0" + }, + "peerDependencies": { + "graphql": "^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.1 || ^14.0.2" + } + }, + "node_modules/subscriptions-transport-ws/node_modules/ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dependencies": { + "acorn-node": "^1.2.0" + } + }, + "node_modules/tabbable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-4.0.0.tgz", + "integrity": "sha512-H1XoH1URcBOa/rZZWxLxHCtOdVUEev+9vo5YdYhC9tCY4wnybX+VQrCYuy9ubkg69fCBxCONJOSLGfw0DWMffQ==" + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/teeny-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.3.tgz", + "integrity": "sha512-TZG/dfd2r6yeji19es1cUIwAlVD8y+/svB1kAC2Y0bjEyysrfbO8EZvJBRwIE6WkwmUoB7uvWLwTIhJbMXZ1Dw==", + "optional": true, + "dependencies": { + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.2.0", + "stream-events": "^1.0.5", + "uuid": "^7.0.0" + } + }, + "node_modules/teeny-request/node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/terser": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.6.0.tgz", + "integrity": "sha512-vyqLMoqadC1uR0vywqOZzriDYzgEkNJFK4q9GeyOBHIbiECHiWLKcWfbQWAUaPfxkjDhapSlZB9f7fkMrvkVjA==", + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "node_modules/through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "optional": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + }, + "node_modules/timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dependencies": { + "process": "~0.11.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/token-types": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-2.1.1.tgz", + "integrity": "sha512-wnQcqlreS6VjthyHO3Y/kpK/emflxDBNhlNUPfh7wE39KnuDdOituXomIbyI79vBtF0Ninpkh72mcuRHo+RG3Q==", + "dependencies": { + "@tokenizer/token": "^0.1.1", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=0.1.98" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tough-cookie/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + }, + "node_modules/try-to-catch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/try-to-catch/-/try-to-catch-3.0.0.tgz", + "integrity": "sha512-eIm6ZXwR35jVF8By/HdbbkcaCDTBI5PpCPkejRKrYp0jyf/DbCCcRhHD7/O9jtFI3ewsqo9WctFEiJTS6i+CQA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/ts-invariant": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.4.4.tgz", + "integrity": "sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA==", + "dependencies": { + "tslib": "^1.9.3" + } + }, + "node_modules/tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + }, + "node_modules/tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "node_modules/twilio": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/twilio/-/twilio-3.47.0.tgz", + "integrity": "sha512-c/apwtmc1Gwvn0EhjGaWaeSuQUKkGykUFJeVoIKWsXYVamAS+4WKC95H7yGNCGDHtB9x5+lxC1lkjyFzy260pg==", + "dependencies": { + "@types/express": "^4.17.3", + "axios": "^0.19.2", + "dayjs": "^1.8.21", + "jsonwebtoken": "^8.5.1", + "lodash": "^4.17.15", + "q": "2.0.x", + "qs": "^6.9.1", + "rootpath": "^0.1.2", + "scmp": "^2.1.0", + "url-parse": "^1.4.7", + "xmlbuilder": "^13.0.2" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/twilio/node_modules/qs": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/uglify-js": { + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.7.tgz", + "integrity": "sha512-SIZhkoh+U/wjW+BHGhVwE9nt8tWJspncloBcFapkpGRwNPqcH8pzX36BXe3TPBjzHWPMUZotpCigak/udWNr1Q==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/umd": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", + "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", + "bin": { + "umd": "bin/cli.js" + } + }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/undeclared-identifiers": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", + "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", + "dependencies": { + "acorn-node": "^1.3.0", + "dash-ast": "^1.0.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + }, + "bin": { + "undeclared-identifiers": "bin.js" + } + }, + "node_modules/uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "optional": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uppload": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uppload/-/uppload-3.2.1.tgz", + "integrity": "sha512-WBTcXe5yCbQ5XJh5vL/u8LhKZ5AnXzNzWT3sQG9iFoLRivyljXP4Gg78qNA74+GofFnBz8IO0iK4B7jTOlz2dQ==", + "dependencies": { + "cropperjs": "^1.5.6", + "download": "^8.0.0", + "focus-trap": "^5.1.0", + "mitt": "^1.2.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-parse": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", + "engines": { + "node": ">= 4" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "node_modules/util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz", + "integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validator": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" + }, + "node_modules/walkdir": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.4.1.tgz", + "integrity": "sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ==", + "optional": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/weak-map": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.5.tgz", + "integrity": "sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes=" + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz", + "integrity": "sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ==", + "optional": true, + "dependencies": { + "is-bigint": "^1.0.0", + "is-boolean-object": "^1.0.0", + "is-number-object": "^1.0.3", + "is-string": "^1.0.4", + "is-symbol": "^1.0.2" + } + }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "optional": true, + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "node_modules/which-typed-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.2.tgz", + "integrity": "sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ==", + "dependencies": { + "available-typed-arrays": "^1.0.2", + "es-abstract": "^1.17.5", + "foreach": "^2.0.5", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.1", + "is-typed-array": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/winston": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", + "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", + "dependencies": { + "@dabh/diagnostics": "^2.0.2", + "async": "^3.1.0", + "is-stream": "^2.0.0", + "logform": "^2.2.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + }, + "engines": { + "node": ">= 6.4.0" + } + }, + "node_modules/winston-transport": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", + "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", + "dependencies": { + "readable-stream": "^2.3.7", + "triple-beam": "^1.2.0" + }, + "engines": { + "node": ">= 6.4.0" + } + }, + "node_modules/winston-transport/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/winston-transport/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/winston-transport/node_modules/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==" + }, + "node_modules/with-open-file": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/with-open-file/-/with-open-file-0.1.7.tgz", + "integrity": "sha512-ecJS2/oHtESJ1t3ZfMI3B7KIDKyfN0O16miWxdn30zdh66Yd3LsRFebXZXq6GU4xfxLf6nVxp9kIqElb5fqczA==", + "dependencies": { + "p-finally": "^1.0.0", + "p-try": "^2.1.0", + "pify": "^4.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wkx": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.8.tgz", + "integrity": "sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/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==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlbuilder": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", + "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/xss": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.7.tgz", + "integrity": "sha512-A9v7tblGvxu8TWXQC9rlpW96a+LN1lyw6wyhpTmmGW+FwRMactchBR3ROKSi33UPCUcUHSu8s9YP6F+K3Mw//w==", + "dependencies": { + "commander": "^2.20.3", + "cssfilter": "0.0.10" + }, + "bin": { + "xss": "bin/xss" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/zen-observable": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", + "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" + }, + "node_modules/zen-observable-ts": { + "version": "0.8.21", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz", + "integrity": "sha512-Yj3yXweRc8LdRMrCC8nIc4kkjWecPAUVh0TI0OUrWXx6aX790vLcDlWca6I4vsyCGH3LpWxq0dJRcMOFoVqmeg==", + "dependencies": { + "tslib": "^1.9.3", + "zen-observable": "^0.8.0" + } + } + }, + "dependencies": { + "@apollo/protobufjs": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.0.4.tgz", + "integrity": "sha512-EE3zx+/D/wur/JiLp6VCiw1iYdyy1lCJMf8CGPkLeDt5QJrN4N8tKFx33Ah4V30AUQzMk7Uz4IXKZ1LOj124gA==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.0", + "@types/node": "^10.1.0", + "long": "^4.0.0" + }, + "dependencies": { + "@types/node": { + "version": "10.17.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.26.tgz", + "integrity": "sha512-myMwkO2Cr82kirHY8uknNRHEVtn0wV3DTQfkrjx17jmkstDRZ24gNUdl8AHXVyVclTYI/bNjgTPTAWvWLqXqkw==" + } + } + }, + "@apollographql/apollo-tools": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.4.8.tgz", + "integrity": "sha512-W2+HB8Y7ifowcf3YyPHgDI05izyRtOeZ4MqIr7LbTArtmJ0ZHULWpn84SGMW7NAvTV1tFExpHlveHhnXuJfuGA==", + "requires": { + "apollo-env": "^0.6.5" + } + }, + "@apollographql/graphql-playground-html": { + "version": "1.6.26", + "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.26.tgz", + "integrity": "sha512-XAwXOIab51QyhBxnxySdK3nuMEUohhDsHQ5Rbco/V1vjlP75zZ0ZLHD9dTpXTN8uxKxopb2lUvJTq+M4g2Q0HQ==", + "requires": { + "xss": "^1.0.6" + } + }, + "@dabh/diagnostics": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", + "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "requires": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "@fast-csv/format": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@fast-csv/format/-/format-4.3.5.tgz", + "integrity": "sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==", + "requires": { + "@types/node": "^14.0.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.isboolean": "^3.0.3", + "lodash.isequal": "^4.5.0", + "lodash.isfunction": "^3.0.9", + "lodash.isnil": "^4.0.0" + } + }, + "@fast-csv/parse": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/@fast-csv/parse/-/parse-4.3.6.tgz", + "integrity": "sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==", + "requires": { + "@types/node": "^14.0.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.groupby": "^4.6.0", + "lodash.isfunction": "^3.0.9", + "lodash.isnil": "^4.0.0", + "lodash.isundefined": "^3.0.1", + "lodash.uniq": "^4.5.0" + } + }, + "@firebase/app-types": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.6.1.tgz", + "integrity": "sha512-L/ZnJRAq7F++utfuoTKX4CLBG5YR7tFO3PLzG1/oXXKEezJ0kRL3CMRoueBEmTCzVb/6SIs2Qlaw++uDgi5Xyg==" + }, + "@firebase/auth-interop-types": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.5.tgz", + "integrity": "sha512-88h74TMQ6wXChPA6h9Q3E1Jg6TkTHep2+k63OWg3s0ozyGVMeY+TTOti7PFPzq5RhszQPQOoCi59es4MaRvgCw==", + "requires": {} + }, + "@firebase/component": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.15.tgz", + "integrity": "sha512-HqFb1qQl1vtlUMIzPM15plNz27jqM8DWjuQQuGeDfG+4iRRflwKfgNw1BOyoP4kQ8vOBCL7t/71yPXSomNdJdQ==", + "requires": { + "@firebase/util": "0.2.50", + "tslib": "^1.11.1" + } + }, + "@firebase/database": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.6.tgz", + "integrity": "sha512-TqUJOaCATF/h3wpqhPT9Fz1nZI6gBv/M2pHZztUjX4A9o9Bq93NyqUurYiZnGB7zpSkEADFCVT4f0VBrWdHlNw==", + "requires": { + "@firebase/auth-interop-types": "0.1.5", + "@firebase/component": "0.1.15", + "@firebase/database-types": "0.5.1", + "@firebase/logger": "0.2.5", + "@firebase/util": "0.2.50", + "faye-websocket": "0.11.3", + "tslib": "^1.11.1" + } + }, + "@firebase/database-types": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.5.1.tgz", + "integrity": "sha512-onQxom1ZBYBJ648w/VNRzUewovEDAH7lvnrrpCd69ukkyrMk6rGEO/PQ9BcNEbhlNtukpsqRS0oNOFlHs0FaSA==", + "requires": { + "@firebase/app-types": "0.6.1" + } + }, + "@firebase/logger": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.5.tgz", + "integrity": "sha512-qqw3m0tWs/qrg7axTZG/QZq24DIMdSY6dGoWuBn08ddq7+GLF5HiqkRj71XznYeUUbfRq5W9C/PSFnN4JxX+WA==" + }, + "@firebase/util": { + "version": "0.2.50", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.50.tgz", + "integrity": "sha512-vFE6+Jfc25u0ViSpFxxq0q5s+XmuJ/y7CL3ud79RQe+WLFFg+j0eH1t23k0yNSG9vZNM7h3uHRIXbV97sYLAyw==", + "requires": { + "tslib": "^1.11.1" + } + }, + "@google-cloud/common": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-2.4.0.tgz", + "integrity": "sha512-zWFjBS35eI9leAHhjfeOYlK5Plcuj/77EzstnrJIZbKgF/nkqjcQuGiMCpzCwOfPyUbz8ZaEOYgbHa759AKbjg==", + "optional": true, + "requires": { + "@google-cloud/projectify": "^1.0.0", + "@google-cloud/promisify": "^1.0.0", + "arrify": "^2.0.0", + "duplexify": "^3.6.0", + "ent": "^2.2.0", + "extend": "^3.0.2", + "google-auth-library": "^5.5.0", + "retry-request": "^4.0.0", + "teeny-request": "^6.0.0" + }, + "dependencies": { + "gcp-metadata": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-3.5.0.tgz", + "integrity": "sha512-ZQf+DLZ5aKcRpLzYUyBS3yo3N0JSa82lNDO8rj3nMSlovLcz2riKFBsYgDzeXcv75oo5eqB2lx+B14UvPoCRnA==", + "optional": true, + "requires": { + "gaxios": "^2.1.0", + "json-bigint": "^0.3.0" + } + }, + "google-auth-library": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-5.10.1.tgz", + "integrity": "sha512-rOlaok5vlpV9rSiUu5EpR0vVpc+PhN62oF4RyX/6++DG1VsaulAFEMlDYBLjJDDPI6OcNOCGAKy9UVB/3NIDXg==", + "optional": true, + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^2.1.0", + "gcp-metadata": "^3.4.0", + "gtoken": "^4.1.0", + "jws": "^4.0.0", + "lru-cache": "^5.0.0" + } + }, + "google-p12-pem": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.4.tgz", + "integrity": "sha512-S4blHBQWZRnEW44OcR7TL9WR+QCqByRvhNDZ/uuQfpxywfupikf/miba8js1jZi6ZOGv5slgSuoshCWh6EMDzg==", + "optional": true, + "requires": { + "node-forge": "^0.9.0" + } + }, + "gtoken": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.4.tgz", + "integrity": "sha512-VxirzD0SWoFUo5p8RDP8Jt2AGyOmyYcT/pOUgDKJCK+iSw0TMqwrVfY37RXTNmoKwrzmDHSk0GMT9FsgVmnVSA==", + "optional": true, + "requires": { + "gaxios": "^2.1.0", + "google-p12-pem": "^2.0.0", + "jws": "^4.0.0", + "mime": "^2.2.0" + } + }, + "json-bigint": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.1.tgz", + "integrity": "sha512-DGWnSzmusIreWlEupsUelHrhwmPPE+FiQvg+drKfk2p+bdEYa5mp4PJ8JsCWqae0M2jQNb0HPvnwvf1qOTThzQ==", + "optional": true, + "requires": { + "bignumber.js": "^9.0.0" + } + }, + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "optional": true + }, + "node-forge": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.2.tgz", + "integrity": "sha512-naKSScof4Wn+aoHU6HBsifh92Zeicm1GDQKd1vp3Y/kOi8ub0DozCa9KpvYNCXslFHYRmLNiqRopGdTGwNLpNw==", + "optional": true + } + } + }, + "@google-cloud/firestore": { + "version": "3.8.6", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-3.8.6.tgz", + "integrity": "sha512-ox80NbrM1MLJgvAAUd1quFLx/ie/nSjrk1PtscSicpoYDlKb9e6j7pHrVpbopBMyliyfNl3tLJWaDh+x+uCXqw==", + "optional": true, + "requires": { + "deep-equal": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^1.15.3", + "readable-stream": "^3.4.0", + "through2": "^3.0.0" + } + }, + "@google-cloud/paginator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-2.0.3.tgz", + "integrity": "sha512-kp/pkb2p/p0d8/SKUu4mOq8+HGwF8NPzHWkj+VKrIPQPyMRw8deZtrO/OcSiy9C/7bpfU5Txah5ltUNfPkgEXg==", + "optional": true, + "requires": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + } + }, + "@google-cloud/projectify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-1.0.4.tgz", + "integrity": "sha512-ZdzQUN02eRsmTKfBj9FDL0KNDIFNjBn/d6tHQmA/+FImH5DO6ZV8E7FzxMgAUiVAUq41RFAkb25p1oHOZ8psfg==", + "optional": true + }, + "@google-cloud/promisify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-1.0.4.tgz", + "integrity": "sha512-VccZDcOql77obTnFh0TbNED/6ZbbmHDf8UMNnzO1d5g9V0Htfm4k5cllY8P1tJsRKC3zWYGRLaViiupcgVjBoQ==", + "optional": true + }, + "@google-cloud/storage": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-4.7.0.tgz", + "integrity": "sha512-f0guAlbeg7Z0m3gKjCfBCu7FG9qS3M3oL5OQQxlvGoPtK7/qg3+W+KQV73O2/sbuS54n0Kh2mvT5K2FWzF5vVQ==", + "optional": true, + "requires": { + "@google-cloud/common": "^2.1.1", + "@google-cloud/paginator": "^2.0.0", + "@google-cloud/promisify": "^1.0.0", + "arrify": "^2.0.0", + "compressible": "^2.0.12", + "concat-stream": "^2.0.0", + "date-and-time": "^0.13.0", + "duplexify": "^3.5.0", + "extend": "^3.0.2", + "gaxios": "^3.0.0", + "gcs-resumable-upload": "^2.2.4", + "hash-stream-validation": "^0.2.2", + "mime": "^2.2.0", + "mime-types": "^2.0.8", + "onetime": "^5.1.0", + "p-limit": "^2.2.0", + "pumpify": "^2.0.0", + "readable-stream": "^3.4.0", + "snakeize": "^0.1.0", + "stream-events": "^1.0.1", + "through2": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "gaxios": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-3.0.3.tgz", + "integrity": "sha512-PkzQludeIFhd535/yucALT/Wxyj/y2zLyrMwPcJmnLHDugmV49NvAi/vb+VUq/eWztATZCNcb8ue+ywPG+oLuw==", + "optional": true, + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.3.0" + } + }, + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "optional": true + } + } + }, + "@grpc/grpc-js": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.0.5.tgz", + "integrity": "sha512-Hm+xOiqAhcpT9RYM8lc15dbQD7aQurM7ZU8ulmulepiPlN7iwBXXwP3vSBUimoFoApRqz7pSIisXU8pZaCB4og==", + "optional": true, + "requires": { + "semver": "^6.2.0" + } + }, + "@grpc/proto-loader": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.4.tgz", + "integrity": "sha512-HTM4QpI9B2XFkPz7pjwMyMgZchJ93TVkL3kWPW8GDMDKYxsMnmf4w2TNMJK7+KNiYHS5cJrCEAFlF+AwtXWVPA==", + "optional": true, + "requires": { + "lodash.camelcase": "^4.3.0", + "protobufjs": "^6.8.6" + } + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, + "@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" + }, + "@tokenizer/token": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz", + "integrity": "sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w==" + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "optional": true + }, + "@types/accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", + "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", + "requires": { + "@types/node": "*" + } + }, + "@types/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-P1bffQfhD3O4LW0ioENXUhZ9OIa0Zn+P7M+pWgkCKaT53wVLSq0mrKksCID/FGHpFhRSxRGhgrQmfhRuzwtKdg==" + }, + "@types/cookies": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.4.tgz", + "integrity": "sha512-oTGtMzZZAVuEjTwCjIh8T8FrC8n/uwy+PG0yTvQcdZ7etoel7C7/3MSd7qrukENTgQtotG7gvBlBojuVs7X5rw==", + "requires": { + "@types/connect": "*", + "@types/express": "*", + "@types/keygrip": "*", + "@types/node": "*" + } + }, + "@types/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-invOmosX0DqbpA+cE2yoHGUlF/blyf7nB0OGYBBiH27crcVm5NmFaZkLP4Ta1hGaesckCi5lVLlydNJCxkTOSg==", + "requires": { + "@types/express": "*" + } + }, + "@types/debug": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz", + "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==" + }, + "@types/express": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.4.tgz", + "integrity": "sha512-DO1L53rGqIDUEvOjJKmbMEQ5Z+BM2cIEPy/eV3En+s166Gz+FeuzRerxcab757u/U4v4XF4RYrZPmqKa+aY/2w==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "*", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.8.tgz", + "integrity": "sha512-1SJZ+R3Q/7mLkOD9ewCBDYD2k0WyZQtWYqF/2VvoNN2/uhI49J9CDN4OAm+wGMA0DbArA4ef27xl4+JwMtGggw==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/fs-capacitor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz", + "integrity": "sha512-FKVPOCFbhCvZxpVAMhdBdTfVfXUpsh15wFHgqOKxh9N9vzWZVuWCSijZ5T4U34XYNnuj2oduh6xcs1i+LPI+BQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/fs-extra": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.1.tgz", + "integrity": "sha512-TcUlBem321DFQzBNuz8p0CLLKp0VvF/XH9E4KHNmgwyp4E3AfgI5cjiIVZWlbfThBop2qxFIh4+LeY6hVWWZ2w==", + "optional": true, + "requires": { + "@types/node": "*" + } + }, + "@types/graphql-upload": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@types/graphql-upload/-/graphql-upload-8.0.3.tgz", + "integrity": "sha512-hmLg9pCU/GmxBscg8GCr1vmSoEmbItNNxdD5YH2TJkXm//8atjwuprB+xJBK714JG1dkxbbhp5RHX+Pz1KsCMA==", + "requires": { + "@types/express": "*", + "@types/fs-capacitor": "*", + "@types/koa": "*", + "graphql": "^14.5.3" + } + }, + "@types/http-assert": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz", + "integrity": "sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ==" + }, + "@types/keygrip": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", + "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==" + }, + "@types/koa": { + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.11.3.tgz", + "integrity": "sha512-ABxVkrNWa4O/Jp24EYI/hRNqEVRlhB9g09p48neQp4m3xL1TJtdWk2NyNQSMCU45ejeELMQZBYyfstyVvO2H3Q==", + "requires": { + "@types/accepts": "*", + "@types/content-disposition": "*", + "@types/cookies": "*", + "@types/http-assert": "*", + "@types/keygrip": "*", + "@types/koa-compose": "*", + "@types/node": "*" + } + }, + "@types/koa-compose": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", + "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", + "requires": { + "@types/koa": "*" + } + }, + "@types/long": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", + "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + }, + "@types/mime": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.2.tgz", + "integrity": "sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q==" + }, + "@types/node": { + "version": "14.0.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.14.tgz", + "integrity": "sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ==" + }, + "@types/node-fetch": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", + "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "@types/qs": { + "version": "6.9.3", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz", + "integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA==" + }, + "@types/range-parser": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" + }, + "@types/readable-stream": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.9.tgz", + "integrity": "sha512-sqsgQqFT7HmQz/V5jH1O0fvQQnXAJO46Gg9LRO/JPfjmVmGUlcx831TZZO3Y3HtWhIkzf3kTsNT0Z0kzIhIvZw==", + "requires": { + "@types/node": "*", + "safe-buffer": "*" + } + }, + "@types/serve-static": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.4.tgz", + "integrity": "sha512-jTDt0o/YbpNwZbQmE/+2e+lfjJEJJR0I3OFaKQKPWkASkCoW3i6fsUnqudSMcNAfbtmADGu8f4MV4q+GqULmug==", + "requires": { + "@types/express-serve-static-core": "*", + "@types/mime": "*" + } + }, + "@types/ws": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.2.6.tgz", + "integrity": "sha512-Q07IrQUSNpr+cXU4E4LtkSIBPie5GLZyyMC1QtQYRLWz701+XcoVygGUZgvLqElq1nU4ICldMYPnexlBsg3dqQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/yauzl": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz", + "integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==", + "optional": true, + "requires": { + "@types/node": "*" + } + }, + "@wry/equality": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.1.11.tgz", + "integrity": "sha512-mwEVBDUVODlsQQ5dfuLUS5/Tf7jqUKyhKYHmVi4fPB6bDMOfWvUPJmKgS1Z7Za/sOI3vzWt4+O7yCiL/70MogA==", + "requires": { + "tslib": "^1.9.3" + } + }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "optional": true, + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "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" + } + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" + }, + "agent-base": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz", + "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==", + "optional": true, + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + } + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + }, + "dependencies": { + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + } + } + }, + "ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "apollo-cache-control": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.11.1.tgz", + "integrity": "sha512-6iHa8TkcKt4rx5SKRzDNjUIpCQX+7/FlZwD7vRh9JDnM4VH8SWhpj8fUR3CiEY8Kuc4ChXnOY8bCcMju5KPnIQ==", + "requires": { + "apollo-server-env": "^2.4.5", + "apollo-server-plugin-base": "^0.9.1" + } + }, + "apollo-datasource": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.7.2.tgz", + "integrity": "sha512-ibnW+s4BMp4K2AgzLEtvzkjg7dJgCaw9M5b5N0YKNmeRZRnl/I/qBTQae648FsRKgMwTbRQIvBhQ0URUFAqFOw==", + "requires": { + "apollo-server-caching": "^0.5.2", + "apollo-server-env": "^2.4.5" + } + }, + "apollo-engine-reporting": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/apollo-engine-reporting/-/apollo-engine-reporting-2.2.1.tgz", + "integrity": "sha512-HPwf70p4VbxKEagHYWTwldqfYNekBE33BXcryHI9owxMm5B8/vutQfx67+4Bf351kOpndCG9I91aOiFBfC2/iQ==", + "requires": { + "apollo-engine-reporting-protobuf": "^0.5.2", + "apollo-graphql": "^0.4.0", + "apollo-server-caching": "^0.5.2", + "apollo-server-env": "^2.4.5", + "apollo-server-errors": "^2.4.2", + "apollo-server-plugin-base": "^0.9.1", + "apollo-server-types": "^0.5.1", + "async-retry": "^1.2.1", + "uuid": "^8.0.0" + } + }, + "apollo-engine-reporting-protobuf": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.5.2.tgz", + "integrity": "sha512-4wm9FR3B7UvJxcK/69rOiS5CAJPEYKufeRWb257ZLfX7NGFTMqvbc1hu4q8Ch7swB26rTpkzfsftLED9DqH9qg==", + "requires": { + "@apollo/protobufjs": "^1.0.3" + } + }, + "apollo-env": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/apollo-env/-/apollo-env-0.6.5.tgz", + "integrity": "sha512-jeBUVsGymeTHYWp3me0R2CZRZrFeuSZeICZHCeRflHTfnQtlmbSXdy5E0pOyRM9CU4JfQkKDC98S1YglQj7Bzg==", + "requires": { + "@types/node-fetch": "2.5.7", + "core-js": "^3.0.1", + "node-fetch": "^2.2.0", + "sha.js": "^2.4.11" + } + }, + "apollo-graphql": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.4.5.tgz", + "integrity": "sha512-0qa7UOoq7E71kBYE7idi6mNQhHLVdMEDInWk6TNw3KsSWZE2/I68gARP84Mj+paFTO5NYuw1Dht66PVX76Cc2w==", + "requires": { + "apollo-env": "^0.6.5", + "lodash.sortby": "^4.7.0" + } + }, + "apollo-link": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.14.tgz", + "integrity": "sha512-p67CMEFP7kOG1JZ0ZkYZwRDa369w5PIjtMjvrQd/HnIV8FRsHRqLqK+oAZQnFa1DDdZtOtHTi+aMIW6EatC2jg==", + "requires": { + "apollo-utilities": "^1.3.0", + "ts-invariant": "^0.4.0", + "tslib": "^1.9.3", + "zen-observable-ts": "^0.8.21" + } + }, + "apollo-server-caching": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.2.tgz", + "integrity": "sha512-HUcP3TlgRsuGgeTOn8QMbkdx0hLPXyEJehZIPrcof0ATz7j7aTPA4at7gaiFHCo8gk07DaWYGB3PFgjboXRcWQ==", + "requires": { + "lru-cache": "^5.0.0" + } + }, + "apollo-server-core": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.15.1.tgz", + "integrity": "sha512-ZRSK3uVPS6YkIV3brm2CjzVphg6NHY0PRhFojZD8BjoQlGo3+pPRP1IHFDvC3UzybGWfyCelcfF4YiVqh4GJHw==", + "requires": { + "@apollographql/apollo-tools": "^0.4.3", + "@apollographql/graphql-playground-html": "1.6.26", + "@types/graphql-upload": "^8.0.0", + "@types/ws": "^7.0.0", + "apollo-cache-control": "^0.11.1", + "apollo-datasource": "^0.7.2", + "apollo-engine-reporting": "^2.2.1", + "apollo-server-caching": "^0.5.2", + "apollo-server-env": "^2.4.5", + "apollo-server-errors": "^2.4.2", + "apollo-server-plugin-base": "^0.9.1", + "apollo-server-types": "^0.5.1", + "apollo-tracing": "^0.11.1", + "fast-json-stable-stringify": "^2.0.0", + "graphql-extensions": "^0.12.4", + "graphql-tag": "^2.9.2", + "graphql-tools": "^4.0.0", + "graphql-upload": "^8.0.2", + "loglevel": "^1.6.7", + "sha.js": "^2.4.11", + "subscriptions-transport-ws": "^0.9.11", + "ws": "^6.0.0" + } + }, + "apollo-server-env": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.5.tgz", + "integrity": "sha512-nfNhmGPzbq3xCEWT8eRpoHXIPNcNy3QcEoBlzVMjeglrBGryLG2LXwBSPnVmTRRrzUYugX0ULBtgE3rBFNoUgA==", + "requires": { + "node-fetch": "^2.1.2", + "util.promisify": "^1.0.0" + } + }, + "apollo-server-errors": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.4.2.tgz", + "integrity": "sha512-FeGxW3Batn6sUtX3OVVUm7o56EgjxDlmgpTLNyWcLb0j6P8mw9oLNyAm3B+deHA4KNdNHO5BmHS2g1SJYjqPCQ==", + "requires": {} + }, + "apollo-server-express": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.15.1.tgz", + "integrity": "sha512-anNb9HJo+KTpgvUqiPOjEl4wPq8y8NmWaIUz/QqPZlhIEDdf7wd/kQo3Sdbov++7J9JNJx6Ownnvw+wxfogUgA==", + "requires": { + "@apollographql/graphql-playground-html": "1.6.26", + "@types/accepts": "^1.3.5", + "@types/body-parser": "1.19.0", + "@types/cors": "^2.8.4", + "@types/express": "4.17.4", + "accepts": "^1.3.5", + "apollo-server-core": "^2.15.1", + "apollo-server-types": "^0.5.1", + "body-parser": "^1.18.3", + "cors": "^2.8.4", + "express": "^4.17.1", + "graphql-subscriptions": "^1.0.0", + "graphql-tools": "^4.0.0", + "parseurl": "^1.3.2", + "subscriptions-transport-ws": "^0.9.16", + "type-is": "^1.6.16" + } + }, + "apollo-server-plugin-base": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.9.1.tgz", + "integrity": "sha512-kvrX4Z3FdpjrZdHkyl5iY2A1Wvp4b6KQp00DeZqss7GyyKNUBKr80/7RQgBLEw7EWM7WB19j459xM/TjvW0FKQ==", + "requires": { + "apollo-server-types": "^0.5.1" + } + }, + "apollo-server-types": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.5.1.tgz", + "integrity": "sha512-my2cPw+DAb2qVnIuBcsRKGyS28uIc2vjFxa1NpRoJZe9gK0BWUBk7wzXnIzWy3HZ5Er11e/40MPTUesNfMYNVA==", + "requires": { + "apollo-engine-reporting-protobuf": "^0.5.2", + "apollo-server-caching": "^0.5.2", + "apollo-server-env": "^2.4.5" + } + }, + "apollo-tracing": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.11.1.tgz", + "integrity": "sha512-l7g+uILw7v32GA46IRXIx5XXbZhFI96BhSqrGK9yyvfq+NMcvVZrj3kIhRImPGhAjMdV+5biA/jztabElAbDjg==", + "requires": { + "apollo-server-env": "^2.4.5", + "apollo-server-plugin-base": "^0.9.1" + } + }, + "apollo-utilities": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.3.4.tgz", + "integrity": "sha512-pk2hiWrCXMAy2fRPwEyhvka+mqwzeP60Jr1tRYi5xru+3ko94HI9o6lK0CT33/w4RDlxWchmdhDCrvdr+pHCig==", + "requires": { + "@wry/equality": "^0.1.2", + "fast-json-stable-stringify": "^2.0.0", + "ts-invariant": "^0.4.0", + "tslib": "^1.10.0" + } + }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, + "archive-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", + "integrity": "sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA=", + "requires": { + "file-type": "^4.2.0" + }, + "dependencies": { + "file-type": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", + "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=" + } + } + }, + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "optional": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "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" + } + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "async-retry": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.1.tgz", + "integrity": "sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA==", + "requires": { + "retry": "0.12.0" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + }, + "available-typed-arrays": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz", + "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==", + "requires": { + "array-filter": "^1.0.0" + } + }, + "aws-sdk": { + "version": "2.860.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.860.0.tgz", + "integrity": "sha512-BUBWw28PNDhRDnPEnXiPEvgTWD8Iyq5pl9lk/WhXC/vkACJ3aUVe+sicezI1/JQRjLrO3R6w7X20YknVWfAibA==", + "requires": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + }, + "dependencies": { + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } + } + }, + "aws-serverless-express": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/aws-serverless-express/-/aws-serverless-express-3.3.8.tgz", + "integrity": "sha512-2TQdF5EhxnAtGeEi+wSi2M3xCfpiemuImnpU7HKih3onH0izJ/G2tkM+gwcGHZEsW/gLWFl/JjQAYGa3fILfvw==", + "requires": { + "binary-case": "^1.0.0", + "type-is": "^1.6.16" + } + }, + "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.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, + "axios": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", + "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "requires": { + "follow-redirects": "1.5.10" + } + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "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" + }, + "dependencies": { + "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==" + } + } + }, + "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" + } + }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + }, + "bignumber.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", + "optional": true + }, + "binary-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/binary-case/-/binary-case-1.1.4.tgz", + "integrity": "sha512-9Kq8m6NZTAgy05Ryuh7U3Qc4/ujLQU1AZ5vMw4cr3igTdi5itZC6kCNrRr2X8NzPiDn2oUIFTfa71DKMnue/Zg==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + }, + "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": { + "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" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "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" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + } + } + }, + "bootstrap-select": { + "version": "1.13.18", + "resolved": "https://registry.npmjs.org/bootstrap-select/-/bootstrap-select-1.13.18.tgz", + "integrity": "sha512-V1IzK4rxBq5FrJtkzSH6RmFLFBsjx50byFbfAf8jYyXROWs7ZpprGjdHeoyq2HSsHyjJhMMwjsQhRoYAfxCGow==", + "requires": {} + }, + "bowser": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.9.0.tgz", + "integrity": "sha512-2ld76tuLBNFekRgmJfT2+3j5MIrP6bFict8WAIT3beq+srz1gcKNAdNKMqHqauQt63NmAa88HfP1/Ypa9Er3HA==" + }, + "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" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browser-pack": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", + "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", + "requires": { + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "JSONStream": "^1.0.3", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "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==" + } + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "requires": { + "resolve": "^1.17.0" + } + }, + "browserify": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz", + "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==", + "requires": { + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^2.0.0", + "browserify-zlib": "~0.2.0", + "buffer": "~5.2.1", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.1", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^3.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.2.1", + "JSONStream": "^1.0.3", + "labeled-stream-splicer": "^2.0.0", + "mkdirp-classic": "^0.5.2", + "module-deps": "^6.2.3", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "^1.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum-object": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^3.0.0", + "stream-http": "^3.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.12.0", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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==" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "requires": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "requires": { + "pako": "~1.0.5" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "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=" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "busboy": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz", + "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==", + "requires": { + "dicer": "0.3.0" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + } + } + }, + "cached-path-relative": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", + "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==" + }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + } + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "camelize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", + "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + }, + "cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", + "requires": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + } + }, + "cartesian-product": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cartesian-product/-/cartesian-product-2.1.2.tgz", + "integrity": "sha1-yahGLFSrGaDF/TIZKSLiOatMpP0=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "child_process": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz", + "integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o=" + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "claudia": { + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/claudia/-/claudia-5.12.0.tgz", + "integrity": "sha512-ukgOGUNeIaU23xQB5r41AqGPAcq8bBd5LGz4Q880aRgGSW6VGHVMD/srsZcWM6mP4XKSmaofHzmJfoIXSmlJFg==", + "requires": { + "archiver": "^3.0.0", + "aws-sdk": "^2.599.0", + "fs-extra": "^6.0.1", + "glob": "^7.1.2", + "gunzip-maybe": "^1.4.0", + "https-proxy-agent": "^3.0.0", + "minimal-request-promise": "^1.1.0", + "minimist": "^1.2.0", + "oh-no-i-insist": "^1.1.1", + "sequential-promise-map": "^1.0.0", + "tar-fs": "^1.14.0", + "uuid": "^2.0.1", + "which": "^1.3.1" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "extraneous": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "extraneous": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "extraneous": true + }, + "acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "extraneous": true + }, + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "extraneous": true, + "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" + } + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "extraneous": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "extraneous": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "extraneous": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "archiver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-3.0.0.tgz", + "integrity": "sha512-5QeR6Xc5hSA9X1rbQfcuQ6VZuUXOaEdB65Dhmk9duuRJHYif/ZyJfuyJqsQrj34PFjU5emv5/MmfgA8un06onw==", + "requires": { + "archiver-utils": "^2.0.0", + "async": "^2.0.0", + "buffer-crc32": "^0.2.1", + "glob": "^7.0.0", + "readable-stream": "^2.0.0", + "tar-stream": "^1.5.0", + "zip-stream": "^2.0.1" + } + }, + "archiver-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.0.0.tgz", + "integrity": "sha512-JRBgcVvDX4Mwu2RBF8bBaHcQCSxab7afsxAPYDQ5W+19quIPP5CfKE7Ql+UHs9wYvwsaNR8oDuhtf5iqrKmzww==", + "requires": { + "glob": "^7.0.0", + "graceful-fs": "^4.1.0", + "lazystream": "^1.0.0", + "lodash.assign": "^4.2.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.toarray": "^4.4.0", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "extraneous": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "extraneous": true + }, + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "requires": { + "lodash": "^4.17.11" + } + }, + "aws-sdk": { + "version": "2.599.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.599.0.tgz", + "integrity": "sha512-7yTXnV5SC9W6m+STbziPd1ZNVh9fTtEZ7Mm0rMqEDm/B2fJBa5xd45TwWG8JvS40X5+9jUBykiWdCuVBBx82rg==", + "requires": { + "buffer": "4.9.1", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + }, + "dependencies": { + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha1-yrHmEY8FEJXli1KBrqjBzSK/wOM=" + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha1-oWCRFxcQPAdBDO9j71Gzl8Alr5w=", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "requires": { + "pako": "~0.2.0" + } + }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha1-iQ3ZDZI6hz4I4Q5f1RpX5bfM4Ow=", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha1-vX3CauKXLQ7aJTvgYdupkjScGfA=" + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha1-h/yqOimDWOCt5uRCz86EB0DRrQQ=" + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "extraneous": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "extraneous": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "extraneous": true + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "extraneous": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "extraneous": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "extraneous": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "extraneous": true + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "extraneous": true + }, + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "extraneous": true, + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "compress-commons": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", + "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", + "requires": { + "buffer-crc32": "^0.2.1", + "crc32-stream": "^2.0.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "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=" + }, + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "requires": { + "buffer": "^5.1.0" + } + }, + "crc32-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", + "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", + "requires": { + "crc": "^3.4.4", + "readable-stream": "^2.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "extraneous": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "extraneous": true + } + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "decompress": { + "version": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz", + "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", + "extraneous": true, + "requires": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + } + }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "extraneous": true, + "requires": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "extraneous": true, + "requires": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", + "extraneous": true + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "extraneous": true, + "requires": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "extraneous": true, + "requires": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "extraneous": true + } + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "extraneous": true + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "extraneous": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dotenv": { + "version": "https://registry.npmjs.org/dotenv/-/dotenv-2.0.0.tgz", + "integrity": "sha1-vXWcNXqqcDZeAclrewvsCKbg2Uk=", + "extraneous": true + }, + "duplexify": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", + "integrity": "sha1-WSkD9dgLONA3IgVBJk1poZj7NBA=", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "extraneous": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", + "requires": { + "once": "^1.4.0" + } + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "extraneous": true + }, + "eslint": { + "version": "https://registry.npmjs.org/eslint/-/eslint-6.5.1.tgz", + "integrity": "sha512-32h99BoLYStT1iq1v2P9uwpyznQ4M2jRiFB6acitKz52Gqn+vPaMDUTB1bYi1WN4Nquj2w+t+bimYUG83DC55A==", + "extraneous": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.2", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.4.1", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "extraneous": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "eslint-config-crockford": { + "version": "https://registry.npmjs.org/eslint-config-crockford/-/eslint-config-crockford-0.2.0.tgz", + "integrity": "sha1-5tpfbqfH4HzOdnGeeNo/OHxnqlU=", + "extraneous": true + }, + "eslint-config-defaults": { + "version": "https://registry.npmjs.org/eslint-config-defaults/-/eslint-config-defaults-9.0.0.tgz", + "integrity": "sha1-oJCtwTspNeP0OzzQSKknAWVOWtU=", + "extraneous": true + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "extraneous": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "extraneous": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "extraneous": true + }, + "espree": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "extraneous": true, + "requires": { + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "extraneous": true + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "extraneous": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "extraneous": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "extraneous": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "extraneous": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "extraneous": true + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "extraneous": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "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=", + "extraneous": true + }, + "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=", + "extraneous": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "extraneous": true + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "extraneous": true, + "requires": { + "pend": "~1.2.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "extraneous": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "extraneous": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=", + "extraneous": true + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "extraneous": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "extraneous": true + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha1-a+Dem+mYzhavivwkSXue6bfM2a0=" + }, + "fs-extra": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", + "integrity": "sha1-irwSj3lG4xATXdyTuYvdtBDno0s=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "extraneous": true + }, + "get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "extraneous": true, + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "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" + } + }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "extraneous": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "extraneous": true + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "extraneous": true + }, + "gunzip-maybe": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.1.tgz", + "integrity": "sha1-Occu2J0bSbpwjhh3ZQBIiQKlICc=", + "requires": { + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "extraneous": true + }, + "https-proxy-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.0.tgz", + "integrity": "sha512-y4jAxNEihqvBI5F3SaO2rtsjIOnnNA8sEbuiP+UhJZJHeM2NRm6c09ax2tgqme+SgUUvjao2fJXF4h3D6Cb2HQ==", + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "extraneous": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha1-UL8k5bnIu5ivSWTJQc2wkY2ntgs=" + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "extraneous": true + }, + "import-fresh": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", + "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", + "extraneous": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "extraneous": true + }, + "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.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "extraneous": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + } + }, + "is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha1-yGKQHDwWH7CdrHzcfnhPgOmPLxQ=" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "extraneous": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "extraneous": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "extraneous": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=" + }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", + "extraneous": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "extraneous": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "extraneous": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "jasmine": { + "version": "https://registry.npmjs.org/jasmine/-/jasmine-2.99.0.tgz", + "integrity": "sha1-jKctEC5jm4Z8ZImFbg4YqceqQrc=", + "extraneous": true, + "requires": { + "exit": "^0.1.2", + "glob": "^7.0.6", + "jasmine-core": "~2.99.0" + } + }, + "jasmine-core": { + "version": "2.99.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz", + "integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=", + "extraneous": true + }, + "jasmine-spec-reporter": { + "version": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-2.7.0.tgz", + "integrity": "sha1-QpB/+ImVKhKcCvwpKeGV9OdMmP8=", + "extraneous": true, + "requires": { + "colors": "1.1.2" + } + }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "extraneous": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "extraneous": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "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==", + "extraneous": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "extraneous": true + }, + "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" + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "requires": { + "readable-stream": "^2.0.5" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "extraneous": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lodash": { + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz", + "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==" + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "extraneous": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "extraneous": true + } + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "extraneous": true + }, + "minimal-request-promise": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/minimal-request-promise/-/minimal-request-promise-1.5.0.tgz", + "integrity": "sha1-YPXX9VtAJtGXB04uFVYm1MxcLrw=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "extraneous": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "extraneous": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "extraneous": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "extraneous": true + }, + "oh-no-i-insist": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/oh-no-i-insist/-/oh-no-i-insist-1.1.1.tgz", + "integrity": "sha1-r28S4tQzZoObrkX4yHC5dqEe7jU=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "extraneous": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "extraneous": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "extraneous": true + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=" + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "extraneous": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "extraneous": true + }, + "peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha1-OzXYS3zLvSYv/zHcENpWhW6tbWc=", + "requires": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "extraneous": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "extraneous": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "extraneous": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "extraneous": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "extraneous": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "extraneous": true + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4=", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "extraneous": true + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "extraneous": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "extraneous": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "extraneous": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "extraneous": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "extraneous": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "rxjs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", + "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", + "extraneous": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "extraneous": true + }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "extraneous": true, + "requires": { + "commander": "~2.8.1" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "extraneous": true + }, + "sequential-promise-map": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/sequential-promise-map/-/sequential-promise-map-1.0.4.tgz", + "integrity": "sha1-6+SlyPmF5yDcjyBVVFp2x4xFGwU=" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "extraneous": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "extraneous": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "extraneous": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "extraneous": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "extraneous": true + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "extraneous": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "extraneous": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "extraneous": true, + "requires": { + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "extraneous": true + } + } + }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "extraneous": true, + "requires": { + "is-natural-number": "^4.0.1" + } + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "extraneous": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "extraneous": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "extraneous": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "extraneous": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "tar-fs": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", + "integrity": "sha1-lmpiiEHaLEAQQGqCFny9Xgxy1Qk=", + "requires": { + "chownr": "^1.0.1", + "mkdirp": "^0.5.1", + "pump": "^1.0.0", + "tar-stream": "^1.1.2" + }, + "dependencies": { + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha1-Xf6DEcM7v2/BgmH580cCxHwIqVQ=", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "tar-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", + "integrity": "sha1-+E7xaWJp1iI8pI9uHu7eP36B85U=", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.1.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.0", + "xtend": "^4.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "extraneous": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "extraneous": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "extraneous": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha1-STvUj2LXxD/N7TE6A9ytsuEhOoA=" + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "extraneous": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "extraneous": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "unbzip2-stream": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", + "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", + "extraneous": true, + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + }, + "dependencies": { + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "extraneous": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + } + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=" + }, + "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==", + "extraneous": true, + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "extraneous": true + } + } + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=" + }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "extraneous": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=", + "requires": { + "isexe": "^2.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "extraneous": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "extraneous": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "extraneous": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "zip-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.0.1.tgz", + "integrity": "sha512-c+eUhhkDpaK87G/py74wvWLtz2kzMPNCCkUApkun50ssE0oQliIQzWpTnwjB+MTKVIf2tGzIgHyqW/Y+W77ecQ==", + "requires": { + "archiver-utils": "^2.0.0", + "compress-commons": "^1.2.0", + "readable-stream": "^2.0.0" + } + } + } + }, + "clean-css": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.1.0.tgz", + "integrity": "sha512-98ALLW4NOhZpvUEoSc2dJO23xE4S4SXc4mLieCVFGo8DNLTFQ3gzi7msW1lqSYJeGZSF5r5+W3KF6cEnkILnFQ==", + "requires": { + "source-map": "~0.6.0" + } + }, + "cli-table": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.6.tgz", + "integrity": "sha512-ZkNZbnZjKERTY5NwC2SeMeLeifSPq/pubeRoTpdr3WchLlnZg6hEgvHkK5zL7KNFdd9PmHN8lxrENUwI3cE8vQ==", + "requires": { + "colors": "1.0.3" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + } + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "cls-bluebird": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz", + "integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=", + "requires": { + "is-bluebird": "^1.0.2", + "shimmer": "^1.1.0" + } + }, + "color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz", + "integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==" + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "colorspace": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", + "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", + "requires": { + "color": "3.0.x", + "text-hex": "1.0.x" + } + }, + "combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "requires": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "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" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "optional": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "optional": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "optional": true, + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + } + }, + "connect-flash": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", + "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=" + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "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" + }, + "dependencies": { + "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==" + } + } + }, + "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==" + }, + "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==" + }, + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=" + }, + "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-parser": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz", + "integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==", + "requires": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6" + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" + }, + "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" + } + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cropperjs": { + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.5.11.tgz", + "integrity": "sha512-SJUeBBhtNBnnn+UrLKluhFRIXLJn7XFPv8QN1j49X5t+BIMwkgvDev541f96bmu8Xe0TgCx3gON22KmY/VddaA==" + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "optional": true + }, + "css-b64-images": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/css-b64-images/-/css-b64-images-0.2.5.tgz", + "integrity": "sha1-QgBdgyBLK0pdk7axpWRBM7WSegI=" + }, + "cssfilter": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", + "integrity": "sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=" + }, + "cwise-compiler": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cwise-compiler/-/cwise-compiler-1.1.3.tgz", + "integrity": "sha1-9NZnQQ6FDToxOn0tt7HlBbsDTMU=", + "requires": { + "uniq": "^1.0.0" + } + }, + "dash-ast": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", + "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==" + }, + "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" + } + }, + "dasherize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz", + "integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg=" + }, + "data-uri-to-buffer": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-0.0.3.tgz", + "integrity": "sha1-GK6XmmoMqZSwYlhTkW0mYruuCxo=" + }, + "date-and-time": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-0.13.1.tgz", + "integrity": "sha512-/Uge9DJAT+s+oAcDxtBhyR8+sKjUnZbYmyhbmWjTHNtX7B7oWD8YyYdeXcBRbwSj6hVvj+IQegJam7m7czhbFw==", + "optional": true + }, + "dayjs": { + "version": "1.8.29", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.29.tgz", + "integrity": "sha512-Vm6teig8ZWK7rH/lxzVGxZJCljPdmUr6q/3f4fr5F0VWNGVkZEjZOQJsAN8hUHUqn+NK4XHNEpJZS1MwLyDcLw==" + }, + "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" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", + "requires": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, + "dependencies": { + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "requires": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + }, + "dependencies": { + "bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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==" + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + } + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "requires": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "requires": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + }, + "dependencies": { + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + } + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "requires": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" + }, + "get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "deeks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/deeks/-/deeks-2.3.0.tgz", + "integrity": "sha512-mrNI+TSdnK5s2Gal4Fv3/RGcrYGtB4NC3tTXU1hu74tYsG9JS6SzNKLD8doq6UWsglouGwC86kXqB1pdO+9hyA==" + }, + "deep-equal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.3.tgz", + "integrity": "sha512-Spqdl4H+ky45I9ByyJtXteOm9CaIrPmnIPmOhrkKGNYWeDgCvJ8jNYVCTjChxW4FqGuZnLHADc8EKRMX6+CgvA==", + "optional": true, + "requires": { + "es-abstract": "^1.17.5", + "es-get-iterator": "^1.1.0", + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.2", + "is-regex": "^1.0.5", + "isarray": "^2.0.5", + "object-is": "^1.1.2", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.2", + "which-boxed-primitive": "^1.0.1", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.2" + } + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "denque": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", + "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "deprecated-decorator": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz", + "integrity": "sha1-AJZjF7ehL+kvPMgx91g68ym4bDc=" + }, + "deps-sort": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz", + "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==", + "requires": { + "JSONStream": "^1.0.3", + "shasum-object": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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==" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detective": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", + "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", + "requires": { + "acorn-node": "^1.6.1", + "defined": "^1.0.0", + "minimist": "^1.1.1" + } + }, + "devtools-protocol": { + "version": "0.0.818844", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.818844.tgz", + "integrity": "sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg==" + }, + "dicer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", + "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", + "requires": { + "streamsearch": "0.1.2" + } + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "dijkstrajs": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.2.tgz", + "integrity": "sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==" + }, + "doc-path": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/doc-path/-/doc-path-2.3.0.tgz", + "integrity": "sha512-RMZA8AXl0I78jI9odw0kFzOfQvBcCFLI6/ZtOs9PwogcL4DHc+sCUZQ34fkealJyqErJryYODVBOtO2IzU/CSw==" + }, + "dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" + }, + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + }, + "domhandler": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz", + "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==", + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz", + "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "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==" + }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + } + } + }, + "dot-prop": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", + "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", + "optional": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + }, + "dottie": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", + "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" + }, + "download": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/download/-/download-8.0.0.tgz", + "integrity": "sha512-ASRY5QhDk7FK+XrQtQyvhpDKanLluEEQtWl/J7Lxuf/b+i8RYh997QeXvL85xitrmRKVlx9c7eTrcRdq2GS4eA==", + "requires": { + "archive-type": "^4.0.0", + "content-disposition": "^0.5.2", + "decompress": "^4.2.1", + "ext-name": "^5.0.0", + "file-type": "^11.1.0", + "filenamify": "^3.0.0", + "get-stream": "^4.1.0", + "got": "^8.3.1", + "make-dir": "^2.1.0", + "p-event": "^2.1.0", + "pify": "^4.0.1" + }, + "dependencies": { + "file-type": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-11.1.0.tgz", + "integrity": "sha512-rM0UO7Qm9K7TWTtA6AShI/t7H5BPjDeGVDaNyg9BjHAj3PysKy7+8C8D137R88jnR3rFJZQB/tFgydl5sN5m7g==" + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "requires": { + "readable-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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==" + } + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "optional": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "optional": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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==", + "optional": true + } + } + }, + "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" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, + "encode-utf8": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", + "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "optional": true + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + }, + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-get-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", + "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", + "optional": true, + "requires": { + "es-abstract": "^1.17.4", + "has-symbols": "^1.0.1", + "is-arguments": "^1.0.4", + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "eta": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/eta/-/eta-1.12.1.tgz", + "integrity": "sha512-H8npoci2J/7XiPnVcCVulBSPsTNGvGaINyMjQDU8AFqp9LGsEYS88g2CiU+d01Sg44WtX7o4nb8wUJ9vnI+tiA==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "optional": true + }, + "eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==" + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "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": { + "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==" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + } + } + }, + "express-ip": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/express-ip/-/express-ip-1.0.4.tgz", + "integrity": "sha512-PP9s2kg1+GHhJGtRqwoVHkBHi8glbL5wXXSj2p2+3qcxUNALwXoNhjtY2eLuNchcnWPkmJGyZcqAWUUpd9ecpA==", + "requires": { + "geoip-lite": "^1.2.2" + } + }, + "express-session": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz", + "integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==", + "requires": { + "cookie": "0.4.0", + "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.2.0", + "uid-safe": "~2.1.5" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + } + } + }, + "ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "requires": { + "mime-db": "^1.28.0" + } + }, + "ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "requires": { + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "requires": { + "@types/yauzl": "^2.9.1", + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-csv": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/fast-csv/-/fast-csv-4.3.6.tgz", + "integrity": "sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==", + "requires": { + "@fast-csv/format": "4.3.5", + "@fast-csv/parse": "4.3.6" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" + }, + "fast-text-encoding": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", + "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==", + "optional": true + }, + "faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "~1.2.0" + } + }, + "feature-policy": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/feature-policy/-/feature-policy-0.3.0.tgz", + "integrity": "sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ==" + }, + "fecha": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", + "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==" + }, + "file-type": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.2.0.tgz", + "integrity": "sha512-1Wwww3mmZCMmLjBfslCluwt2mxH80GsAXYrvPnfQ42G1EGWag336kB1iyCgyn7UXiKY3cJrNykXPrCwA7xb5Ag==", + "requires": { + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.0.3", + "token-types": "^2.0.0", + "typedarray-to-buffer": "^3.1.5" + } + }, + "filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=" + }, + "filenamify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-3.0.0.tgz", + "integrity": "sha512-5EFZ//MsvJgXjBAFJ+Bh2YaCTRF/VP1YOmGrgt+KJ4SFRLjI87EIdwLLuT6wQX0I4F9W41xutobzczjsOKlI/g==", + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + } + }, + "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" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "firebase-admin": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-8.13.0.tgz", + "integrity": "sha512-krXj5ncWMJBhCpXSn9UFY6zmDWjFjqgx+1e9ATXKFYndEjmKtNBuJzqdrAdDh7aTUR7X6+0TPx4Hbc08kd0lwQ==", + "requires": { + "@firebase/database": "^0.6.0", + "@google-cloud/firestore": "^3.0.0", + "@google-cloud/storage": "^4.1.2", + "@types/node": "^8.10.59", + "dicer": "^0.3.0", + "jsonwebtoken": "^8.5.1", + "node-forge": "^0.7.6" + }, + "dependencies": { + "@types/node": { + "version": "8.10.61", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.61.tgz", + "integrity": "sha512-l+zSbvT8TPRaCxL1l9cwHCb0tSqGAGcjPJFItGGYat5oCTiq1uQQKYg5m7AF1mgnEBzFXGLJ2LRmNjtreRX76Q==" + } + } + }, + "flat": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", + "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "requires": { + "is-buffer": "~2.0.3" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" + } + } + }, + "fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, + "focus-trap": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-5.1.0.tgz", + "integrity": "sha512-CkB/nrO55069QAUjWFBpX6oc+9V90Qhgpe6fBWApzruMq5gnlh90Oo7iSSDK7pKiV5ugG6OY2AXM5mxcmL3lwQ==", + "requires": { + "tabbable": "^4.0.0", + "xtend": "^4.0.1" + } + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + }, + "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" + } + } + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "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": "3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", + "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "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=" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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==" + } + } + }, + "fs-capacitor": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-2.0.4.tgz", + "integrity": "sha512-8S4f4WsCryNw2mJJchi46YgB6CR5Ze+4L1h8ewl9tEpL4SJ3ZO+c/bS4BWhB8bK+O3TMqhuZarTitd0S0eh2pA==" + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "optional": true + }, + "gaxios": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-2.3.4.tgz", + "integrity": "sha512-US8UMj8C5pRnao3Zykc4AAVr+cffoNKRTg9Rsf2GiuZCW69vgJj38VK2PzlPuQU73FZ/nTk9/Av6/JGcE1N9vA==", + "optional": true, + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.3.0" + } + }, + "gcs-resumable-upload": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-2.3.3.tgz", + "integrity": "sha512-sf896I5CC/1AxeaGfSFg3vKMjUq/r+A3bscmVzZm10CElyRanN0XwPu/MxeIO4LSP+9uF6yKzXvNsaTsMXUG6Q==", + "optional": true, + "requires": { + "abort-controller": "^3.0.0", + "configstore": "^5.0.0", + "gaxios": "^2.0.0", + "google-auth-library": "^5.0.0", + "pumpify": "^2.0.0", + "stream-events": "^1.0.4" + }, + "dependencies": { + "gcp-metadata": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-3.5.0.tgz", + "integrity": "sha512-ZQf+DLZ5aKcRpLzYUyBS3yo3N0JSa82lNDO8rj3nMSlovLcz2riKFBsYgDzeXcv75oo5eqB2lx+B14UvPoCRnA==", + "optional": true, + "requires": { + "gaxios": "^2.1.0", + "json-bigint": "^0.3.0" + } + }, + "google-auth-library": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-5.10.1.tgz", + "integrity": "sha512-rOlaok5vlpV9rSiUu5EpR0vVpc+PhN62oF4RyX/6++DG1VsaulAFEMlDYBLjJDDPI6OcNOCGAKy9UVB/3NIDXg==", + "optional": true, + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^2.1.0", + "gcp-metadata": "^3.4.0", + "gtoken": "^4.1.0", + "jws": "^4.0.0", + "lru-cache": "^5.0.0" + } + }, + "google-p12-pem": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.4.tgz", + "integrity": "sha512-S4blHBQWZRnEW44OcR7TL9WR+QCqByRvhNDZ/uuQfpxywfupikf/miba8js1jZi6ZOGv5slgSuoshCWh6EMDzg==", + "optional": true, + "requires": { + "node-forge": "^0.9.0" + } + }, + "gtoken": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.4.tgz", + "integrity": "sha512-VxirzD0SWoFUo5p8RDP8Jt2AGyOmyYcT/pOUgDKJCK+iSw0TMqwrVfY37RXTNmoKwrzmDHSk0GMT9FsgVmnVSA==", + "optional": true, + "requires": { + "gaxios": "^2.1.0", + "google-p12-pem": "^2.0.0", + "jws": "^4.0.0", + "mime": "^2.2.0" + } + }, + "json-bigint": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.1.tgz", + "integrity": "sha512-DGWnSzmusIreWlEupsUelHrhwmPPE+FiQvg+drKfk2p+bdEYa5mp4PJ8JsCWqae0M2jQNb0HPvnwvf1qOTThzQ==", + "optional": true, + "requires": { + "bignumber.js": "^9.0.0" + } + }, + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "optional": true + }, + "node-forge": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.2.tgz", + "integrity": "sha512-naKSScof4Wn+aoHU6HBsifh92Zeicm1GDQKd1vp3Y/kOi8ub0DozCa9KpvYNCXslFHYRmLNiqRopGdTGwNLpNw==", + "optional": true + } + } + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "requires": { + "is-property": "^1.0.2" + } + }, + "geoip-lite": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/geoip-lite/-/geoip-lite-1.4.2.tgz", + "integrity": "sha512-1rUNqar68+ldSSlSMdpLZPAM+NRokIDzB2lpQFRHSOaDVqtmy25jTAWe0lM2GqWFeaA35RiLhF8GF0vvL+qOKA==", + "requires": { + "async": "^2.1.1", + "colors": "^1.1.2", + "iconv-lite": "^0.4.13", + "ip-address": "^5.8.9", + "lazy": "^1.0.11", + "rimraf": "^2.5.2", + "yauzl": "^2.9.2" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "get-assigned-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-pixels": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/get-pixels/-/get-pixels-3.3.2.tgz", + "integrity": "sha512-6ar+8yPxRd1pskEcl2GSEu1La0+xYRjjnkby6AYiRDDwZ0tJbPQmHnSeH9fGLskT8kvR0OukVgtZLcsENF9YKQ==", + "requires": { + "data-uri-to-buffer": "0.0.3", + "jpeg-js": "^0.3.2", + "mime-types": "^2.0.1", + "ndarray": "^1.0.13", + "ndarray-pack": "^1.1.1", + "node-bitmap": "0.0.1", + "omggif": "^1.0.5", + "parse-data-uri": "^0.2.0", + "pngjs": "^3.3.3", + "request": "^2.44.0", + "through": "^2.3.4" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, + "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" + } + }, + "gl-mat2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gl-mat2/-/gl-mat2-1.0.1.tgz", + "integrity": "sha1-FCUFcwpcL+Hp8l2ezj0NbMJxCjA=" + }, + "gl-vec2": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/gl-vec2/-/gl-vec2-1.3.0.tgz", + "integrity": "sha512-YiqaAuNsheWmUV0Sa8k94kBB0D6RWjwZztyO+trEYS8KzJ6OQB/4686gdrf59wld4hHFIvaxynO3nRxpk1Ij/A==" + }, + "gl-vec3": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gl-vec3/-/gl-vec3-1.1.3.tgz", + "integrity": "sha512-jduKUqT0SGH02l8Yl+mV1yVsDfYgQAJyXGxkJQGyxPLHRiW25DwVIRPt6uvhrEMHftJfqhqKthRcyZqNEl9Xdw==" + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "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" + } + }, + "google-gax": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-1.15.3.tgz", + "integrity": "sha512-3JKJCRumNm3x2EksUTw4P1Rad43FTpqrtW9jzpf3xSMYXx+ogaqTM1vGo7VixHB4xkAyATXVIa3OcNSh8H9zsQ==", + "optional": true, + "requires": { + "@grpc/grpc-js": "~1.0.3", + "@grpc/proto-loader": "^0.5.1", + "@types/fs-extra": "^8.0.1", + "@types/long": "^4.0.0", + "abort-controller": "^3.0.0", + "duplexify": "^3.6.0", + "google-auth-library": "^5.0.0", + "is-stream-ended": "^0.1.4", + "lodash.at": "^4.6.0", + "lodash.has": "^4.5.2", + "node-fetch": "^2.6.0", + "protobufjs": "^6.8.9", + "retry-request": "^4.0.0", + "semver": "^6.0.0", + "walkdir": "^0.4.0" + }, + "dependencies": { + "gcp-metadata": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-3.5.0.tgz", + "integrity": "sha512-ZQf+DLZ5aKcRpLzYUyBS3yo3N0JSa82lNDO8rj3nMSlovLcz2riKFBsYgDzeXcv75oo5eqB2lx+B14UvPoCRnA==", + "optional": true, + "requires": { + "gaxios": "^2.1.0", + "json-bigint": "^0.3.0" + } + }, + "google-auth-library": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-5.10.1.tgz", + "integrity": "sha512-rOlaok5vlpV9rSiUu5EpR0vVpc+PhN62oF4RyX/6++DG1VsaulAFEMlDYBLjJDDPI6OcNOCGAKy9UVB/3NIDXg==", + "optional": true, + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^2.1.0", + "gcp-metadata": "^3.4.0", + "gtoken": "^4.1.0", + "jws": "^4.0.0", + "lru-cache": "^5.0.0" + } + }, + "google-p12-pem": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.4.tgz", + "integrity": "sha512-S4blHBQWZRnEW44OcR7TL9WR+QCqByRvhNDZ/uuQfpxywfupikf/miba8js1jZi6ZOGv5slgSuoshCWh6EMDzg==", + "optional": true, + "requires": { + "node-forge": "^0.9.0" + } + }, + "gtoken": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.4.tgz", + "integrity": "sha512-VxirzD0SWoFUo5p8RDP8Jt2AGyOmyYcT/pOUgDKJCK+iSw0TMqwrVfY37RXTNmoKwrzmDHSk0GMT9FsgVmnVSA==", + "optional": true, + "requires": { + "gaxios": "^2.1.0", + "google-p12-pem": "^2.0.0", + "jws": "^4.0.0", + "mime": "^2.2.0" + } + }, + "json-bigint": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.1.tgz", + "integrity": "sha512-DGWnSzmusIreWlEupsUelHrhwmPPE+FiQvg+drKfk2p+bdEYa5mp4PJ8JsCWqae0M2jQNb0HPvnwvf1qOTThzQ==", + "optional": true, + "requires": { + "bignumber.js": "^9.0.0" + } + }, + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "optional": true + }, + "node-forge": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.2.tgz", + "integrity": "sha512-naKSScof4Wn+aoHU6HBsifh92Zeicm1GDQKd1vp3Y/kOi8ub0DozCa9KpvYNCXslFHYRmLNiqRopGdTGwNLpNw==", + "optional": true + } + } + }, + "got": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", + "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "requires": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + }, + "dependencies": { + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + }, + "graphql": { + "version": "14.6.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.6.0.tgz", + "integrity": "sha512-VKzfvHEKybTKjQVpTFrA5yUq2S9ihcZvfJAtsDBBCuV6wauPu1xl/f9ehgVf0FcEJJs4vz6ysb/ZMkGigQZseg==", + "requires": { + "iterall": "^1.2.2" + } + }, + "graphql-extensions": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.12.4.tgz", + "integrity": "sha512-GnR4LiWk3s2bGOqIh6V1JgnSXw2RCH4NOgbCFEWvB6JqWHXTlXnLZ8bRSkCiD4pltv7RHUPWqN/sGh8R6Ae/ag==", + "requires": { + "@apollographql/apollo-tools": "^0.4.3", + "apollo-server-env": "^2.4.5", + "apollo-server-types": "^0.5.1" + } + }, + "graphql-fields": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/graphql-fields/-/graphql-fields-2.0.3.tgz", + "integrity": "sha512-x3VE5lUcR4XCOxPIqaO4CE+bTK8u6gVouOdpQX9+EKHr+scqtK5Pp/l8nIGqIpN1TUlkKE6jDCCycm/WtLRAwA==" + }, + "graphql-subscriptions": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-1.1.0.tgz", + "integrity": "sha512-6WzlBFC0lWmXJbIVE8OgFgXIP4RJi3OQgTPa0DVMsDXdpRDjTsM1K9wfl5HSYX7R87QAGlvcv2Y4BIZa/ItonA==", + "requires": { + "iterall": "^1.2.1" + } + }, + "graphql-tag": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.10.3.tgz", + "integrity": "sha512-4FOv3ZKfA4WdOKJeHdz6B3F/vxBLSgmBcGeAFPf4n1F64ltJUvOOerNj0rsJxONQGdhUMynQIvd6LzB+1J5oKA==", + "requires": {} + }, + "graphql-tools": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-4.0.8.tgz", + "integrity": "sha512-MW+ioleBrwhRjalKjYaLQbr+920pHBgy9vM/n47sswtns8+96sRn5M/G+J1eu7IMeKWiN/9p6tmwCHU7552VJg==", + "requires": { + "apollo-link": "^1.2.14", + "apollo-utilities": "^1.0.1", + "deprecated-decorator": "^0.1.6", + "iterall": "^1.1.3", + "uuid": "^3.1.0" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } + } + }, + "graphql-upload": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-8.1.0.tgz", + "integrity": "sha512-U2OiDI5VxYmzRKw0Z2dmfk0zkqMRaecH9Smh1U277gVgVe9Qn+18xqf4skwr4YJszGIh7iQDZ57+5ygOK9sM/Q==", + "requires": { + "busboy": "^0.3.1", + "fs-capacitor": "^2.0.4", + "http-errors": "^1.7.3", + "object-path": "^0.11.4" + } + }, + "handlebars": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^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.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "requires": { + "has-symbol-support-x": "^1.4.1" + } + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + }, + "dependencies": { + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + } + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "hash-stream-validation": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.3.tgz", + "integrity": "sha512-OEohGLoUOh+bwsIpHpdvhIXFyRGjeLqJbT8Yc5QTZPbRM7LKywagTQxnX/6mghLDOrD9YGz88hy5mLN2eKflYQ==", + "optional": true, + "requires": { + "through2": "^2.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "optional": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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==", + "optional": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "optional": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + }, + "helmet": { + "version": "3.23.3", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.23.3.tgz", + "integrity": "sha512-U3MeYdzPJQhtvqAVBPntVgAvNSOJyagwZwyKsFdyRa8TV3pOKVFljalPOCxbw5Wwf2kncGhmP0qHjyazIdNdSA==", + "requires": { + "depd": "2.0.0", + "dont-sniff-mimetype": "1.1.0", + "feature-policy": "0.3.0", + "helmet-crossdomain": "0.4.0", + "helmet-csp": "2.10.0", + "hide-powered-by": "1.1.0", + "hpkp": "2.0.0", + "hsts": "2.2.0", + "nocache": "2.1.0", + "referrer-policy": "1.2.0", + "x-xss-protection": "1.3.0" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + } + } + }, + "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.10.0", + "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.10.0.tgz", + "integrity": "sha512-Rz953ZNEFk8sT2XvewXkYN0Ho4GEZdjAZy4stjiEQV3eN7GDxg1QKmYggH7otDyIA7uGA6XnUMVSgeJwbR5X+w==", + "requires": { + "bowser": "2.9.0", + "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==" + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "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" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + } + } + }, + "html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==" + }, + "html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "requires": { + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" + }, + "dependencies": { + "clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "requires": { + "source-map": "~0.6.0" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + } + } + } + } + }, + "html-pdf-node": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/html-pdf-node/-/html-pdf-node-1.0.7.tgz", + "integrity": "sha512-fBvV3/+GxqEuyZuYGPou9aKEP84VbN/1wmL1ujF1UsLSy10srESfQelbOrSgJkOHs23yPfUG9uGMajat6+1UfQ==", + "requires": { + "bluebird": "^3.7.2", + "handlebars": "^4.7.6", + "puppeteer": "^5.1.0" + } + }, + "htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=" + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" + }, + "http-errors": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", + "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "http-parser-js": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.2.tgz", + "integrity": "sha512-opCO9ASqg5Wy2FNo7A0sxy71yGbbkJJXLdgMK04Tcypw9jr2MgWbyubb0+WdmDmGnFflO7fRbqbaihh/ENDlRQ==" + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "optional": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + } + } + }, + "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" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "optional": true, + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + } + } + }, + "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" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "image-size": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.0.tgz", + "integrity": "sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw==", + "requires": { + "queue": "6.0.2" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "optional": true + }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" + }, + "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==" + }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "requires": { + "source-map": "~0.5.3" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "insert-module-globals": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz", + "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==", + "requires": { + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "JSONStream": "^1.0.3", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + }, + "dependencies": { + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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==" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", + "requires": { + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "iota-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz", + "integrity": "sha1-ge9X/l0FgUzVjCSDYyqZwwoOgIc=" + }, + "ip-address": { + "version": "5.9.4", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-5.9.4.tgz", + "integrity": "sha512-dHkI3/YNJq4b/qQaz+c8LuarD3pY24JqZWfjB8aZx1gtpc2MDILu9L9jpZe1sHpzo/yWFweQVn+U//FhazUxmw==", + "requires": { + "jsbn": "1.1.0", + "lodash": "^4.17.15", + "sprintf-js": "1.1.2" + }, + "dependencies": { + "jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha1-sBMHyym2GKHtJux56RH4A8TaAEA=" + } + } + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" + }, + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, + "is-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.0.tgz", + "integrity": "sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g==", + "optional": true + }, + "is-bluebird": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz", + "integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI=" + }, + "is-boolean-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.1.tgz", + "integrity": "sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==", + "optional": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", + "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==" + }, + "is-core-module": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz", + "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==", + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", + "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", + "optional": true + }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" + }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "optional": true + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "optional": true + }, + "is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==" + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", + "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==" + }, + "is-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", + "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==", + "optional": true + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + }, + "is-stream-ended": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", + "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==", + "optional": true + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "optional": true + }, + "is-svg": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", + "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", + "requires": { + "html-comment-regex": "^1.1.0" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typed-array": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.3.tgz", + "integrity": "sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ==", + "requires": { + "available-typed-arrays": "^1.0.0", + "es-abstract": "^1.17.4", + "foreach": "^2.0.5", + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "optional": true + }, + "is-weakset": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz", + "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw==", + "optional": true + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "optional": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } + }, + "iterall": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", + "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==" + }, + "jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=" + }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, + "jpeg-js": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.7.tgz", + "integrity": "sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-2-csv": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/json-2-csv/-/json-2-csv-3.11.0.tgz", + "integrity": "sha512-sElSEXF0ukJAnzmwVn839tPuzOvcl1GZi6d/ne9n1/6dI4/9Q/xCuBsDD3coWLGv5FYWRxCz9BtYa6P54VRjMQ==", + "requires": { + "deeks": "2.3.0", + "doc-path": "2.3.0" + } + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, + "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=" + }, + "json-to-csv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-to-csv/-/json-to-csv-1.0.0.tgz", + "integrity": "sha1-RkC/ffkwwOu6atE9EqbULTt+ohM=", + "requires": { + "json2csv": "^3.4.2", + "ramda": "^0.21.0" + } + }, + "json2csv": { + "version": "3.11.5", + "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-3.11.5.tgz", + "integrity": "sha512-ORsw84BuRKMLxfI+HFZuvxRDnsJps53D5fIGr6tLn4ZY+ymcG8XU00E+JJ2wfAiHx5w2QRNmOLE8xHiGAeSfuQ==", + "requires": { + "cli-table": "^0.3.1", + "commander": "^2.8.1", + "debug": "^3.1.0", + "flat": "^4.0.0", + "lodash.clonedeep": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.get": "^4.4.0", + "lodash.set": "^4.3.0", + "lodash.uniq": "^4.5.0", + "path-is-absolute": "^1.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "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" + }, + "dependencies": { + "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" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "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": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "optional": true, + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "optional": true, + "requires": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "requires": { + "json-buffer": "3.0.0" + } + }, + "klona": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz", + "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==" + }, + "kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, + "labeled-stream-splicer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", + "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", + "requires": { + "inherits": "^2.0.1", + "stream-splicer": "^2.0.0" + } + }, + "lazy": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", + "integrity": "sha1-2qBoIGKCVCwIgojpdcKXwa53tpA=" + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.at": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.at/-/lodash.at-4.6.0.tgz", + "integrity": "sha1-k83OZk8KGZTqM9181A4jr9EbD/g=", + "optional": true + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "optional": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, + "lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "lodash.groupby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", + "integrity": "sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E=" + }, + "lodash.has": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", + "integrity": "sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI=" + }, + "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.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnil": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", + "integrity": "sha1-SeKM1VkBNFjIFMVHnTxmOiG/qmw=" + }, + "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.isundefined": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", + "integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=" + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, + "lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + }, + "logform": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", + "integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==", + "requires": { + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "loglevel": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz", + "integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA==" + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "requires": { + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + } + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "optional": true, + "requires": { + "semver": "^6.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "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=" + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "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.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==" + }, + "mime-types": { + "version": "2.1.29", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", + "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "requires": { + "mime-db": "1.46.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "optional": true + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "minify": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/minify/-/minify-7.0.1.tgz", + "integrity": "sha512-U3CjnPKRjPu3DxZX7NsB833r2ijbw9af3fHsaChn6o7BHKvaT/zxYDQ8Q/3W7VFXGDrnkAx6XBx3ggEf5KJm7A==", + "requires": { + "clean-css": "^5.0.1", + "css-b64-images": "~0.2.5", + "debug": "^4.1.0", + "html-minifier-terser": "^5.1.1", + "terser": "^5.3.2", + "try-to-catch": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "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" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "mitt": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz", + "integrity": "sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==" + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "module-deps": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz", + "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==", + "requires": { + "browser-resolve": "^2.0.0", + "cached-path-relative": "^1.0.2", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.2.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "JSONStream": "^1.0.3", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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==" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + }, + "moment-timezone": { + "version": "0.5.31", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", + "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", + "requires": { + "moment": ">= 2.9.0" + } + }, + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multer": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.2.tgz", + "integrity": "sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "dependencies": { + "busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "requires": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + } + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "requires": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "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" + } + }, + "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==" + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "multer-s3": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/multer-s3/-/multer-s3-2.9.0.tgz", + "integrity": "sha512-qLF8pCD5HhXLLd954q49B63x3bk6Fe0jqD3eM0FVcGtqhiSVuTrchEDAo0mnO5pc34cMuX/CVCCbPkGTjX2xUA==", + "requires": { + "file-type": "^3.3.0", + "is-svg": "^2.1.0", + "run-parallel": "^1.1.6" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" + } + } + }, + "mysql2": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.1.0.tgz", + "integrity": "sha512-9kGVyi930rG2KaHrz3sHwtc6K+GY9d8wWk1XRSYxQiunvGcn4DwuZxOwmK11ftuhhwrYDwGx9Ta4VBwznJn36A==", + "requires": { + "cardinal": "^2.1.1", + "denque": "^1.4.1", + "generate-function": "^2.3.1", + "iconv-lite": "^0.5.0", + "long": "^4.0.0", + "lru-cache": "^5.1.1", + "named-placeholders": "^1.1.2", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.1" + }, + "dependencies": { + "iconv-lite": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", + "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "named-placeholders": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", + "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", + "requires": { + "lru-cache": "^4.1.3" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + } + } + }, + "nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==" + }, + "ndarray": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.19.tgz", + "integrity": "sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ==", + "requires": { + "iota-array": "^1.0.0", + "is-buffer": "^1.0.2" + } + }, + "ndarray-linear-interpolate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ndarray-linear-interpolate/-/ndarray-linear-interpolate-1.0.0.tgz", + "integrity": "sha1-eLySuFuavBW25n7mWCj54hN65ys=" + }, + "ndarray-pack": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ndarray-pack/-/ndarray-pack-1.2.1.tgz", + "integrity": "sha1-jK6+qqJNXs9w/4YCBjeXfajuWFo=", + "requires": { + "cwise-compiler": "^1.1.2", + "ndarray": "^1.0.13" + } + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + } + } + }, + "nocache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz", + "integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q==" + }, + "node-bitmap": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/node-bitmap/-/node-bitmap-0.0.1.tgz", + "integrity": "sha1-GA6scAPgxwdhjvMTaPYvhLKmkJE=" + }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + }, + "node-forge": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz", + "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==" + }, + "node-input-validator": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/node-input-validator/-/node-input-validator-4.3.3.tgz", + "integrity": "sha512-yzMvEMjnFxGocb1u/Zdb9L0SsLd6b/+fEVfAMoHbG7RHXWN8AsAs3xi45flphef1dvXNFMFjVVo0/lZXYXoG4g==", + "requires": { + "file-type": "^16.2.0", + "image-size": "^0.8.3", + "lodash.has": "^4.5.2", + "mime-types": "^2.1.28", + "moment": "^2.29.1", + "read-chunk": "^3.2.0", + "validator": "^13.5.2" + }, + "dependencies": { + "image-size": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.8.3.tgz", + "integrity": "sha512-SMtq1AJ+aqHB45c3FsB4ERK0UCiA2d3H1uq8s+8T0Pf8A3W4teyBQyaFaktH6xvZqh+npwlKU7i4fJo0r7TYTg==", + "requires": { + "queue": "6.0.1" + } + }, + "queue": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.1.tgz", + "integrity": "sha512-AJBQabRCCNr9ANq8v77RJEv73DPbn55cdTb+Giq4X0AVnNVZvMHlYp7XlQiN+1npCZj1DuSmaA2hYVUUDgxFDg==", + "requires": { + "inherits": "~2.0.3" + } + }, + "validator": { + "version": "13.5.2", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.5.2.tgz", + "integrity": "sha512-mD45p0rvHVBlY2Zuy3F3ESIe1h5X58GPfAtslBjY7EtTqGquZTj+VX/J4RnHWN8FKq0C9WRVt1oWAcytWRuYLQ==" + } + } + }, + "nodemailer": { + "version": "6.4.11", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.11.tgz", + "integrity": "sha512-BVZBDi+aJV4O38rxsUh164Dk1NCqgh6Cm0rQSb9SK/DHGll/DrCMnycVDD7msJgZCnmVa8ASo8EZzR7jsgTukQ==" + }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "requires": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" + }, + "object-is": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", + "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", + "optional": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object-path": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", + "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=" + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" + }, + "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==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "requires": { + "fn.name": "1.x.x" + } + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "optional": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, + "p-cancelable": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==" + }, + "p-event": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz", + "integrity": "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==", + "requires": { + "p-timeout": "^2.0.1" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "requires": { + "p-finally": "^1.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "package-merge": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/package-merge/-/package-merge-0.1.2.tgz", + "integrity": "sha1-wng55RHV2AlOmjb/zFRmzCfWazw=", + "requires": { + "jju": "^1.2.0", + "semver": "^4.3.6", + "semver-set": "^0.1.1" + }, + "dependencies": { + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" + } + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + } + } + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "requires": { + "path-platform": "~0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-data-uri": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/parse-data-uri/-/parse-data-uri-0.2.0.tgz", + "integrity": "sha1-vwTYUd1ch7CrI45dAazklLYEtMk=", + "requires": { + "data-uri-to-buffer": "0.0.3" + } + }, + "parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha1-8r0iH2zJcKk42IVWq8WJyqqiveE=" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + } + } + }, + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==" + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "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=" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=" + }, + "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=" + }, + "pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "peek-readable": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-3.1.3.tgz", + "integrity": "sha512-mpAcysyRJxmICBcBa5IXH7SZPvWkcghm6Fk8RekoS3v+BpbSzlZzuWbMx+GXrlUwESi9qHar4nVEZNMKylIHvg==" + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "requires": { + "find-up": "^4.0.0" + } + }, + "pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" + }, + "pop-iterate": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pop-iterate/-/pop-iterate-1.0.1.tgz", + "integrity": "sha1-zqz9q0q/NT16DyqqLB/Hs/lBO6M=" + }, + "postcss": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.5.tgz", + "integrity": "sha512-NxTuJocUhYGsMiMFHDUkmjSKT3EdH4/WbGF6GCi1NDGk+vbcUTun4fpbOqaPtD8IIsztA2ilZm2DhYCuyN58gA==", + "requires": { + "colorette": "^1.2.2", + "nanoid": "^3.1.23", + "source-map-js": "^0.6.2" + }, + "dependencies": { + "nanoid": { + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==" + } + } + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + }, + "protobufjs": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.9.0.tgz", + "integrity": "sha512-LlGVfEWDXoI/STstRDdZZKb/qusoAWUnmLg9R8OLSO473mBLWHowx8clbX5/+mKDEI+v7GzjoK9tRPZMMcoTrg==", + "optional": true, + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": "^13.7.0", + "long": "^4.0.0" + }, + "dependencies": { + "@types/node": { + "version": "13.13.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.12.tgz", + "integrity": "sha512-zWz/8NEPxoXNT9YyF2osqyA9WjssZukYpgI4UYZpOjcyqwIUqWGkcCionaEb9Ki+FULyPyvNFpg/329Kd2/pbw==", + "optional": true + } + } + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", + "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", + "optional": true, + "requires": { + "duplexify": "^4.1.1", + "inherits": "^2.0.3", + "pump": "^3.0.0" + }, + "dependencies": { + "duplexify": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.1.tgz", + "integrity": "sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==", + "optional": true, + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + } + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "puppeteer": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-5.5.0.tgz", + "integrity": "sha512-OM8ZvTXAhfgFA7wBIIGlPQzvyEETzDjeRa4mZRCRHxYL+GNH5WAuYUQdja3rpWZvkX/JKqmuVgbsxDNsDFjMEg==", + "requires": { + "debug": "^4.1.0", + "devtools-protocol": "0.0.818844", + "extract-zip": "^2.0.0", + "https-proxy-agent": "^4.0.0", + "node-fetch": "^2.6.1", + "pkg-dir": "^4.2.0", + "progress": "^2.0.1", + "proxy-from-env": "^1.0.0", + "rimraf": "^3.0.2", + "tar-fs": "^2.0.0", + "unbzip2-stream": "^1.3.3", + "ws": "^7.2.3" + }, + "dependencies": { + "agent-base": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==" + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "https-proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "requires": { + "agent-base": "5", + "debug": "4" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "ws": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz", + "integrity": "sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==", + "requires": {} + } + } + }, + "q": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/q/-/q-2.0.3.tgz", + "integrity": "sha1-dbjbAlWhpa+C9Yw/Oqoe/sfQ0TQ=", + "requires": { + "asap": "^2.0.0", + "pop-iterate": "^1.0.1", + "weak-map": "^1.0.5" + } + }, + "qrcode": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.0.tgz", + "integrity": "sha512-9MgRpgVc+/+47dFvQeD6U2s0Z92EsKzcHogtum4QB+UNd025WOJSHvn/hjk9xmzj7Stj95CyUAs31mrjxliEsQ==", + "requires": { + "dijkstrajs": "^1.0.1", + "encode-utf8": "^1.0.3", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "dependencies": { + "pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==" + } + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "quagga": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/quagga/-/quagga-0.12.1.tgz", + "integrity": "sha1-b0jFbtmS3F/euQ2+5wacLhzd6Lc=", + "requires": { + "get-pixels": "^3.2.3", + "gl-mat2": "^1.0.0", + "gl-vec2": "^1.0.0", + "gl-vec3": "^1.0.3", + "lodash": "^4.17.4", + "ndarray": "^1.0.18", + "ndarray-linear-interpolate": "^1.0.0" + } + }, + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" + }, + "querystringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", + "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==" + }, + "queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "requires": { + "inherits": "~2.0.3" + } + }, + "queue-microtask": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.2.tgz", + "integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg==" + }, + "ramda": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.21.0.tgz", + "integrity": "sha1-oAGr7bP/YQd9T/HVd9RN536NCjU=" + }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "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==" + }, + "read-chunk": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-3.2.0.tgz", + "integrity": "sha512-CEjy9LCzhmD7nUpJ1oVOE6s/hBkejlcJEgLQHVnQznOSilOPb+kpKktlLfFDK3/WP43+F80xkUTM2VOkYoSYvQ==", + "requires": { + "pify": "^4.0.1", + "with-open-file": "^0.1.6" + } + }, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "requires": { + "readable-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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==" + } + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readable-web-to-node-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.1.tgz", + "integrity": "sha512-4zDC6CvjUyusN7V0QLsXVB7pJCD9+vtrM9bYDRv6uBQ+SKfx36rp5AFNPRgh9auKRul/a1iFZJYXcCbwRL+SaA==", + "requires": { + "@types/readable-stream": "^2.3.9", + "readable-stream": "^3.6.0" + } + }, + "redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", + "requires": { + "esprima": "~4.0.0" + } + }, + "referrer-policy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.2.0.tgz", + "integrity": "sha512-LgQJIuS6nAy1Jd88DCQRemyE3mS+ispwlqMk3b0yjZ257fI1v9c+/p6SD5gP5FGyXUIgrNOAfmyioHwZtYv2VA==" + }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "optional": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=" + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "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.3", + "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.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "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" + } + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" + }, + "retry-as-promised": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", + "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", + "requires": { + "any-promise": "^1.3.0" + } + }, + "retry-request": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.1.1.tgz", + "integrity": "sha512-BINDzVtLI2BDukjWmjAIRZ0oglnCAkpP2vQjM3jdLhmT62h0xnQgciPwBRDAvHqpkPT2Wo1XuUyLyn6nbGrZQQ==", + "optional": true, + "requires": { + "debug": "^4.1.1", + "through2": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + } + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rootpath": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/rootpath/-/rootpath-0.1.2.tgz", + "integrity": "sha1-Wzeah9ypBum5HWkKWZQ5vvJn6ms=" + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sanitize-html": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.4.0.tgz", + "integrity": "sha512-Y1OgkUiTPMqwZNRLPERSEi39iOebn2XJLbeiGOBhaJD/yLqtLGu6GE5w7evx177LeGgSE+4p4e107LMiydOf6A==", + "requires": { + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^6.0.0", + "is-plain-object": "^5.0.0", + "klona": "^2.0.3", + "parse-srcset": "^1.0.2", + "postcss": "^8.0.2" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + } + } + }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "scmp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz", + "integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==" + }, + "seek-bzip": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", + "requires": { + "commander": "^2.8.1" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "semver-set": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/semver-set/-/semver-set-0.1.2.tgz", + "integrity": "sha512-ds4+upjcYVTChXvPjO9x+9Xsqp/r9FCNAFmXqPZcpxf80IpD+T3AR1zVnTu6rpVm3q8J+RFTfm7kLI40E3bHPw==", + "requires": { + "cartesian-product": "^2.1.2", + "invariant": "^2.1.0", + "lodash": "^3.9.3", + "semver": "^4.3.6" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" + } + } + }, + "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": { + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "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==" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + } + } + }, + "seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" + }, + "sequelize": { + "version": "5.22.3", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.22.3.tgz", + "integrity": "sha512-+nxf4TzdrB+PRmoWhR05TP9ukLAurK7qtKcIFv5Vhxm5Z9v+d2PcTT6Ea3YAoIQVkZ47QlT9XWAIUevMT/3l8Q==", + "requires": { + "bluebird": "^3.5.0", + "cls-bluebird": "^2.1.0", + "debug": "^4.1.1", + "dottie": "^2.0.0", + "inflection": "1.12.0", + "lodash": "^4.17.15", + "moment": "^2.24.0", + "moment-timezone": "^0.5.21", + "retry-as-promised": "^3.2.0", + "semver": "^6.3.0", + "sequelize-pool": "^2.3.0", + "toposort-class": "^1.0.1", + "uuid": "^3.3.3", + "validator": "^10.11.0", + "wkx": "^0.4.8" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } + } + }, + "sequelize-pool": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-2.3.0.tgz", + "integrity": "sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA==" + }, + "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" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shasum-object": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz", + "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==", + "requires": { + "fast-safe-stringify": "^2.0.7" + } + }, + "shell-quote": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", + "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" + }, + "shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + }, + "side-channel": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz", + "integrity": "sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==", + "optional": true, + "requires": { + "es-abstract": "^1.17.0-next.1", + "object-inspect": "^1.7.0" + } + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "optional": true + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "^0.3.1" + } + }, + "snakeize": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz", + "integrity": "sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=", + "optional": true + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", + "requires": { + "sort-keys": "^1.0.0" + }, + "dependencies": { + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "requires": { + "is-plain-obj": "^1.0.0" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", + "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==" + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + }, + "sqlstring": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.2.tgz", + "integrity": "sha512-vF4ZbYdKS8OnoJAWBmMxCQDkiEBkGQYU7UZPtL8flbDRSNkhaXvRJ279ZtI6M+zDaQovVU4tuRgzK5fVhvFAhg==" + }, + "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" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "requires": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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==" + } + } + }, + "stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "optional": true, + "requires": { + "stubs": "^3.0.0" + } + }, + "stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "optional": true + }, + "stream-splicer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", + "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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==" + } + } + }, + "streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "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==" + } + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "requires": { + "is-natural-number": "^4.0.1" + } + }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "stripe": { + "version": "8.138.0", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-8.138.0.tgz", + "integrity": "sha512-Cr+jzcacXOlL1Wrd7xxcE9nk9OBF0l73Z/oCAlBHXldtRr2FRflg/2h4g4Na3LTlcLRYtx+jnKs64/WPOqmpsA==", + "requires": { + "@types/node": ">=8.1.0", + "qs": "^6.6.0" + } + }, + "strtok3": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.0.8.tgz", + "integrity": "sha512-QLgv+oiXwXgCgp2PdPPa+Jpp4D9imK9e/0BsyfeFMr6QL6wMVqoVn9+OXQ9I7MZbmUzN6lmitTJ09uwS2OmGcw==", + "requires": { + "@tokenizer/token": "^0.1.1", + "@types/debug": "^4.1.5", + "peek-readable": "^3.1.3" + } + }, + "stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", + "optional": true + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "requires": { + "minimist": "^1.1.0" + } + }, + "subscriptions-transport-ws": { + "version": "0.9.16", + "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.16.tgz", + "integrity": "sha512-pQdoU7nC+EpStXnCfh/+ho0zE0Z+ma+i7xvj7bkXKb1dvYHSZxgRPaU6spRP+Bjzow67c/rRDoix5RT0uU9omw==", + "requires": { + "backo2": "^1.0.2", + "eventemitter3": "^3.1.0", + "iterall": "^1.2.1", + "symbol-observable": "^1.0.4", + "ws": "^5.2.0" + }, + "dependencies": { + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + }, + "syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "requires": { + "acorn-node": "^1.2.0" + } + }, + "tabbable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-4.0.0.tgz", + "integrity": "sha512-H1XoH1URcBOa/rZZWxLxHCtOdVUEev+9vo5YdYhC9tCY4wnybX+VQrCYuy9ubkg69fCBxCONJOSLGfw0DWMffQ==" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + }, + "teeny-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.3.tgz", + "integrity": "sha512-TZG/dfd2r6yeji19es1cUIwAlVD8y+/svB1kAC2Y0bjEyysrfbO8EZvJBRwIE6WkwmUoB7uvWLwTIhJbMXZ1Dw==", + "optional": true, + "requires": { + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.2.0", + "stream-events": "^1.0.5", + "uuid": "^7.0.0" + }, + "dependencies": { + "uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "optional": true + } + } + }, + "terser": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.6.0.tgz", + "integrity": "sha512-vyqLMoqadC1uR0vywqOZzriDYzgEkNJFK4q9GeyOBHIbiECHiWLKcWfbQWAUaPfxkjDhapSlZB9f7fkMrvkVjA==", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" + } + } + }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "optional": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "requires": { + "process": "~0.11.0" + } + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "token-types": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-2.1.1.tgz", + "integrity": "sha512-wnQcqlreS6VjthyHO3Y/kpK/emflxDBNhlNUPfh7wE39KnuDdOituXomIbyI79vBtF0Ninpkh72mcuRHo+RG3Q==", + "requires": { + "@tokenizer/token": "^0.1.1", + "ieee754": "^1.2.1" + } + }, + "toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } + } + }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + }, + "try-to-catch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/try-to-catch/-/try-to-catch-3.0.0.tgz", + "integrity": "sha512-eIm6ZXwR35jVF8By/HdbbkcaCDTBI5PpCPkejRKrYp0jyf/DbCCcRhHD7/O9jtFI3ewsqo9WctFEiJTS6i+CQA==" + }, + "ts-invariant": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.4.4.tgz", + "integrity": "sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA==", + "requires": { + "tslib": "^1.9.3" + } + }, + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" + }, + "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=" + }, + "twilio": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/twilio/-/twilio-3.47.0.tgz", + "integrity": "sha512-c/apwtmc1Gwvn0EhjGaWaeSuQUKkGykUFJeVoIKWsXYVamAS+4WKC95H7yGNCGDHtB9x5+lxC1lkjyFzy260pg==", + "requires": { + "@types/express": "^4.17.3", + "axios": "^0.19.2", + "dayjs": "^1.8.21", + "jsonwebtoken": "^8.5.1", + "lodash": "^4.17.15", + "q": "2.0.x", + "qs": "^6.9.1", + "rootpath": "^0.1.2", + "scmp": "^2.1.0", + "url-parse": "^1.4.7", + "xmlbuilder": "^13.0.2" + }, + "dependencies": { + "qs": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==" + } + } + }, + "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" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "uglify-js": { + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.7.tgz", + "integrity": "sha512-SIZhkoh+U/wjW+BHGhVwE9nt8tWJspncloBcFapkpGRwNPqcH8pzX36BXe3TPBjzHWPMUZotpCigak/udWNr1Q==", + "optional": true + }, + "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" + } + }, + "umd": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", + "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==" + }, + "unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "undeclared-identifiers": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", + "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", + "requires": { + "acorn-node": "^1.3.0", + "dash-ast": "^1.0.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "optional": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "uppload": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uppload/-/uppload-3.2.1.tgz", + "integrity": "sha512-WBTcXe5yCbQ5XJh5vL/u8LhKZ5AnXzNzWT3sQG9iFoLRivyljXP4Gg78qNA74+GofFnBz8IO0iK4B7jTOlz2dQ==", + "requires": { + "cropperjs": "^1.5.6", + "download": "^8.0.0", + "focus-trap": "^5.1.0", + "mitt": "^1.2.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } + } + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "url-parse": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "requires": { + "prepend-http": "^2.0.0" + } + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" + }, + "util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz", + "integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==" + }, + "validator": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "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" + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" + }, + "walkdir": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.4.1.tgz", + "integrity": "sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ==", + "optional": true + }, + "weak-map": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.5.tgz", + "integrity": "sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes=" + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + }, + "which-boxed-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz", + "integrity": "sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ==", + "optional": true, + "requires": { + "is-bigint": "^1.0.0", + "is-boolean-object": "^1.0.0", + "is-number-object": "^1.0.3", + "is-string": "^1.0.4", + "is-symbol": "^1.0.2" + } + }, + "which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "optional": true, + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "which-typed-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.2.tgz", + "integrity": "sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ==", + "requires": { + "available-typed-arrays": "^1.0.2", + "es-abstract": "^1.17.5", + "foreach": "^2.0.5", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.1", + "is-typed-array": "^1.1.3" + } + }, + "winston": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", + "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", + "requires": { + "@dabh/diagnostics": "^2.0.2", + "async": "^3.1.0", + "is-stream": "^2.0.0", + "logform": "^2.2.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + } + }, + "winston-transport": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", + "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", + "requires": { + "readable-stream": "^2.3.7", + "triple-beam": "^1.2.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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==" + } + } + }, + "with-open-file": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/with-open-file/-/with-open-file-0.1.7.tgz", + "integrity": "sha512-ecJS2/oHtESJ1t3ZfMI3B7KIDKyfN0O16miWxdn30zdh66Yd3LsRFebXZXq6GU4xfxLf6nVxp9kIqElb5fqczA==", + "requires": { + "p-finally": "^1.0.0", + "p-try": "^2.1.0", + "pify": "^4.0.1" + } + }, + "wkx": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.8.tgz", + "integrity": "sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==", + "requires": { + "@types/node": "*" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "optional": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "requires": { + "async-limiter": "~1.0.0" + } + }, + "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==" + }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "optional": true + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + }, + "dependencies": { + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + } + } + }, + "xmlbuilder": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", + "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==" + }, + "xss": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.7.tgz", + "integrity": "sha512-A9v7tblGvxu8TWXQC9rlpW96a+LN1lyw6wyhpTmmGW+FwRMactchBR3ROKSi33UPCUcUHSu8s9YP6F+K3Mw//w==", + "requires": { + "commander": "^2.20.3", + "cssfilter": "0.0.10" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "zen-observable": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", + "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" + }, + "zen-observable-ts": { + "version": "0.8.21", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz", + "integrity": "sha512-Yj3yXweRc8LdRMrCC8nIc4kkjWecPAUVh0TI0OUrWXx6aX790vLcDlWca6I4vsyCGH3LpWxq0dJRcMOFoVqmeg==", + "requires": { + "tslib": "^1.9.3", + "zen-observable": "^0.8.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..185b38a --- /dev/null +++ b/package.json @@ -0,0 +1,67 @@ +{ + "name": "node_code_builder", + "version": "1.0.0", + "description": "", + "main": "lambda.js", + "scripts": { + "deploy": "claudia create --region us-east-2 --handler lambda.handler", + "update": "claudia update" + }, + "keywords": [], + "author": "Ryan Wong", + "private": true, + "license": "Private", + "dependencies": { + "apollo-server-express": "^2.11.0", + "aws-sdk": "^2.860.0", + "aws-serverless-express": "^3.3.7", + "axios": "^0.19.2", + "bcryptjs": "^2.4.3", + "body-parser": "^1.19.0", + "bootstrap-select": "^1.13.18", + "browserify": "^17.0.0", + "child_process": "^1.0.2", + "claudia": "^5.12.0", + "connect-flash": "^0.1.1", + "cookie-parser": "~1.4.4", + "cors": "^2.8.5", + "dotenv": "^8.2.0", + "eta": "^1.12", + "express": "^4.17.1", + "express-ip": "^1.0.4", + "express-session": "^1.17.1", + "fast-csv": "^4.3.6", + "firebase-admin": "^8.12.1", + "fs-extra": "^9.1.0", + "graphql-fields": "^2.0.3", + "helmet": "^3.19.0", + "html-pdf-node": "^1.0.7", + "image-size": "^1.0.0", + "jju": "^1.4.0", + "json-2-csv": "^3.11.0", + "json-to-csv": "^1.0.0", + "jsonwebtoken": "^8.5.1", + "lodash": "^4.17.21", + "mime-types": "^2.1.29", + "minify": "^7.0.1", + "moment": "^2.26.0", + "morgan": "~1.9.1", + "multer": "^1.4.2", + "multer-s3": "^2.9.0", + "mysql2": "^2.1.0", + "nanoid": "^3.1.20", + "node-input-validator": "^4.3.2", + "nodemailer": "^6.4.11", + "package-merge": "^0.1.2", + "qrcode": "^1.5.0", + "quagga": "^0.12.1", + "querystring": "^0.2.0", + "sanitize-html": "^2.4.0", + "semver-set": "^0.1.2", + "sequelize": "^5.21.3", + "stripe": "^8.138.0", + "twilio": "^3.41.1", + "uppload": "^3.2.1", + "winston": "^3.3.3" + } +} diff --git a/public/css/.gitkeep b/public/css/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/css/all_letters.css b/public/css/all_letters.css new file mode 100644 index 0000000..0ecf1a3 --- /dev/null +++ b/public/css/all_letters.css @@ -0,0 +1,512 @@ +* { + box-sizing: border-box; +} +@font-face { + font-family: "TT Nooks Script"; + src: url("/fonts/TTNooksScript-Bold.woff2") format("woff2"), url("/fonts/TTNooksScript-Bold.woff") format("woff"); + font-weight: bold; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: "Bradford LL"; + src: url("/fonts/BradfordLL-Regular.woff2") format("woff2"), url("/fonts/BradfordLL-Regular.woff") format("woff"); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Bradford LL"; + src: url("/fonts/BradfordLL-Italic.woff2") format("woff2"), url("/fonts/BradfordLL-Italic.woff") format("woff"); + font-weight: normal; + font-style: italic; + font-display: swap; +} +@font-face { + font-family: "Necto Mono"; + src: url("/fonts/Necto-Mono.woff2") format("woff2"), url("/fonts/Necto-Mono.woff") format("woff"); + font-weight: normal; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: "Debrovnik Hill Italic"; + src: url("/fonts/Debrovnik Hill Italic.ttf") format("truetype"); +} +@font-face { + font-family: "Debrovnik Hill Reguler"; + src: url("/fonts/Debrovnik Hill Reguler.ttf") format("truetype"); +} +html { + height: 100%; +} +body { + margin: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + overflow: visible; + flex-grow: 1; + -webkit-print-color-adjust: exact; +} +.logo-svg { + transform: rotate(90deg); + margin: 10px; +} +#main-letter { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + width: 100%; + /* max-width: 618px; */ + margin: auto; + background-color: white; + height: 100vh; + /* min-height: 100%; */ +} +#main-letter.print { + max-width: unset; +} +#main-letter .left, +#main-letter .right { + width: max-content; + padding: 20px 8px; + font-family: "Bradford LL"; + font-style: italic; + text-transform: capitalize; + font-size: 20px; + min-height: max-content; + text-align: center; +} +#main-letter .left { + transform: rotate(180deg); + writing-mode: vertical-lr; + margin-left: 6px; +} +#main-letter .right { + writing-mode: vertical-rl; + margin-right: 6px; +} +#main-letter .center { + display: flex; + flex-direction: column; + flex-grow: 1; + border: 1px solid black; + border-top: none; + border-bottom: none; +} +#main-letter .center .top { + padding: 20px 0 24px; + border-bottom: 1px solid black; +} +#main-letter .center .top .header-logo { + display: flex; + flex-direction: column; + width: max-content; + padding: 1px 24px; + margin: 0 auto; + position: relative; +} +#main-letter .center .top .header-logo::after { + content: ""; + width: 100%; + position: absolute; + bottom: 0; + left: 0; + height: 1.5px; + border-radius: 1px; + background-color: black; +} +#main-letter .center .header-logo .cr-logo { + font-family: "TT Nooks Script"; + font-weight: 700; + font-size: 40px; +} +#main-letter .center .header-logo .customer-name { + text-align: center; + font-family: "Debrovnik Hill Italic"; + text-transform: capitalize; + font-weight: 700; + color: black; + font-size: 32px; +} + +#main-letter .center .middle { + padding: 24px 56px; + font-family: "Necto Mono"; + font-size: 15px; + font-weight: 500; + border-bottom: 1px solid black; +} +#main-letter .center .middle .header { + font-family: "Bradford LL"; + font-size: 28px; + text-align: center; + margin-bottom: 24px; +} +#main-letter .center .middle .body .customer-name { + font-weight: 700; + text-transform: capitalize; +} +#main-letter .center .middle .body p { + margin-bottom: 8px; + line-height: 140%; + display: block; +} + +#main-letter .center .footer { + margin-top: 24px; +} +#main-letter .center .footer h5 { + font-family: "Bradford LL"; + font-size: 16px; + font-style: italic; +} + +#profile-letter { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + width: 100%; + /* min-height: 100%; */ + /* max-width: 618px; */ + margin: auto; + height: 100vh; + + background-color: white; +} +#profile-letter.print { + max-width: unset; +} +#profile-letter .left, +#profile-letter .right { + width: max-content; + padding: 20px 8px; + font-family: "Bradford LL"; + font-style: italic; + text-transform: capitalize; + font-size: 20px; + height: 100%; + min-height: max-content; + text-align: center; +} +#profile-letter .left { + transform: rotate(180deg); + writing-mode: vertical-lr; + margin-left: 6px; +} +#profile-letter .right { + writing-mode: vertical-rl; + margin-right: 6px; +} +#profile-letter .center { + display: flex; + flex-direction: column; + flex-grow: 1; + border: 1px solid black; + border-top: none; + border-bottom: none; + min-height: 100%; + align-items: center; +} +#profile-letter .center .header { + font-family: "Bradford LL"; + font-weight: 500; + font-size: 32px; + text-transform: capitalize; + text-align: center; + margin-top: 8px; + margin-bottom: 8px; + padding: 20px 0; +} +#profile-letter .center .body { + width: 100%; +} + +#profile-letter .progress-container { + width: 100%; + min-width: 100%; + padding: 14px 20px 20px 20px; + border-bottom: 1px solid black; +} +#profile-letter .progress-container:last-of-type { + border-bottom: none; +} + +#profile-letter .progress-container .profile-title h3 { + color: #000000; + text-align: center; + font: italic 30px "Bradford LL"; + line-height: 40px; + margin: 0; + margin-bottom: 16px; + font-weight: 500; +} + +#profile-letter .progress-container .profile-body { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; +} +#profile-letter .profile-container { + width: 45%; + margin: 0 0 18px 0; +} +#profile-letter .profile-container .title { + font: 16px "Necto Mono"; + color: #231f20; + margin-bottom: 8px; + display: inline-block; +} +#profile-letter .profile-container .progress { + width: 100%; + height: 6px; + border: 1px solid black; + border-radius: 1px; + text-align: left; +} +#profile-letter .profile-container .progress .bar { + height: 100%; + background-color: black; + z-index: 9; +} + +#formula-letter { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + width: 100%; + height: 100vh; + /* max-width: 618px; */ + margin: auto; + background-color: white; +} +#formula-letter.print { + max-width: unset; +} +#formula-letter .left, +#formula-letter .right { + width: max-content; + padding: 20px 8px; + font-family: "Bradford LL"; + font-style: italic; + text-transform: capitalize; + font-size: 20px; + height: 100%; + min-height: max-content; + text-align: center; +} +#formula-letter .left { + transform: rotate(180deg); + writing-mode: vertical-lr; + margin-left: 6px; +} +#formula-letter .right { + writing-mode: vertical-rl; + margin-right: 6px; +} +#formula-letter .center { + display: flex; + flex-direction: column; + flex-grow: 1; + border: 1px solid black; + border-top: none; + border-bottom: none; + min-height: 100%; + align-items: center; +} +#formula-letter .center .header { + font-family: "Bradford LL"; + font-weight: 500; + font-size: 32px; + text-transform: capitalize; + text-align: center; + margin-top: 8px; + margin-bottom: 8px; + padding: 20px 0; +} +#formula-letter .center .body { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; +} +#formula-letter .center .step { + display: flex; + flex-direction: column; + width: 100%; + margin-bottom: 8px; +} +#formula-letter .center .step div { + width: 100%; +} +#formula-letter .center .step .title { + font-family: "Bradford LL"; + font-size: 26px; + font-style: italic; + text-align: left; + padding-left: 8px; +} +#formula-letter .center .step._two .title { + border-bottom: 1px solid black; +} +#formula-letter .center .step._two .content { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + grid-auto-rows: 1fr; +} +#formula-letter .center .step._two .content .active { + border-bottom: 1px solid black; +} +#formula-letter .center .step._two .content .active:nth-child(odd) { + border-right: 1px solid black; +} +#formula-letter .center .step .content { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + flex-grow: 1; + font-family: "Necto Mono"; +} + +#formula-letter .center .step .content .qrcode { + width: max-content; + margin-right: 8px; + margin-left: 4px; +} +#formula-letter .center .step .content .explanation { + font-family: "Necto Mono"; + font-size: 16px; + font-weight: 500; + display: flex; + align-items: center; + justify-content: center; + padding-right: 4px; +} +#formula-letter .step._two .name-qrcode { + margin-top: 4px; + display: flex; + align-items: center; + justify-content: space-between; +} +#formula-letter .step._two .name-qrcode .active-name { + padding-left: 8px; + font-size: 15px; +} +#formula-letter .step._two .description { + padding: 8px; + font-size: 14px; + font-size: 13px; + text-transform: capitalize; +} +#formula-letter .footer-note { + padding: 10px; + font-family: "Bradford LL"; + font-size: 16px; + font-style: italic; + width: 100%; +} + +#instructions-letter { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + width: 100%; + /* max-width: 618px; */ + margin: auto; + background-color: white; + height: 100vh; +} +#instructions-letter.print { + max-width: unset; +} +#instructions-letter .left, +#instructions-letter .right { + width: max-content; + padding: 20px 8px; + font-family: "Bradford LL"; + font-style: italic; + text-transform: capitalize; + font-size: 20px; + min-height: max-content; + text-align: center; +} +#instructions-letter .left { + transform: rotate(180deg); + writing-mode: vertical-lr; + margin-left: 6px; +} +#instructions-letter .right { + writing-mode: vertical-rl; + margin-right: 6px; +} +#instructions-letter .center { + display: flex; + flex-direction: column; + flex-grow: 1; + border: 1px solid black; + border-top: none; + border-bottom: none; +} +#instructions-letter .center .header { + font-family: "Bradford LL"; + font-weight: 500; + font-size: 36px; + text-transform: capitalize; + text-align: center; + margin-top: 8px; + margin-bottom: 8px; + padding: 20px 0; +} +#instructions-letter .section { + padding: 8px 10px; +} +#instructions-letter .section .sub-header { + font-family: "Bradford LL"; + font-weight: 500; + margin-top: 0; + font-size: 28px; + font-style: italic; + text-transform: capitalize; + margin-bottom: 8px; +} +#instructions-letter .items .list { + list-style: none; + margin-top: 0; + padding-left: 16px; + font-family: "Necto Mono"; + font-size: 15px; + line-height: 18px; +} +#instructions-letter .items .list li { + padding-bottom: 6px; +} +#instructions-letter .items .list li ul { + margin-top: 6px; + padding-left: 3rem; +} + +#instructions-letter .mixing-steps .list { + margin-top: 0; + padding-left: 56px; + padding-right: 16px; + font-family: "Necto Mono"; + font-size: 15px; + line-height: 18px; +} +#instructions-letter .mixing-steps .list li { + padding-bottom: 6px; +} +#instructions-letter .notes .list { + list-style: disc; + margin-top: 0; + padding-left: 48px; + padding-right: 16px; + font-family: "Necto Mono"; + font-size: 15px; + line-height: 18px; +} diff --git a/public/css/formula_letter.css b/public/css/formula_letter.css new file mode 100644 index 0000000..80c2aea --- /dev/null +++ b/public/css/formula_letter.css @@ -0,0 +1,197 @@ +* { + box-sizing: border-box; +} +@font-face { + font-family: "TT Nooks Script"; + src: url("/fonts/TTNooksScript-Bold.woff2") format("woff2"), url("/fonts/TTNooksScript-Bold.woff") format("woff"); + font-weight: bold; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: "Bradford LL"; + src: url("/fonts/BradfordLL-Regular.woff2") format("woff2"), url("/fonts/BradfordLL-Regular.woff") format("woff"); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Bradford LL"; + src: url("/fonts/BradfordLL-Italic.woff2") format("woff2"), url("/fonts/BradfordLL-Italic.woff") format("woff"); + font-weight: normal; + font-style: italic; + font-display: swap; +} +@font-face { + font-family: "Necto Mono"; + src: url("/fonts/Necto-Mono.woff2") format("woff2"), url("/fonts/Necto-Mono.woff") format("woff"); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Debrovnik Hill Italic"; + src: url("/fonts/Debrovnik Hill Italic.ttf") format("truetype"); +} +@font-face { + font-family: "Debrovnik Hill Reguler"; + src: url("/fonts/Debrovnik Hill Reguler.ttf") format("truetype"); +} + +@font-face { + font-family: "rotation-roman"; + src: url("/fonts/RotationLTStd-Roman.otf") format("opentype"); +} + +html { + height: 100%; +} +body { + height: 100%; + margin: 0; + display: flex; + align-items: center; + justify-content: center; + -webkit-print-color-adjust: exact; +} +.logo-svg { + transform: rotate(90deg); + margin: 10px; +} +#formula-letter { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + width: 100%; + min-height: 100%; + /* max-width: 618px; */ + margin: auto; + background-color: white; +} +#formula-letter.print { + max-width: unset; +} +#formula-letter .left, +#formula-letter .right { + width: max-content; + padding: 20px 8px; + font-family: "Bradford LL"; + font-style: italic; + text-transform: capitalize; + font-size: 20px; + height: 100%; + min-height: max-content; + text-align: center; +} +#formula-letter .left { + transform: rotate(180deg); + margin-left: 6px; + writing-mode: vertical-lr; +} +#formula-letter .right { + margin-right: 6px; + writing-mode: vertical-rl; +} +#formula-letter .center { + display: flex; + flex-direction: column; + flex-grow: 1; + border: 1px solid black; + border-top: none; + border-bottom: none; + min-height: 100%; + align-items: center; +} +#formula-letter .center .header { + font-family: "Bradford LL"; + font-weight: 500; + font-size: 32px; + text-transform: capitalize; + text-align: center; + margin-top: 8px; + margin-bottom: 8px; + padding: 20px 0; +} +#formula-letter .center .body { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; +} +#formula-letter .center .step { + display: flex; + flex-direction: column; + width: 100%; + margin-bottom: 8px; +} +#formula-letter .center .step div { + width: 100%; +} +#formula-letter .center .step .title { + font-family: "Bradford LL"; + font-size: 26px; + font-style: italic; + text-align: left; + padding-left: 8px; +} +#formula-letter .center .step._two .title { + border-bottom: 1px solid black; +} +#formula-letter .center .step._two .content { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + grid-auto-rows: 1fr; +} +#formula-letter .center .step._two .content .active { + border-bottom: 1px solid black; +} +#formula-letter .center .step._two .content .active:nth-child(odd) { + border-right: 1px solid black; +} +#formula-letter .center .step .content { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + flex-grow: 1; + font-family: "Necto Mono"; +} + +#formula-letter .center .step .content .qrcode { + width: max-content; + margin-right: 8px; + margin-left: 4px; +} +#formula-letter .center .step .content .explanation { + font-family: "Necto Mono"; + font-size: 16px; + font-weight: 500; + display: flex; + align-items: center; + justify-content: center; + padding-right: 4px; +} +#formula-letter .step._two .name-qrcode { + margin-top: 4px; + display: flex; + align-items: center; + justify-content: space-between; +} +#formula-letter .step._two .name-qrcode .active-name { + padding-left: 8px; + font-size: 15px; +} +#formula-letter .step._two .description { + padding: 8px; + font-size: 14px; + font-size: 13px; + text-transform: capitalize; +} +#formula-letter .footer-note { + padding: 10px; + font-family: "Bradford LL"; + font-size: 16px; + font-style: italic; + width: 100%; +} diff --git a/public/css/instructions_letter.css b/public/css/instructions_letter.css new file mode 100644 index 0000000..cafafb3 --- /dev/null +++ b/public/css/instructions_letter.css @@ -0,0 +1,158 @@ +* { + box-sizing: border-box; +} +@font-face { + font-family: "TT Nooks Script"; + src: url("/fonts/TTNooksScript-Bold.woff2") format("woff2"), url("/fonts/TTNooksScript-Bold.woff") format("woff"); + font-weight: bold; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: "Bradford LL"; + src: url("/fonts/BradfordLL-Regular.woff2") format("woff2"), url("/fonts/BradfordLL-Regular.woff") format("woff"); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Bradford LL"; + src: url("/fonts/BradfordLL-Italic.woff2") format("woff2"), url("/fonts/BradfordLL-Italic.woff") format("woff"); + font-weight: normal; + font-style: italic; + font-display: swap; +} +@font-face { + font-family: "Necto Mono"; + src: url("/fonts/Necto-Mono.woff2") format("woff2"), url("/fonts/Necto-Mono.woff") format("woff"); + font-weight: normal; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: "Debrovnik Hill Italic"; + src: url("/fonts/Debrovnik Hill Italic.ttf") format("truetype"); +} +@font-face { + font-family: "Debrovnik Hill Reguler"; + src: url("/fonts/Debrovnik Hill Reguler.ttf") format("truetype"); +} +html { + height: 100%; +} +body { + height: 100%; + margin: 0; + display: flex; + align-items: center; + justify-content: center; + overflow: visible; + flex-grow: 1; + -webkit-print-color-adjust: exact; +} +.logo-svg { + transform: rotate(90deg); + margin: 10px; +} + +#instructions-letter { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + width: 100%; + /* max-width: 618px; */ + margin: auto; + background-color: white; + height: 100%; + min-height: 100%; +} +#instructions-letter.print { + max-width: unset; +} +#instructions-letter .left, +#instructions-letter .right { + width: max-content; + padding: 20px 8px; + font-family: "Bradford LL"; + font-style: italic; + text-transform: capitalize; + font-size: 20px; + min-height: max-content; + text-align: center; +} +#instructions-letter .left { + transform: rotate(180deg); + writing-mode: vertical-lr; + margin-left: 6px; +} +#instructions-letter .right { + margin-right: 6px; + writing-mode: vertical-rl; +} +#instructions-letter .center { + display: flex; + flex-direction: column; + flex-grow: 1; + border: 1px solid black; + border-top: none; + border-bottom: none; +} +#instructions-letter .center .header { + font-family: "Bradford LL"; + font-weight: 500; + font-size: 36px; + text-transform: capitalize; + text-align: center; + margin-top: 8px; + margin-bottom: 8px; + padding: 20px 0; +} +#instructions-letter .section { + padding: 8px 10px; +} +#instructions-letter .section .sub-header { + font-family: "Bradford LL"; + font-weight: 500; + margin-top: 0; + font-size: 28px; + font-style: italic; + text-transform: capitalize; + margin-bottom: 8px; +} +#instructions-letter .items .list { + list-style: none; + margin-top: 0; + padding-left: 16px; + font-family: "Necto Mono"; + font-size: 15px; + line-height: 18px; +} +#instructions-letter .items .list li { + padding-bottom: 6px; +} +#instructions-letter .items .list li ul { + margin-top: 6px; + padding-left: 3rem; +} + +#instructions-letter .mixing-steps .list { + margin-top: 0; + padding-left: 56px; + padding-right: 16px; + font-family: "Necto Mono"; + font-size: 15px; + line-height: 18px; +} +#instructions-letter .mixing-steps .list li { + padding-bottom: 6px; +} +#instructions-letter .notes .list { + list-style: disc; + margin-top: 0; + padding-left: 48px; + padding-right: 16px; + font-family: "Necto Mono"; + font-size: 15px; + line-height: 18px; +} diff --git a/public/css/main_letter.css b/public/css/main_letter.css new file mode 100644 index 0000000..da93c5e --- /dev/null +++ b/public/css/main_letter.css @@ -0,0 +1,164 @@ +* { + box-sizing: border-box; +} +@font-face { + font-family: "TT Nooks Script"; + src: url("/fonts/TTNooksScript-Bold.woff2") format("woff2"), url("/fonts/TTNooksScript-Bold.woff") format("woff"); + font-weight: bold; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: "Bradford LL"; + src: url("/fonts/BradfordLL-Regular.woff2") format("woff2"), url("/fonts/BradfordLL-Regular.woff") format("woff"); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Bradford LL"; + src: url("/fonts/BradfordLL-Italic.woff2") format("woff2"), url("/fonts/BradfordLL-Italic.woff") format("woff"); + font-weight: normal; + font-style: italic; + font-display: swap; +} +@font-face { + font-family: "Necto Mono"; + src: url("/fonts/Necto-Mono.woff2") format("woff2"), url("/fonts/Necto-Mono.woff") format("woff"); + font-weight: normal; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: "Debrovnik Hill Italic"; + src: url("/fonts/Debrovnik Hill Italic.ttf") format("truetype"); +} +@font-face { + font-family: "Debrovnik Hill Reguler"; + src: url("/fonts/Debrovnik Hill Reguler.ttf") format("truetype"); +} +html { + height: 100%; +} +body { + height: 100%; + margin: 0; + display: flex; + align-items: center; + justify-content: center; + overflow: visible; + flex-grow: 1; + -webkit-print-color-adjust: exact; +} +#main-letter { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + width: 100%; + margin: auto; + background-color: white; + height: 100%; + min-height: 100%; +} +#main-letter.print { + max-width: unset; +} +#main-letter .left, +#main-letter .right { + width: max-content; + padding: 20px 8px; + font-family: "Bradford LL"; + font-style: italic; + text-transform: capitalize; + font-size: 20px; + min-height: max-content; + text-align: center; +} +#main-letter .left { + transform: rotate(180deg); + writing-mode: vertical-lr; + margin-left: 6px; +} +#main-letter .right { + writing-mode: vertical-rl; + margin-right: 6px; +} +#main-letter .center { + display: flex; + flex-direction: column; + flex-grow: 1; + border: 1px solid black; + border-top: none; + border-bottom: none; +} +#main-letter .center .top { + padding: 20px 0 24px; + border-bottom: 1px solid black; +} +#main-letter .center .top .header-logo { + display: flex; + flex-direction: column; + width: max-content; + padding: 1px 24px; + margin: 0 auto; + position: relative; +} +#main-letter .center .top .header-logo::after { + content: ""; + width: 100%; + position: absolute; + bottom: 0; + left: 0; + height: 1.5px; + border-radius: 1px; + background-color: black; +} +#main-letter .center .header-logo .cr-logo { + font-family: "TT Nooks Script"; + font-weight: 700; + font-size: 40px; +} +#main-letter .center .header-logo .customer-name { + text-align: center; + font-family: "Debrovnik Hill Italic"; + text-transform: capitalize; + font-weight: 700; + color: black; + font-size: 32px; +} + +#main-letter .center .middle { + padding: 24px 56px; + font-family: "Necto Mono"; + font-size: 15px; + font-weight: 500; + border-bottom: 1px solid black; +} +#main-letter .center .middle .header { + font-family: "Bradford LL"; + font-size: 28px; + text-align: center; + margin-bottom: 24px; +} +#main-letter .center .middle .body .customer-name { + font-weight: 700; + text-transform: capitalize; +} +#main-letter .center .middle .body p { + margin-bottom: 8px; + line-height: 140%; + display: block; +} +.logo-svg { + transform: rotate(90deg); + margin: 10px; +} +#main-letter .center .footer { + margin-top: 24px; +} +#main-letter .center .footer h5 { + font-family: "Bradford LL"; + font-size: 16px; + font-style: italic; +} diff --git a/public/css/module.merge.css b/public/css/module.merge.css new file mode 100644 index 0000000..0b3e557 --- /dev/null +++ b/public/css/module.merge.css @@ -0,0 +1,3 @@ + + @import "https://unpkg.com/uppload/dist/uppload.css"; +@import "https://unpkg.com/uppload/dist/themes/light.css"; diff --git a/public/css/profile_letter.css b/public/css/profile_letter.css new file mode 100644 index 0000000..3d90e07 --- /dev/null +++ b/public/css/profile_letter.css @@ -0,0 +1,169 @@ +* { + box-sizing: border-box; +} +@font-face { + font-family: "TT Nooks Script"; + src: url("/fonts/TTNooksScript-Bold.woff2") format("woff2"), url("/fonts/TTNooksScript-Bold.woff") format("woff"); + font-weight: bold; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: "Bradford LL"; + src: url("/fonts/BradfordLL-Regular.woff2") format("woff2"), url("/fonts/BradfordLL-Regular.woff") format("woff"); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Bradford LL"; + src: url("/fonts/BradfordLL-Italic.woff2") format("woff2"), url("/fonts/BradfordLL-Italic.woff") format("woff"); + font-weight: normal; + font-style: italic; + font-display: swap; +} +@font-face { + font-family: "Necto Mono"; + src: url("/fonts/Necto-Mono.woff2") format("woff2"), url("/fonts/Necto-Mono.woff") format("woff"); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Debrovnik Hill Italic"; + src: url("/fonts/Debrovnik Hill Italic.ttf") format("truetype"); +} +@font-face { + font-family: "Debrovnik Hill Reguler"; + src: url("/fonts/Debrovnik Hill Reguler.ttf") format("truetype"); +} + +@font-face { + font-family: "rotation-roman"; + src: url("/fonts/RotationLTStd-Roman.otf") format("opentype"); +} + +html { + height: 100%; +} +body { + height: 100%; + margin: 0; + display: flex; + align-items: center; + justify-content: center; + -webkit-print-color-adjust: exact; +} +.logo-svg { + transform: rotate(90deg); + margin: 10px; +} +#profile-letter { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + width: 100%; + min-height: 100%; + /* max-width: 618px; */ + margin: auto; + background-color: white; +} +#profile-letter.print { + max-width: unset; +} +#profile-letter .left, +#profile-letter .right { + width: max-content; + padding: 20px 8px; + font-family: "Bradford LL"; + font-style: italic; + text-transform: capitalize; + font-size: 20px; + height: 100%; + min-height: max-content; + text-align: center; +} +#profile-letter .left { + transform: rotate(180deg); + margin-left: 6px; + writing-mode: vertical-lr; +} +#profile-letter .right { + margin-right: 6px; + writing-mode: vertical-rl; +} +#profile-letter .center { + display: flex; + flex-direction: column; + flex-grow: 1; + border: 1px solid black; + border-top: none; + border-bottom: none; + min-height: 100%; + align-items: center; +} +#profile-letter .center .header { + font-family: "Bradford LL"; + font-weight: 500; + font-size: 32px; + text-transform: capitalize; + text-align: center; + margin-top: 8px; + margin-bottom: 8px; + padding: 20px 0; +} +#profile-letter .center .body { + width: 100%; +} + +#profile-letter .progress-container { + width: 100%; + min-width: 100%; + padding: 14px 20px 20px 20px; + border-bottom: 1px solid black; +} +#profile-letter .progress-container:last-of-type { + border-bottom: none; +} + +#profile-letter .progress-container .profile-title h3 { + color: #000000; + text-align: center; + font: italic 30px "Bradford LL"; + line-height: 40px; + margin: 0; + margin-bottom: 16px; + font-weight: 500; +} + +#profile-letter .progress-container .profile-body { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; +} +#profile-letter .profile-container { + width: 45%; + margin: 0 0 18px 0; +} +#profile-letter .profile-container .title { + font: 16px "Necto Mono"; + color: #231f20; + margin-bottom: 8px; + display: inline-block; +} +#profile-letter .profile-container .progress { + width: 100%; + height: 6px; + border: 1px solid black; + border-radius: 1px; + text-align: left; +} +#profile-letter .profile-container .progress .bar { + height: 100%; + background-color: black; + z-index: 9; +} diff --git a/public/css/select2.min.css b/public/css/select2.min.css new file mode 100644 index 0000000..0a36ffb --- /dev/null +++ b/public/css/select2.min.css @@ -0,0 +1,709 @@ +.select2-container { + box-sizing: border-box; + display: inline-block; + margin: 0; + position: relative; + vertical-align: middle; +} +.select2-container .select2-selection--single { + box-sizing: border-box; + cursor: pointer; + display: block; + height: 28px; + user-select: none; + -webkit-user-select: none; +} +.select2-container .select2-selection--single .select2-selection__rendered { + display: block; + padding-left: 8px; + padding-right: 20px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.select2-container .select2-selection--single .select2-selection__clear { + background-color: transparent; + border: none; + font-size: 1em; +} +.select2-container[dir='rtl'] + .select2-selection--single + .select2-selection__rendered { + padding-right: 8px; + padding-left: 20px; +} +.select2-container .select2-selection--multiple { + box-sizing: border-box; + cursor: pointer; + display: block; + min-height: 32px; + user-select: none; + -webkit-user-select: none; +} +.select2-container .select2-selection--multiple .select2-selection__rendered { + display: inline; + list-style: none; + padding: 0; +} +.select2-container .select2-selection--multiple .select2-selection__clear { + background-color: transparent; + border: none; + font-size: 1em; +} +.select2-container .select2-search--inline .select2-search__field { + box-sizing: border-box; + border: none; + font-size: 100%; + margin-top: 5px; + margin-left: 5px; + padding: 0; + max-width: 100%; + resize: none; + height: 18px; + vertical-align: bottom; + font-family: sans-serif; + overflow: hidden; + word-break: keep-all; +} +.select2-container + .select2-search--inline + .select2-search__field::-webkit-search-cancel-button { + -webkit-appearance: none; +} +.select2-dropdown { + background-color: white; + border: 1px solid #aaa; + border-radius: 4px; + box-sizing: border-box; + display: block; + position: absolute; + left: -100000px; + width: 100%; + z-index: 1051; +} +.select2-results { + display: block; +} +.select2-results__options { + list-style: none; + margin: 0; + padding: 0; +} +.select2-results__option { + padding: 6px; + user-select: none; + -webkit-user-select: none; +} +.select2-results__option--selectable { + cursor: pointer; +} +.select2-container--open .select2-dropdown { + left: 0; +} +.select2-container--open .select2-dropdown--above { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +.select2-container--open .select2-dropdown--below { + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.select2-search--dropdown { + display: block; + padding: 4px; +} +.select2-search--dropdown .select2-search__field { + padding: 4px; + width: 100%; + box-sizing: border-box; +} +.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button { + -webkit-appearance: none; +} +.select2-search--dropdown.select2-search--hide { + display: none; +} +.select2-close-mask { + border: 0; + margin: 0; + padding: 0; + display: block; + position: fixed; + left: 0; + top: 0; + min-height: 100%; + min-width: 100%; + height: auto; + width: auto; + opacity: 0; + z-index: 99; + background-color: #fff; + filter: alpha(opacity=0); +} +.select2-hidden-accessible { + border: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(50%) !important; + clip-path: inset(50%) !important; + height: 1px !important; + overflow: hidden !important; + padding: 0 !important; + position: absolute !important; + width: 1px !important; + white-space: nowrap !important; +} +.select2-container--default .select2-selection--single { + background-color: #fff; + border: 1px solid #aaa; + border-radius: 4px; +} +.select2-container--default + .select2-selection--single + .select2-selection__rendered { + color: #444; + line-height: 28px; +} +.select2-container--default + .select2-selection--single + .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; + height: 26px; + margin-right: 20px; + padding-right: 0px; +} +.select2-container--default + .select2-selection--single + .select2-selection__placeholder { + color: #999; +} +.select2-container--default + .select2-selection--single + .select2-selection__arrow { + height: 26px; + position: absolute; + top: 1px; + right: 1px; + width: 20px; +} +.select2-container--default + .select2-selection--single + .select2-selection__arrow + b { + border-color: #888 transparent transparent transparent; + border-style: solid; + border-width: 5px 4px 0 4px; + height: 0; + left: 50%; + margin-left: -4px; + margin-top: -2px; + position: absolute; + top: 50%; + width: 0; +} +.select2-container--default[dir='rtl'] + .select2-selection--single + .select2-selection__clear { + float: left; +} +.select2-container--default[dir='rtl'] + .select2-selection--single + .select2-selection__arrow { + left: 1px; + right: auto; +} +.select2-container--default.select2-container--disabled + .select2-selection--single { + background-color: #eee; + cursor: default; +} +.select2-container--default.select2-container--disabled + .select2-selection--single + .select2-selection__clear { + display: none; +} +.select2-container--default.select2-container--open + .select2-selection--single + .select2-selection__arrow + b { + border-color: transparent transparent #888 transparent; + border-width: 0 4px 5px 4px; +} +.select2-container--default .select2-selection--multiple { + background-color: white; + border: 1px solid #aaa; + border-radius: 4px; + cursor: text; + padding-bottom: 5px; + padding-right: 5px; + position: relative; +} +.select2-container--default + .select2-selection--multiple.select2-selection--clearable { + padding-right: 25px; +} +.select2-container--default + .select2-selection--multiple + .select2-selection__clear { + cursor: pointer; + font-weight: bold; + height: 20px; + margin-right: 10px; + margin-top: 5px; + position: absolute; + right: 0; + padding: 1px; +} +.select2-container--default + .select2-selection--multiple + .select2-selection__choice { + background-color: #e4e4e4; + border: 1px solid #aaa; + border-radius: 4px; + box-sizing: border-box; + display: inline-block; + margin-left: 5px; + margin-top: 5px; + padding: 0; + padding-left: 20px; + position: relative; + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: bottom; + white-space: nowrap; +} +.select2-container--default + .select2-selection--multiple + .select2-selection__choice__display { + cursor: default; + padding-left: 2px; + padding-right: 5px; +} +.select2-container--default + .select2-selection--multiple + .select2-selection__choice__remove { + background-color: transparent; + border: none; + border-right: 1px solid #aaa; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + color: #999; + cursor: pointer; + font-size: 1em; + font-weight: bold; + padding: 0 4px; + position: absolute; + left: 0; + top: 0; +} +.select2-container--default + .select2-selection--multiple + .select2-selection__choice__remove:hover, +.select2-container--default + .select2-selection--multiple + .select2-selection__choice__remove:focus { + background-color: #f1f1f1; + color: #333; + outline: none; +} +.select2-container--default[dir='rtl'] + .select2-selection--multiple + .select2-selection__choice { + margin-left: 5px; + margin-right: auto; +} +.select2-container--default[dir='rtl'] + .select2-selection--multiple + .select2-selection__choice__display { + padding-left: 5px; + padding-right: 2px; +} +.select2-container--default[dir='rtl'] + .select2-selection--multiple + .select2-selection__choice__remove { + border-left: 1px solid #aaa; + border-right: none; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +.select2-container--default[dir='rtl'] + .select2-selection--multiple + .select2-selection__clear { + float: left; + margin-left: 10px; + margin-right: auto; +} +.select2-container--default.select2-container--focus + .select2-selection--multiple { + border: solid black 1px; + outline: 0; +} +.select2-container--default.select2-container--disabled + .select2-selection--multiple { + background-color: #eee; + cursor: default; +} +.select2-container--default.select2-container--disabled + .select2-selection__choice__remove { + display: none; +} +.select2-container--default.select2-container--open.select2-container--above + .select2-selection--single, +.select2-container--default.select2-container--open.select2-container--above + .select2-selection--multiple { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.select2-container--default.select2-container--open.select2-container--below + .select2-selection--single, +.select2-container--default.select2-container--open.select2-container--below + .select2-selection--multiple { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +.select2-container--default .select2-search--dropdown .select2-search__field { + border: 1px solid #aaa; +} +.select2-container--default .select2-search--inline .select2-search__field { + background: transparent; + border: none; + outline: 0; + box-shadow: none; + -webkit-appearance: textfield; +} +.select2-container--default .select2-results > .select2-results__options { + max-height: 200px; + overflow-y: auto; +} +.select2-container--default .select2-results__option .select2-results__option { + padding-left: 1em; +} +.select2-container--default + .select2-results__option + .select2-results__option + .select2-results__group { + padding-left: 0; +} +.select2-container--default + .select2-results__option + .select2-results__option + .select2-results__option { + margin-left: -1em; + padding-left: 2em; +} +.select2-container--default + .select2-results__option + .select2-results__option + .select2-results__option + .select2-results__option { + margin-left: -2em; + padding-left: 3em; +} +.select2-container--default + .select2-results__option + .select2-results__option + .select2-results__option + .select2-results__option + .select2-results__option { + margin-left: -3em; + padding-left: 4em; +} +.select2-container--default + .select2-results__option + .select2-results__option + .select2-results__option + .select2-results__option + .select2-results__option + .select2-results__option { + margin-left: -4em; + padding-left: 5em; +} +.select2-container--default + .select2-results__option + .select2-results__option + .select2-results__option + .select2-results__option + .select2-results__option + .select2-results__option + .select2-results__option { + margin-left: -5em; + padding-left: 6em; +} +.select2-container--default .select2-results__option--group { + padding: 0; +} +.select2-container--default .select2-results__option--disabled { + color: #999; +} +.select2-container--default .select2-results__option--selected { + background-color: #ddd; +} +.select2-container--default + .select2-results__option--highlighted.select2-results__option--selectable { + background-color: #5897fb; + color: white; +} +.select2-container--default .select2-results__group { + cursor: default; + display: block; + padding: 6px; +} +.select2-container--classic .select2-selection--single { + background-color: #f7f7f7; + border: 1px solid #aaa; + border-radius: 4px; + outline: 0; + background-image: -webkit-linear-gradient(top, #fff 50%, #eee 100%); + background-image: -o-linear-gradient(top, #fff 50%, #eee 100%); + background-image: linear-gradient(to bottom, #fff 50%, #eee 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); +} +.select2-container--classic .select2-selection--single:focus { + border: 1px solid #5897fb; +} +.select2-container--classic + .select2-selection--single + .select2-selection__rendered { + color: #444; + line-height: 28px; +} +.select2-container--classic + .select2-selection--single + .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; + height: 26px; + margin-right: 20px; +} +.select2-container--classic + .select2-selection--single + .select2-selection__placeholder { + color: #999; +} +.select2-container--classic + .select2-selection--single + .select2-selection__arrow { + background-color: #ddd; + border: none; + border-left: 1px solid #aaa; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + height: 26px; + position: absolute; + top: 1px; + right: 1px; + width: 20px; + background-image: -webkit-linear-gradient(top, #eee 50%, #ccc 100%); + background-image: -o-linear-gradient(top, #eee 50%, #ccc 100%); + background-image: linear-gradient(to bottom, #eee 50%, #ccc 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); +} +.select2-container--classic + .select2-selection--single + .select2-selection__arrow + b { + border-color: #888 transparent transparent transparent; + border-style: solid; + border-width: 5px 4px 0 4px; + height: 0; + left: 50%; + margin-left: -4px; + margin-top: -2px; + position: absolute; + top: 50%; + width: 0; +} +.select2-container--classic[dir='rtl'] + .select2-selection--single + .select2-selection__clear { + float: left; +} +.select2-container--classic[dir='rtl'] + .select2-selection--single + .select2-selection__arrow { + border: none; + border-right: 1px solid #aaa; + border-radius: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + left: 1px; + right: auto; +} +.select2-container--classic.select2-container--open .select2-selection--single { + border: 1px solid #5897fb; +} +.select2-container--classic.select2-container--open + .select2-selection--single + .select2-selection__arrow { + background: transparent; + border: none; +} +.select2-container--classic.select2-container--open + .select2-selection--single + .select2-selection__arrow + b { + border-color: transparent transparent #888 transparent; + border-width: 0 4px 5px 4px; +} +.select2-container--classic.select2-container--open.select2-container--above + .select2-selection--single { + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; + background-image: -webkit-linear-gradient(top, #fff 0%, #eee 50%); + background-image: -o-linear-gradient(top, #fff 0%, #eee 50%); + background-image: linear-gradient(to bottom, #fff 0%, #eee 50%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); +} +.select2-container--classic.select2-container--open.select2-container--below + .select2-selection--single { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + background-image: -webkit-linear-gradient(top, #eee 50%, #fff 100%); + background-image: -o-linear-gradient(top, #eee 50%, #fff 100%); + background-image: linear-gradient(to bottom, #eee 50%, #fff 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); +} +.select2-container--classic .select2-selection--multiple { + background-color: white; + border: 1px solid #aaa; + border-radius: 4px; + cursor: text; + outline: 0; + padding-bottom: 5px; + padding-right: 5px; +} +.select2-container--classic .select2-selection--multiple:focus { + border: 1px solid #5897fb; +} +.select2-container--classic + .select2-selection--multiple + .select2-selection__clear { + display: none; +} +.select2-container--classic + .select2-selection--multiple + .select2-selection__choice { + background-color: #e4e4e4; + border: 1px solid #aaa; + border-radius: 4px; + display: inline-block; + margin-left: 5px; + margin-top: 5px; + padding: 0; +} +.select2-container--classic + .select2-selection--multiple + .select2-selection__choice__display { + cursor: default; + padding-left: 2px; + padding-right: 5px; +} +.select2-container--classic + .select2-selection--multiple + .select2-selection__choice__remove { + background-color: transparent; + border: none; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + color: #888; + cursor: pointer; + font-size: 1em; + font-weight: bold; + padding: 0 4px; +} +.select2-container--classic + .select2-selection--multiple + .select2-selection__choice__remove:hover { + color: #555; + outline: none; +} +.select2-container--classic[dir='rtl'] + .select2-selection--multiple + .select2-selection__choice { + margin-left: 5px; + margin-right: auto; +} +.select2-container--classic[dir='rtl'] + .select2-selection--multiple + .select2-selection__choice__display { + padding-left: 5px; + padding-right: 2px; +} +.select2-container--classic[dir='rtl'] + .select2-selection--multiple + .select2-selection__choice__remove { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +.select2-container--classic.select2-container--open + .select2-selection--multiple { + border: 1px solid #5897fb; +} +.select2-container--classic.select2-container--open.select2-container--above + .select2-selection--multiple { + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.select2-container--classic.select2-container--open.select2-container--below + .select2-selection--multiple { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +.select2-container--classic .select2-search--dropdown .select2-search__field { + border: 1px solid #aaa; + outline: 0; +} +.select2-container--classic .select2-search--inline .select2-search__field { + outline: 0; + box-shadow: none; +} +.select2-container--classic .select2-dropdown { + background-color: #fff; + border: 1px solid transparent; +} +.select2-container--classic .select2-dropdown--above { + border-bottom: none; +} +.select2-container--classic .select2-dropdown--below { + border-top: none; +} +.select2-container--classic .select2-results > .select2-results__options { + max-height: 200px; + overflow-y: auto; +} +.select2-container--classic .select2-results__option--group { + padding: 0; +} +.select2-container--classic .select2-results__option--disabled { + color: grey; +} +.select2-container--classic + .select2-results__option--highlighted.select2-results__option--selectable { + background-color: #3875d7; + color: #fff; +} +.select2-container--classic .select2-results__group { + cursor: default; + display: block; + padding: 6px; +} +.select2-container--classic.select2-container--open .select2-dropdown { + border-color: #5897fb; +} diff --git a/public/css/styles.css b/public/css/styles.css new file mode 100644 index 0000000..7951c18 --- /dev/null +++ b/public/css/styles.css @@ -0,0 +1,880 @@ +@charset "UTF-8"; +@font-face { + font-family: "TT Nooks Script"; + src: url("/fonts/TTNooksScript-Bold.woff2") format("woff2"), url("/fonts/TTNooksScript-Bold.woff") format("woff"); + font-weight: bold; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: "Bradford LL"; + src: url("/fonts/BradfordLL-Regular.woff2") format("woff2"), url("/fonts/BradfordLL-Regular.woff") format("woff"); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Bradford LL"; + src: url("/fonts/BradfordLL-Italic.woff2") format("woff2"), url("/fonts/BradfordLL-Italic.woff") format("woff"); + font-weight: normal; + font-style: italic; + font-display: swap; +} +@font-face { + font-family: "Necto Mono"; + src: url("/fonts/Necto-Mono.woff2") format("woff2"), url("/fonts/Necto-Mono.woff") format("woff"); + font-weight: normal; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: "Debrovnik Hill Italic"; + src: url("/fonts/Debrovnik Hill Italic.ttf") format("truetype"); +} +@font-face { + font-family: "Debrovnik Hill Reguler"; + src: url("/fonts/Debrovnik Hill Reguler.ttf") format("truetype"); +} +#mkd-login-container, +.mkd-form-signup-container { + width: 412px; + margin: 10vh auto; + background-color: #f3f3f3; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); + transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); +} +#mkd-login-container form, +.mkd-form-signup-container form { + width: 100%; + max-width: 410px; + padding: 15px; + margin: auto; +} +#mkd-login-container .form-control, +.mkd-form-signup-container .form-control { + position: relative; + box-sizing: border-box; + height: auto; + padding: 10px; + font-size: 16px; +} +#mkd-login-container .form-control:focus, +.mkd-form-signup-container .form-control:focus { + z-index: 2; +} +#mkd-login-container .mkd-login-form-container input[type="email"], +.mkd-form-signup-container .mkd-login-form-container input[type="email"] { + margin-bottom: -1px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +#mkd-login-container .mkd-login-form-container input[type="password"], +.mkd-form-signup-container .mkd-login-form-container input[type="password"] { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +#mkd-login-container .social-login, +.mkd-form-signup-container .social-login { + width: 390px; + margin: 0 auto; + margin-bottom: 14px; +} +#mkd-login-container .social-btn, +.mkd-form-signup-container .social-btn { + font-weight: 100; + color: white; + width: 49%; + display: inline; + font-size: 0.9rem; + margin: 0 2px; + padding-top: 5px; +} +#mkd-login-container a, +.mkd-form-signup-container a { + display: block; + padding-top: 10px; + color: black; +} + +#mkd-login-container .lines { + width: 200px; + border: 1px solid red; +} + +#mkd-login-container button[type="submit"] { + margin-top: 10px; +} +#mkd-login-container .facebook-btn { + background-color: #3c589c; +} +#mkd-login-container .google-btn { + background-color: #df4b3b; +} +#mkd-login-container input { + margin-bottom: 10px; +} + +@media screen and (max-width: 500px) { + #mkd-login-container { + width: 300px; + } + #mkd-login-container .social-login { + width: 200px; + margin: 0 auto; + margin-bottom: 10px; + } + #mkd-login-container .social-btn { + font-size: 1.3rem; + font-weight: 100; + color: white; + width: 200px; + height: 56px; + display: block; + line-height: 45px; + } + #mkd-login-container .social-btn:nth-child(1) { + margin-bottom: 5px; + } + #mkd-login-container .social-btn span { + display: none; + } + #mkd-login-container .facebook-btn:after { + content: "Facebook"; + } + #mkd-login-container .google-btn:after { + content: "Google+"; + } +} +body { + background: #e9ecef; +} + +a { + /* color: inherit; */ + text-decoration: none; + transition: all 0.3s; +} +a:hover { + color: inherit; + text-decoration: none; + transition: all 0.3s; +} +a:focus { + color: inherit; + text-decoration: none; + transition: all 0.3s; +} + +.navbar { + padding: 15px 10px; + background: #fff; + border: none; + border-radius: 0; + margin-bottom: 40px; + box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1); +} + +.navbar-btn { + box-shadow: none; + outline: none !important; + border: none; +} + +.line { + width: 100%; + height: 1px; + border-bottom: 1px dashed #ddd; + margin: 40px 0; +} + +.wrapper { + overflow: hidden; +} + +.copyright { + font-size: 12px; + display: block; + padding: 6px; +} + +#sidebar { + max-width: 250px; + width: 100%; + background: #151515; + color: #fff; + z-index: 2; + transition: all 0.3s; + -webkit-box-shadow: 2px 0px 4px 0px rgba(0, 0, 0, 0.75); + -moz-box-shadow: 2px 0px 4px 0px rgba(0, 0, 0, 0.75); + box-shadow: 2px 0px 4px 0px rgba(0, 0, 0, 0.75); + position: relative; + min-height: 100%; +} +#sidebar .sidebar-header { + padding: 20px; + background: #2c5ed6; +} +#sidebar ul.components { + padding: 0px 0px 20px 0px; +} +#sidebar ul p { + color: #fff; + padding: 10px; +} +#sidebar ul li a { + padding: 10px; + font-size: 1em; + display: block; +} +#sidebar ul li a:hover { + color: #151515; + background: #fff !important; +} +#sidebar ul li.active > a { + color: #fff; + background: #151515; +} +#sidebar a.active { + color: black; + background-color: #fff; +} + +#sidebar.active { + margin-left: -100%; + position: absolute; +} + +a[aria-expanded="true"] { + color: #fff; + background: #151515; +} + +a[data-toggle="collapse"] { + position: relative; +} + +.dropdown-toggle::after { + display: block; + position: absolute; + top: 50%; + right: 20px; + transform: translateY(-50%); +} + +ul ul a { + font-size: 0.9em !important; + padding-left: 30px !important; + background: #151515; +} + +#content { + width: 100%; + padding: 0px; + min-height: 100vh; + transition: all 0.3s; +} + +.btn:focus, +.btn:active:focus, +.btn.active:focus { + outline: none; + box-shadow: none; +} + +*:focus:not(a) { + outline: none; + box-shadow: none !important; +} + +#snackbar { + visibility: hidden; + /* Hidden by default. Visible on click */ + min-width: 250px; + /* Set a default minimum width */ + margin-left: -125px; + /* Divide value of min-width by 2 */ + background-color: #333; + /* Black background color */ + color: #fff; + /* White text color */ + text-align: center; + /* Centered text */ + border-radius: 2px; + /* Rounded borders */ + padding: 16px; + /* Padding */ + position: fixed; + /* Sit on top of the screen */ + z-index: 1; + /* Add a z-index if needed */ + left: 50%; + /* Center the snackbar */ + bottom: 30px; + /* 30px from the bottom */ +} +#snackbar .show { + visibility: visible; + /* Show the snackbar */ + /* Add animation: Take 0.5 seconds to fade in and out the snackbar. + However, delay the fade out process for 2.5 seconds */ + -webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s; + animation: fadein 0.5s, fadeout 0.5s 2.5s; +} + +@-webkit-keyframes fadein { + from { + bottom: 0; + opacity: 0; + } + to { + bottom: 30px; + opacity: 1; + } +} +@keyframes fadein { + from { + bottom: 0; + opacity: 0; + } + to { + bottom: 30px; + opacity: 1; + } +} +@-webkit-keyframes fadeout { + from { + bottom: 30px; + opacity: 1; + } + to { + bottom: 0; + opacity: 0; + } +} +@keyframes fadeout { + from { + bottom: 30px; + opacity: 1; + } + to { + bottom: 0; + opacity: 0; + } +} +@media (max-width: 768px) { + #sidebar { + margin-left: -250px; + position: relative; + } + + #sidebar.active { + margin-left: 0; + position: relative; + } +} +@media (min-width: 992px) { + .modal-xl { + max-width: 1200px; + } +} +.mkd-image-container { + max-width: 100px; +} + +.mkd-upload-btn-wrapper { + position: relative; + overflow: hidden; + display: inline-block; + margin: 100px auto; +} +.mkd-upload-btn-wrapper input[type="file"] { + font-size: 100px; + position: absolute; + left: 0; + top: 0; + opacity: 0; +} +.mkd-upload-btn-wrapper .mkd-upload-btn { + border: 2px solid gray; + color: gray; + background-color: white; + padding: 8px 20px; + border-radius: 8px; + font-size: 20px; + font-weight: bold; +} + +.mkd-upload-form-btn-wrapper { + position: relative; + overflow: hidden; + display: inline-block; +} +.mkd-upload-form-btn-wrapper input[type="file"] { + font-size: 100px; + position: absolute; + left: 0; + top: 0; + opacity: 0; +} +/* .mkd-upload-form-btn-wrapper .mkd-upload-btn { + border: 2px solid gray; + color: gray; + background-color: white; + padding: 4px 10px; + border-radius: 8px; + font-size: 10px; + font-weight: bold; } */ + +#mkd-media-upload-container, +#mkd-media-crop-container { + display: none; +} + +.mkd-media-panel-2, +.mkd-media-panel-3 { + display: none; + text-align: right; +} + +#mkd-crop-upload-container-wrapper { + margin: 0 auto; +} + +#mkd-media-gallery-wrapper img { + -webkit-box-shadow: 0px 0px 14px 0px rgba(0, 0, 0, 0.75); + -moz-box-shadow: 0px 0px 14px 0px rgba(0, 0, 0, 0.75); + box-shadow: 0px 0px 14px 0px rgba(0, 0, 0, 0.75); +} + +.mkd-gallery-image-image:hover { + outline: 5px dotted black; +} + +.mkd-gallery-image-image.active { + outline: 5px solid black; +} + +.mkd-choose-image { + display: inline-block; + margin-top: 15px; +} + +.form-group img { + display: block; +} + +.croppie-container { + width: 100%; + height: 100%; +} +.croppie-container .cr-image { + z-index: -1; + position: absolute; + top: 0; + left: 0; + transform-origin: 0 0; + max-height: none; + max-width: none; + -webkit-transform: translateZ(0); + -moz-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); +} +.croppie-container .cr-boundary { + position: relative; + overflow: hidden; + margin: 0 auto; + z-index: 1; + width: 100%; + height: 100%; +} +.croppie-container .cr-viewport { + position: absolute; + border: 2px solid #fff; + margin: auto; + top: 0; + bottom: 0; + right: 0; + left: 0; + box-shadow: 0 0 2000px 2000px rgba(0, 0, 0, 0.5); + z-index: 0; + -webkit-transform: translateZ(0); + -moz-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); +} +.croppie-container .cr-resizer { + position: absolute; + border: 2px solid #fff; + margin: auto; + top: 0; + bottom: 0; + right: 0; + left: 0; + box-shadow: 0 0 2000px 2000px rgba(0, 0, 0, 0.5); + z-index: 0; + z-index: 2; + box-shadow: none; + pointer-events: none; +} +.croppie-container .cr-resizer-vertical { + position: absolute; + pointer-events: all; + bottom: -5px; + cursor: row-resize; + width: 100%; + height: 10px; +} +.croppie-container .cr-resizer-vertical::after { + display: block; + position: absolute; + box-sizing: border-box; + border: 1px solid black; + background: #fff; + width: 10px; + height: 10px; + content: ""; + left: 50%; + margin-left: -5px; +} +.croppie-container .cr-resizer-horisontal { + position: absolute; + pointer-events: all; + right: -5px; + cursor: col-resize; + width: 10px; + height: 100%; +} +.croppie-container .cr-resizer-horisontal::after { + display: block; + position: absolute; + box-sizing: border-box; + border: 1px solid black; + background: #fff; + width: 10px; + height: 10px; + content: ""; + top: 50%; + margin-top: -5px; +} +.croppie-container .cr-original-image { + display: none; +} +.croppie-container .cr-vp-circle { + border-radius: 50%; +} +.croppie-container .cr-overlay { + z-index: 1; + position: absolute; + cursor: move; + touch-action: none; + -webkit-transform: translateZ(0); + -moz-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); +} +.croppie-container .cr-slider-wrap { + width: 75%; + margin: 15px auto; + text-align: center; +} + +.croppie-result { + position: relative; + overflow: hidden; +} +.croppie-result img { + position: absolute; +} + +.cr-slider { + -webkit-appearance: none; + width: 300px; + max-width: 100%; + padding-top: 8px; + padding-bottom: 8px; + background-color: transparent; +} +.cr-slider::-webkit-slider-runnable-track { + width: 100%; + height: 3px; + background: rgba(0, 0, 0, 0.5); + border: 0; + border-radius: 3px; +} +.cr-slider::-webkit-slider-thumb { + -webkit-appearance: none; + border: none; + height: 16px; + width: 16px; + border-radius: 50%; + background: #ddd; + margin-top: -6px; +} +.cr-slider:focus { + outline: none; +} +.cr-slider:focus::-ms-fill-lower { + background: rgba(0, 0, 0, 0.5); +} +.cr-slider:focus::-ms-fill-upper { + background: rgba(0, 0, 0, 0.5); +} +.cr-slider::-moz-range-track { + width: 100%; + height: 3px; + background: rgba(0, 0, 0, 0.5); + border: 0; + border-radius: 3px; +} +.cr-slider::-moz-range-thumb { + border: none; + height: 16px; + width: 16px; + border-radius: 50%; + background: #ddd; + margin-top: -6px; +} +.cr-slider:-moz-focusring { + outline: 1px solid white; + outline-offset: -1px; +} +.cr-slider::-ms-track { + width: 100%; + height: 5px; + background: transparent; + border-color: transparent; + border-width: 6px 0; + color: transparent; +} +.cr-slider::-ms-fill-lower { + background: rgba(0, 0, 0, 0.5); + border-radius: 10px; +} +.cr-slider::-ms-fill-upper { + background: rgba(0, 0, 0, 0.5); + border-radius: 10px; +} +.cr-slider::-ms-thumb { + border: none; + height: 16px; + width: 16px; + border-radius: 50%; + background: #ddd; + margin-top: 1px; +} + +.cr-rotate-controls { + position: absolute; + bottom: 5px; + left: 5px; + z-index: 1; +} +.cr-rotate-controls button { + border: 0; + background: none; +} +.cr-rotate-controls i:before { + display: inline-block; + font-style: normal; + font-weight: 900; + font-size: 22px; +} + +.cr-rotate-l i:before { + content: "↺"; +} + +.cr-rotate-r i:before { + content: "↻"; +} + +#sidebar ul.collapse li a { + background-color: #3e3f40; +} + +.table .thead-light th:first-child, +table .tbody-light td:first-child { + border-left: 1px solid #dee2e6; +} + +.table .thead-light th:last-child, +table .tbody-light td:last-child { + border-right: 1px solid #dee2e6; +} + +.table .tbody-light tr:last-child { + border-bottom: 1px solid #dee2e6; +} + +.breadcrumb-link { + color: #2c549c; +} + +.navigation-row { + background-color: white; + padding: 20px 20px 20px 10px; +} + +.text-underline { + text-decoration: underline !important; +} + +.btn-light { + background-color: white; + border: none; +} +.form-container-auth { + max-width: 30rem; + margin: auto; +} + +.auth-wrapper { + margin-top: 10vh; +} + +.hamburger { + position: absolute; + right: -48px; + top: 0px; +} + +.list-group-item-action:hover, +.list-group-item-action:active, +.custom-list-item.active.collapsed { + color: #151515; + background-color: white; +} +.custom-list-item.active { + background-color: transparent; + color: white; +} + +.custom-list-item { + height: 50px; + background-color: transparent; + color: white; + padding: 0 10px; + border-radius: 0; +} +#sidebar .card { + border: none; + background-color: transparent; +} +#sidebar .card-header { + border-bottom: none; +} +#sidebar .card-header:first-child { + border-radius: 0; +} +.dropdownMenuItem { + background-color: rgba(0, 0, 0, 0.4); +} + +.menu-item { + color: white; +} +.menu-active { + background-color: white; + color: black; +} + +#body { + width: 100%; +} + +#modal-image-slot { + width: 100%; +} + +#bulkDeleteButton, +#bulkEditButton { + display: none; +} + +/* required field red asterisk */ +.form-group.required .control-label:after { + color: red; + content: "*"; + margin-left: 5px; + font-size: 20px; +} + +.main-body { + height: 100%; + min-height: 100vh; + flex-wrap: nowrap; + overflow: auto; + overflow-x: hidden; +} + +.google-button, +.facebook-button { + height: 50px; + background-color: white; + border-radius: 10px; + display: flex; + justify-content: center; + align-items: center; +} + +.facebook-button { + background-color: #3b5998; + color: white; +} + +.flash-response { + width: 100%; + margin: 0; +} +.hide-answer-select, +.answer-value, +.answer-image { + display: none; +} +.hide-answer-select.show, +.answer-value.show, +.answer-image.show { + display: block; +} + +.order-arrows { + width: 20px; + display: inline-block; + margin-bottom: -3px; +} + +.weight-active-score.has-value { + outline: blue 1px solid; +} +.custom-picker { + border: 1px solid #ced4da; + border-radius: 4px; +} + +.custom-flash-message { + color: black; + width: 80%; + max-width: 700px; + padding: 16px; + border-radius: 4px; + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23); + position: fixed; + top: 20px; + right: 20px; + background-color: white; + transform: translateX(1000%); + transition: 300ms all cubic-bezier(0.165, 0.84, 0.44, 1); +} +.custom-flash-message.show { + z-index: 1051; + transform: translateX(0%); + transition: 300ms all cubic-bezier(0.165, 0.84, 0.44, 1); +} +.custom-flash-message.show.success { + color: green; +} +.custom-flash-message.show.error { + color: red; +} diff --git a/public/fonts/BradfordLL-Italic.woff b/public/fonts/BradfordLL-Italic.woff new file mode 100644 index 0000000..a16d133 Binary files /dev/null and b/public/fonts/BradfordLL-Italic.woff differ diff --git a/public/fonts/BradfordLL-Italic.woff2 b/public/fonts/BradfordLL-Italic.woff2 new file mode 100644 index 0000000..6fcfb04 Binary files /dev/null and b/public/fonts/BradfordLL-Italic.woff2 differ diff --git a/public/fonts/BradfordLL-Regular.woff b/public/fonts/BradfordLL-Regular.woff new file mode 100644 index 0000000..2609f5c Binary files /dev/null and b/public/fonts/BradfordLL-Regular.woff differ diff --git a/public/fonts/BradfordLL-Regular.woff2 b/public/fonts/BradfordLL-Regular.woff2 new file mode 100644 index 0000000..b737ae9 Binary files /dev/null and b/public/fonts/BradfordLL-Regular.woff2 differ diff --git a/public/fonts/Debrovnik Hill Italic.ttf b/public/fonts/Debrovnik Hill Italic.ttf new file mode 100644 index 0000000..037e498 Binary files /dev/null and b/public/fonts/Debrovnik Hill Italic.ttf differ diff --git a/public/fonts/Debrovnik Hill Reguler.ttf b/public/fonts/Debrovnik Hill Reguler.ttf new file mode 100644 index 0000000..662ef55 Binary files /dev/null and b/public/fonts/Debrovnik Hill Reguler.ttf differ diff --git a/public/fonts/Necto-Mono.woff b/public/fonts/Necto-Mono.woff new file mode 100644 index 0000000..e9306c9 Binary files /dev/null and b/public/fonts/Necto-Mono.woff differ diff --git a/public/fonts/Necto-Mono.woff2 b/public/fonts/Necto-Mono.woff2 new file mode 100644 index 0000000..0b273ef Binary files /dev/null and b/public/fonts/Necto-Mono.woff2 differ diff --git a/public/fonts/RotationLTStd-Roman.otf b/public/fonts/RotationLTStd-Roman.otf new file mode 100644 index 0000000..7ef8221 Binary files /dev/null and b/public/fonts/RotationLTStd-Roman.otf differ diff --git a/public/fonts/TTNooksScript-Bold.woff b/public/fonts/TTNooksScript-Bold.woff new file mode 100644 index 0000000..fecbf86 Binary files /dev/null and b/public/fonts/TTNooksScript-Bold.woff differ diff --git a/public/fonts/TTNooksScript-Bold.woff2 b/public/fonts/TTNooksScript-Bold.woff2 new file mode 100644 index 0000000..501f8aa Binary files /dev/null and b/public/fonts/TTNooksScript-Bold.woff2 differ diff --git a/public/frontend_css/mobile_styles.css b/public/frontend_css/mobile_styles.css new file mode 100644 index 0000000..862d70e --- /dev/null +++ b/public/frontend_css/mobile_styles.css @@ -0,0 +1,126 @@ +@media only screen and (max-height: 580px) { + #page1 .secondRow { + height: auto; + } +} +@media only screen and (max-width: 992px) { + #page1 .main-image-container { + display: none; + } + #page1 .columns { + width: 100%; + margin-left: 0; + padding: 0 8px; + } + #page1 .firstRow { + height: 100px; + } + #page1 .secondRow { + height: auto; + } + #page1 .secondRow .heading { + font-size: 40px; + margin-bottom: 48px; + } + #page1 .secondRow .para { + margin-bottom: 56px; + font-size: 15px; + } + #page1 .secondRow .beginButton { + font-size: 11px; + } + #page2 h4 { + font-size: 24px; + } + #page2 h1 { + font-size: 36px; + } + .progressBar .progressColumns p { + font-size: 10px; + } + #page3 .questionRow h1 { + font-size: 36px; + line-height: 56px; + padding: 0 8px; + } + .answerInner.typeText input, + .answerInner.typeNum input { + font-size: 16px; + } + #page4 .createdByDiv, + .createdByDiv { + font-size: 10px; + } + .noteRow { + margin-bottom: 10vh; + } + #page3 .questionRow.mtb { + padding: 24px 0; + } + #page3 .noteRow { + flex-direction: column; + margin-bottom: 10vh; + } + #page3 .noteRow .noteTitle { + border: 1px solid #101010 !important; + border-top: none !important; + } + #page3 .noteRow .noteTitle h4 { + font-size: 12px; + margin: 8px 0; + } + #page3 .noteRow .noteDesc { + border: 1px solid #101010 !important; + border-top: none !important; + } + #page3 .noteRow .noteDesc p { + margin: 8px 0; + font-size: 13px; + text-align: center; + } + .multiBtns { + font-size: 12px; + padding: 14px 10px; + } + #page3 .noteRow.image-below { + margin-bottom: 5vh !important; + } + #page3 .questionRow.mtb.no-note { + margin-bottom: 8vh !important; + } + #page3 .questionRow.mtb.no-note.no-image { + margin-bottom: 16vh !important; + } + #page3 .answerRow { + margin-top: 24px; + } + #page4 .headerRow, + .headerRow { + height: 50px; + } + .sliderDiv { + margin: 32px auto 8px auto; + width: 90%; + } + #typeGeo .answerInner input { + font-size: 16px; + } + #weatherApi .header { + text-align: center; + } + #page5 .responseRow .responseInner .responseBody p { + padding: 0 8px; + } + .control-arrows img { + width: 15px; + } + .sliderRanges .ranges { + font-size: 12px; + } + #page5 .responseRow .responseInner .responseHead h1 { + font-size: 36px; + } + #page5 .responseRow .responseInner .responseBody p { + font-size: 13px; + } +} diff --git a/public/frontend_css/style.css b/public/frontend_css/style.css new file mode 100644 index 0000000..d9a9ac3 --- /dev/null +++ b/public/frontend_css/style.css @@ -0,0 +1,1441 @@ +html, +body { + scroll-behavior: smooth; + max-width: 100%; + overflow-x: hidden; +} +body { + background: #f3f4ee; + margin: 0; + height: 100%; + height: 100vh; + min-height: 100vh; +} +* { + box-sizing: border-box; +} +@font-face { + font-family: "Bradford LL"; + src: url("/fonts/BradfordLL-Regular.woff2") format("woff2"), url("/fonts/BradfordLL-Regular.woff") format("woff"); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Bradford LL"; + src: url("/fonts/BradfordLL-Italic.woff2") format("woff2"), url("/fonts/BradfordLL-Italic.woff") format("woff"); + font-weight: normal; + font-style: italic; + font-display: swap; +} +@font-face { + font-family: "Necto Mono"; + src: url("/fonts/Necto-Mono.woff2") format("woff2"), url("/fonts/Necto-Mono.woff") format("woff"); + font-weight: normal; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: "TT Nooks Script"; + src: url("/fonts/TTNooksScript-Bold.woff2") format("woff2"), url("/fonts/TTNooksScript-Bold.woff") format("woff"); + font-weight: bold; + font-style: normal; + font-display: swap; +} +/* Chrome, Safari, Edge, Opera */ +input::-webkit-outer-spin-button, +input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +/* Firefox */ +input[type="number"] { + -moz-appearance: textfield; +} +/*arrows*/ +.arrow { + display: block; + height: 100%; + width: 10px; +} +.arrow::after { + border-bottom-style: solid; + border-bottom-width: 2px; + border-right-style: solid; + border-right-width: 2px; + content: ""; + display: inline-block; + position: absolute; + height: 5px; + left: 0px; + bottom: 0px; + width: 5px; +} +.arrow.is-triangle::after { + border-style: solid; + border-width: 0 0 12px 12px; + height: 0; + width: 0; +} +.arrow.is-check::after { + width: 6px; +} +.arrow.arrow-bar::before { + position: absolute; + bottom: 1px; + left: 5px; + content: ""; + height: 17px; + width: 2px; + transform-origin: bottom; + -moz-transform: rotate(-45deg); + -ms-transform: rotate(-45deg); + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); +} +.arrow.is-top { + -moz-transform: rotate(225deg); + -ms-transform: rotate(225deg); + -webkit-transform: rotate(225deg); + transform: rotate(225deg); +} +.arrow.is-right { + -moz-transform: rotate(-45deg); + -ms-transform: rotate(-45deg); + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); +} +.arrow.is-bottom { + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + -webkit-transform: rotate(45deg); + transform: rotate(45deg); +} +.arrow.is-left { + -moz-transform: rotate(135deg); + -ms-transform: rotate(135deg); + -webkit-transform: rotate(135deg); + transform: rotate(135deg); +} +.arrow::after, +.arrow .arrow::after { + border-color: #231f20; +} +.arrow.is-triangle::after, +.arrow .arrow.is-triangle::after { + border-color: transparent; + border-bottom-color: red; +} +.arrow::before, +.arrow .arrow::before { + background-color: #231f20; +} + +#arrowTopLeft { + position: absolute; + margin: 0px 0px 0px 0px; +} +#arrowTopRight { + position: absolute; + margin: 0px 0px 0px 0px; +} + +/*arrows end*/ + +/*page 1 starts*/ +#page1 { + display: block; + overflow-x: hidden; + max-width: 100%; + height: 100vh; + min-height: 560px; +} +#page1 .container { + height: 100%; + min-height: 100%; + max-width: 100%; + overflow-x: hidden; +} + +#page1 .firstRow { + width: 100%; + height: 120px; + display: flex; + z-index: 2; + flex-direction: row; + align-items: center; + justify-content: flex-start; + border-bottom: 1px solid; + background: #f3f4ee; +} +#page1 .firstRow .dash { + width: 4px; + height: 1px; + margin-right: 8px; + /* display: inline-block; */ + background-color: #101010; +} +#page1 .secondRow { + width: 100%; + height: calc(100vh - 120px); + display: flex; + align-items: center; + justify-content: space-between; + padding: 0px; +} +#page1 .columns { + overflow: hidden; + display: block; + width: 50%; + max-width: 640px; + height: 100%; + display: flex; + margin-left: clamp(20px, 3%, 5%); + flex-direction: column; + align-items: flex-start; + justify-content: center; +} +#page1 .main-image-container { + height: 100%; + width: 100%; + max-width: 50%; + text-align: end; +} +#page1 .main-image-container img { + height: 100%; + max-height: 100%; + border-left: 1px solid black; + width: 90%; + + object-fit: cover; +} + +#page1 .firstRow h1 { + display: inline-block; + margin: 0; + margin-left: 3vw; + padding-right: 15px; + font: italic 32px "Bradford LL"; + font-weight: 500; + color: #231f20; + line-height: 40px; + margin-bottom: 6px; +} +#page1 .firstRow h5 { + margin: 0; + font: 10px "Necto Mono"; + color: #231f20; + line-height: 20px; + display: inline-flex; + align-items: center; + justify-content: center; +} + +#page1 .secondRow .heading { + font: italic 44px "Bradford LL"; + color: #231f20; + text-align: left; + margin-bottom: 72px; + padding-left: 8px; +} +#page1 .secondRow .underlineSpan { + padding-bottom: 4px; + border-bottom: 1px solid; +} +#page1 .secondRow .para { + font: 16px "Necto Mono"; + color: #231f20; + padding-left: 8px; + text-align: left; + margin-bottom: 100px; +} + +#page1 .secondRow .beginButton { + background: #737a73; + color: #ffffff; + padding: 10px 65px; + font: 12px "Necto Mono"; + border: none; + margin-bottom: 16px; + margin-left: 8px; + cursor: pointer; + transition: all 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275); +} +#page1 .secondRow .beginButton:hover { + background: #444242; + color: white; + transition: all 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275); +} +#page1 .secondRow .beginButton:focus { + background: #444242; +} + +/*page 1 ends*/ + +/*page 2 starts*/ +#page2 { + display: none; + min-height: 100%; + height: 100%; +} +#page2 .container { + min-height: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} +#page2 .row { + text-align: center; + margin-bottom: 32px; +} +#page2 h4 { + margin-top: 0; + font: 32px "Necto Mono"; + color: #231f20; +} +#page2 h1 { + font: italic 56px "Bradford LL"; + color: #231f20; +} +/*page 2 ends*/ + +/*page 3 starts*/ +#page3 { + display: none; + height: 100%; + min-height: 100%; +} +.container { + width: 100%; + /* height: 100%; */ + min-height: 100%; +} +.container.center-everything { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 60px 0px 60px 0px; +} +.container.mto { + padding: 60px 0px 60px 0px; +} +.headerRow { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 60px; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + border: 1px solid #101010; + background: #f3f4ee; + z-index: 1101; +} +.headerRow .nav-item { + padding: 0px 8px; + height: 100%; + width: calc(100% / 3); + display: flex; + align-items: center; + justify-content: center; + position: relative; +} +.nav-item.nextBtn { + justify-content: flex-end; + cursor: pointer; +} +.nav-item.prevBtn { + cursor: pointer; + justify-content: flex-start; +} +.nav-item.bordered { + border-right: 1px solid #101010; + border-left: 1px solid #101010; +} +#page3 .headerRow .nav-item.hide { + display: none; +} +.control-arrows { + cursor: pointer; + height: 100%; + padding: 0 16px 0 8px; + display: flex; + align-items: center; + justify-content: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; +} +.control-arrows img { + width: 20px; +} +.createdByDiv { + text-align: center; + font: 14px "Necto Mono"; +} + +#page3 .questionRow { + text-align: center; +} +#page3 .questionRow.mtb { + padding: 36px 0; + border-bottom: 1px solid #101010; +} +#page3 .questionRow.mtb.no-note { + margin-bottom: 10vh; +} +#page3 .questionRow.mtb.no-note.no-image { + margin-bottom: 16vh; +} + +#page3 .questionRow h1 { + font: italic 40px "Bradford LL"; + margin: 0; + color: #231f20; + line-height: 66px; +} +#page3 .noteRow { + position: relative; + width: 100%; + display: flex; + z-index: 1100; + flex-direction: row; + justify-content: stretch; +} +.noteRow { + position: relative; + width: 100%; + display: flex; + z-index: 1100; + margin-bottom: 16vh; + flex-direction: row; + justify-content: stretch; +} +#page3 .row.noteRow.image-below { + margin-bottom: 8vh; +} +#page3 .noteRow .noteTitle { + border-bottom: 1px solid #101010; + border-right: 1px solid #101010; + display: flex; + position: relative; + background: transparent; + align-items: center; + justify-content: center; + -webkit-appearance: none; + text-transform: uppercase; + padding: 0 16px; +} +#page3 .noteRow .noteTitle h4 { + font: 15px "Necto Mono"; + white-space: nowrap; +} +#page3 .noteRow .noteDesc { + border-bottom: 1px solid #101010; + display: flex; + position: relative; + background: none; + align-items: center; + justify-content: center; + -webkit-appearance: none; + padding: 0 6vw; + width: 100%; +} +#page3 .noteRow .noteDesc p { + font: 14px "Necto Mono"; +} +#page3 #noteRow, +#page3 #questionRow { + display: none; +} + +#page3 .answerRow { + width: 100%; + display: none; + text-align: center; +} +.answerInner.typeText, +.answerInner.typeNum { + display: flex; + align-items: center; + justify-content: space-between; + width: 95%; + max-width: 524px; + margin: 0 auto; + border-bottom: 1px solid #101010; +} +.answerInner.typeText input, +.answerInner.typeNum input { + width: 85%; + height: 100%; + padding: 16px 0 16px 60px; + background: transparent; + border: none; + color: #231f20; + font: 24px "Necto Mono"; + line-height: 30px; + text-align: center; +} +.answerInner.typeText .nextBtn, +.answerInner.typeNum .nextBtn { + height: 100%; + padding: 20px 0 20px 20px; + cursor: pointer; +} +input::placeholder { + color: #464846; + opacity: 1; +} +input:-ms-input-placeholder { + color: #464846; +} +input::-ms-input-placeholder { + color: #464846; +} +.typeText input:focus, +.typeNum input:focus { + outline: none; +} +.answerInner { + display: flex; + flex-direction: row; + margin: auto; + align-items: center; + justify-content: center; + flex-wrap: wrap; +} +.answerInner .arrowAnswerBtn { + display: flex; + width: 15%; + align-items: center; + justify-content: flex-end; +} +.typeSlide .answerInner { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} +.typeMcq .answerInner .mcqOptions { + height: 100%; +} +.typeMcq .answerInner .multiBtns { + height: 100%; + width: 100%; +} +.typeMcq .answerInner { + display: grid; + margin: auto; + align-items: center; + justify-content: center; + grid-auto-rows: 1fr; + grid-template-columns: repeat(auto-fit, 200px); + gap: 16px; +} +.typeMcqi .answerInner { + width: 95%; +} +.typeSelection .answerInner { + width: 50%; +} + +.mcqOptions { + display: inline-block; + /* margin: 10px 10px; */ + vertical-align: -webkit-baseline-middle; + vertical-align: -moz-baseline-middle; +} +.mcqiBtn { + padding: 0px; + margin: 0px; + border: none; + height: 100%; + width: 100%; +} +.mcqiBtn:hover { + transform: scale(1.1); +} +.mcqiBtn:focus { + transform: scale(1.1); +} +.mcqiOptions { + display: inline-block; + margin: 5px 5px; +} +.mcqiOptions .mcqiImg { + width: 100%; + height: 100%; + object-fit: cover; +} +.selectionOptions { + display: inline-block; + margin: 10px 10px; +} + +.multiBtns { + cursor: pointer; + background: #000; + color: #ffff; + border: #000; + padding: 16px 12px; + width: 100%; + height: 100%; + text-align: center; + font: 14px "Necto Mono"; + transition: all 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275); +} +.multiBtns:hover { + background: #444242; + color: whitesmoke; + border: #000; + transition: all 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275); +} +.multiBtns:focus { + background: #444242; + color: whitesmoke; + border: #000; + transition: all 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275); +} +.selectionBtns { + background: #000; + color: #ffff; + border: #000; + padding: 5px 5px; + width: 196px; + height: 36px; + font: 14px "Necto Mono"; + cursor: pointer; +} +.selectionBtns:hover { + background: #444242; + color: whitesmoke; + border: #000; +} +.selectionBtns:active, +.active { + background: #444242; + color: whitesmoke; + border: #000; +} +#progressBarSection { + display: none; +} +#myBar { + width: 1%; + height: 30px; + background-color: #000; + z-index: 99999; +} +.progressColumnsDiv { + position: absolute; + top: 0px; + height: 30px; + display: flex; + flex-direction: row; + width: 100%; +} + +.progressBar { + position: fixed; + bottom: 0; + width: 100%; + z-index: 9999; + background: #f3f4ee; + border: 1px solid #101010; +} +.progressBar .progressColumns { + display: flex; + flex: 1; + flex-direction: column; + align-self: center; + border: none; + border-right: 1px solid #101010; + height: 30px; + padding: 0; + background: none; + align-items: center; + width: 33.33334%; + justify-content: center; +} +.progressBar .progressColumns:last-child { + border-right: none; +} +.progressBar .progressColumns:first-child { + border-left: none; +} +.progressBar .progressColumns p { + font: 12px "Necto mono"; + margin: 0; +} +.typeSlide .imgDiv { + display: none; +} +.typeSlide .imgDiv img { + height: 150px; + width: auto; +} +.sliderDiv { + margin: 48px auto 0 auto; + width: 85%; +} +.slidecontainer { + width: 100%; +} +.slider { + appearance: none; + -moz-appearance: none; + -webkit-appearance: none; + outline: none; + width: 100%; + height: 20px; + -webkit-box-shadow: inset 0px 0px 0px 1px #000; + -moz-box-shadow: inset 0px 0px 0px 1px #000; + box-shadow: inset 0px 0px 0px 1px #000; + background: transparent; + opacity: 1; +} +.slider::-webkit-slider-thumb { + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + width: 15px; + height: 45px; + background: #d8d8d8; + opacity: 0.9; + border: 1px solid #00000035; + cursor: pointer; + -webkit-transition: opacity 200ms; + -moz-transition: opacity 200ms; + transition: opacity 200ms; +} +.slider::-moz-range-thumb { + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + width: 15px; + height: 45px; + background: #d8d8d8; + opacity: 0.9; + border: 1px solid #00000035; + cursor: pointer; + -webkit-transition: opacity 200ms; + -moz-transition: opacity 200ms; + transition: opacity 200ms; +} +.slider.active::-webkit-slider-thumb { + opacity: 1; + background: #000000; + border: 1px solid #000000; +} +.slider.active::-moz-range-thumb { + opacity: 1; + background: #000000; + border: 1px solid #000000; +} +.sliderRanges { + display: flex; + flex-direction: row; + margin: 30px auto; + color: #000; + line-height: 20px; + word-break: break-word; + overflow: hidden; +} +.sliderRanges .ranges { + font: 16px "Necto Mono"; +} +.sliderRanges :first-child { + text-align: left; +} +.sliderRanges :last-child { + text-align: right; +} +.ranges { + flex: 1; +} + +#page3 .responseRow { + margin-top: 170px; + margin-bottom: 240px; + text-align: -webkit-center; +} +#page3 .responseRow .responseInner { + width: 50%; +} +#page3 .responseRow .responseInner h4 { + width: 60%; + font: italic 28px "Bradford LL"; + color: #231f20; + line-height: 30px; +} +#page3 .responseRow .responseInner p { + width: 60%; + text-align: left; + font: 16px "Bradford LL"; + color: #231f20; + line-height: 22px; +} + +/*page 3 ends*/ + +/*page 4 starts*/ +#page4 { + display: none; + height: 100%; + min-height: 100%; +} +#page4 .container { + width: 100%; + display: flex; + min-height: 100%; + flex-direction: column; + align-items: center; + justify-content: center; +} +#page4 .headerRow { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 60px; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + border: 1px solid #101010; + background: #f3f4ee; + z-index: 1101; +} +#page4 .headerRow .nav-item { + padding: 0px 8px; + height: 100%; + width: calc(100% / 3); + text-align: center; + position: relative; +} +#page4 .createdByDiv { + text-align: center; + font: 14px "Necto Mono"; +} + +#page4 .customImgRow { + text-align: -webkit-center; + text-align: -moz-center; +} +#page4 .customImgRow .imgRowInner { + width: max-content; + width: -moz-max-content; + position: relative; +} +#page4 .createdByName { + font: 16px "Necto Mono"; + font-weight: 700; + width: max-content; + width: -moz-max-content; + padding-bottom: 4px; + border-bottom: 1px solid black; +} +#page4 .customImgRow img { + width: 335px; + margin-right: 50px; +} +@media only screen and (max-width: 992px) { + #page4 .createdByNameContainer { + left: 39%; + } + #page4 .customImgRow img { + margin-right: unset; + } +} +/*page 4 ends*/ + +/*page5 starts*/ +#page5 { + display: none; + height: 100%; + min-height: 100%; +} + +#page5 .responseRow { + text-align: -webkit-center; + text-align: -moz-center; +} +#page5 .responseRow .responseInner { + width: 100%; + max-width: 648px; +} +#page5 .responseRow .responseInner .responseHead { + text-align: center; +} +#page5 .responseRow .responseInner .responseHead h1 { + margin: 0 0 36px 0; + font: italic 44px "Bradford LL"; + font-weight: bold; + color: #231f20; +} +#page5 .responseRow .responseInner .responseBody { + text-align: center; +} +#page5 .responseRow .responseInner .responseBody p { + font: 15px "Necto Mono"; + font-weight: 500; + color: #231f20; + line-height: 30px; + margin: 0px; +} +/*page 5 ends here*/ + +/*page6 starts*/ +#page6 { + display: none; + height: 100%; + min-height: 100%; +} +#page6 .container { + display: flex; + align-items: center; + justify-content: center; + padding-bottom: 110px; + background-color: #f5f6ef; +} +#page6 .finalRow { + /* margin: 180px auto; + width: 80%; */ + text-align: center; +} +#page6 .finalDesc h3 { + margin: 0; + font: italic 40px "Bradford LL"; +} +#page6 .imgDiv img { + max-height: 220px; + margin-bottom: 72px; + width: auto; + object-fit: contain; +} + +/*page6 ends*/ + +/*page7 starts*/ +#page7 { + display: none; + height: 100%; + min-height: 100%; +} +#page7 .container { + padding: 60px 0; +} +#page7 .headerRow { + justify-content: center !important; +} +#page7 .finalProfileDiv { + font: 14px "Necto Mono"; +} +#page7 .topline { + border-width: 2px; +} +#page7 .finalProfileArrows { + top: unset !important; +} +#page7 .finalArrowLine { + position: relative; + top: 7px; + right: -2px; +} +#page7 #arrowLineRight { + width: 12px; + height: 1px; + background-color: #343a40; +} + +#page7 .messageRow { + padding: 60px 0px; + width: 100%; + text-align: -webkit-center; + border-bottom: 1px solid #000; +} +#page7 .messageRow .messageInner { + /* width: 60%; */ + padding: 0 16px; +} +#page7 .messageRow .nameDiv h5 { + text-align: center; + margin: 0; + margin-bottom: 16px; + font: 18px "Necto Mono"; + text-transform: uppercase; +} +#page7 .messageRow .messageDiv { + margin: 0 auto 16px auto; +} +#page7 .messageRow .messageDiv h3 { + text-align: center; + font: italic 44px "Bradford LL"; + font-weight: 700; + margin: 0; + margin-bottom: 16px; +} +#page7 .messageRow .paraDiv { + width: 100%; + max-width: 710px; + text-align: center; +} +#page7 .messageRow .paraDiv p { + font: 16px "Necto Mono"; + text-align: center; + margin: 0; + margin-bottom: 20px; +} +#page7 .messageRow .buttonDiv { + position: relative; +} +#page7 .messageRow .buttonDiv .button { + background: #737a73; + color: #ffffff; + padding: 10px 65px; + font: 12px "Necto Mono"; + border: none; + cursor: pointer; + transition: all 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275); + position: relative; +} +#page7 .messageRow .buttonDiv .button:hover { + background: #444242; + color: white; + transition: all 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275); +} +#page7 .messageRow .buttonDiv .button:focus { + background: #444242; +} + +#page7 .messageRow .buttonDiv .arrow::before { + background-color: #fff; +} +#page7 .messageRow .buttonDiv .arrow.arrow-bar::before { + bottom: 30px; + content: ""; + height: 7px; + position: absolute; + right: 4px; + left: unset; + transform-origin: bottom; + width: 1px; + -moz-transform: rotate(-45deg); + -ms-transform: rotate(-45deg); + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); +} +#page7 .messageRow .buttonDiv .arrow::after { + border-color: #fff; + border-bottom-style: solid; + border-bottom-width: 2px; + border-right-style: solid; + border-right-width: 2px; + content: ""; + display: inline-block; + height: 3px; + left: 4px; + position: absolute; + top: 3px; + width: 3px; +} + +#page7 .profile-row { + padding: 50px 0px 80px 0px; + width: 100%; + text-align: -webkit-center; + border-bottom: 1px solid #000; +} +#page7 .profile-row .rowInner { + width: 100%; + padding: 0 5%; +} +#page7 .profile-row .rowInner h1 { + font: italic 40px "Bradford LL"; + color: #231f20; + line-height: 66px; +} +#page7 .main-body { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + justify-content: flex-start; +} +#page7 .main-body .bodyTitle h4 { + font: 24px "Necto Mono"; + text-transform: uppercase; + color: #231f20; + margin-top: 16px; + margin-bottom: 20px; + display: inline-block; +} +#page7 .main-body .bodyDesc { + margin-bottom: 34px; +} +#page7 .main-body .bodyDesc p { + margin: 0; + font: 14px "Necto Mono"; +} +#page7 .main-body .bodyProgress { + margin-bottom: 16px; +} +#page7 .profile-row .bodyCols { + width: 45%; + max-width: 720px; + min-width: 320px; + margin: 30px auto; +} +#page7 .profile-row .bodyProgress { + width: 100%; + height: 10px; + border: 1px solid black; + text-align: left; +} +#page7 .profile-row .movingBar { + height: 100%; + background-color: #000; + z-index: 9; +} + +#page7 .aboutRow { + padding: 50px 0px; + width: 100%; + text-align: -webkit-center; +} +#page7 .aboutRow .aboutInner { + /* width: 90%; */ + padding: 0 16px; +} +#page7 .aboutRow .nameDiv { + font: 24px "Bradford LL"; + margin: 5px auto; +} +#page7 .aboutRow .nameDiv h5 { + margin: auto; +} +#page7 .aboutRow .aboutDiv { + font: italic 30px "Bradford LL"; +} +#page7 .aboutRow .aboutDiv h3 { + text-align: center; + margin: 60px auto 48px auto; +} +#page7 .aboutRow .paraDiv { + width: 100%; +} +#page7 .aboutRow .paraDiv p { + max-width: 710px; + text-align: center; + font: 16px "Necto Mono"; + margin-bottom: 60px; +} +#page7 .buttonDiv { + position: relative; +} +#page7 .buttonDiv .button { + background: #737a73; + color: #ffffff; + padding: 10px 65px; + font: 12px "Necto Mono"; + border: none; + cursor: pointer; + transition: all 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275); + display: flex; + align-items: center; + justify-content: space-between; +} +#page7 .buttonDiv .button:hover { + background: #444242; + color: white; + transition: all 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275); +} +#page7 .buttonDiv .button:focus { + background: #444242; +} + +#page7 .arrowCustom { + padding: 0 0 0 10px; + margin-right: -15px; + display: inline-flex; +} +#page7 .arrowCustom.control-arrows img { + width: 11px; +} +/*page7 ends here*/ + +/*page8 starts*/ +#page8 .headerRow { + position: fixed; + top: 0; + width: 100%; + display: flex; + flex-direction: row; + justify-content: stretch; + border: 1px solid; + border-left: none; + border-right: none; + background: #f3f4ee; + z-index: 1101; +} +#page8 .headerColumns { + flex: 1; + display: flex; + padding: 0; + position: relative; + background: none; + align-items: center; + justify-content: center; +} +#page8 .prevBtn { + position: fixed; + left: 0px; + top: 1%; + height: 41px; + width: 65px; + background: transparent; + border: none; + padding: 10px 45px 0px 0px; +} +#page8 #arrowTopLeft { + position: relative; +} +#page8 .nextBtnTop { + position: fixed; + right: 0px; + top: 1%; + height: 41px; + width: 65px; + background: transparent; + border: none; + padding: 0px 00px 0px 45px; +} +#page8 #arrowTopRight { + position: relative; +} +#page8 .createdByDiv { + width: 25%; + text-align: center; + border: 1px solid; + padding: 15px; + border-bottom: none; + border-top: none; +} +#page8 .topline { + border-width: 2px; +} +#page8 .envProfileRow { + margin-top: 170px; + margin-bottom: 170px; + text-align: -webkit-center; +} +#page8 .envProfileRow .envInner { + width: 50%; +} +#page8 .envProfileRow .envInner .envHeading { + width: 50%; + font: italic 28px "Bradford LL"; + color: #231f20; + line-height: 30px; +} +#page8 .envProfileRow .envInner .envDesc { + width: 50%; +} +#page8 .envProfileRow .envInner .envDesc .descRow { + display: flex; + flex-direction: row; + margin: 15px auto; +} +#page8 .envProfileRow .envInner .envDesc .envTitle { + display: inline-block; + flex: 1; + text-align: left; + align-self: center; +} +#page8 .envProfileRow .envInner .envDesc .envTitle h6 { + font: 16px "Bradford LL"; + margin: auto; +} +#page8 .envProfileRow .envInner .envDesc .envValue { + display: inline-block; + flex: 1; + text-align: right; + align-self: center; +} +#page8 .envProfileRow .envInner .envDesc .envValue h3 { + font: italic 38px "Bradford LL"; + margin: auto; +} + +/*page8 ends here*/ + +input:-webkit-autofill, +input:-webkit-autofill:hover, +input:-webkit-autofill:focus, +input:-webkit-autofill:active { + box-shadow: 0 0 0 40px #f3f4ee inset !important; + -webkit-box-shadow: 0 0 0 40px #f3f4ee inset !important; +} + +#typeMcq button.highlight, +#typeMcqi button.highlight, +#typeSelection button.highlight { + border: 2px solid white; + outline: 3px solid #000; + transition: border 200ms ease-in-out, outline 200ms ease-in-out; +} + +#weatherApi { + display: none; + max-width: 500px; + padding: 0 16px; + margin: auto; +} +#weatherApi .header { + font: italic 42px "Bradford LL"; + margin-bottom: 50px; +} +#weatherApi .info .item { + display: flex; + justify-content: space-between; + margin-bottom: 24px; +} +#weatherApi .info .item .info-header { + font: 14px "Necto Mono"; + display: flex; + align-items: center; +} +#weatherApi .info .item .info-value { + font: italic 44px "Bradford LL"; + display: flex; + align-items: center; + text-transform: capitalize; +} + +.lds-ring { + width: 80px; + height: 80px; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 999999; + display: none; + justify-content: center; + align-items: center; + background: #00000090; +} +.lds-ring.active { + display: inline-flex; +} +.lds-ring div { + box-sizing: border-box; + display: block; + position: absolute; + width: 64px; + height: 64px; + margin: 8px; + border: 8px solid #fff; + border-radius: 50%; + animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; + border-color: #fff transparent transparent transparent; +} +.lds-ring div:nth-child(1) { + animation-delay: -0.45s; +} +.lds-ring div:nth-child(2) { + animation-delay: -0.3s; +} +.lds-ring div:nth-child(3) { + animation-delay: -0.15s; +} +@keyframes lds-ring { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + +#typeGeo .answerInner { + display: flex; + align-items: center; + justify-content: space-between; + width: 95%; + position: relative; + max-width: 524px; + margin: 0 auto; + border-bottom: 1px solid #101010; +} +#typeGeo .answerInner input { + width: 100%; + height: 100%; + padding: 16px 0; + background: transparent; + border: none; + color: #231f20; + font: 24px "Necto Mono"; + line-height: 30px; + text-align: center; +} +#typeGeo .answerInner input:focus { + outline: none; +} +#typeGeo .answerInner .arrowAnswerBtn { + display: flex; + height: 100%; + width: 20%; + position: absolute; + top: 0; + right: 0; + align-items: center; + justify-content: flex-end; + padding: 20px 0 20px 20px; + cursor: pointer; +} +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} +#typeGeo #result { + display: none; + position: absolute; + top: 100%; + width: 100%; + color: #000000; + border-left: 1px solid #ccc; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; +} +#typeGeo #result ul { + padding: 4px 0; + list-style-type: none; + margin: 0; +} +#typeGeo #result ul li { + padding: 8px; + text-align: left; + font: 16px "Necto Mono"; +} +#typeGeo #result ul li:hover, +#typeGeo #result ul li:active, +#typeGeo #result ul li.active { + background: #eee; + color: #101010; + cursor: pointer; +} + +img.image-missing { + display: none; + border-left: none; +} diff --git a/public/frontend_images/FinalScreenAnimation/final.gif b/public/frontend_images/FinalScreenAnimation/final.gif new file mode 100644 index 0000000..68e8939 Binary files /dev/null and b/public/frontend_images/FinalScreenAnimation/final.gif differ diff --git a/public/frontend_images/Icons/PNG/Blotchiness/Lot's of Blotchiness.png b/public/frontend_images/Icons/PNG/Blotchiness/Lot's of Blotchiness.png new file mode 100644 index 0000000..1404253 Binary files /dev/null and b/public/frontend_images/Icons/PNG/Blotchiness/Lot's of Blotchiness.png differ diff --git a/public/frontend_images/Icons/PNG/Blotchiness/No Blotchiness.png b/public/frontend_images/Icons/PNG/Blotchiness/No Blotchiness.png new file mode 100644 index 0000000..d24431a Binary files /dev/null and b/public/frontend_images/Icons/PNG/Blotchiness/No Blotchiness.png differ diff --git a/public/frontend_images/Icons/PNG/Dry_Oily Skin/Dry Skin.png b/public/frontend_images/Icons/PNG/Dry_Oily Skin/Dry Skin.png new file mode 100644 index 0000000..e85c925 Binary files /dev/null and b/public/frontend_images/Icons/PNG/Dry_Oily Skin/Dry Skin.png differ diff --git a/public/frontend_images/Icons/PNG/Dry_Oily Skin/Normal and Combination.png b/public/frontend_images/Icons/PNG/Dry_Oily Skin/Normal and Combination.png new file mode 100644 index 0000000..9c3d48d Binary files /dev/null and b/public/frontend_images/Icons/PNG/Dry_Oily Skin/Normal and Combination.png differ diff --git a/public/frontend_images/Icons/PNG/Dry_Oily Skin/Oily.png b/public/frontend_images/Icons/PNG/Dry_Oily Skin/Oily.png new file mode 100644 index 0000000..05fe21d Binary files /dev/null and b/public/frontend_images/Icons/PNG/Dry_Oily Skin/Oily.png differ diff --git a/public/frontend_images/Icons/PNG/Face Lines/A Few Lines Observable at all times.png b/public/frontend_images/Icons/PNG/Face Lines/A Few Lines Observable at all times.png new file mode 100644 index 0000000..b0c5f13 Binary files /dev/null and b/public/frontend_images/Icons/PNG/Face Lines/A Few Lines Observable at all times.png differ diff --git a/public/frontend_images/Icons/PNG/Face Lines/A Few Lines.png b/public/frontend_images/Icons/PNG/Face Lines/A Few Lines.png new file mode 100644 index 0000000..e40ab46 Binary files /dev/null and b/public/frontend_images/Icons/PNG/Face Lines/A Few Lines.png differ diff --git a/public/frontend_images/Icons/PNG/Face Lines/A Few Wrinkles.png b/public/frontend_images/Icons/PNG/Face Lines/A Few Wrinkles.png new file mode 100644 index 0000000..2fa75a9 Binary files /dev/null and b/public/frontend_images/Icons/PNG/Face Lines/A Few Wrinkles.png differ diff --git a/public/frontend_images/Icons/PNG/Face Lines/Lines Plus Hints of Wrinkles.png b/public/frontend_images/Icons/PNG/Face Lines/Lines Plus Hints of Wrinkles.png new file mode 100644 index 0000000..9603f1e Binary files /dev/null and b/public/frontend_images/Icons/PNG/Face Lines/Lines Plus Hints of Wrinkles.png differ diff --git a/public/frontend_images/Icons/PNG/Face Lines/Lots of Wrinkles.png b/public/frontend_images/Icons/PNG/Face Lines/Lots of Wrinkles.png new file mode 100644 index 0000000..8e80b89 Binary files /dev/null and b/public/frontend_images/Icons/PNG/Face Lines/Lots of Wrinkles.png differ diff --git a/public/frontend_images/Icons/PNG/Face Lines/No Wrinkles.png b/public/frontend_images/Icons/PNG/Face Lines/No Wrinkles.png new file mode 100644 index 0000000..0e58789 Binary files /dev/null and b/public/frontend_images/Icons/PNG/Face Lines/No Wrinkles.png differ diff --git a/public/frontend_images/Icons/PNG/Face Lines/Some Lines.png b/public/frontend_images/Icons/PNG/Face Lines/Some Lines.png new file mode 100644 index 0000000..339a531 Binary files /dev/null and b/public/frontend_images/Icons/PNG/Face Lines/Some Lines.png differ diff --git a/public/frontend_images/Icons/PNG/Skin Sensitivity/Extremely Sensitive.png b/public/frontend_images/Icons/PNG/Skin Sensitivity/Extremely Sensitive.png new file mode 100644 index 0000000..871549b Binary files /dev/null and b/public/frontend_images/Icons/PNG/Skin Sensitivity/Extremely Sensitive.png differ diff --git a/public/frontend_images/Icons/PNG/Skin Sensitivity/Moderately Sensitive.png b/public/frontend_images/Icons/PNG/Skin Sensitivity/Moderately Sensitive.png new file mode 100644 index 0000000..4e06b3a Binary files /dev/null and b/public/frontend_images/Icons/PNG/Skin Sensitivity/Moderately Sensitive.png differ diff --git a/public/frontend_images/Icons/PNG/Skin Sensitivity/Non Sensitive Skin.png b/public/frontend_images/Icons/PNG/Skin Sensitivity/Non Sensitive Skin.png new file mode 100644 index 0000000..f1a366d Binary files /dev/null and b/public/frontend_images/Icons/PNG/Skin Sensitivity/Non Sensitive Skin.png differ diff --git a/public/frontend_images/Icons/PNG/Water/1 Glass of Water.png b/public/frontend_images/Icons/PNG/Water/1 Glass of Water.png new file mode 100644 index 0000000..2a28603 Binary files /dev/null and b/public/frontend_images/Icons/PNG/Water/1 Glass of Water.png differ diff --git a/public/frontend_images/Icons/PNG/Water/4 Glasses of Water.png b/public/frontend_images/Icons/PNG/Water/4 Glasses of Water.png new file mode 100644 index 0000000..d741589 Binary files /dev/null and b/public/frontend_images/Icons/PNG/Water/4 Glasses of Water.png differ diff --git a/public/frontend_images/Icons/PNG/Water/8 Glasses of Water.png b/public/frontend_images/Icons/PNG/Water/8 Glasses of Water.png new file mode 100644 index 0000000..c37f246 Binary files /dev/null and b/public/frontend_images/Icons/PNG/Water/8 Glasses of Water.png differ diff --git a/public/frontend_images/Icons/SVG/Blotchiness/Lot's of Blotchiness.svg b/public/frontend_images/Icons/SVG/Blotchiness/Lot's of Blotchiness.svg new file mode 100644 index 0000000..77fc010 --- /dev/null +++ b/public/frontend_images/Icons/SVG/Blotchiness/Lot's of Blotchiness.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Blotchiness/No Blotchiness.svg b/public/frontend_images/Icons/SVG/Blotchiness/No Blotchiness.svg new file mode 100644 index 0000000..35c93cc --- /dev/null +++ b/public/frontend_images/Icons/SVG/Blotchiness/No Blotchiness.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Dry_Oily Skin/Dry Skin.svg b/public/frontend_images/Icons/SVG/Dry_Oily Skin/Dry Skin.svg new file mode 100644 index 0000000..95f3af0 --- /dev/null +++ b/public/frontend_images/Icons/SVG/Dry_Oily Skin/Dry Skin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Dry_Oily Skin/Normal and Combination.svg b/public/frontend_images/Icons/SVG/Dry_Oily Skin/Normal and Combination.svg new file mode 100644 index 0000000..29318b3 --- /dev/null +++ b/public/frontend_images/Icons/SVG/Dry_Oily Skin/Normal and Combination.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Dry_Oily Skin/Oily.svg b/public/frontend_images/Icons/SVG/Dry_Oily Skin/Oily.svg new file mode 100644 index 0000000..c11c47f --- /dev/null +++ b/public/frontend_images/Icons/SVG/Dry_Oily Skin/Oily.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Face Lines/A Few Lines Observable at all times.svg b/public/frontend_images/Icons/SVG/Face Lines/A Few Lines Observable at all times.svg new file mode 100644 index 0000000..2cc2e23 --- /dev/null +++ b/public/frontend_images/Icons/SVG/Face Lines/A Few Lines Observable at all times.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Face Lines/A Few Lines.svg b/public/frontend_images/Icons/SVG/Face Lines/A Few Lines.svg new file mode 100644 index 0000000..5f0850e --- /dev/null +++ b/public/frontend_images/Icons/SVG/Face Lines/A Few Lines.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Face Lines/A Few Wrinkles.svg b/public/frontend_images/Icons/SVG/Face Lines/A Few Wrinkles.svg new file mode 100644 index 0000000..8144e61 --- /dev/null +++ b/public/frontend_images/Icons/SVG/Face Lines/A Few Wrinkles.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Face Lines/Lines Plus Hints of Wrinkles.svg b/public/frontend_images/Icons/SVG/Face Lines/Lines Plus Hints of Wrinkles.svg new file mode 100644 index 0000000..24634ac --- /dev/null +++ b/public/frontend_images/Icons/SVG/Face Lines/Lines Plus Hints of Wrinkles.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Face Lines/Lots of Wrinkles.svg b/public/frontend_images/Icons/SVG/Face Lines/Lots of Wrinkles.svg new file mode 100644 index 0000000..06f869b --- /dev/null +++ b/public/frontend_images/Icons/SVG/Face Lines/Lots of Wrinkles.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Face Lines/No Wrinkles.svg b/public/frontend_images/Icons/SVG/Face Lines/No Wrinkles.svg new file mode 100644 index 0000000..bd07e4b --- /dev/null +++ b/public/frontend_images/Icons/SVG/Face Lines/No Wrinkles.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Face Lines/Some Lines.svg b/public/frontend_images/Icons/SVG/Face Lines/Some Lines.svg new file mode 100644 index 0000000..07af3d6 --- /dev/null +++ b/public/frontend_images/Icons/SVG/Face Lines/Some Lines.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Skin Sensitivity/Extremely Sensitive.svg b/public/frontend_images/Icons/SVG/Skin Sensitivity/Extremely Sensitive.svg new file mode 100644 index 0000000..4b4b47c --- /dev/null +++ b/public/frontend_images/Icons/SVG/Skin Sensitivity/Extremely Sensitive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Skin Sensitivity/Moderately Sensitive.svg b/public/frontend_images/Icons/SVG/Skin Sensitivity/Moderately Sensitive.svg new file mode 100644 index 0000000..31d3ecf --- /dev/null +++ b/public/frontend_images/Icons/SVG/Skin Sensitivity/Moderately Sensitive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Skin Sensitivity/Non Sensitive Skin.svg b/public/frontend_images/Icons/SVG/Skin Sensitivity/Non Sensitive Skin.svg new file mode 100644 index 0000000..63d25ae --- /dev/null +++ b/public/frontend_images/Icons/SVG/Skin Sensitivity/Non Sensitive Skin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Water/1 Glass of Water.svg b/public/frontend_images/Icons/SVG/Water/1 Glass of Water.svg new file mode 100644 index 0000000..71507df --- /dev/null +++ b/public/frontend_images/Icons/SVG/Water/1 Glass of Water.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Water/4 Glasses of Water.svg b/public/frontend_images/Icons/SVG/Water/4 Glasses of Water.svg new file mode 100644 index 0000000..dfb0fb8 --- /dev/null +++ b/public/frontend_images/Icons/SVG/Water/4 Glasses of Water.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/Icons/SVG/Water/8 Glasses of Water.svg b/public/frontend_images/Icons/SVG/Water/8 Glasses of Water.svg new file mode 100644 index 0000000..4a45521 --- /dev/null +++ b/public/frontend_images/Icons/SVG/Water/8 Glasses of Water.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/frontend_images/JarWithName/Jar.eps b/public/frontend_images/JarWithName/Jar.eps new file mode 100644 index 0000000..75e917a Binary files /dev/null and b/public/frontend_images/JarWithName/Jar.eps differ diff --git a/public/frontend_images/JarWithName/Jar.png b/public/frontend_images/JarWithName/Jar.png new file mode 100644 index 0000000..2844f17 Binary files /dev/null and b/public/frontend_images/JarWithName/Jar.png differ diff --git a/public/frontend_images/MainImage/background.jpg b/public/frontend_images/MainImage/background.jpg new file mode 100644 index 0000000..f2a0b55 Binary files /dev/null and b/public/frontend_images/MainImage/background.jpg differ diff --git a/public/frontend_images/MainImage/main_quiz_image.png b/public/frontend_images/MainImage/main_quiz_image.png new file mode 100644 index 0000000..72b2a95 Binary files /dev/null and b/public/frontend_images/MainImage/main_quiz_image.png differ diff --git a/public/frontend_images/SkintoneGraphics/1.png b/public/frontend_images/SkintoneGraphics/1.png new file mode 100644 index 0000000..29f7aea Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/1.png differ diff --git a/public/frontend_images/SkintoneGraphics/10.png b/public/frontend_images/SkintoneGraphics/10.png new file mode 100644 index 0000000..50f33c8 Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/10.png differ diff --git a/public/frontend_images/SkintoneGraphics/11.png b/public/frontend_images/SkintoneGraphics/11.png new file mode 100644 index 0000000..03d435f Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/11.png differ diff --git a/public/frontend_images/SkintoneGraphics/12.png b/public/frontend_images/SkintoneGraphics/12.png new file mode 100644 index 0000000..634dbdf Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/12.png differ diff --git a/public/frontend_images/SkintoneGraphics/13.png b/public/frontend_images/SkintoneGraphics/13.png new file mode 100644 index 0000000..88551cb Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/13.png differ diff --git a/public/frontend_images/SkintoneGraphics/14.png b/public/frontend_images/SkintoneGraphics/14.png new file mode 100644 index 0000000..79e56e1 Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/14.png differ diff --git a/public/frontend_images/SkintoneGraphics/15.png b/public/frontend_images/SkintoneGraphics/15.png new file mode 100644 index 0000000..aa517ce Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/15.png differ diff --git a/public/frontend_images/SkintoneGraphics/2.png b/public/frontend_images/SkintoneGraphics/2.png new file mode 100644 index 0000000..2a2cbf8 Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/2.png differ diff --git a/public/frontend_images/SkintoneGraphics/3.png b/public/frontend_images/SkintoneGraphics/3.png new file mode 100644 index 0000000..ac3872d Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/3.png differ diff --git a/public/frontend_images/SkintoneGraphics/4.png b/public/frontend_images/SkintoneGraphics/4.png new file mode 100644 index 0000000..ece1bc6 Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/4.png differ diff --git a/public/frontend_images/SkintoneGraphics/5.png b/public/frontend_images/SkintoneGraphics/5.png new file mode 100644 index 0000000..fe699e2 Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/5.png differ diff --git a/public/frontend_images/SkintoneGraphics/6.png b/public/frontend_images/SkintoneGraphics/6.png new file mode 100644 index 0000000..19a9ae8 Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/6.png differ diff --git a/public/frontend_images/SkintoneGraphics/7.png b/public/frontend_images/SkintoneGraphics/7.png new file mode 100644 index 0000000..5fb21f4 Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/7.png differ diff --git a/public/frontend_images/SkintoneGraphics/8.png b/public/frontend_images/SkintoneGraphics/8.png new file mode 100644 index 0000000..066e685 Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/8.png differ diff --git a/public/frontend_images/SkintoneGraphics/9.png b/public/frontend_images/SkintoneGraphics/9.png new file mode 100644 index 0000000..71e942c Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/9.png differ diff --git a/public/frontend_images/SkintoneGraphics/Created By Skin Texture.psd b/public/frontend_images/SkintoneGraphics/Created By Skin Texture.psd new file mode 100644 index 0000000..d45037c Binary files /dev/null and b/public/frontend_images/SkintoneGraphics/Created By Skin Texture.psd differ diff --git a/public/frontend_js/calculation_sample.js b/public/frontend_js/calculation_sample.js new file mode 100644 index 0000000..701a970 --- /dev/null +++ b/public/frontend_js/calculation_sample.js @@ -0,0 +1,67 @@ +const accumlatedUniqueWeightsExample = { + Pollution: 50, + Sun: 48.39329657056177, + Temperature: null, + Hydration: 51.46427809019712, + Sensitivity: 100, + Breakouts: 49.433316280351, + Color: 66.6667, + Hyperpigmentation: 6.66667, + Redness: 99.9311321868482, + Lines: 23.869584038408604, + Age: 23.8695840384086, + Pores: 51.7000511589469, + Blackheads: 52.3296997363347, + Stress: 47.0406516862776, + Oxygenation: 100, +}; + +const sortedFinalActiveslistExample = [ + "Chamomile", + "Bakuchiol", + "Gotu Kola", + "Dragon's Blood", + "Chia", + "Moringa", + "Sandalwood", + "Cucumber", + "Colloidal Oat", + "White Willow Bark", + "Ginseng", + "Olive Squalane", + "Acai", + "Coconut", + "Sake Extract", + "Tonka Bean", + "Licorice Root", + "Rose Hip", + "Okra Extract", + "Moth Bean", + "Yeast Extract (Collagen)", + "Cogon Grass", +]; + +const sortedFinalActiveslistWithScoresExample = [ + ["Chamomile", 35.006895600311815], + ["Bakuchiol", 34.864335454841665], + ["Gotu Kola", 34.59752576741149], + ["Dragon's Blood", 34.26806861254431], + ["Chia", 32.58056256473667], + ["Moringa", 32.45812046796087], + ["Sandalwood", 32.04473463715295], + ["Cucumber", 31.836800387130516], + ["Colloidal Oat", 30.050176997154054], + ["White Willow Bark", 29.492484199162032], + ["Ginseng", 29.43202696221447], + ["Olive Squalane", 29.239855303321928], + ["Acai", 29.075506820190608], + ["Coconut", 28.861007423453366], + ["Sake Extract", 27.361047426489453], + ["Tonka Bean", 27.159613954853334], + ["Licorice Root", 26.5144316605475], + ["Rose Hip", 26.448523943345933], + ["Okra Extract", 26.363374564468685], + ["Moth Bean", 26.125180561661274], + ["Yeast Extract (Collagen)", 24.58725443087142], + ["Cogon Grass", 18.28511298894312], +]; diff --git a/public/frontend_js/jquery-2.1.3.js b/public/frontend_js/jquery-2.1.3.js new file mode 100644 index 0000000..ac29c4d --- /dev/null +++ b/public/frontend_js/jquery-2.1.3.js @@ -0,0 +1,9205 @@ +/*! + * jQuery JavaScript Library v2.1.3 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2014-12-18T15:11Z + */ + +(function( global, factory ) { + + if ( typeof module === "object" && typeof module.exports === "object" ) { + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Support: Firefox 18+ +// Can't be in strict mode, several libs including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// + +var arr = []; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var support = {}; + + + +var + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + + version = "2.1.3", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android<4.1 + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num != null ? + + // Return just the one element from the set + ( num < 0 ? this[ num + this.length ] : this[ num ] ) : + + // Return all the elements in a clean array + slice.call( this ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray, + + isWindow: function( obj ) { + return obj != null && obj === obj.window; + }, + + isNumeric: function( obj ) { + // parseFloat NaNs numeric-cast false positives (null|true|false|"") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + // adding 1 corrects loss of precision from parseFloat (#15100) + return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0; + }, + + isPlainObject: function( obj ) { + // Not plain objects: + // - Any object or value whose internal [[Class]] property is not "[object Object]" + // - DOM nodes + // - window + if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.constructor && + !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { + return false; + } + + // If the function hasn't returned already, we're confident that + // |obj| is a plain object, created by {} or constructed with new Object + return true; + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + // Support: Android<4.0, iOS<6 (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call(obj) ] || "object" : + typeof obj; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + var script, + indirect = eval; + + code = jQuery.trim( code ); + + if ( code ) { + // If the code includes a valid, prologue position + // strict mode pragma, execute code by injecting a + // script tag into the document. + if ( code.indexOf("use strict") === 1 ) { + script = document.createElement("script"); + script.text = code; + document.head.appendChild( script ).parentNode.removeChild( script ); + } else { + // Otherwise, avoid the DOM node creation, insertion + // and removal by using an indirect global eval + indirect( code ); + } + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Support: IE9-11+ + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Support: Android<4.1 + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var tmp, args, proxy; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: Date.now, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.2.0-pre + * http://sizzlejs.com/ + * + * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2014-12-16 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // General-purpose constants + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // http://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + characterEncoding + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + nodeType = context.nodeType; + + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + if ( !seed && documentIsHTML ) { + + // Try to shortcut find operations when possible (e.g., not under DocumentFragment) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document (jQuery #6963) + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType !== 1 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, parent, + doc = node ? node.ownerDocument || node : preferredDoc; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + parent = doc.defaultView; + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent !== parent.top ) { + // IE11 does not have attachEvent, so all must suffer + if ( parent.addEventListener ) { + parent.addEventListener( "unload", unloadHandler, false ); + } else if ( parent.attachEvent ) { + parent.attachEvent( "onunload", unloadHandler ); + } + } + + /* Support tests + ---------------------------------------------------------------------- */ + documentIsHTML = !isXML( doc ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( doc.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [ m ] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + docElem.appendChild( div ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( div.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+ + if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibing-combinator selector` fails + if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( div ) { + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( div.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (oldCache = outerCache[ dir ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + outerCache[ dir ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context !== document && context; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is no seed and only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + + +var rneedsContext = jQuery.expr.match.needsContext; + +var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); + + + +var risSimple = /^.[^:#\[\.,]*$/; + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( risSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) >= 0 ) !== not; + }); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); +}; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + len = this.length, + ret = [], + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +}); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + init = jQuery.fn.init = function( selector, context ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Support: Blackberry 4.6 + // gEBID returns nodes no longer in the document (#6963) + if ( elem && elem.parentNode ) { + // Inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return typeof rootjQuery.ready !== "undefined" ? + rootjQuery.ready( selector ) : + // Execute immediately if ready is not present + selector( jQuery ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.extend({ + dir: function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; + }, + + sibling: function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; + } +}); + +jQuery.fn.extend({ + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter(function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + matched.push( cur ); + break; + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.unique( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return elem.contentDocument || jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.unique( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +}); +var rnotwhite = (/\S+/g); + + + +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // Flag to know if list is currently firing + firing, + // First callback to fire (used internally by add and fireWith) + firingStart, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // Add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // If we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); + + +// The deferred used on DOM ready +var readyList; + +jQuery.fn.ready = function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; +}; + +jQuery.extend({ + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + jQuery( document ).off( "ready" ); + } + } +}); + +/** + * The ready event handler and self cleanup method + */ +function completed() { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + jQuery.ready(); +} + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // We once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + } else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + } + } + return readyList.promise( obj ); +}; + +// Kick off the DOM ready check even if the user does not +jQuery.ready.promise(); + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + len ? fn( elems[0], key ) : emptyGet; +}; + + +/** + * Determines whether an object can have data + */ +jQuery.acceptData = function( owner ) { + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + /* jshint -W018 */ + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + +function Data() { + // Support: Android<4, + // Old WebKit does not have Object.preventExtensions/freeze method, + // return new empty object instead with no [[set]] accessor + Object.defineProperty( this.cache = {}, 0, { + get: function() { + return {}; + } + }); + + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; +Data.accepts = jQuery.acceptData; + +Data.prototype = { + key: function( owner ) { + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return the key for a frozen object. + if ( !Data.accepts( owner ) ) { + return 0; + } + + var descriptor = {}, + // Check if the owner object already has a cache key + unlock = owner[ this.expando ]; + + // If not, create one + if ( !unlock ) { + unlock = Data.uid++; + + // Secure it in a non-enumerable, non-writable property + try { + descriptor[ this.expando ] = { value: unlock }; + Object.defineProperties( owner, descriptor ); + + // Support: Android<4 + // Fallback to a less secure definition + } catch ( e ) { + descriptor[ this.expando ] = unlock; + jQuery.extend( owner, descriptor ); + } + } + + // Ensure the cache object + if ( !this.cache[ unlock ] ) { + this.cache[ unlock ] = {}; + } + + return unlock; + }, + set: function( owner, data, value ) { + var prop, + // There may be an unlock assigned to this node, + // if there is no entry for this "owner", create one inline + // and set the unlock as though an owner entry had always existed + unlock = this.key( owner ), + cache = this.cache[ unlock ]; + + // Handle: [ owner, key, value ] args + if ( typeof data === "string" ) { + cache[ data ] = value; + + // Handle: [ owner, { properties } ] args + } else { + // Fresh assignments by object are shallow copied + if ( jQuery.isEmptyObject( cache ) ) { + jQuery.extend( this.cache[ unlock ], data ); + // Otherwise, copy the properties one-by-one to the cache object + } else { + for ( prop in data ) { + cache[ prop ] = data[ prop ]; + } + } + } + return cache; + }, + get: function( owner, key ) { + // Either a valid cache is found, or will be created. + // New caches will be created and the unlock returned, + // allowing direct access to the newly created + // empty data object. A valid owner object must be provided. + var cache = this.cache[ this.key( owner ) ]; + + return key === undefined ? + cache : cache[ key ]; + }, + access: function( owner, key, value ) { + var stored; + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ((key && typeof key === "string") && value === undefined) ) { + + stored = this.get( owner, key ); + + return stored !== undefined ? + stored : this.get( owner, jQuery.camelCase(key) ); + } + + // [*]When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, name, camel, + unlock = this.key( owner ), + cache = this.cache[ unlock ]; + + if ( key === undefined ) { + this.cache[ unlock ] = {}; + + } else { + // Support array or space separated string of keys + if ( jQuery.isArray( key ) ) { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = key.concat( key.map( jQuery.camelCase ) ); + } else { + camel = jQuery.camelCase( key ); + // Try the string as a key before any manipulation + if ( key in cache ) { + name = [ key, camel ]; + } else { + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + name = camel; + name = name in cache ? + [ name ] : ( name.match( rnotwhite ) || [] ); + } + } + + i = name.length; + while ( i-- ) { + delete cache[ name[ i ] ]; + } + } + }, + hasData: function( owner ) { + return !jQuery.isEmptyObject( + this.cache[ owner[ this.expando ] ] || {} + ); + }, + discard: function( owner ) { + if ( owner[ this.expando ] ) { + delete this.cache[ owner[ this.expando ] ]; + } + } +}; +var data_priv = new Data(); + +var data_user = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /([A-Z])/g; + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + data_user.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend({ + hasData: function( elem ) { + return data_user.hasData( elem ) || data_priv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return data_user.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + data_user.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to data_priv methods, these can be deprecated. + _data: function( elem, name, data ) { + return data_priv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + data_priv.remove( elem, name ); + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = data_user.get( elem ); + + if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE11+ + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + data_priv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + data_user.set( this, key ); + }); + } + + return access( this, function( value ) { + var data, + camelKey = jQuery.camelCase( key ); + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + // Attempt to get data from the cache + // with the key as-is + data = data_user.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to get data from the cache + // with the key camelized + data = data_user.get( elem, camelKey ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, camelKey, undefined ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each(function() { + // First, attempt to store a copy or reference of any + // data that might've been store with a camelCased key. + var data = data_user.get( this, camelKey ); + + // For HTML5 data-* attribute interop, we have to + // store property names with dashes in a camelCase form. + // This might not apply to all properties...* + data_user.set( this, camelKey, value ); + + // *... In the case of properties that might _actually_ + // have dashes, we need to also store a copy of that + // unchanged property. + if ( key.indexOf("-") !== -1 && data !== undefined ) { + data_user.set( this, key, value ); + } + }); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each(function() { + data_user.remove( this, key ); + }); + } +}); + + +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = data_priv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray( data ) ) { + queue = data_priv.access( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return data_priv.get( elem, key ) || data_priv.access( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + data_priv.remove( elem, [ type + "queue", key ] ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = data_priv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHidden = function( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); + }; + +var rcheckableType = (/^(?:checkbox|radio)$/i); + + + +(function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Safari<=5.1 + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Safari<=5.1, Android<4.2 + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<=11+ + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; +})(); +var strundefined = typeof undefined; + + + +support.focusinBubbles = "onfocusin" in window; + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = data_priv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = data_priv.hasData( elem ) && data_priv.get( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + data_priv.remove( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && jQuery.acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, j, ret, matched, handleObj, + handlerQueue = [], + args = slice.call( arguments ), + handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or 2) have namespace(s) + // a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, matches, sel, handleObj, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.disabled !== true || event.type !== "click" ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var eventDoc, doc, body, + button = original.button; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: Cordova 2.5 (WebKit) (#13255) + // All events should have a target; Cordova deviceready doesn't + if ( !event.target ) { + event.target = document; + } + + // Support: Safari 6.0+, Chrome<28 + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + this.focus(); + return false; + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } +}; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + // Support: Android<4.0 + src.returnValue === false ? + returnTrue : + returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && e.preventDefault ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && e.stopPropagation ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && e.stopImmediatePropagation ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +// Support: Chrome 15+ +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// Support: Firefox, Chrome, Safari +// Create "bubbling" focus and blur events +if ( !support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = data_priv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + data_priv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = data_priv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + data_priv.remove( doc, fix ); + + } else { + data_priv.access( doc, fix, attaches ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); + + +var + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rhtml = /<|&#?\w+;/, + rnoInnerhtml = /<(?:script|style|link)/i, + // checked="checked" or checked + rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, + rscriptType = /^$|\/(?:java|ecma)script/i, + rscriptTypeMasked = /^true\/(.*)/, + rcleanScript = /^\s*\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + + // Support: IE9 + option: [ 1, "" ], + + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] + }; + +// Support: IE9 +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: 1.x compatibility +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + + if ( match ) { + elem.type = match[ 1 ]; + } else { + elem.removeAttribute("type"); + } + + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + data_priv.set( + elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" ) + ); + } +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( data_priv.hasData( src ) ) { + pdataOld = data_priv.access( src ); + pdataCur = data_priv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( data_user.hasData( src ) ) { + udataOld = data_user.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + data_user.set( dest, udataCur ); + } +} + +function getAll( context, tag ) { + var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) : + context.querySelectorAll ? context.querySelectorAll( tag || "*" ) : + []; + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], ret ) : + ret; +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var elem, tmp, tag, wrap, contains, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + // Support: QtWebKit, PhantomJS + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: QtWebKit, PhantomJS + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; + }, + + cleanData: function( elems ) { + var data, elem, type, key, + special = jQuery.event.special, + i = 0; + + for ( ; (elem = elems[ i ]) !== undefined; i++ ) { + if ( jQuery.acceptData( elem ) ) { + key = elem[ data_priv.expando ]; + + if ( key && (data = data_priv.cache[ key ]) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + if ( data_priv.cache[ key ] ) { + // Discard any remaining `private` data + delete data_priv.cache[ key ]; + } + } + } + // Discard any remaining `user` data + delete data_user.cache[ elem[ data_user.expando ] ]; + } + } +}); + +jQuery.fn.extend({ + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each(function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + }); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + remove: function( selector, keepData /* Internal Use Only */ ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map(function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var arg = arguments[ 0 ]; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + arg = this.parentNode; + + jQuery.cleanData( getAll( this ) ); + + if ( arg ) { + arg.replaceChild( elem, this ); + } + }); + + // Force removal if there was no new content (e.g., from empty arguments) + return arg && (arg.length || arg.nodeType) ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[ 0 ], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + self.domManip( args, callback ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + // Support: QtWebKit + // jQuery.merge because push.apply(_, arraylike) throws + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); + } + } + } + } + } + } + + return this; + } +}); + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: QtWebKit + // .get() because push.apply(_, arraylike) throws + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + + +var iframe, + elemdisplay = {}; + +/** + * Retrieve the actual display of a element + * @param {String} name nodeName of the element + * @param {Object} doc Document object + */ +// Called only from within defaultDisplay +function actualDisplay( name, doc ) { + var style, + elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), + + // getDefaultComputedStyle might be reliably used only on attached element + display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? + + // Use of this method is a temporary fix (more like optimization) until something better comes along, + // since it was removed from specification and supported only in FF + style.display : jQuery.css( elem[ 0 ], "display" ); + + // We don't have any data stored on the element, + // so use "detach" method as fast way to get rid of the element + elem.detach(); + + return display; +} + +/** + * Try to determine the default display value of an element + * @param {String} nodeName + */ +function defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + + // Use the already-created iframe if possible + iframe = (iframe || jQuery( " + + +
+ +
+ `; + } + /** + * Render the content inside the widget container + */ + render() { + return ` + ${this.error ? `
${this.error}
` : ""} + ${ + this.activeEffect + ? `
+ ${this.activeEffect && this.file ? this.renderActiveEffect(this.file) : ""} +
` + : `
+ ${this.activeEffect && this.file ? "" : this.renderActiveService()} + ${this.activeService === "default" ? this.getNavbar() : ""} +
` + }`; + } + /** + * Render the currently active service + */ + renderActiveService() { + const activeServices = this.services.filter((service) => service.name === this.activeService); + if (activeServices.length) { + const activeService = activeServices[0]; + requestAnimationFrame(() => { + if (typeof activeService.handlers === "function") + activeService.handlers({ + next: this.next.bind(this), + upload: this.upload.bind(this), + uploadMultiple: this.uploadMultiple.bind(this), + handle: this.handle.bind(this), + showHelp: this.showHelp.bind(this), + uppload: this, + translate, + }); + }); + return `${typeof activeService.template === "function" ? activeService.template({ translate, uppload: this }) : ""}`; + } + } + /** + * Render the currently active effect + */ + renderActiveEffect(file) { + const activeEffects = this.effects.filter((effect) => effect.name === this.activeEffect); + if (activeEffects.length) { + const activeEffect = activeEffects[0]; + requestAnimationFrame(() => { + if (typeof activeEffect.handlers === "function") + activeEffect.handlers({ + next: this.next.bind(this), + upload: this.upload.bind(this), + uploadMultiple: this.uploadMultiple.bind(this), + handle: this.handle.bind(this), + showHelp: this.showHelp.bind(this), + uppload: this, + translate, + }); + }); + return ` +
${typeof activeEffect.template === "function" ? activeEffect.template({ file, translate }) : ""}
+ `; + } + } + /** + * Uploads multiple files to the server + * @param file + * @returns JSON response from server + */ + uploadMultiple(file) { + this.emitter.emit("before-upload"); + return new Promise((resolve) => { + this.navigate("uploading"); + if (this.uploader && typeof this.uploader === "function") { + this.uploader(file, this.updateProgress.bind(this)) + .then((response) => { + this.navigate("default"); + resolve(response); + this.emitter.emit("upload", response); + this.close(); + }) + .catch((error) => this.handle(error)); + } else { + this.handle(new Error("no-uploader")); + } + }); + } + hideHelp() { + const help = this.container.querySelector(".uppload-help"); + const helpLoading = this.container.querySelector(".uppload-help-loading"); + const sideNavbar = this.container.querySelector("aside"); + const section = this.container.querySelector("section"); + if (helpLoading) helpLoading.classList.remove("visible"); + if (help) help.classList.remove("visible"); + if (sideNavbar) sideNavbar.style.display = ""; + if (section) section.style.display = ""; + this.emitter.emit("hide-help"); + } + /** + * Show the help article for this plugin in a frame + * @param url - URL of help webpage + */ + showHelp(url) { + this.emitter.emit("help", url); + const aside = this.container.querySelector("aside"); + if (aside) aside.style.display = "none"; + const section = this.container.querySelector("section"); + if (section) section.style.display = "none"; + const helpLoading = this.container.querySelector(".uppload-help-loading"); + if (helpLoading) helpLoading.classList.add("visible"); + const help = this.container.querySelector(".uppload-help"); + if (help) { + const iframe = help.querySelector("iframe"); + if (iframe) { + iframe.setAttribute("src", `https://uppload.js.org/help${url}`); + const listener = () => { + help.classList.add("visible"); + if (helpLoading) helpLoading.classList.remove("visible"); + }; + safeListen(iframe, "load", listener); + safeListen(iframe, "error", () => { + this.hideHelp(); + }); + } + } + } + /** + * Updates the file and goes to the active effect + * @param file - The currently active file Blob + */ + next(file) { + this.emitter.emit("next", file); + this.file = file; + if (this.activeEffect); + else { + // Find the first effect and navigate to that + // Unless the file type is not an image + if (this.effects.length && file.type && file.type.indexOf("image/") === 0) { + this.activeEffect = this.effects[0].name; + this.update(); + } else { + return this.upload(safeUpploadFileToFile(file)); + } + } + // Set active state to current effect + const activeRadio = this.container.querySelector(`input[name='uppload-effect-radio'][value='${this.activeEffect}']`); + if (activeRadio) activeRadio.setAttribute("checked", "checked"); + } + compress(file) { + if (this.settings.compressionFromMimes && this.settings.compressionFromMimes.indexOf(file.type) === -1) return new Promise((resolve) => resolve(file)); + if (typeof this.settings.compressor === "function") return this.settings.compressor(file); + return compressImage(file, this.settings); + } + /** + * Upload a file to the server + * @param file - A Blob object containing the file to upload + * @returns The file URL + */ + upload(file) { + this.emitter.emit("before-upload", file); + return new Promise((resolve, reject) => { + this.navigate("uploading"); + let upploadFile = blobToUpploadFile(file); + try { + if (typeof file.name === "string") upploadFile = blobToUpploadFile(file, file.name, file.type, new Date(file.lastModified)); + } catch (error) {} + if (this.uploader && typeof this.uploader === "function") { + this.compress(file) + .then((file) => { + if (this.settings.compression) this.emitter.emit("compress", file); + return file; + }) + .then((blob) => { + upploadFile.blob = blob; + return safeUpploadFileToFile(upploadFile); + }) + .then((file) => this.uploader(file, this.updateProgress.bind(this))) + .then((url) => { + this.bind(url); + this.navigate("default"); + resolve(url); + this.emitter.emit("upload", url); + this.close(); + }) + .catch((error) => this.handle(error)); + } else { + reject("no-uploader"); + } + }); + } + /** + * Gracefully display an error message + * @param error - Error to display + */ + handle(error) { + this.error = translate(error.message) || error.message; + this.emitter.emit("error", this.error); + this.update(); + if (this.activeService === "uploading") this.navigate("default"); + setTimeout(() => { + this.error = undefined; + this.update(); + }, 4000); + } + /** + * Adds event handlers for the widget + */ + handlers() { + const openFunction = () => this.open(); + const closeFunction = () => this.close(); + /** + * Clicking on each sidebar link should open its service + */ + const defaultServiceLinks = this.container.querySelectorAll(".uppload-service--default .uppload-service-name button"); + defaultServiceLinks.forEach((link) => { + const linkFunction = (e) => { + const service = link.getAttribute("data-uppload-service"); + if (service) { + this.navigate(service); + const serviceDiv = this.container.querySelector(`[data-uppload-service="${service}"]`); + if (serviceDiv && serviceDiv.parentElement) { + let top = 0; + let left = 0; + const serviceDivRect = serviceDiv.getBoundingClientRect(); + const serviceNavRect = serviceDiv.parentElement.getBoundingClientRect(); + top = serviceDivRect.top - serviceNavRect.top; + left = serviceDivRect.left - serviceNavRect.left; + const aside = serviceDiv.parentElement.parentElement; + try { + // Edge doesn't support scrollTo and throws an error + if (aside) aside.scrollTo(left, top); + } catch (error) {} + } + } + const serviceRadio = this.container.querySelector(`input[type=radio][value='${service}']`); + if (serviceRadio) serviceRadio.setAttribute("checked", "checked"); + e.preventDefault(); + return false; + }; + safeListen(link, "click", linkFunction); + }); + /** + * Clicking on each sidebar link should open its service + */ + const inputRadios = this.container.querySelectorAll(".uppload-services input[type='radio']"); + inputRadios.forEach((radio) => { + const radioFunction = (e) => { + const inputRadio = this.container.querySelector("[name='uppload-radio']:checked"); + if (!inputRadio) return; + const service = inputRadio.value; + this.navigate(service); + }; + safeListen(radio, "change", radioFunction); + }); + /** + * Clicking on each sidebar link should open its service + */ + const effectInputRadios = this.container.querySelectorAll(".effects-nav input[type='radio']"); + effectInputRadios.forEach((radio) => { + const radioFunction = (e) => { + const inputRadio = this.container.querySelector("[name='uppload-effect-radio']:checked"); + if (!inputRadio) return; + const effect = inputRadio.value; + this.activeEffect = effect; + this.update(); + }; + safeListen(radio, "change", radioFunction); + }); + /** + * Clicking on the background should close the modal + */ + const background = this.container.querySelector(".uppload-modal-bg"); + const closeButton = this.container.querySelector(".uppload-close"); + if (background && !this.settings.disableModalClickClose) { + safeListen(background, "click", closeFunction); + } else if (closeButton) { + safeListen(closeButton, "click", closeFunction); + } + /** + * All elements in `call` should open the modal on click + */ + if (this.settings.call) { + const elements = getElements(this.settings.call); + elements.forEach((element) => { + safeListen(element, "click", openFunction); + }); + } + /** + * Clicking on the cancel button restarts the process + */ + const cancelButton = this.container.querySelector(".effects-continue--cancel"); + if (cancelButton) + safeListen(cancelButton, "click", () => { + this.file = { blob: new Blob() }; + this.activeService = "default"; + this.activeEffect = ""; + this.update(); + }); + /** + * Clicking on the cancel button restarts the process + */ + const uploadButton = this.container.querySelector(".effects-continue--upload"); + if (uploadButton) + safeListen(uploadButton, "click", () => { + if (!this.file) return; + this.activeService = ""; + this.activeEffect = ""; + this.upload(safeUpploadFileToFile(this.file)); + }); + } + /** + * Stops any actions being done by the currently active service + * For example, if your webcame is being accessed, kill that process + */ + stopCurrentService() { + const currentService = this.services.filter((item) => item.name === this.activeService); + if (currentService.length) { + const service = currentService[0]; + service.stop(); + } + } + /** + * Navigate to an Uppload service page + * @param service - Slug name of service (e.g., instagram) + */ + navigate(service) { + if (!this.services.filter((item) => item.name === service).length) throw new Error("invalid-service"); + this.stopCurrentService(); + this.activeService = service; + this.update(); + const focusable = this.container.querySelector(".uppload-active-container input, .uppload-active-container button"); + if (focusable) focusable.focus(); + } + /** + * Add an event listener + * @param type - Type of event listener (e.g., open) + * @param handler - Event handler function + */ + on(type, handler) { + return this.emitter.on(type, handler); + } + /** + * Remove an event listener + * @param type - Type of event listener (e.g., open) + * @param handler - Event handler function + */ + off(type, handler) { + return this.emitter.off(type, handler); + } + /** + * Updates the upload progress + * @param progressPercent Current progress in percent + */ + updateProgress(progressPercent) { + this.uploadProgress = progressPercent; + const progressText = this.container.querySelector(".uppload-loader-text .progress"); + if (progressText) progressText.innerHTML = `${parseInt(progressPercent.toString())}%`; + this.emitter.emit("progress", this.updateProgress); + } + } + + class UpploadEffect { + constructor() { + this.type = "effect"; + this.name = ""; + this.invisible = false; + this.noRecolor = false; + this.color = "#000"; + this.icon = ""; + this.template = () => ""; + this.handlers = () => {}; + this.supports = () => true; + } + } + + /** + * Make an HTTP request with the Fetch API and cache results + * @param input API endpoint + * @param settings HTTP Fetch configuration + */ + function cachedFetch(input, settings) { + const storage = sessionStorage; + return new Promise((resolve, reject) => { + const key = `uppload_cache_${JSON.stringify(input)}`; + const maxTTL = new Date(); + maxTTL.setDate(maxTTL.getDate() + 1); + const cachedResult = storage.getItem(key); + if (cachedResult) { + const cachedResultData = JSON.parse(cachedResult); + if (cachedResultData.ttl && new Date(cachedResultData.ttl).getTime() > new Date().getTime()) return resolve(cachedResultData.result); + } + window + .fetch(input, settings) + .then((response) => { + if (!response.ok) throw new Error("errors.response_not_ok"); + return response.json(); + }) + .then((result) => { + storage.setItem( + key, + JSON.stringify({ + ttl: maxTTL, + updatedAt: new Date(), + result, + }) + ); + resolve(result); + }) + .catch((error) => reject(error)); + }); + } + /** + * Get a file Blob from an image URL + * @param url - URL of an image + */ + const imageUrlToBlob = (url) => { + return new Promise((resolve, reject) => { + window + .fetch(`https://images.weserv.nl/?url=${encodeURIComponent(url)}`) + .then((response) => { + if (!response.ok) throw new Error("errors.response_not_ok"); + return response.blob(); + }) + .then((blob) => resolve(blob)) + .catch((error) => reject(error)); + }); + }; + + const de = { + upload: "Hochladen", + cancel: "Stornieren", + close: "Schließen", + uploading: "Hochladen ...", + uploaded: "Hochgeladen", + fetching: "Bild abrufen von $1$ ...", + poweredBy: "Ermöglicht durch $1$", + needHelp: "Benötigen Sie Hilfe?", + units: { + px: "px", + "%": "%", + deg: "°", + }, + errors: { + response_not_ok: "Beim Abrufen dieser Datei ist ein Fehler aufgetreten", + unable_to_search: "Bei der Suche ist ein Fehler aufgetreten", + invalid_service_url: "Dies ist keine $1$ -URL", + invalid_url: "Diese URL ist ungültig", + upload_aborted: "Dein Upload wurde abgebrochen", + upload_error: "Beim Hochladen dieser Datei ist ein Fehler aufgetreten", + file_type_not_allowed: "Dieser Dateityp wird nicht unterstützt", + file_too_large: "Die Datei muss kleiner als $1$ sein", + }, + help: { + loading: "Ladehilfe...", + close: "Hilfe schließen", + }, + services: { + default: { + heading: "Wählen Sie ein Bild aus", + }, + local: { + title: "Wählen Sie eine Datei", + button: "Wählen Sie eine Datei aus", + or: "von", + drop: "Ziehen Sie eine Datei hierher, um sie hochzuladen", + }, + camera: { + title: "Kamera", + button: "Webcam Foto", + switch: "Kamera wechseln", + waiting: "Warten auf Kameraerlaubnis ...", + unableToRead: + "Wir können das Video nicht von Ihrer Kamera lesen. Dies kann daran liegen, dass Sie nicht die erforderliche Berechtigung erteilt haben oder dass Ihr Gerät den Kamerazugriff nicht unterstützt.", + }, + microlink: { + button: "Import von $1$", + label: "$1$ $2$ URL", + placeholder: "Geben Sie eine URL von 1 bis 2 US-Dollar ein", + type: "Post", + }, + url: { + title: "Direkte URL", + label: "Bild-URL", + placeholder: "Geben Sie eine Bild-URL ein", + }, + instagram: { + title: "Instagram", + }, + facebook: { + title: "Facebook", + }, + flickr: { + title: "Flickr", + type: "ein foto", + }, + ninegag: { + title: "9GAG", + type: "ein foto", + }, + deviantart: { + title: "DeviantArt", + }, + artstation: { + title: "ArtStation", + }, + twitter: { + title: "Twitter", + type: "Foto-Tweet", + }, + pinterest: { + title: "Pinterest", + type: "Stift", + }, + flipboard: { + title: "Flipboard", + type: "artikel", + }, + fotki: { + title: "Fotos", + type: "ein foto", + }, + linkedin: { + title: "LinkedIn", + }, + reddit: { + title: "Reddit", + }, + tumblr: { + title: "Tumblr", + }, + weheartit: { + title: "Wir lieben es", + }, + screenshot: { + title: "Bildschirmfoto", + button: "Screenshot machen", + label: "URL der Webseite", + placeholder: "Geben Sie eine URL ein", + loading: "Machen Sie einen Screenshot ...", + }, + search: { + button: "Suchen Sie nach $1$", + label: "Suchen Sie nach einem Bild", + placeholder: "Suche nach etwas", + imagesPoweredBy: "Bilder möglich gemacht von $1$", + }, + giphy: { + title: "GIPHY", + }, + unsplash: { + title: "Aufspritzen", + }, + pixabay: { + title: "Pixabay", + }, + pexels: { + title: "Pexels", + }, + }, + effects: { + preview: { + title: "Beispiel", + }, + filters: { + title: "Filter", + }, + crop: { + title: "Zuschneiden", + aspectRatios: { + free: "Frei", + square: "voll", + }, + }, + rotate: { + title: "Wende dich", + }, + flip: { + title: "Dreh dich um", + buttons: { + horizontal: "Horizontal", + vertical: "Vertikal", + }, + }, + sharpen: { + title: "Schärfen", + }, + blur: { + title: "Unschärfe", + }, + brightness: { + title: "Helligkeit", + }, + contrast: { + title: "Kontrast", + }, + grayscale: { + title: "Graustufen", + }, + "hue-rotate": { + title: "Farbton drehen", + }, + invert: { + title: "Umdrehen", + }, + saturate: { + title: "Sättigen", + }, + sepia: { + title: "Sepia", + }, + }, + }; + + const en = { + upload: "Upload", + cancel: "Cancel", + close: "Close", + uploading: "Uploading...", + uploaded: "Uploaded", + fetching: "Getting your image from $1$...", + poweredBy: "Powered by $1$", + needHelp: "Need help?", + units: { + px: "px", + "%": "%", + deg: "°", + }, + errors: { + response_not_ok: "We got an error fetching this file", + unable_to_search: "We got an error searching", + invalid_service_url: "This is not $A$ $1$ URL", + invalid_url: "This URL seems to be invalid", + upload_aborted: "Your upload was cancelled", + upload_error: "We got an error uploading this file", + file_type_not_allowed: "This file type is not allowed", + file_too_large: "Your file should be smaller than $1$", + }, + help: { + loading: "Loading help...", + close: "Close help", + }, + services: { + default: { + heading: "Select an image", + }, + local: { + title: "Choose file", + button: "Select a file", + or: "or", + drop: "Drop files here", + }, + camera: { + title: "Camera", + button: "Click photo", + switch: "Switch camera", + waiting: "Waiting for permission...", + unableToRead: "We're not able to read your camera's video. This may be because you didn't grant the required permission, or because your device doesn't support camera access.", + }, + microlink: { + button: "Import from $1$", + label: "$1$ $2$ URL", + placeholder: "Enter $A$ $1$ $2$ URL", + type: "post", + }, + url: { + title: "Direct URL", + label: "Image URL", + placeholder: "Enter an image URL", + }, + instagram: { + title: "Instagram", + }, + facebook: { + title: "Facebook", + }, + flickr: { + title: "Flickr", + type: "photo", + }, + ninegag: { + title: "9GAG", + type: "photo", + }, + deviantart: { + title: "DeviantArt", + }, + artstation: { + title: "ArtStation", + }, + twitter: { + title: "Twitter", + type: "image tweet", + }, + pinterest: { + title: "Pinterest", + type: "pin", + }, + flipboard: { + title: "Flipboard", + type: "article", + }, + fotki: { + title: "Fotki", + type: "photo", + }, + linkedin: { + title: "LinkedIn", + }, + reddit: { + title: "Reddit", + }, + tumblr: { + title: "Tumblr", + }, + weheartit: { + title: "We Heart It", + }, + screenshot: { + title: "Screenshot", + button: "Take screenshot", + label: "Webpage URL", + placeholder: "Enter a webpage URL", + loading: "Taking a screenshot...", + }, + search: { + button: "Search on $1$", + label: "Find an image", + placeholder: "Search for something", + imagesPoweredBy: "Images powered by $1$", + }, + giphy: { + title: "GIPHY", + }, + unsplash: { + title: "Unsplash", + }, + pixabay: { + title: "Pixabay", + }, + pexels: { + title: "Pexels", + }, + }, + effects: { + preview: { + title: "Preview", + }, + filters: { + title: "Filters", + }, + crop: { + title: "Crop", + aspectRatios: { + free: "Free", + square: "Square", + }, + }, + rotate: { + title: "Rotate", + }, + flip: { + title: "Flip", + buttons: { + horizontal: "Horizontal", + vertical: "Vertical", + }, + }, + sharpen: { + title: "Sharpen", + }, + blur: { + title: "Blur", + }, + brightness: { + title: "Brightness", + }, + contrast: { + title: "Contrast", + }, + grayscale: { + title: "Grayscale", + }, + "hue-rotate": { + title: "Hue rotate", + }, + invert: { + title: "Invert", + }, + saturate: { + title: "Saturate", + }, + sepia: { + title: "Sepia", + }, + }, + /** + * Helpers can transform a string before returning it + * You can define a language-specific helper here + */ + helper: (text) => { + // Replace all instances of $A$ with "a" or "an" + const AAN = "$A$"; + while (text.indexOf(AAN) !== -1) { + const index = text.indexOf(AAN); + if (text.length > index + 3) { + if (["a", "e", "i", "o", "u"].indexOf(text[index + 4].toLowerCase()) !== -1) { + text = text.replace(AAN, "an"); + } else { + text = text.replace(AAN, "a"); + } + } + } + return text; + }, + }; + + const es = { + upload: "Subir", + cancel: "Cancelar", + close: "Cerrar", + uploading: "Subiendo...", + uploaded: "Subido", + fetching: "Obteniendo imagen desde $1$ ...", + poweredBy: "Hecho posible por $1$", + needHelp: "¿Necesitas ayuda?", + units: { + px: "px", + "%": "%", + deg: "°", + }, + errors: { + response_not_ok: "Se produjo un error al obtener este archivo", + unable_to_search: "Se produjo un error al buscar", + invalid_service_url: "Esta no es una URL de $1$", + invalid_url: "Esta URL no es válida.", + upload_aborted: "Tu carga ha sido cancelada", + upload_error: "Se produjo un error al subir este archivo", + file_type_not_allowed: "Este tipo de archivo no está permitido", + file_too_large: "El archivo debe ser inferior a $1$", + }, + help: { + loading: "Cargando ayuda...", + close: "Cerrar ayuda", + }, + services: { + default: { + heading: "Selecciona una imagen", + }, + local: { + title: "Elige un archivo", + button: "Selecciona un archivo", + or: "o", + drop: "Arrastra un archivo aquí para subir", + }, + camera: { + title: "Cámara", + button: "Foto de la webcam", + switch: "Cambiar de cámara", + waiting: "Esperando el permiso de la cámara...", + unableToRead: "No podemos leer el video de su cámara. Esto puede deberse a que no ha otorgado el permiso requerido o porque su dispositivo no admite el acceso a la cámara.", + }, + microlink: { + button: "Importar desde $1$", + label: "$1$ $2$ URL", + placeholder: "Ingrese una URL de $1$ $2$", + type: "enviar", + }, + url: { + title: "URL directa", + label: "URL de la imagen", + placeholder: "Ingrese la URL de la imagen", + }, + instagram: { + title: "Instagram", + }, + facebook: { + title: "Facebook", + }, + flickr: { + title: "Flickr", + type: "una foto", + }, + ninegag: { + title: "9GAG", + type: "una foto", + }, + deviantart: { + title: "DeviantArt", + }, + artstation: { + title: "ArtStation", + }, + twitter: { + title: "Twitter", + type: "imagen de twitter", + }, + pinterest: { + title: "Pinterest", + type: "pin", + }, + flipboard: { + title: "Flipboard", + type: "artículo", + }, + fotki: { + title: "fotos", + type: "una foto", + }, + linkedin: { + title: "LinkedIn", + }, + reddit: { + title: "Reddit", + }, + tumblr: { + title: "Tumblr", + }, + weheartit: { + title: "We Heart It", + }, + screenshot: { + title: "Captura de pantalla", + button: "Tomar captura de pantalla", + label: "URL de la página web", + placeholder: "Ingresa una URL", + loading: "Tomando una captura de pantalla ...", + }, + search: { + button: "Buscar en $1$", + label: "Busca una imagen", + placeholder: "Buscar algo", + imagesPoweredBy: "Imágenes posibles por $1$", + }, + giphy: { + title: "GIPHY", + }, + unsplash: { + title: "Unsplash", + }, + pixabay: { + title: "Pixabay", + }, + pexels: { + title: "Pexels", + }, + }, + effects: { + preview: { + title: "Vista Previa", + }, + filters: { + title: "Filtros", + }, + crop: { + title: "Recortar", + aspectRatios: { + free: "Libre", + square: "Cuadrado", + }, + }, + rotate: { + title: "Rotar", + }, + flip: { + title: "Dar vuelta", + buttons: { + horizontal: "Horizontal", + vertical: "Vertical", + }, + }, + sharpen: { + title: "Agudizar", + }, + blur: { + title: "Desenfocar", + }, + brightness: { + title: "Brillo", + }, + contrast: { + title: "Contraste", + }, + grayscale: { + title: "Escala de grises", + }, + "hue-rotate": { + title: "Rotar tono", + }, + invert: { + title: "Invertir", + }, + saturate: { + title: "Saturar", + }, + sepia: { + title: "Sepia", + }, + }, + }; + + const fr = { + upload: "Télécharger", + cancel: "Annuler", + close: "Fermer", + uploading: "Télécharger...", + uploaded: "Téléchargé", + fetching: "Obtenir une image à partir de $1$ ...", + poweredBy: "Rendu possible par $1$", + needHelp: "Besoin d'aide?", + units: { + px: "px", + "%": "%", + deg: "°", + }, + errors: { + response_not_ok: "Une erreur s'est produite lors de la récupération de ce fichier.", + unable_to_search: "Une erreur est survenue lors de la recherche", + invalid_service_url: "Ce n'est pas une URL $1$", + invalid_url: "Cette URL est invalide", + upload_aborted: "Votre téléchargement a été annulé", + upload_error: "Une erreur s'est produite lors du téléchargement de ce fichier.", + file_type_not_allowed: "Ce type de fichier n'est pas supporté", + file_too_large: "Le fichier doit être inférieur à $1$", + }, + help: { + loading: "Aide au chargement...", + close: "Fermer l'aide", + }, + services: { + default: { + heading: "Sélectionnez une image", + }, + local: { + title: "Choisissez un fichier", + button: "Sélectionnez un fichier", + or: "de", + drop: "Faites glisser un fichier ici pour le télécharger", + }, + camera: { + title: "Caméra", + button: "Photo webcam", + switch: "Changer de caméra", + waiting: "En attente de la permission de la caméra ...", + unableToRead: + "Nous ne pouvons pas lire la vidéo à partir de votre caméra. Cela peut être dû au fait que vous n'avez pas accordé l'autorisation requise ou que votre appareil ne prend pas en charge l'accès à la caméra.", + }, + microlink: { + button: "Importation à partir de $1$", + label: "$1$ $2$ URL", + placeholder: "Entrez une URL $1$ $2$", + type: "poster", + }, + url: { + title: "Directe URL", + label: "URL de l'image", + placeholder: "Entrez une URL d'image", + }, + instagram: { + title: "Instagram", + }, + facebook: { + title: "Facebook", + }, + flickr: { + title: "Flickr", + type: "une photo", + }, + ninegag: { + title: "9GAG", + type: "une photo", + }, + deviantart: { + title: "DeviantArt", + }, + artstation: { + title: "ArtStation", + }, + twitter: { + title: "Gazouillement", + type: "photo tweet", + }, + pinterest: { + title: "Pinterest", + type: "épingle", + }, + flipboard: { + title: "Flipboard", + type: "article", + }, + fotki: { + title: "Photos", + type: "une photo", + }, + linkedin: { + title: "LinkedIn", + }, + reddit: { + title: "Reddit", + }, + tumblr: { + title: "Tumblr", + }, + weheartit: { + title: "Nous avons le coeur", + }, + screenshot: { + title: "Capture d'écran", + button: "Prendre une capture d'écran", + label: "URL de la page Web", + placeholder: "Entrez une URL", + loading: "Prenez une capture d'écran ...", + }, + search: { + button: "Recherche de $1$", + label: "Rechercher une image", + placeholder: "Rechercher quelque chose", + imagesPoweredBy: "Images rendues possibles par $1$", + }, + giphy: { + title: "GIPHY", + }, + unsplash: { + title: "Unsplash", + }, + pixabay: { + title: "Pixabay", + }, + pexels: { + title: "Pexels", + }, + }, + effects: { + preview: { + title: "Exemple", + }, + filters: { + title: "Les filtres", + }, + crop: { + title: "Récolte", + aspectRatios: { + free: "Libre", + square: "Plein", + }, + }, + rotate: { + title: "Tournant", + }, + flip: { + title: "Faire demi-tour", + buttons: { + horizontal: "Horizontal", + vertical: "Vertical", + }, + }, + sharpen: { + title: "Netteté", + }, + blur: { + title: "Flou", + }, + brightness: { + title: "La luminosité", + }, + contrast: { + title: "Contraste", + }, + grayscale: { + title: "Niveaux de gris", + }, + "hue-rotate": { + title: "Faire pivoter la teinte", + }, + invert: { + title: "Retourner", + }, + saturate: { + title: "Saturer", + }, + sepia: { + title: "Sépia", + }, + }, + }; + + const hi = { + upload: "अपलोड", + cancel: "रद्द करना", + close: "बंद करे", + uploading: "अपलोड हो रहा है...", + uploaded: "अपलोड हो गया", + fetching: "हम आपकी तस्वीर $1$ से ला रहे हैं...", + poweredBy: "$1$ द्वारा संचालित", + needHelp: "मदद चाहिए?", + units: { + px: "पिक्सेल", + "%": "प्रतिशत", + deg: "डिग्री", + }, + errors: { + response_not_ok: "आपकी फ़ाइल लाने में एक त्रुटि हुई", + unable_to_search: "ढूंढे में एक त्रुटि हुई", + invalid_service_url: "यह एक $1$ यूआरएल नहीं है", + invalid_url: "यह यूआरएल गलत है", + upload_aborted: "आपका अपलोड रद्द हो गया है", + upload_error: "आपका अपलोड कारसे टूट एक त्रुटि हुई", + file_type_not_allowed: "यह फाइल टाइप अनुमति नहीं हैं", + file_too_large: "आपकी फाइल $1$ से छोटी होनी चाहिए", + }, + help: { + loading: "मदद लोड हो रही है...", + close: "मदद बंद करें", + }, + services: { + default: { + heading: "एक तस्वीर चुनें", + }, + local: { + title: "एक फाइल चुनें", + button: "फाइल चुनें", + or: "या", + drop: "यहां फाइल छोड़ें", + }, + camera: { + title: "कैमरा", + button: "तस्वीर खीचें", + switch: "कैमरा बदलें", + waiting: "अनुमति की प्रतीक्षा की जा रही है...", + unableToRead: "हम आपका वीडियो नहीं पढ़ पा रहे हैं I यह इसीलिए हो सकता है क्यूंकि आपने अनुमति नहीं दी, या क्योंकि आपके युक्ति में कैमरा नहीं है I", + }, + microlink: { + button: "$1$ से आयात", + label: "$1$ $2$ यूआरएल", + placeholder: "एक $1$ $2$ यूआरएल दर्ज करें", + type: "पद", + }, + url: { + title: "यूआरएल", + label: "छवि यूआरएल", + placeholder: "एक छवि यूआरएल दर्ज करें", + }, + instagram: { + title: "इंस्टाग्राम", + }, + facebook: { + title: "फेसबुक", + }, + flickr: { + title: "फ़्लिकर", + type: "तस्वीर", + }, + ninegag: { + title: "नाइन गैग", + type: "तस्वीर", + }, + deviantart: { + title: "देवीअनत-आर्ट", + }, + artstation: { + title: "आर्ट-स्टेशन", + }, + twitter: { + title: "ट्विटर", + type: "तस्वीर ट्वीट", + }, + pinterest: { + title: "पिनटेरेस्ट", + type: "पिन", + }, + flipboard: { + title: "फ्लिपबोर्ड", + type: "लेख", + }, + fotki: { + title: "फोटकी", + type: "तस्वीर", + }, + linkedin: { + title: "लिंक्ड-इन", + }, + reddit: { + title: "रेड्डिट", + }, + tumblr: { + title: "तुमब्लर", + }, + weheartit: { + title: "वी हार्ट इट", + }, + screenshot: { + title: "स्क्रीनशॉट", + button: "स्क्रीनशॉट लें", + label: "वेब पृष्ठ यूआरएल", + placeholder: "एक वेब पृष्ठ यूआरएल दर्ज करें", + loading: "स्क्रीनशॉट लिया जा रहा है...", + }, + search: { + button: "$1$ पर ढूंढें", + label: "तस्वीर ढूंढें", + placeholder: "कुछ ढूंढें", + imagesPoweredBy: "तस्वीरें $1$ द्वारा संचालित", + }, + giphy: { + title: "गिफी", + }, + unsplash: { + title: "उनस्प्लैश", + }, + pixabay: { + title: "पिक्साबे", + }, + pexels: { + title: "पिक्सेल्स", + }, + }, + effects: { + preview: { + title: "पूर्वावलोकन", + }, + filters: { + title: "फ़िल्टर", + }, + crop: { + title: "क्रॉप", + aspectRatios: { + free: "फ़्री", + square: "वर्ग", + }, + }, + rotate: { + title: "घुमाएँ", + }, + flip: { + title: "फ्लिप", + buttons: { + horizontal: "क्षैतिज", + vertical: "खड़ा", + }, + }, + sharpen: { + title: "पैना", + }, + blur: { + title: "कलंक", + }, + brightness: { + title: "चमक", + }, + contrast: { + title: "कंट्रास्ट", + }, + grayscale: { + title: "ग्रेस्केल", + }, + "hue-rotate": { + title: "रंग घुमाना", + }, + invert: { + title: "रंग पलटना", + }, + saturate: { + title: "सैच्युरेट", + }, + sepia: { + title: "सीपिया", + }, + }, + }; + + const it = { + upload: "Caricare", + cancel: "Annulla", + close: "Vicino", + uploading: "Carica ...", + uploaded: "caricato", + fetching: "Ottieni immagine da $1$ ...", + poweredBy: "Reso possibile da $1$", + needHelp: "Hai bisogno di aiuto?", + units: { + px: "px", + "%": "%", + deg: "°", + }, + errors: { + response_not_ok: "Si è verificato un errore durante il recupero di questo file", + unable_to_search: "Si è verificato un errore durante la ricerca", + invalid_service_url: "Questo non è un $1$ URL", + invalid_url: "Questo URL non è valido", + upload_aborted: "Il tuo caricamento è stato annullato", + upload_error: "Si è verificato un errore durante il caricamento di questo file", + file_type_not_allowed: "Questo tipo di file non è supportato", + file_too_large: "Il file deve essere inferiore a $1$", + }, + help: { + loading: "Caricamento della guida...", + close: "Aiuto vicino", + }, + services: { + default: { + heading: "Seleziona un'immagine", + }, + local: { + title: "Scegli un file", + button: "Seleziona un file", + or: "di", + drop: "Trascina qui un file per caricarlo", + }, + camera: { + title: "telecamera", + button: "Foto della webcam", + switch: "Cambia fotocamera", + waiting: "In attesa di autorizzazione della fotocamera ...", + unableToRead: + "Non possiamo leggere il video dalla tua fotocamera. Ciò può essere dovuto al fatto che non hai concesso l'autorizzazione richiesta o perché il tuo dispositivo non supporta l'accesso alla videocamera.", + }, + microlink: { + button: "Importa da $1$", + label: "$1$ $2$ URL", + placeholder: "Inserisci un URL da $1$ $2$", + type: "inviare", + }, + url: { + title: "URL diretto", + label: "URL immagine", + placeholder: "Inserisci un URL immagine", + }, + instagram: { + title: "Instagram", + }, + facebook: { + title: "Facebook", + }, + flickr: { + title: "Flickr", + type: "una foto", + }, + ninegag: { + title: "9GAG", + type: "una foto", + }, + deviantart: { + title: "DeviantArt", + }, + artstation: { + title: "ArtStation", + }, + twitter: { + title: "cinguettio", + type: "tweet fotografico", + }, + pinterest: { + title: "Pinterest", + type: "perno", + }, + flipboard: { + title: "Flipboard", + type: "articolo", + }, + fotki: { + title: "foto", + type: "una foto", + }, + linkedin: { + title: "LinkedIn", + }, + reddit: { + title: "Reddit", + }, + tumblr: { + title: "Tumblr", + }, + weheartit: { + title: "We Heart It", + }, + screenshot: { + title: "Immagine dello schermo", + button: "Fai uno screenshot", + label: "URL della pagina web", + placeholder: "Inserisci un URL", + loading: "Fai uno screenshot ...", + }, + search: { + button: "Cerca $1$", + label: "Cerca un'immagine", + placeholder: "Cerca qualcosa", + imagesPoweredBy: "Immagini rese possibili da $1$", + }, + giphy: { + title: "GIPHY", + }, + unsplash: { + title: "Unsplash", + }, + pixabay: { + title: "Pixabay", + }, + pexels: { + title: "Pexels", + }, + }, + effects: { + preview: { + title: "esempio", + }, + filters: { + title: "filtri", + }, + crop: { + title: "raccolto", + aspectRatios: { + free: "Gratuito", + square: "pieno", + }, + }, + rotate: { + title: "torcere", + }, + flip: { + title: "Voltati", + buttons: { + horizontal: "orizzontale", + vertical: "verticale", + }, + }, + sharpen: { + title: "affinare", + }, + blur: { + title: "dissolvenza", + }, + brightness: { + title: "luminosità", + }, + contrast: { + title: "Contrasto", + }, + grayscale: { + title: "Scala di grigi", + }, + "hue-rotate": { + title: "Ruota tonalità", + }, + invert: { + title: "Girare", + }, + saturate: { + title: "satiate", + }, + sepia: { + title: "nero di seppia", + }, + }, + }; + + const nl = { + upload: "Uploaden", + cancel: "Annuleren", + close: "Sluiten", + uploading: "Uploaden...", + uploaded: "Geupload", + fetching: "Bezig met het ophalen van afbeelding vanaf $1$...", + poweredBy: "Mede mogelijk gemaakt door $1$", + needHelp: "Hulp nodig?", + units: { + px: "px", + "%": "%", + deg: "°", + }, + errors: { + response_not_ok: "Er is een fout opgetreden bij het ophalen van dit bestand", + unable_to_search: "Er is een fout opgetreden bij het zoeken", + invalid_service_url: "Dit is geen $1$-URL", + invalid_url: "Deze URL is ongeldig", + upload_aborted: "Je upload is geannuleerd", + upload_error: "Er is een fout opgetreden bij het uploaden van dit bestand", + file_type_not_allowed: "Dit bestandstype wordt niet ondersteund", + file_too_large: "Het bestand moet kleiner zijn dan $1$", + }, + help: { + loading: "Bezig met het laden van hulp...", + close: "Hulp sluiten", + }, + services: { + default: { + heading: "Selecteer een afbeelding", + }, + local: { + title: "Kies een bestand", + button: "Selecteer een bestand", + or: "of", + drop: "Sleep hier een bestand om te uploaden", + }, + camera: { + title: "Camera", + button: "Webcam foto", + switch: "Switch camera", + waiting: "Wachten op camera permissie...", + unableToRead: "We kunnen de video van uw camera niet lezen. Dit kan zijn omdat u niet de vereiste toestemming hebt verleend of omdat uw apparaat geen cameratoegang ondersteunt.", + }, + microlink: { + button: "Importeer van $1$", + label: "$1$ $2$ URL", + placeholder: "Voer een $1$-$2$-URL in", + type: "post", + }, + url: { + title: "Directe URL", + label: "Afbeeldings-URL", + placeholder: "Voer een afbeeldings-URL in", + }, + instagram: { + title: "Instagram", + }, + facebook: { + title: "Facebook", + }, + flickr: { + title: "Flickr", + type: "foto", + }, + ninegag: { + title: "9GAG", + type: "foto", + }, + deviantart: { + title: "DeviantArt", + }, + artstation: { + title: "ArtStation", + }, + twitter: { + title: "Twitter", + type: "foto tweet", + }, + pinterest: { + title: "Pinterest", + type: "pin", + }, + flipboard: { + title: "Flipboard", + type: "artikel", + }, + fotki: { + title: "Fotki", + type: "foto", + }, + linkedin: { + title: "LinkedIn", + }, + reddit: { + title: "Reddit", + }, + tumblr: { + title: "Tumblr", + }, + weheartit: { + title: "We Heart It", + }, + screenshot: { + title: "Screenshot", + button: "Screenshot maken", + label: "URL van webpagina", + placeholder: "Voer een URL in", + loading: "Bezig met het maken van een screenshot...", + }, + search: { + button: "Zoeken op $1$", + label: "Zoek een afbeelding", + placeholder: "Zoek naar iets", + imagesPoweredBy: "Afbeeldingen mogelijk gemaakt door $1$", + }, + giphy: { + title: "GIPHY", + }, + unsplash: { + title: "Unsplash", + }, + pixabay: { + title: "Pixabay", + }, + pexels: { + title: "Pexels", + }, + }, + effects: { + preview: { + title: "Voorbeeld", + }, + filters: { + title: "Filters", + }, + crop: { + title: "Bijsnijden", + aspectRatios: { + free: "Free", + square: "Plein", + }, + }, + rotate: { + title: "Draaien", + }, + flip: { + title: "Omdraaien", + buttons: { + horizontal: "Horizontaal", + vertical: "Verticaal", + }, + }, + sharpen: { + title: "Verscherpen", + }, + blur: { + title: "Vervagen", + }, + brightness: { + title: "Helderheid", + }, + contrast: { + title: "Contrast", + }, + grayscale: { + title: "Grijstinten", + }, + "hue-rotate": { + title: "Tint roteren", + }, + invert: { + title: "Omkeren", + }, + saturate: { + title: "Verzadigen", + }, + sepia: { + title: "Sepia", + }, + }, + }; + + const pt = { + upload: "Enviar", + cancel: "Cancelar", + close: "Fechar", + uploading: "Enviando...", + uploaded: "Enviado", + fetching: "Buscando imagem de $1$...", + poweredBy: "Fornecido por $1$", + needHelp: "Precisa de ajuda?", + units: { + px: "px", + "%": "%", + deg: "°", + }, + errors: { + response_not_ok: "Ocorreu um erro ao buscar este arquivo", + unable_to_search: "Não foi possível realizar a busca", + invalid_service_url: "Esta URL não pertence a $1$", + invalid_url: "Esta URL parece ser inválida", + upload_aborted: "Seu envio foi cancelado", + upload_error: "Ocorreu um erro durante o envio deste arquivo", + file_type_not_allowed: "Este tipo de arquivo não é permitido", + file_too_large: "Seu arquivo deve ser menor que $1$", + }, + help: { + loading: "Carregando ajuda...", + close: "Fechar Ajuda", + }, + services: { + default: { + heading: "Selecione uma imagem", + }, + local: { + title: "Escolher arquivo", + button: "Selecione um arquivo", + or: "ou", + drop: "Arraste-os para cá", + }, + camera: { + title: "Câmera", + button: "Tirar foto", + switch: "Mudar câmera", + waiting: "Esperando a permissão...", + unableToRead: "Não foi possível obter acesso a câmera. Isto pode ter ocorrido se você não tiver permitido ou seu dispositivo suportar acesso a câmera.", + }, + microlink: { + button: "Importar $1$", + label: "$2$ do $1$", + placeholder: "Insira a URL do $2$ do $1$", + type: "post", + }, + url: { + title: "URL", + label: "URL da imagem", + placeholder: "Insira a URL da imagem", + }, + instagram: { + title: "Instagram", + }, + facebook: { + title: "Facebook", + }, + flickr: { + title: "Flickr", + type: "foto", + }, + ninegag: { + title: "9GAG", + type: "foto", + }, + deviantart: { + title: "DeviantArt", + }, + artstation: { + title: "ArtStation", + }, + twitter: { + title: "Twitter", + type: "tweet", + }, + pinterest: { + title: "Pinterest", + type: "pin", + }, + flipboard: { + title: "Flipboard", + type: "artigo", + }, + fotki: { + title: "Fotki", + type: "foto", + }, + linkedin: { + title: "LinkedIn", + }, + reddit: { + title: "Reddit", + }, + tumblr: { + title: "Tumblr", + }, + weheartit: { + title: "We Heart It", + }, + screenshot: { + title: "Captura de tela (screenshot)", + button: "Fazer captura da tela", + label: "URL do site", + placeholder: "Insira a URL do site", + loading: "Fazendo captura...", + }, + search: { + button: "Pesquisar no $1$", + label: "Procure uma imagem", + placeholder: "Procurar algo", + imagesPoweredBy: "Busca de imagens fornecida por $1$", + }, + giphy: { + title: "GIPHY", + }, + unsplash: { + title: "Unsplash", + }, + pixabay: { + title: "Pixabay", + }, + pexels: { + title: "Pexels", + }, + }, + effects: { + preview: { + title: "Previsualização", + }, + filters: { + title: "Filtros", + }, + crop: { + title: "Corte", + aspectRatios: { + free: "Livre", + square: "Quadrado", + }, + }, + rotate: { + title: "Rotacionar", + }, + flip: { + title: "Inverter", + buttons: { + horizontal: "Horizontal", + vertical: "Vertical", + }, + }, + sharpen: { + title: "Aguçar", + }, + blur: { + title: "Desfocar", + }, + brightness: { + title: "Brilho", + }, + contrast: { + title: "Contraste", + }, + grayscale: { + title: "Escala de cinza", + }, + "hue-rotate": { + title: "Matiz", + }, + invert: { + title: "Inverter", + }, + saturate: { + title: "Saturar", + }, + sepia: { + title: "Sépia", + }, + }, + }; + + const ro = { + upload: "Încărcare", + cancel: "Anulare", + close: "Închide", + uploading: "Încărcare...", + uploaded: "Încărcat", + fetching: "Obținere imagine de la $1$...", + poweredBy: "Susținut de $1$", + needHelp: "Ai nevoie de ajutor?", + units: { + px: "px", + "%": "%", + deg: "°", + }, + errors: { + response_not_ok: "S-a produs o eroare in timpul obținerii acestui fișier", + unable_to_search: "S-a produs o eroare in timpul căutării", + invalid_service_url: "Acesta nu este un URL de $1$", + invalid_url: "Acest URL nu este valid", + upload_aborted: "Încărcare a fost anulată", + upload_error: "S-a produs o eroare in timpul încărcarii acestui fișier", + file_type_not_allowed: "Acest tip de fișier nu este permis.", + file_too_large: "Fișierul trebuie să fie mai mic de $1$", + }, + help: { + loading: "Se obține ajutor...", + close: "Închidere ajutor", + }, + services: { + default: { + heading: "Selectează o imagine", + }, + local: { + title: "Alege un fișier", + button: "Selectează un fișier", + or: "ori", + drop: "Plasați fișierele aici", + }, + camera: { + title: "Cameră", + button: "Capturează o imagine", + switch: "Schimbă camera", + waiting: "Se așteaptă permisiunea...", + unableToRead: + "Nu putem să citim semnalul video al camerei. Acest lucru se poate întâmpla pentru că nu ați acordat permisiunea necesară sau pentru că dispozitivul dvs. nu acceptă accesul camerei.", + }, + microlink: { + button: "Importă de pe $1$", + label: "$1$ $2$ URL", + placeholder: "Tastează $1$ $2$ URL", + type: "trimite", + }, + url: { + title: "URL direct", + label: "URL imagine", + placeholder: "Tastează URL-ul imaginii", + }, + instagram: { + title: "Instagram", + }, + facebook: { + title: "Facebook", + }, + flickr: { + title: "Flickr", + type: "fotografie", + }, + ninegag: { + title: "9GAG", + type: "fotografie", + }, + deviantart: { + title: "DeviantArt", + }, + artstation: { + title: "ArtStation", + }, + twitter: { + title: "Twitter", + type: "tweet imagine", + }, + pinterest: { + title: "Pinterest", + type: "pin", + }, + flipboard: { + title: "Flipboard", + type: "articol", + }, + fotki: { + title: "Fotki", + type: "fotografie", + }, + linkedin: { + title: "LinkedIn", + }, + reddit: { + title: "Reddit", + }, + tumblr: { + title: "Tumblr", + }, + weheartit: { + title: "We Heart It", + }, + screenshot: { + title: "Captură de ecran", + button: "Capturează ecran", + label: "URL pagină web", + placeholder: "Tastează URL-ul imaginii", + loading: "Se capturează ecranul...", + }, + search: { + button: "Caută pe $1$", + label: "Găsește o imagine", + placeholder: "Caută ceva", + imagesPoweredBy: "Imagini provenite de la $1$", + }, + giphy: { + title: "GIPHY", + }, + unsplash: { + title: "Unsplash", + }, + pixabay: { + title: "Pixabay", + }, + pexels: { + title: "Pexels", + }, + }, + effects: { + preview: { + title: "Previzualizare", + }, + filters: { + title: "Filtre", + }, + crop: { + title: "Decupare", + aspectRatios: { + free: "Liber", + square: "Pătrat", + }, + }, + rotate: { + title: "Rotire", + }, + flip: { + title: "Oglindire", + buttons: { + horizontal: "Orizontal", + vertical: "Vertical", + }, + }, + sharpen: { + title: "Accentuare", + }, + blur: { + title: "Estompare", + }, + brightness: { + title: "Luminozitate", + }, + contrast: { + title: "Contrast", + }, + grayscale: { + title: "Scară tonurilor de gri", + }, + "hue-rotate": { + title: "Rotire tonuri", + }, + invert: { + title: "Inversare", + }, + saturate: { + title: "Saturare", + }, + sepia: { + title: "Sepia", + }, + }, + }; + + const ru = { + upload: "Загрузить", + cancel: "Отмена", + close: "близко", + uploading: "Загрузка... ", + uploaded: "загруженное", + fetching: "Скачиваем изображение с $1$... ", + poweredBy: "Стало возможным благодаря $1$", + needHelp: "Нужна помощь?", + units: { + px: "px", + "%": "%", + deg: "°", + }, + errors: { + response_not_ok: "Произошла ошибка при получении этого файла", + unable_to_search: "Произошла ошибка при поиске", + invalid_service_url: "Это не URL $1$", + invalid_url: "Этот URL недействителен", + upload_aborted: "Ваша загрузка была отменена", + upload_error: "Произошла ошибка при загрузке этого файла", + file_type_not_allowed: "Этот тип файла не поддерживается", + file_too_large: "Файл должен быть не более $1$", + }, + help: { + loading: "Загрузка...", + close: "Закрыть", + }, + services: { + default: { + heading: "Выберите изображение", + }, + local: { + title: "Выберите файл", + button: "Выберите файл", + or: "или", + drop: "Перетащите файл сюда, чтобы загрузить", + }, + camera: { + title: "Камера", + button: "Cделать фото", + switch: "Переключить камеру", + waiting: "Жду разрешения камеры...", + unableToRead: "Мы не можем получить доступ к вашей камере. Это может быть связано с тем, что вы не предоставили разрешение, или ваше устройство не поддерживает доступ к камере.", + }, + microlink: { + button: "Скачать из $1$", + label: "Ссылка на $1$ $2$", + placeholder: "Введите ссылку на $1$ $2$", + type: "пост", + }, + url: { + title: "Ссылка", + label: "Ссылка на изображение", + placeholder: "Введите ссылку на изображение", + button: "Скачать изображение", + }, + instagram: { + title: "Instagram", + }, + facebook: { + title: "Facebook", + }, + flickr: { + title: "Flickr", + type: "фото", + }, + ninegag: { + title: "9GAG", + type: "фото", + }, + deviantart: { + title: "DeviantArt", + }, + artstation: { + title: "ArtStation", + }, + twitter: { + title: "Twitter", + type: "фото твит", + }, + pinterest: { + title: "Pinterest", + type: "pin", + }, + flipboard: { + title: "Flipboard", + type: "статья", + }, + fotki: { + title: "Fotki", + type: "фото", + }, + linkedin: { + title: "LinkedIn", + }, + reddit: { + title: "Reddit", + }, + tumblr: { + title: "Tumblr", + }, + weheartit: { + title: "We Heart It", + }, + screenshot: { + title: "Скриншот", + button: "Сделать скриншот", + label: "Ссылка на сайт", + placeholder: "Введите ссылку", + loading: "Скриншотим...", + }, + search: { + button: "Поиск на $1$", + label: "Поиск изображений", + placeholder: "", + imagesPoweredBy: "картинки предоставлены $1$", + }, + giphy: { + title: "GIPHY", + }, + unsplash: { + title: "Unsplash", + }, + pixabay: { + title: "Pixabay", + }, + pexels: { + title: "Pexels", + }, + }, + effects: { + preview: { + title: "пример", + }, + filters: { + title: "Фильтры", + }, + crop: { + title: "Обрезать", + aspectRatios: { + free: "Свободный", + square: "Квадрат", + }, + }, + rotate: { + title: "Поворот", + }, + flip: { + title: "Отразить", + buttons: { + horizontal: "Горизонтально", + vertical: "Вертикально", + }, + }, + sharpen: { + title: "Резкость", + }, + blur: { + title: "Размытие", + }, + brightness: { + title: "Яркость", + }, + contrast: { + title: "Контраст", + }, + grayscale: { + title: "Оттенки серого", + }, + "hue-rotate": { + title: "Повернуть оттенок", + }, + invert: { + title: "Инверсия", + }, + saturate: { + title: "Насыщенность", + }, + sepia: { + title: "Сепия", + }, + }, + }; + + const tr = { + upload: "Yükleme", + cancel: "İptal etmek", + close: "Kapat", + uploading: "Yükle ...", + uploaded: "yüklenen", + fetching: "$1$ 'dan resim al ...", + poweredBy: "$1$ ile mümkün oldu", + needHelp: "Yardıma mı ihtiyacınız var?", + units: { + px: "px", + "%": "%", + deg: "°", + }, + errors: { + response_not_ok: "Bu dosya alınırken bir hata oluştu", + unable_to_search: "Aranırken bir hata oluştu", + invalid_service_url: "Bu bir $1$ URL değil", + invalid_url: "Bu URL geçersiz", + upload_aborted: "Yüklemeniz iptal edildi", + upload_error: "Bu dosya yüklenirken bir hata oluştu", + file_type_not_allowed: "Bu dosya türü desteklenmiyor", + file_too_large: "Dosya $1$ 'dan az olmalı", + }, + help: { + loading: "Yardım yükleniyor...", + close: "Yardımı kapat", + }, + services: { + default: { + heading: "Bir resim seç", + }, + local: { + title: "Bir dosya seç", + button: "Bir dosya seç", + or: "arasında", + drop: "Yüklemek için bir dosyayı buraya sürükleyin", + }, + camera: { + title: "Kamera", + button: "Webcam fotoğraf", + switch: "Kamera değiştir", + waiting: "Kamera izni bekleniyor ...", + unableToRead: "Videoyu kameranızdan okuyamıyoruz. Bunun nedeni gerekli izni vermediğiniz veya cihazınızın kamera erişimini desteklememesi olabilir.", + }, + microlink: { + button: "1 $ 'dan içe aktar", + label: "$1$ $2$ URL", + placeholder: "Bir $1$ $2$ URL girin", + type: "posta", + }, + url: { + title: "Doğrudan URL", + label: "Image URL", + placeholder: "Bir resim URL’si girin", + }, + instagram: { + title: "Instagram", + }, + facebook: { + title: "Facebook", + }, + flickr: { + title: "Flickr", + type: "bir fotoğraf", + }, + ninegag: { + title: "9gag", + type: "bir fotoğraf", + }, + deviantart: { + title: "DeviantArt", + }, + artstation: { + title: "ArtStation", + }, + twitter: { + title: "heyecan", + type: "fotoğraf tweet", + }, + pinterest: { + title: "pinterest", + type: "toplu iğne", + }, + flipboard: { + title: "Flipboard", + type: "makale", + }, + fotki: { + title: "Resimler", + type: "bir fotoğraf", + }, + linkedin: { + title: "LinkedIn", + }, + reddit: { + title: "Reddit", + }, + tumblr: { + title: "Tumblr", + }, + weheartit: { + title: "Biz kalp", + }, + screenshot: { + title: "Ekran görüntüsü", + button: "Ekran görüntüsü al", + label: "Web sayfasının URL'si", + placeholder: "Bir URL girin", + loading: "Ekran görüntüsü al ...", + }, + search: { + button: "$1$ için ara", + label: "Bir resim arayın", + placeholder: "Bir şey arayın", + imagesPoweredBy: "Görüntüler $1$ 'a kadar mümkün kılındı", + }, + giphy: { + title: "GIPHY", + }, + unsplash: { + title: "Unsplash", + }, + pixabay: { + title: "Pixabay", + }, + pexels: { + title: "Pexels", + }, + }, + effects: { + preview: { + title: "örnek", + }, + filters: { + title: "Filtreler", + }, + crop: { + title: "ekin", + aspectRatios: { + free: "Ücretsiz", + square: "tam", + }, + }, + rotate: { + title: "büküm", + }, + flip: { + title: "Arkanı dön", + buttons: { + horizontal: "yatay", + vertical: "dikey", + }, + }, + sharpen: { + title: "keskinleştirme", + }, + blur: { + title: "karartmak", + }, + brightness: { + title: "parlaklık", + }, + contrast: { + title: "Kontrast", + }, + grayscale: { + title: "Gri tonlama", + }, + "hue-rotate": { + title: "Tonu döndür", + }, + invert: { + title: "Ters çevir", + }, + saturate: { + title: "doyurmak", + }, + sepia: { + title: "Sepya", + }, + }, + }; + + const zhTW = { + upload: "上載", + cancel: "取消", + close: "關", + uploading: "上傳中...", + uploaded: "已上傳", + fetching: "正在取得您的影像從 $1$...", + poweredBy: "由 $1$ 提供", + needHelp: "需要幫助嗎?", + units: { + px: "px", + "%": "%", + deg: "°", + }, + errors: { + response_not_ok: "我們在抓取這個檔案時發生錯誤", + unable_to_search: "我們在搜尋時發生錯誤", + invalid_service_url: "這不是一個 $1$ 網址", + invalid_url: "這個網址似乎無效", + upload_aborted: "您的上傳已取消", + upload_error: "我們在上傳這個檔案時發生錯誤", + file_type_not_allowed: "這個檔案類型不被允許", + file_too_large: "您的檔案應該小於 $1$", + }, + help: { + loading: "讀取幫助中...", + close: "關閉幫助", + }, + services: { + default: { + heading: "選擇一個影像", + }, + local: { + title: "選擇檔案", + button: "選擇一個檔案", + or: "或", + drop: "拖曳檔案至此", + }, + camera: { + title: "相機", + button: "點擊照片", + switch: "切換照片", + waiting: "等待權限授權中...", + unableToRead: "我們無法從您的相機讀取影像,這可能是因為您拒絕了授予權限或是因為您的裝置不支援存取相機", + }, + microlink: { + button: "匯入 $1$", + label: "$1$ $2$ 網址", + placeholder: "請輸入一個 $1$ 的 $2$ 網址", + type: "post", + }, + url: { + title: "網址", + label: "影像網址", + placeholder: "請輸入一個影像網址", + }, + instagram: { + title: "Instagram", + }, + facebook: { + title: "Facebook", + }, + flickr: { + title: "Flickr", + type: "圖像", + }, + ninegag: { + title: "9GAG", + type: "圖像", + }, + deviantart: { + title: "DeviantArt", + }, + artstation: { + title: "ArtStation", + }, + twitter: { + title: "Twitter", + type: "影像推文", + }, + pinterest: { + title: "Pinterest", + type: "釘文", + }, + flipboard: { + title: "Flipboard", + type: "文章", + }, + fotki: { + title: "Fotki", + type: "影像", + }, + linkedin: { + title: "LinkedIn", + }, + reddit: { + title: "Reddit", + }, + tumblr: { + title: "Tumblr", + }, + weheartit: { + title: "We Heart It", + }, + screenshot: { + title: "螢幕截圖", + button: "擷取螢幕截圖", + label: "網頁網址", + placeholder: "請輸入一個網頁網址", + loading: "正在擷取螢幕截圖...", + }, + search: { + button: "搜尋 $1$", + label: "找一張影像", + placeholder: "請輸入關鍵字", + imagesPoweredBy: "影像由 $1$ 提供", + }, + giphy: { + title: "GIPHY", + }, + unsplash: { + title: "Unsplash", + }, + pixabay: { + title: "Pixabay", + }, + pexels: { + title: "Pexels", + }, + }, + effects: { + preview: { + title: "預覽", + }, + filters: { + title: "濾鏡", + }, + crop: { + title: "剪裁", + aspectRatios: { + free: "自由", + square: "正方形", + }, + }, + rotate: { + title: "旋轉", + }, + flip: { + title: "翻轉", + buttons: { + horizontal: "水平", + vertical: "垂直", + }, + }, + sharpen: { + title: "銳化", + }, + blur: { + title: "模糊", + }, + brightness: { + title: "亮度", + }, + contrast: { + title: "對比", + }, + grayscale: { + title: "灰階", + }, + "hue-rotate": { + title: "色相旋轉", + }, + invert: { + title: "負片效果", + }, + saturate: { + title: "飽和度", + }, + sepia: { + title: "懷舊(黃褐色)", + }, + }, + }; + + const xhrUploader = ({ endpoint, fileKeyName = "file", method = "POST", responseKey = "url", responseFunction, settingsFunction }) => { + return (file, updateProgress) => + new Promise((resolve, reject) => { + const formData = new FormData(); + formData.append(fileKeyName, file); + const xmlHttp = new XMLHttpRequest(); + xmlHttp.open(method, endpoint, true); + if (typeof settingsFunction === "function") settingsFunction(xmlHttp); + xmlHttp.addEventListener("progress", (event) => { + if (typeof updateProgress === "function") updateProgress(event.loaded / event.total); + }); + xmlHttp.addEventListener("load", () => { + const responseText = xmlHttp.responseText; + if (typeof responseFunction === "function") return resolve(responseFunction(responseText)); + const json = JSON.parse(responseText); + return resolve(json[responseKey]); + }); + xmlHttp.addEventListener("error", () => reject("errors.response_not_ok")); + xmlHttp.addEventListener("abort", () => reject("errors.upload_aborted")); + xmlHttp.send(formData); + }); + }; + const fetchUploader = ({ endpoint, settingsFunction, method = "POST", fileKeyName = "file", responseKey = "url", responseFunction }) => { + return (file) => + new Promise((resolve, reject) => { + const formData = new FormData(); + formData.append(fileKeyName, file); + window + .fetch( + endpoint, + settingsFunction + ? settingsFunction(file) + : { + method, + body: formData, + } + ) + .then((response) => { + if (!response.ok) throw new Error("errors.response_not_ok"); + return response.json(); + }) + .then((json) => { + if (typeof responseFunction === "function") return resolve(responseFunction(json)); + return resolve(json[responseKey]); + }) + .catch(() => reject("errors.response_not_ok")); + }); + }; + + class Camera extends UpploadService { + constructor() { + super(...arguments); + this.name = "camera"; + this.icon = ``; + this.color = "#16a085"; + this.canvas = document.createElement("canvas"); + this.gotError = false; + this.waiting = false; + this.frontCamera = false; + this.supports = () => !!(window.navigator.mediaDevices && window.navigator.mediaDevices.enumerateDevices && !/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)); + this.template = ({ translate }) => { + return ` +
+
${translate("services.camera.waiting")}
+
+

${translate("services.camera.unableToRead")}

+

${translate("needHelp")}

+
+
+ +
+
+
+ + +
+ + `; + }; + this.stop = () => { + if (this.stream) this.stream.getTracks().forEach((track) => track.stop()); + }; + this.handlers = (params) => { + this.waiting = true; + this.update(params); + const constraints = { + audio: false, + video: { width: 1280, height: 1280 }, + }; + this.startStream(params, constraints); + const clickButton = params.uppload.container.querySelector(".camera-click"); + if (clickButton) safeListen(clickButton, "click", this.clickPhoto.bind(this, params)); + const switchButton = params.uppload.container.querySelector(".camera-click"); + if (switchButton) safeListen(switchButton, "click", this.switchCamera.bind(this, params)); + const helpButton = params.uppload.container.querySelector(".need-help-link"); + if (helpButton) safeListen(helpButton, "click", () => params.showHelp("/services/camera")); + }; + } + update(params) { + const waiting = params.uppload.container.querySelector(".camera-waiting"); + if (waiting) { + waiting.style.display = "none"; + waiting.style.opacity = "0"; + } + const error = params.uppload.container.querySelector(".camera-error"); + if (error) { + error.style.display = "none"; + error.style.opacity = "0"; + } + const success = params.uppload.container.querySelector(".camera-success"); + if (success) { + success.style.display = "none"; + success.style.opacity = "0"; + } + const footer = params.uppload.container.querySelector(".service-footer"); + if (footer) { + footer.style.display = "none"; + footer.style.opacity = "0"; + } + if (this.gotError) { + if (error) { + error.style.display = ""; + error.style.opacity = "1"; + } + } else if (this.waiting) { + if (waiting) { + waiting.style.display = ""; + waiting.style.opacity = "1"; + } + } else { + if (success) { + success.style.display = ""; + success.style.opacity = "1"; + } + if (footer) { + footer.style.display = ""; + footer.style.opacity = "1"; + } + } + } + switchCamera(params) { + this.frontCamera = !this.frontCamera; + const constraints = { + audio: false, + video: { + width: 1280, + height: 1280, + facingMode: this.frontCamera ? "user" : "environment", + }, + }; + this.startStream(params, constraints); + } + clickPhoto(params) { + this.canvas = document.createElement("canvas"); + const video = params.uppload.container.querySelector("video.camera-stream"); + if (!video) return; + if (!this.stream) return; + const videoSize = video.getBoundingClientRect(); + let width = videoSize.width; + let height = videoSize.height; + this.stream.getTracks().forEach((track) => { + const settings = track.getSettings(); + if (settings.width) width = settings.width; + if (settings.height) height = settings.height; + }); + this.canvas.width = width; + this.canvas.height = height; + const context = this.canvas.getContext("2d"); + if (!context) return; + context.clearRect(0, 0, this.canvas.width, this.canvas.height); + context.drawImage(video, 0, 0, width, height); + canvasToBlob(this.canvas).then((blob) => params.next(blobToUpploadFile(blob, `camera-photo-${Math.random().toString(36).slice(2)}.png`, "image/png", new Date()))); + } + startStream(params, constraints) { + this.stop(); + window.navigator.mediaDevices + .getUserMedia(constraints) + .then((mediaStream) => { + this.stream = mediaStream; + const video = params.uppload.container.querySelector("video.camera-stream"); + if (video) { + video.srcObject = mediaStream; + safeListen(video, "loadedmetadata", () => video.play()); + fitImageToContainer(params, video); + } + }) + .catch(() => { + this.gotError = true; + }) + .then(() => { + this.waiting = false; + this.update(params); + }); + } + } + + const generateFileName = (file, service) => { + file.name = `${service}-import-${Math.random().toString(36).slice(2)}`; + return file; + }; + class MicrolinkBaseClass extends UpploadService { + constructor() { + super(...arguments); + this.loading = false; + this.exampleURL = ""; + this.validator = () => true; + this.template = ({ translate }) => { + return ` + + `; + }; + this.handlers = (params) => { + const form = params.uppload.container.querySelector(`.microlink-search-form`); + if (form) { + safeListen(form, "submit", (event) => { + event.preventDefault(); + const input = params.uppload.container.querySelector(`.microlink-search-input`); + if (input) { + const url = input.value; + if (!this.validator(url)) return params.handle(new Error("errors.invalid_url")); + this.loading = true; + this.update(params); + if (this.name === "screenshot") { + imageUrlToBlob(`https://api.microlink.io?url=${encodeURIComponent(url)}&screenshot=true&meta=false&embed=screenshot.url`) + .then((blob) => params.next(generateFileName(blobToUpploadFile(blob), this.name))) + .catch((error) => params.handle(error)) + .then(() => (this.loading = false)); + } else if (this.name === "url") { + imageUrlToBlob(url) + .then((blob) => params.next(generateFileName(blobToUpploadFile(blob), this.name))) + .catch((error) => params.handle(error)); + } else { + cachedFetch(`https://api.microlink.io/?url=${encodeURIComponent(url)}`) + .then((result) => { + if (!result.data.image || !result.data.image.url) throw new Error("errors.response_not_ok"); + return result.data.image.url; + }) + .then((url) => imageUrlToBlob(url)) + .then((blob) => params.next(generateFileName(blobToUpploadFile(blob), this.name))) + .catch((error) => params.handle(error)); + } + } + return false; + }); + } + const helpButton = params.uppload.container.querySelector(".need-help-link"); + if (helpButton) + safeListen(helpButton, "click", () => params.showHelp(`/services/${["url", "screenshot"].indexOf(this.name) !== -1 ? this.name : `import-from-web-service/${this.name}`}`)); + }; + } + update(params) { + const loader = params.uppload.container.querySelector(".microlink-loader"); + const container = params.uppload.container.querySelector(".microlink-container"); + if (container) container.style.display = this.loading ? "none" : ""; + if (loader) loader.style.display = this.loading ? "flex" : "none"; + } + } + + class Instagram extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "instagram"; + this.icon = ``; + this.color = "#cc3366"; + this.exampleURL = "https://www.instagram.com/p/Bu_T4RihQFB/"; + this.validator = (input) => /(https?:\/\/(.+?\.)?(instagram|instagr)\.(com|am)(\/[A-Za-z0-9\-\._~:\/\?#\[\]@!$&'\(\)\*\+,;\=]*)?)/.test(input); + } + } + + class Facebook extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "facebook"; + this.icon = ``; + this.color = "#1b69f6"; + this.exampleURL = "https://www.facebook.com/elninotech/photos/a.2066268863489861/2066268886823192/?type=3&theater"; + this.validator = (input) => /(https?:\/\/(.+?\.)?(facebook|fb)\.(com|me)(\/[A-Za-z0-9\-\._~:\/\?#\[\]@!$&'\(\)\*\+,;\=]*)?)/.test(input); + } + } + + class Local extends UpploadService { + constructor({ mimeTypes, maxFileSize } = {}) { + super(); + this.name = "local"; + this.icon = ``; + this.color = "#34495e"; + this.mimeTypes = ["image/gif", "image/jpeg", "image/jpg", "image/png"]; + this.maxFileSize = Infinity; + this.template = (params) => { + return `
+
${params.translate("services.local.drop")}
+ ${params.translate("services.local.or")} + +
+
+
`; + }; + this.handlers = (params) => { + const dropArea = params.uppload.container.querySelector(".drop-area"); + if (dropArea) { + safeListen(dropArea, "drop", (event) => this.dropHandler(params, event)); + safeListen(dropArea, "dragover", (event) => this.dragHandler(params, event)); + safeListen(dropArea, "dragend", (event) => this.dragStop(params, event)); + safeListen(dropArea, "dragexit", (event) => this.dragStop(params, event)); + safeListen(dropArea, "dragleave", (event) => this.dragStop(params, event)); + safeListen(dropArea, "click", (event) => this.fileSelect(params, event)); + } + const input = params.uppload.container.querySelector(".alternate-input input[type=file]"); + if (input) safeListen(input, "change", (event) => this.getFile(params, event)); + const helpButton = params.uppload.container.querySelector(".need-help-link"); + if (helpButton) safeListen(helpButton, "click", () => params.showHelp("/services/local")); + }; + if (mimeTypes) this.mimeTypes = mimeTypes; + if (maxFileSize) this.maxFileSize = maxFileSize; + } + getFile(params, event) { + event.preventDefault(); + const files = event.target.files; + let file = null; + if (files) { + if (params.uppload.settings.multiple && files.length > 1) return params.uploadMultiple(Array.from(files)); + for (let i = 0; i < files.length; i++) { + const item = files[i]; + if (this.mimeTypes.indexOf(item.type) !== -1) + if (item.size < this.maxFileSize) file = item; + else params.handle(new Error(params.translate("errors.file_too_large", `${this.maxFileSize} bytes`))); + } + } + if (!file) return; + if (file) + params.next({ + blob: file, + size: file.size, + type: file.type, + lastModified: file.lastModified ? new Date(file.lastModified) : undefined, + name: file.name, + }); + } + fileSelect(params, event) { + const input = params.uppload.container.querySelector(".alternate-input input[type=file]"); + if (input) input.click(); + } + dragStop(params, event) { + const dropArea = params.uppload.container.querySelector(".drop-area"); + if (dropArea) dropArea.classList.remove("drop-area-active"); + } + dragHandler(params, event) { + event.preventDefault(); + const dropArea = params.uppload.container.querySelector(".drop-area"); + if (dropArea) dropArea.classList.add("drop-area-active"); + } + dropHandler(params, event) { + event.preventDefault(); + this.dragStop(params, event); + let file = null; // getAsFile() returns File | null + if (event.dataTransfer && event.dataTransfer.items) { + for (let i = 0; i < event.dataTransfer.items.length; i++) { + const item = event.dataTransfer.items[i]; + if (item.kind === "file" && this.mimeTypes.indexOf(item.type) !== -1) { + file = item.getAsFile(); + if (!file || file.size > this.maxFileSize) { + file = null; + params.handle(new Error(params.translate("errors.file_too_large", `${this.maxFileSize} bytes`))); + } + } + } + } + if (!file) return; + if (file) + params.next({ + blob: file, + size: file.size, + type: file.type, + lastModified: file.lastModified ? new Date(file.lastModified) : undefined, + name: file.name, + }); + } + } + + const generateFileName$1 = (file, service, query) => { + file.name = `${query || `${service}-import`}-${Math.random().toString(36).slice(2)}.jpg`; + file.type = "image/jpeg"; + return file; + }; + class SearchBaseClass extends UpploadService { + constructor({ apiKey, name, icon, color, poweredByUrl, popularEndpoint, searchEndpoint, getButton, getPopularResults, getSearchResults, noRecolor, fetchSettings }) { + super(); + this.results = []; + this.loading = false; + this.noRecolor = false; + this.template = ({ translate }) => { + return ` +
+
${colorSVG(this.icon, this)}
+ + +
+
+
+ +
+
+

${translate("fetching", translate(`services.${this.name}.title`))}

+
+ `; + }; + this.handlers = (params) => { + const form = params.uppload.container.querySelector(`.search-search-form`); + if (form) { + safeListen(form, "submit", (event) => { + const input = params.uppload.container.querySelector(`.search-search-input`); + if (input) { + const query = input.value; + cachedFetch(this.searchEndpoint(this.apiKey, query), this.fetchSettings) + .then((json) => { + this.results = this.getSearchResults(json); + this.update(params); + }) + .catch(() => params.handle(new Error("errors.unable_to_search"))); + } + event.preventDefault(); + return false; + }); + } + this.updateImages(params); + const imageButtons = params.uppload.container.querySelectorAll(".search-images button"); + imageButtons.forEach((image) => { + safeListen(image, "click", () => { + const url = image.getAttribute("data-full-url"); + this.loading = true; + this.update(params); + if (url) + imageUrlToBlob(url) + .then((blob) => params.next(generateFileName$1(blobToUpploadFile(blob), this.name, image.getAttribute("aria-label")))) + .catch((error) => params.handle("errors.response_not_ok")) + .then(() => (this.loading = false)); + }); + }); + const helpButton = params.uppload.container.querySelector(".need-help-link"); + if (helpButton) safeListen(helpButton, "click", () => params.showHelp(`/services/search/${this.name}`)); + }; + this.name = name; + this.icon = icon; + this.color = color; + this.apiKey = apiKey; + this.noRecolor = !!noRecolor; + this.poweredByUrl = poweredByUrl; + this.popularEndpoint = popularEndpoint(this.apiKey); + this.searchEndpoint = searchEndpoint; + this.getButton = getButton; + this.getPopularResults = getPopularResults; + this.getSearchResults = getSearchResults; + if (fetchSettings) this.fetchSettings = fetchSettings(this.apiKey); + if (this.popularEndpoint) + cachedFetch(this.popularEndpoint, this.fetchSettings) + .then((photos) => { + this.results = this.getPopularResults(photos); + }) + .catch(() => {}); + } + updateImages(params) { + const imagesContainer = params.uppload.container.querySelector(".search-images"); + if (imagesContainer) { + imagesContainer.innerHTML = ` + ${this.results.map((result) => this.getButton(result)).join("\n")} + `; + } + } + update(params) { + this.updateImages(params); + if (params) this.handlers(params); + const loader = params.uppload.container.querySelector(".search-loader"); + const container = params.uppload.container.querySelector(".search-container"); + if (container) container.style.display = this.loading ? "none" : ""; + if (loader) loader.style.display = this.loading ? "flex" : "none"; + } + } + + class GIPHY extends SearchBaseClass { + constructor(apiKey) { + super({ + apiKey, + name: "giphy", + icon: ``, + color: "#a800ff", + noRecolor: true, + poweredByUrl: "https://giphy.com", + popularEndpoint: (apiKey) => `https://api.giphy.com/v1/gifs/trending?api_key=${apiKey}&limit=18&rating=G`, + searchEndpoint: (apiKey, query) => `https://api.giphy.com/v1/gifs/search?api_key=${apiKey}&q=${encodeURIComponent(query)}&limit=18&offset=0&rating=G&lang=en`, + getButton: (image) => `
+
`, + getSearchResults: (response) => response.data, + getPopularResults: (response) => response.data, + }); + } + } + + class Pixabay extends SearchBaseClass { + constructor(apiKey) { + super({ + apiKey, + name: "pixabay", + icon: ``, + color: "#2ec66d", + poweredByUrl: "https://pixabay.com", + popularEndpoint: (apiKey) => `https://pixabay.com/api/?key=${apiKey}&per_page=18&image_type=photo`, + searchEndpoint: (apiKey, query) => `https://pixabay.com/api/?key=${apiKey}&per_page=18&q=${encodeURIComponent(query)}&image_type=photo`, + getButton: (image) => `
+ + + ${image.user} +
`, + getSearchResults: (response) => response.hits, + getPopularResults: (response) => response.hits, + }); + } + } + + class Unsplash extends SearchBaseClass { + constructor(apiKey) { + super({ + apiKey, + name: "unsplash", + icon: ``, + color: "#333", + poweredByUrl: "https://unsplash.com", + popularEndpoint: (apiKey) => `https://api.unsplash.com/photos?client_id=${apiKey}`, + searchEndpoint: (apiKey, query) => `https://api.unsplash.com/search/photos?client_id=${this.apiKey}&page=1&query=${encodeURIComponent(query)}`, + getButton: (image) => `
+ + + + ${image.user.name} + +
`, + getSearchResults: (response) => response.results, + getPopularResults: (response) => response, + }); + } + } + + class Pexels extends SearchBaseClass { + constructor(apiKey) { + super({ + apiKey, + name: "pexels", + icon: ``, + color: "#05a081", + poweredByUrl: "https://pexels.com", + popularEndpoint: (apiKey) => `https://api.pexels.com/v1/curated?per_page=9&page=1`, + searchEndpoint: (apiKey, query) => `https://api.pexels.com/v1/search?query=${encodeURIComponent(query)}&per_page=12&page=1`, + getButton: (image) => `
+ + ${image.photographer} +
`, + getSearchResults: (response) => response.photos, + getPopularResults: (response) => response.photos, + fetchSettings: (apiKey) => ({ + headers: { + Authorization: apiKey, + }, + }), + }); + } + } + + class URL$1 extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "url"; + this.icon = ``; + this.color = "#8e44ad"; + } + } + + class Screenshot extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "screenshot"; + this.icon = ``; + this.color = "#e67e22"; + } + } + + class Flickr extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "flickr"; + this.icon = ``; + this.noRecolor = true; + this.color = "#ff0084"; + this.exampleURL = "https://www.flickr.com/photos/renewolf/26111951000/"; + this.validator = (input) => /(https?:\/\/(.+?\.)?(flickr|flic)\.(com|kr)(\/[A-Za-z0-9\-\._~:\/\?#\[\]@!$&'\(\)\*\+,;\=]*)?)/.test(input); + } + } + + class Pinterest extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "pinterest"; + this.icon = ``; + this.color = "#e60023"; + this.exampleURL = "https://pinterest.com/pin/437201076327078006/"; + this.validator = (input) => /(https?:\/\/(.+?\.)?(pinterest|pin)\.(com|it)(\/[A-Za-z0-9\-\._~:\/\?#\[\]@!$&'\(\)\*\+,;\=]*)?)/.test(input); + } + } + + class DeviantArt extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "deviantart"; + this.icon = ``; + this.color = "#00d159"; + this.exampleURL = "https://www.deviantart.com/artbycatherineradley/art/Despair-820869682"; + this.validator = (input) => /(https?:\/\/(.+?\.)?(deviantart|fav)\.(com|me)(\/[A-Za-z0-9\-\._~:\/\?#\[\]@!$&'\(\)\*\+,;\=]*)?)/.test(input); + } + } + + class NineGag extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "ninegag"; + this.icon = ``; + this.color = "#000"; + this.exampleURL = "https://9gag.com/gag/awoBXb8"; + this.validator = (input) => /(https?:\/\/(.+?\.)?9gag\.com(\/[A-Za-z0-9\-\._~:\/\?#\[\]@!$&'\(\)\*\+,;\=]*)?)/.test(input); + } + } + + class ArtStation extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "artstation"; + this.icon = ``; + this.color = "#3ea2cf"; + this.exampleURL = "https://www.artstation.com/artwork/VdGOkZ"; + this.validator = (input) => /(https?:\/\/(.+?\.)?artstation\.com(\/[A-Za-z0-9\-\._~:\/\?#\[\]@!$&'\(\)\*\+,;\=]*)?)/.test(input); + } + } + + class Twitter extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "twitter"; + this.icon = ``; + this.color = "#1da1f2"; + this.exampleURL = "https://twitter.com/elninoict/status/1106176415622418433"; + this.validator = (input) => /(https?:\/\/(.+?\.)?(twitter|t)\.(co|com)(\/[A-Za-z0-9\-\._~:\/\?#\[\]@!$&'\(\)\*\+,;\=]*)?)/.test(input); + } + } + + class Flipboard extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "flipboard"; + this.icon = ``; + this.color = "#e12828"; + this.exampleURL = "https://flipboard.com/@bbcfuture/how-climate-change-could-kill-the-red-apple/f-c8d499b4ca%2Fbbc.com"; + this.validator = (input) => /(https?:\/\/(.+?\.)?(flipboard|flip)\.(com|it)(\/[A-Za-z0-9\-\._~:\/\?#\[\]@!$&'\(\)\*\+,;\=]*)?)/.test(input); + } + } + + class Fotki extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "fotki"; + this.icon = ``; + this.color = "#5471B9"; + this.exampleURL = "https://public.fotki.com/EricAnke/holland/molens/20170928-162510.html"; + this.validator = (input) => /(https?:\/\/(.+?\.)?fotki\.com(\/[A-Za-z0-9\-\._~:\/\?#\[\]@!$&'\(\)\*\+,;\=]*)?)/.test(input); + } + } + + class LinkedIn extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "linkedin"; + this.icon = ``; + this.color = "#0e76a8"; + this.exampleURL = "https://www.linkedin.com/posts/explorius-vastgoedontwikkeling-b-v-_el-nino-huurt-kantoor-in-enschede-activity-6480386878641180672-7DC_"; + this.validator = (input) => /(https?:\/\/(.+?\.)?linkedin\.com(\/[A-Za-z0-9\-\._~:\/\?#\[\]@!$&'\(\)\*\+,;\=]*)?)/.test(input); + } + } + + class Reddit extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "reddit"; + this.icon = ``; + this.color = "#ff4301"; + this.exampleURL = "https://www.reddit.com/r/thenetherlands/comments/dz1myk/a_beautiful_morning_in_ermelo/"; + this.validator = (input) => /(https?:\/\/(.+?\.)?reddit\.com(\/[A-Za-z0-9\-\._~:\/\?#\[\]@!$&'\(\)\*\+,;\=]*)?)/.test(input); + } + } + + class Tumblr extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "tumblr"; + this.icon = ``; + this.color = "#34526f"; + this.exampleURL = "https://germanpostwarmodern.tumblr.com/post/186653088149/cubicus-building-of-twente-university-1969-73-in"; + this.validator = (input) => /(https?:\/\/(.+?\.)?tumblr\.com(\/[A-Za-z0-9\-\._~:\/\?#\[\]@!$&'\(\)\*\+,;\=]*)?)/.test(input); + } + } + + class WeHeartIt extends MicrolinkBaseClass { + constructor() { + super(...arguments); + this.name = "weheartit"; + this.icon = ``; + this.color = "#ff5464"; + this.exampleURL = "https://weheartit.com/entry/221671573"; + this.validator = (input) => /(https?:\/\/(.+?\.)?weheartit\.com(\/[A-Za-z0-9\-\._~:\/\?#\[\]@!$&'\(\)\*\+,;\=]*)?)/.test(input); + } + } + + class Crop extends UpploadEffect { + constructor({ aspectRatio, aspectRatioOptions, hideAspectRatioSettings, autoCropArea, viewMode } = {}) { + super(); + this.name = "crop"; + this.icon = ``; + this.aspectRatio = NaN; + this.hideAspectRatioSettings = false; + this.aspectRatioOptions = { + free: NaN, + square: 1, + "16:9": 16 / 9, + }; + this.autoCropArea = 1; + this.viewMode = 1; + this.originalFile = { blob: new Blob() }; + this.template = ({ file, translate }) => { + const image = URL.createObjectURL(file.blob); + this.originalFile = file; + return ` +
+ +
+ ${ + !this.aspectRatio && !this.hideAspectRatioSettings + ? `
+ ${Object.keys(this.aspectRatioOptions) + .map( + (aspectRatio, index) => ` + + ` + ) + .join("")} +
` + : "" + } + `; + }; + this.handlers = (params) => { + const cropperElement = params.uppload.container.querySelector(".uppload-cropping-element img"); + const originalFile = this.originalFile; + const type = originalFile.type && ["image/jpeg", "image/webp"].indexOf(originalFile.type) !== -1 ? originalFile.type : "image/png"; + if (cropperElement) { + fitImageToContainer(params, cropperElement).then(() => { + const cropper = new Cropper(cropperElement, { + aspectRatio: this.aspectRatio, + autoCropArea: this.autoCropArea, + viewMode: this.viewMode, + ready() { + canvasToBlob(cropper.getCroppedCanvas(), type).then((blob) => { + originalFile.blob = blob; + params.next(originalFile); + }); + }, + cropend() { + canvasToBlob(cropper.getCroppedCanvas(), type).then((blob) => { + originalFile.blob = blob; + params.next(originalFile); + }); + }, + }); + const aspectRatios = params.uppload.container.querySelectorAll("input[name='crop-aspect-ratio']"); + aspectRatios.forEach((aspectRatio) => { + safeListen(aspectRatio, "change", () => { + const selectedAspectRatio = params.uppload.container.querySelector("input[name='crop-aspect-ratio']:checked"); + if (selectedAspectRatio) { + cropper.setAspectRatio(this.aspectRatioOptions[selectedAspectRatio.getAttribute("data-name") || "free"]); + canvasToBlob(cropper.getCroppedCanvas(), type).then((blob) => { + originalFile.blob = blob; + params.next(originalFile); + }); + } + }); + }); + }); + } + }; + if (aspectRatio) this.aspectRatio = aspectRatio; + if (aspectRatioOptions) this.aspectRatioOptions = aspectRatioOptions; + if (autoCropArea) this.autoCropArea = autoCropArea; + if (viewMode) this.viewMode = viewMode; + if (hideAspectRatioSettings) this.hideAspectRatioSettings = hideAspectRatioSettings; + } + } + + class Rotate extends UpploadEffect { + constructor() { + super(...arguments); + this.name = "rotate"; + this.icon = ``; + this.value = 0; + this.max = 360; + this.unit = "deg"; + this.originalFile = { blob: new Blob() }; + this.template = ({ file, translate }) => { + const image = URL.createObjectURL(file.blob); + this.originalFile = file; + return ` +
+ +
+
+ + 0${translate(`units.${this.unit}`) || this.unit} +
+ `; + }; + this.handlers = (params) => { + const rotatorElement = params.uppload.container.querySelector(".uppload-rotating-element img"); + const originalFile = this.originalFile; + if (rotatorElement) { + fitImageToContainer(params, rotatorElement).then(() => { + const rotator = new Cropper(rotatorElement, { + autoCropArea: 1, + viewMode: 1, + dragMode: "none", + cropBoxMovable: false, + cropBoxResizable: false, + toggleDragModeOnDblclick: false, + ready() { + params.uppload.emitter.emit("processing"); + canvasToBlob(rotator.getCroppedCanvas()).then((blob) => { + originalFile.blob = blob; + params.uppload.emitter.emit("process"); + params.next(originalFile); + }); + }, + }); + const range = params.uppload.container.querySelector(".settings input[type='range']"); + if (range) + safeListen(range, "change", () => { + let value = 0; + const range = params.uppload.container.querySelector(".settings input[type='range']"); + if (range) value = parseInt(range.value); + const displayer = params.uppload.container.querySelector(".settings .value span"); + if (displayer) displayer.innerHTML = value.toString(); + rotator.rotate(value - this.value); + this.value = value; + params.uppload.emitter.emit("processing"); + canvasToBlob(rotator.getCroppedCanvas()).then((blob) => { + originalFile.blob = blob; + params.uppload.emitter.emit("process"); + params.next(originalFile); + }); + }); + }); + } + }; + } + } + + class Flip extends UpploadEffect { + constructor() { + super(...arguments); + this.name = "flip"; + this.originalfileURL = ""; + this.originalFile = { blob: new Blob() }; + this.icon = ``; + this.canvas = document.createElement("canvas"); + this.template = ({ file, translate }) => { + const image = URL.createObjectURL(file.blob); + this.originalfileURL = image; + this.originalFile = file; + return ` +
+ +
+
+ + +
+ `; + }; + this.handlers = (params) => { + const img = params.uppload.container.querySelector(".uppload-flip img"); + if (img) { + fitImageToContainer(params, img).then(() => { + const horizontal = params.uppload.container.querySelector(".settings button.flip-btn-horizontal"); + if (horizontal) safeListen(horizontal, "click", this.update.bind(this, params, true, false)); + const vertical = params.uppload.container.querySelector(".settings button.flip-btn-vertical"); + if (vertical) safeListen(vertical, "click", this.update.bind(this, params, false, true)); + }); + } + }; + } + imageToCanvasBlob(params, flipH = false, flipV = false) { + return new Promise((resolve) => { + params.uppload.emitter.emit("processing"); + const scaleH = flipH ? -1 : 1; + const scaleV = flipV ? -1 : 1; + this.canvas = document.createElement("canvas"); + const image = document.createElement("img"); + image.src = this.originalfileURL; + image.onload = () => { + this.canvas.width = image.width; + this.canvas.height = image.height; + const posX = flipH ? image.width * -1 : 0; + const posY = flipV ? image.height * -1 : 0; + const context = this.canvas.getContext("2d"); + if (!context) return; + context.clearRect(0, 0, this.canvas.width, this.canvas.height); + context.scale(scaleH, scaleV); + context.drawImage(image, posX, posY); + canvasToBlob(this.canvas).then((blob) => { + const image = URL.createObjectURL(blob); + this.originalfileURL = image; + params.uppload.emitter.emit("process"); + return resolve(blob); + }); + }; + }); + } + update(params, x, y) { + const img = params.uppload.container.querySelector(".uppload-flip img"); + if (!img) return; + this.imageToCanvasBlob(params, x, y).then((blob) => { + if (!blob) return; + let file = this.originalFile; + file.blob = blob; + params.next(file); + const image = URL.createObjectURL(blob); + img.setAttribute("src", image); + }); + } + } + + class Preview extends UpploadEffect { + constructor() { + super(...arguments); + this.name = "preview"; + this.icon = ``; + this.template = ({ file }) => { + const image = URL.createObjectURL(file.blob); + return ` +
+ +
+ `; + }; + this.handlers = (params) => { + const image = params.uppload.container.querySelector(".uppload-preview-element img"); + if (image) fitImageToContainer(params, image); + }; + } + } + + class UpploadFilterBaseClass extends UpploadEffect { + constructor() { + super(...arguments); + this.canvas = document.createElement("canvas"); + this.originalfileURL = ""; + this.originalFile = { blob: new Blob() }; + this.cssFilter = ""; + this.max = 10; + this.unit = "px"; + this.value = 0; + this.supports = () => { + var _a; + return !!(this.canvas.getContext && this.canvas.getContext("2d") && typeof ((_a = this.canvas.getContext("2d")) === null || _a === void 0 ? void 0 : _a.filter) === "string"); + }; + this.template = ({ file, translate }) => { + const image = URL.createObjectURL(file.blob); + this.originalfileURL = image; + this.originalFile = file; + return ` +
+ +
+
+ + 0${translate(`units.${this.unit}`) || this.unit} +
+ `; + }; + this.handlers = (params) => { + const hueElement = params.uppload.container.querySelector(".uppload-hue-image img"); + if (hueElement) { + fitImageToContainer(params, hueElement).then(() => { + const range = params.uppload.container.querySelector(".settings input[type='range']"); + if (range) safeListen(range, "change", this.update.bind(this, params)); + }); + } + }; + } + imageToCanvasBlob(params, filters) { + params.uppload.emitter.emit("processing"); + return new Promise((resolve) => { + this.canvas = document.createElement("canvas"); + const image = document.createElement("img"); + image.src = this.originalfileURL; + image.onload = () => { + this.canvas.width = image.width; + this.canvas.height = image.height; + const context = this.canvas.getContext("2d"); + if (!context) return; + context.clearRect(0, 0, this.canvas.width, this.canvas.height); + context.filter = filters; + context.drawImage(image, 0, 0); + canvasToBlob(this.canvas).then((blob) => { + params.uppload.emitter.emit("process"); + return resolve(blob); + }); + }; + }); + } + update(params) { + let value = 0; + const range = params.uppload.container.querySelector(".settings input[type='range']"); + if (range) value = parseInt(range.value); + const displayer = params.uppload.container.querySelector(".settings .value span"); + if (displayer) displayer.innerHTML = value.toString(); + const hueElement = params.uppload.container.querySelector(".uppload-hue-image img"); + if (!hueElement) return; + this.imageToCanvasBlob(params, `${this.cssFilter}(${range.value}${this.unit})`).then((blob) => { + if (!blob) return; + this.originalFile.blob = blob; + params.next(this.originalFile); + const image = URL.createObjectURL(blob); + hueElement.setAttribute("src", image); + }); + } + } + + class Brightness extends UpploadFilterBaseClass { + constructor() { + super(...arguments); + this.name = "brightness"; + this.icon = ``; + this.cssFilter = "brightness"; + this.unit = "%"; + this.value = 100; + this.max = 200; + } + } + + class Blur extends UpploadFilterBaseClass { + constructor() { + super(...arguments); + this.name = "blur"; + this.icon = ``; + this.cssFilter = "blur"; + this.unit = "px"; + } + } + + class Contrast extends UpploadFilterBaseClass { + constructor() { + super(...arguments); + this.name = "contrast"; + this.icon = ``; + this.cssFilter = "contrast"; + this.unit = "%"; + this.value = 100; + this.max = 200; + } + } + + class Grayscale extends UpploadFilterBaseClass { + constructor() { + super(...arguments); + this.name = "grayscale"; + this.icon = ``; + this.cssFilter = "grayscale"; + this.unit = "%"; + this.value = 0; + this.max = 100; + } + } + + class HueRotate extends UpploadFilterBaseClass { + constructor() { + super(...arguments); + this.name = "hue-rotate"; + this.icon = ``; + this.cssFilter = "hue-rotate"; + this.unit = "deg"; + this.value = 0; + this.max = 360; + } + } + + class Invert extends UpploadFilterBaseClass { + constructor() { + super(...arguments); + this.name = "invert"; + this.icon = ``; + this.cssFilter = "invert"; + this.unit = "%"; + this.value = 0; + this.max = 100; + } + } + + class Sepia extends UpploadFilterBaseClass { + constructor() { + super(...arguments); + this.name = "sepia"; + this.icon = ``; + this.cssFilter = "sepia"; + this.unit = "%"; + this.value = 0; + this.max = 100; + } + } + + class Saturate extends UpploadFilterBaseClass { + constructor() { + super(...arguments); + this.name = "saturate"; + this.icon = ``; + this.cssFilter = "saturate"; + this.unit = "%"; + this.value = 100; + this.max = 200; + } + } + + exports.ArtStation = ArtStation; + exports.Blur = Blur; + exports.Brightness = Brightness; + exports.Camera = Camera; + exports.Contrast = Contrast; + exports.Crop = Crop; + exports.DeviantArt = DeviantArt; + exports.Facebook = Facebook; + exports.Flickr = Flickr; + exports.Flip = Flip; + exports.Flipboard = Flipboard; + exports.Fotki = Fotki; + exports.GIPHY = GIPHY; + exports.Grayscale = Grayscale; + exports.HueRotate = HueRotate; + exports.Instagram = Instagram; + exports.Invert = Invert; + exports.LinkedIn = LinkedIn; + exports.Local = Local; + exports.NineGag = NineGag; + exports.Pexels = Pexels; + exports.Pinterest = Pinterest; + exports.Pixabay = Pixabay; + exports.Preview = Preview; + exports.Reddit = Reddit; + exports.Rotate = Rotate; + exports.Saturate = Saturate; + exports.Screenshot = Screenshot; + exports.Sepia = Sepia; + exports.Tumblr = Tumblr; + exports.Twitter = Twitter; + exports.URL = URL$1; + exports.Unsplash = Unsplash; + exports.Uppload = Uppload; + exports.UpploadEffect = UpploadEffect; + exports.UpploadService = UpploadService; + exports.WeHeartIt = WeHeartIt; + exports.cachedFetch = cachedFetch; + exports.canvasToBlob = canvasToBlob; + exports.compressImage = compressImage; + exports.de = de; + exports.en = en; + exports.es = es; + exports.fetchUploader = fetchUploader; + exports.fitImageToContainer = fitImageToContainer; + exports.flattenObject = flattenObject; + exports.fr = fr; + exports.getElements = getElements; + exports.hi = hi; + exports.imageUrlToBlob = imageUrlToBlob; + exports.it = it; + exports.nl = nl; + exports.pt = pt; + exports.ro = ro; + exports.ru = ru; + exports.safeListen = safeListen; + exports.setI18N = setI18N; + exports.tr = tr; + exports.translate = translate; + exports.xhrUploader = xhrUploader; + exports.zhTW = zhTW; + + Object.defineProperty(exports, "__esModule", { value: true }); + }); + }, + { cropperjs: 2, "focus-trap": 3, mitt: 4 }, + ], + 7: [ + function (require, module, exports) { + module.exports = extend; + + var hasOwnProperty = Object.prototype.hasOwnProperty; + + function extend() { + var target = {}; + + for (var i = 0; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + } + }, + {}, + ], + }, + {}, + [1] +); diff --git a/public/js/printThis.js b/public/js/printThis.js new file mode 100644 index 0000000..e69de29 diff --git a/public/js/qrcode.js b/public/js/qrcode.js new file mode 100644 index 0000000..95b885f --- /dev/null +++ b/public/js/qrcode.js @@ -0,0 +1 @@ +var QRCode=function(t){"use strict";var r,e=function(){return"function"==typeof Promise&&Promise.prototype&&Promise.prototype.then},n=[0,26,44,70,100,134,172,196,242,292,346,404,466,532,581,655,733,815,901,991,1085,1156,1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465,2611,2761,2876,3034,3196,3362,3532,3706],o=function(t){if(!t)throw new Error('"version" cannot be null or undefined');if(t<1||t>40)throw new Error('"version" should be in range from 1 to 40');return 4*t+17},a=function(t){return n[t]},i=function(t){for(var r=0;0!==t;)r++,t>>>=1;return r},u=function(t){if("function"!=typeof t)throw new Error('"toSJISFunc" is not a valid function.');r=t},s=function(){return void 0!==r},f=function(t){return r(t)};function h(t,r){return t(r={exports:{}},r.exports),r.exports}var c=h((function(t,r){r.L={bit:1},r.M={bit:0},r.Q={bit:3},r.H={bit:2},r.isValid=function(t){return t&&void 0!==t.bit&&t.bit>=0&&t.bit<4},r.from=function(t,e){if(r.isValid(t))return t;try{return function(t){if("string"!=typeof t)throw new Error("Param is not a string");switch(t.toLowerCase()){case"l":case"low":return r.L;case"m":case"medium":return r.M;case"q":case"quartile":return r.Q;case"h":case"high":return r.H;default:throw new Error("Unknown EC Level: "+t)}}(t)}catch(t){return e}}}));function g(){this.buffer=[],this.length=0}c.L,c.M,c.Q,c.H,c.isValid,g.prototype={get:function(t){var r=Math.floor(t/8);return 1==(this.buffer[r]>>>7-t%8&1)},put:function(t,r){for(var e=0;e>>r-e-1&1))},getLengthInBits:function(){return this.length},putBit:function(t){var r=Math.floor(this.length/8);this.buffer.length<=r&&this.buffer.push(0),t&&(this.buffer[r]|=128>>>this.length%8),this.length++}};var d=g;function l(t){if(!t||t<1)throw new Error("BitMatrix size must be defined and greater than 0");this.size=t,this.data=new Uint8Array(t*t),this.reservedBit=new Uint8Array(t*t)}l.prototype.set=function(t,r,e,n){var o=t*this.size+r;this.data[o]=e,n&&(this.reservedBit[o]=!0)},l.prototype.get=function(t,r){return this.data[t*this.size+r]},l.prototype.xor=function(t,r,e){this.data[t*this.size+r]^=e},l.prototype.isReserved=function(t,r){return this.reservedBit[t*this.size+r]};var v=l,p=h((function(t,r){var e=o;r.getRowColCoords=function(t){if(1===t)return[];for(var r=Math.floor(t/7)+2,n=e(t),o=145===n?26:2*Math.ceil((n-13)/(2*r-2)),a=[n-7],i=1;i=0&&t<=7},r.from=function(t){return r.isValid(t)?parseInt(t,10):void 0},r.getPenaltyN1=function(t){for(var r=t.size,n=0,o=0,a=0,i=null,u=null,s=0;s=5&&(n+=e+(o-5)),i=h,o=1),(h=t.get(f,s))===u?a++:(a>=5&&(n+=e+(a-5)),u=h,a=1)}o>=5&&(n+=e+(o-5)),a>=5&&(n+=e+(a-5))}return n},r.getPenaltyN2=function(t){for(var r=t.size,e=0,o=0;o=10&&(1488===n||93===n)&&e++,a=a<<1&2047|t.get(u,i),u>=10&&(1488===a||93===a)&&e++}return e*o},r.getPenaltyN4=function(t){for(var r=0,e=t.data.length,n=0;n=0;){for(var n=e[0],o=0;o0){var o=new Uint8Array(this.degree);return o.set(e,n),o}return e};var L=T,b=function(t){return!isNaN(t)&&t>=1&&t<=40},U="(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+",x="(?:(?![A-Z0-9 $%*+\\-./:]|"+(U=U.replace(/u/g,"\\u"))+")(?:.|[\r\n]))+",k=new RegExp(U,"g"),F=new RegExp("[^A-Z0-9 $%*+\\-./:]+","g"),S=new RegExp(x,"g"),D=new RegExp("[0-9]+","g"),Y=new RegExp("[A-Z $%*+\\-./:]+","g"),_=new RegExp("^"+U+"$"),z=new RegExp("^[0-9]+$"),H=new RegExp("^[A-Z0-9 $%*+\\-./:]+$"),J={KANJI:k,BYTE_KANJI:F,BYTE:S,NUMERIC:D,ALPHANUMERIC:Y,testKanji:function(t){return _.test(t)},testNumeric:function(t){return z.test(t)},testAlphanumeric:function(t){return H.test(t)}},K=h((function(t,r){r.NUMERIC={id:"Numeric",bit:1,ccBits:[10,12,14]},r.ALPHANUMERIC={id:"Alphanumeric",bit:2,ccBits:[9,11,13]},r.BYTE={id:"Byte",bit:4,ccBits:[8,16,16]},r.KANJI={id:"Kanji",bit:8,ccBits:[8,10,12]},r.MIXED={bit:-1},r.getCharCountIndicator=function(t,r){if(!t.ccBits)throw new Error("Invalid mode: "+t);if(!b(r))throw new Error("Invalid version: "+r);return r>=1&&r<10?t.ccBits[0]:r<27?t.ccBits[1]:t.ccBits[2]},r.getBestModeForData=function(t){return J.testNumeric(t)?r.NUMERIC:J.testAlphanumeric(t)?r.ALPHANUMERIC:J.testKanji(t)?r.KANJI:r.BYTE},r.toString=function(t){if(t&&t.id)return t.id;throw new Error("Invalid mode")},r.isValid=function(t){return t&&t.bit&&t.ccBits},r.from=function(t,e){if(r.isValid(t))return t;try{return function(t){if("string"!=typeof t)throw new Error("Param is not a string");switch(t.toLowerCase()){case"numeric":return r.NUMERIC;case"alphanumeric":return r.ALPHANUMERIC;case"kanji":return r.KANJI;case"byte":return r.BYTE;default:throw new Error("Unknown mode: "+t)}}(t)}catch(t){return e}}}));K.NUMERIC,K.ALPHANUMERIC,K.BYTE,K.KANJI,K.MIXED,K.getCharCountIndicator,K.getBestModeForData,K.isValid;var O=h((function(t,r){var e=i(7973);function n(t,r){return K.getCharCountIndicator(t,r)+4}function o(t,r){var e=0;return t.forEach((function(t){var o=n(t.mode,r);e+=o+t.getBitsLength()})),e}r.from=function(t,r){return b(t)?parseInt(t,10):r},r.getCapacity=function(t,r,e){if(!b(t))throw new Error("Invalid QR Code version");void 0===e&&(e=K.BYTE);var o=8*(a(t)-M(t,r));if(e===K.MIXED)return o;var i=o-n(e,t);switch(e){case K.NUMERIC:return Math.floor(i/10*3);case K.ALPHANUMERIC:return Math.floor(i/11*2);case K.KANJI:return Math.floor(i/13);case K.BYTE:default:return Math.floor(i/8)}},r.getBestVersionForData=function(t,e){var n,a=c.from(e,c.M);if(Array.isArray(t)){if(t.length>1)return function(t,e){for(var n=1;n<=40;n++){if(o(t,n)<=r.getCapacity(n,e,K.MIXED))return n}}(t,a);if(0===t.length)return 1;n=t[0]}else n=t;return function(t,e,n){for(var o=1;o<=40;o++)if(e<=r.getCapacity(o,n,t))return o}(n.mode,n.getLength(),a)},r.getEncodedBits=function(t){if(!b(t)||t<7)throw new Error("Invalid QR Code version");for(var r=t<<12;i(r)-e>=0;)r^=7973<=0;)n^=1335<0&&(e=this.data.substr(r),n=parseInt(e,10),t.put(n,3*o+1))};var j=q,$=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","$","%","*","+","-",".","/",":"];function X(t){this.mode=K.ALPHANUMERIC,this.data=t}X.getBitsLength=function(t){return 11*Math.floor(t/2)+t%2*6},X.prototype.getLength=function(){return this.data.length},X.prototype.getBitsLength=function(){return X.getBitsLength(this.data.length)},X.prototype.write=function(t){var r;for(r=0;r+2<=this.data.length;r+=2){var e=45*$.indexOf(this.data[r]);e+=$.indexOf(this.data[r+1]),t.put(e,11)}this.data.length%2&&t.put($.indexOf(this.data[r]),6)};var Z=X;function W(t){this.mode=K.BYTE,this.data=new Uint8Array(function(t){for(var r=[],e=t.length,n=0;n=55296&&o<=56319&&e>n+1){var a=t.charCodeAt(n+1);a>=56320&&a<=57343&&(o=1024*(o-55296)+a-56320+65536,n+=1)}o<128?r.push(o):o<2048?(r.push(o>>6|192),r.push(63&o|128)):o<55296||o>=57344&&o<65536?(r.push(o>>12|224),r.push(o>>6&63|128),r.push(63&o|128)):o>=65536&&o<=1114111?(r.push(o>>18|240),r.push(o>>12&63|128),r.push(o>>6&63|128),r.push(63&o|128)):r.push(239,191,189)}return new Uint8Array(r).buffer}(t))}W.getBitsLength=function(t){return 8*t},W.prototype.getLength=function(){return this.data.length},W.prototype.getBitsLength=function(){return W.getBitsLength(this.data.length)},W.prototype.write=function(t){for(var r=0,e=this.data.length;r=33088&&e<=40956)e-=33088;else{if(!(e>=57408&&e<=60351))throw new Error("Invalid SJIS character: "+this.data[r]+"\nMake sure your charset is UTF-8");e-=49472}e=192*(e>>>8&255)+(255&e),t.put(e,13)}};var rt=tt,et=h((function(t){var r={single_source_shortest_paths:function(t,e,n){var o={},a={};a[e]=0;var i,u,s,f,h,c,g,d=r.PriorityQueue.make();for(d.push(e,0);!d.empty();)for(s in u=(i=d.pop()).value,f=i.cost,h=t[u]||{})h.hasOwnProperty(s)&&(c=f+h[s],g=a[s],(void 0===a[s]||g>c)&&(a[s]=c,d.push(s,c),o[s]=u));if(void 0!==n&&void 0===a[n]){var l=["Could not find a path from ",e," to ",n,"."].join("");throw new Error(l)}return o},extract_shortest_path_from_predecessor_list:function(t,r){for(var e=[],n=r;n;)e.push(n),n=t[n];return e.reverse(),e},find_path:function(t,e,n){var o=r.single_source_shortest_paths(t,e,n);return r.extract_shortest_path_from_predecessor_list(o,n)},PriorityQueue:{make:function(t){var e,n=r.PriorityQueue,o={};for(e in t=t||{},n)n.hasOwnProperty(e)&&(o[e]=n[e]);return o.queue=[],o.sorter=t.sorter||n.default_sorter,o},default_sorter:function(t,r){return t.cost-r.cost},push:function(t,r){var e={value:t,cost:r};this.queue.push(e),this.queue.sort(this.sorter)},pop:function(){return this.queue.shift()},empty:function(){return 0===this.queue.length}}};t.exports=r})),nt=h((function(t,r){function e(t){return unescape(encodeURIComponent(t)).length}function n(t,r,e){for(var n,o=[];null!==(n=t.exec(e));)o.push({data:n[0],index:n.index,mode:r,length:n[0].length});return o}function o(t){var r,e,o=n(J.NUMERIC,K.NUMERIC,t),a=n(J.ALPHANUMERIC,K.ALPHANUMERIC,t);return s()?(r=n(J.BYTE,K.BYTE,t),e=n(J.KANJI,K.KANJI,t)):(r=n(J.BYTE_KANJI,K.BYTE,t),e=[]),o.concat(a,r,e).sort((function(t,r){return t.index-r.index})).map((function(t){return{data:t.data,mode:t.mode,length:t.length}}))}function a(t,r){switch(r){case K.NUMERIC:return j.getBitsLength(t);case K.ALPHANUMERIC:return Z.getBitsLength(t);case K.KANJI:return rt.getBitsLength(t);case K.BYTE:return G.getBitsLength(t)}}function i(t,r){var e,n=K.getBestModeForData(t);if((e=K.from(r,n))!==K.BYTE&&e.bit=0?t[t.length-1]:null;return e&&e.mode===r.mode?(t[t.length-1].data+=r.data,t):(t.push(r),t)}),[])}(s))},r.rawSplit=function(t){return r.fromArray(o(t))}}));function ot(t,r,e){var n,o,a=t.size,i=V(r,e);for(n=0;n<15;n++)o=1==(i>>n&1),n<6?t.set(n,8,o,!0):n<8?t.set(n+1,8,o,!0):t.set(a-15+n,8,o,!0),n<8?t.set(8,a-n-1,o,!0):n<9?t.set(8,15-n-1+1,o,!0):t.set(8,15-n-1,o,!0);t.set(a-8,8,1,!0)}function at(t,r,e){var n=new d;e.forEach((function(r){n.put(r.mode.bit,4),n.put(r.getLength(),K.getCharCountIndicator(r.mode,t)),r.write(n)}));var o=8*(a(t)-M(t,r));for(n.getLengthInBits()+4<=o&&n.put(0,4);n.getLengthInBits()%8!=0;)n.putBit(0);for(var i=(o-n.getLengthInBits())/8,u=0;u=0&&u<=6&&(0===s||6===s)||s>=0&&s<=6&&(0===u||6===u)||u>=2&&u<=4&&s>=2&&s<=4?t.set(a+u,i+s,!0,!0):t.set(a+u,i+s,!1,!0))}(c,r),function(t){for(var r=t.size,e=8;e=7&&function(t,r){for(var e,n,o,a=t.size,i=O.getEncodedBits(r),u=0;u<18;u++)e=Math.floor(u/3),n=u%3+a-8-3,o=1==(i>>u&1),t.set(e,n,o,!0),t.set(n,e,o,!0)}(c,r),function(t,r){for(var e=t.size,n=-1,o=e-1,a=7,i=0,u=e-1;u>0;u-=2)for(6===u&&u--;;){for(var s=0;s<2;s++)if(!t.isReserved(o,u-s)){var f=!1;i>>a&1)),t.set(o,u-s,f),-1===--a&&(i++,a=7)}if((o+=n)<0||e<=o){o-=n,n=-n;break}}}(c,f),isNaN(n)&&(n=E.getBestMask(c,ot.bind(null,c,e))),E.applyMask(n,c),ot(c,e,n),{modules:c,version:r,errorCorrectionLevel:e,maskPattern:n,segments:a}}nt.fromArray,nt.fromString,nt.rawSplit;var ut=function(t,r){if(void 0===t||""===t)throw new Error("No input text");var e,n,o=c.M;return void 0!==r&&(o=c.from(r.errorCorrectionLevel,c.M),e=O.from(r.version),n=E.from(r.maskPattern),r.toSJISFunc&&u(r.toSJISFunc)),it(t,e,o,n)},st=h((function(t,r){function e(t){if("number"==typeof t&&(t=t.toString()),"string"!=typeof t)throw new Error("Color should be defined as hex string");var r=t.slice().replace("#","").split("");if(r.length<3||5===r.length||r.length>8)throw new Error("Invalid hex color: "+t);3!==r.length&&4!==r.length||(r=Array.prototype.concat.apply([],r.map((function(t){return[t,t]})))),6===r.length&&r.push("F","F");var e=parseInt(r.join(""),16);return{r:e>>24&255,g:e>>16&255,b:e>>8&255,a:255&e,hex:"#"+r.slice(0,6).join("")}}r.getOptions=function(t){t||(t={}),t.color||(t.color={});var r=void 0===t.margin||null===t.margin||t.margin<0?4:t.margin,n=t.width&&t.width>=21?t.width:void 0,o=t.scale||4;return{width:n,scale:n?4:o,margin:r,color:{dark:e(t.color.dark||"#000000ff"),light:e(t.color.light||"#ffffffff")},type:t.type,rendererOpts:t.rendererOpts||{}}},r.getScale=function(t,r){return r.width&&r.width>=t+2*r.margin?r.width/(t+2*r.margin):r.scale},r.getImageWidth=function(t,e){var n=r.getScale(t,e);return Math.floor((t+2*e.margin)*n)},r.qrToImageData=function(t,e,n){for(var o=e.modules.size,a=e.modules.data,i=r.getScale(o,n),u=Math.floor((o+2*n.margin)*i),s=n.margin*i,f=[n.color.light,n.color.dark],h=0;h=s&&c>=s&&h':"",s="0&&s>0&&t[u-1]||(n+=a?ct("M",s+e,.5+f+e):ct("m",o,0),o=0,a=!1),s+1',f='viewBox="0 0 '+i+" "+i+'"',h=''+u+s+"\n";return"function"==typeof e&&e(null,h),h};function dt(t,r,n,o,a){var i=[].slice.call(arguments,1),u=i.length,s="function"==typeof i[u-1];if(!s&&!e())throw new Error("Callback required as last argument");if(!s){if(u<1)throw new Error("Too few arguments provided");return 1===u?(n=r,r=o=void 0):2!==u||r.getContext||(o=n,n=r,r=void 0),new Promise((function(e,a){try{var i=ut(n,o);e(t(i,r,o))}catch(t){a(t)}}))}if(u<2)throw new Error("Too few arguments provided");2===u?(a=n,n=r,r=o=void 0):3===u&&(r.getContext&&void 0===a?(a=o,o=void 0):(a=o,o=n,n=r,r=void 0));try{var f=ut(n,o);a(null,t(f,r,o))}catch(t){a(t)}}var lt=ut,vt=dt.bind(null,ft.render),pt=dt.bind(null,ft.renderToDataURL),wt=dt.bind(null,(function(t,r,e){return gt(t,e)})),mt={create:lt,toCanvas:vt,toDataURL:pt,toString:wt};return t.create=lt,t.default=mt,t.toCanvas=vt,t.toDataURL=pt,t.toString=wt,Object.defineProperty(t,"__esModule",{value:!0}),t}({}); diff --git a/public/js/select2.min.js b/public/js/select2.min.js new file mode 100644 index 0000000..2f06127 --- /dev/null +++ b/public/js/select2.min.js @@ -0,0 +1,4033 @@ +/*! Select2 4.1.0-rc.0 | https://github.com/select2/select2/blob/master/LICENSE.md */ +!(function (n) { + 'function' == typeof define && define.amd + ? define(['jquery'], n) + : 'object' == typeof module && module.exports + ? (module.exports = function (e, t) { + return ( + void 0 === t && + (t = + 'undefined' != typeof window + ? require('jquery') + : require('jquery')(e)), + n(t), + t + ); + }) + : n(jQuery); + })(function (t) { + var e, + n, + s, + p, + r, + o, + h, + f, + g, + m, + y, + v, + i, + a, + _, + s = + (t && t.fn && t.fn.select2 && t.fn.select2.amd && (u = t.fn.select2.amd), + (u && u.requirejs) || + (u ? (n = u) : (u = {}), + (g = {}), + (m = {}), + (y = {}), + (v = {}), + (i = Object.prototype.hasOwnProperty), + (a = [].slice), + (_ = /\.js$/), + (h = function (e, t) { + var n, + s, + i = c(e), + r = i[0], + t = t[1]; + return ( + (e = i[1]), + r && (n = x((r = l(r, t)))), + r + ? (e = + n && n.normalize + ? n.normalize( + e, + ((s = t), + function (e) { + return l(e, s); + }), + ) + : l(e, t)) + : ((r = (i = c((e = l(e, t))))[0]), (e = i[1]), r && (n = x(r))), + { f: r ? r + '!' + e : e, n: e, pr: r, p: n } + ); + }), + (f = { + require: function (e) { + return w(e); + }, + exports: function (e) { + var t = g[e]; + return void 0 !== t ? t : (g[e] = {}); + }, + module: function (e) { + return { + id: e, + uri: '', + exports: g[e], + config: + ((t = e), + function () { + return (y && y.config && y.config[t]) || {}; + }), + }; + var t; + }, + }), + (r = function (e, t, n, s) { + var i, + r, + o, + a, + l, + c = [], + u = typeof n, + d = A((s = s || e)); + if ('undefined' == u || 'function' == u) { + for ( + t = !t.length && n.length ? ['require', 'exports', 'module'] : t, + a = 0; + a < t.length; + a += 1 + ) + if ('require' === (r = (o = h(t[a], d)).f)) c[a] = f.require(e); + else if ('exports' === r) (c[a] = f.exports(e)), (l = !0); + else if ('module' === r) i = c[a] = f.module(e); + else if (b(g, r) || b(m, r) || b(v, r)) c[a] = x(r); + else { + if (!o.p) throw new Error(e + ' missing ' + r); + o.p.load( + o.n, + w(s, !0), + (function (t) { + return function (e) { + g[t] = e; + }; + })(r), + {}, + ), + (c[a] = g[r]); + } + (u = n ? n.apply(g[e], c) : void 0), + e && + (i && i.exports !== p && i.exports !== g[e] + ? (g[e] = i.exports) + : (u === p && l) || (g[e] = u)); + } else e && (g[e] = n); + }), + (e = n = o = function (e, t, n, s, i) { + if ('string' == typeof e) return f[e] ? f[e](t) : x(h(e, A(t)).f); + if (!e.splice) { + if (((y = e).deps && o(y.deps, y.callback), !t)) return; + t.splice ? ((e = t), (t = n), (n = null)) : (e = p); + } + return ( + (t = t || function () {}), + 'function' == typeof n && ((n = s), (s = i)), + s + ? r(p, e, t, n) + : setTimeout(function () { + r(p, e, t, n); + }, 4), + o + ); + }), + (o.config = function (e) { + return o(e); + }), + (e._defined = g), + ((s = function (e, t, n) { + if ('string' != typeof e) + throw new Error( + 'See almond README: incorrect module build, no module name', + ); + t.splice || ((n = t), (t = [])), + b(g, e) || b(m, e) || (m[e] = [e, t, n]); + }).amd = { jQuery: !0 }), + (u.requirejs = e), + (u.require = n), + (u.define = s)), + u.define('almond', function () {}), + u.define('jquery', [], function () { + var e = t || $; + return ( + null == e && + console && + console.error && + console.error( + 'Select2: An instance of jQuery or a jQuery-compatible library was not found. Make sure that you are including jQuery before Select2 on your web page.', + ), + e + ); + }), + u.define('select2/utils', ['jquery'], function (r) { + var s = {}; + function c(e) { + var t, + n = e.prototype, + s = []; + for (t in n) + 'function' == typeof n[t] && 'constructor' !== t && s.push(t); + return s; + } + (s.Extend = function (e, t) { + var n, + s = {}.hasOwnProperty; + function i() { + this.constructor = e; + } + for (n in t) s.call(t, n) && (e[n] = t[n]); + return ( + (i.prototype = t.prototype), + (e.prototype = new i()), + (e.__super__ = t.prototype), + e + ); + }), + (s.Decorate = function (s, i) { + var e = c(i), + t = c(s); + function r() { + var e = Array.prototype.unshift, + t = i.prototype.constructor.length, + n = s.prototype.constructor; + 0 < t && + (e.call(arguments, s.prototype.constructor), + (n = i.prototype.constructor)), + n.apply(this, arguments); + } + (i.displayName = s.displayName), + (r.prototype = new (function () { + this.constructor = r; + })()); + for (var n = 0; n < t.length; n++) { + var o = t[n]; + r.prototype[o] = s.prototype[o]; + } + for (var a = 0; a < e.length; a++) { + var l = e[a]; + r.prototype[l] = (function (e) { + var t = function () {}; + e in r.prototype && (t = r.prototype[e]); + var n = i.prototype[e]; + return function () { + return ( + Array.prototype.unshift.call(arguments, t), + n.apply(this, arguments) + ); + }; + })(l); + } + return r; + }); + function e() { + this.listeners = {}; + } + (e.prototype.on = function (e, t) { + (this.listeners = this.listeners || {}), + e in this.listeners + ? this.listeners[e].push(t) + : (this.listeners[e] = [t]); + }), + (e.prototype.trigger = function (e) { + var t = Array.prototype.slice, + n = t.call(arguments, 1); + (this.listeners = this.listeners || {}), + null == n && (n = []), + 0 === n.length && n.push({}), + (n[0]._type = e) in this.listeners && + this.invoke(this.listeners[e], t.call(arguments, 1)), + '*' in this.listeners && + this.invoke(this.listeners['*'], arguments); + }), + (e.prototype.invoke = function (e, t) { + for (var n = 0, s = e.length; n < s; n++) e[n].apply(this, t); + }), + (s.Observable = e), + (s.generateChars = function (e) { + for (var t = '', n = 0; n < e; n++) + t += Math.floor(36 * Math.random()).toString(36); + return t; + }), + (s.bind = function (e, t) { + return function () { + e.apply(t, arguments); + }; + }), + (s._convertData = function (e) { + for (var t in e) { + var n = t.split('-'), + s = e; + if (1 !== n.length) { + for (var i = 0; i < n.length; i++) { + var r = n[i]; + (r = r.substring(0, 1).toLowerCase() + r.substring(1)) in s || + (s[r] = {}), + i == n.length - 1 && (s[r] = e[t]), + (s = s[r]); + } + delete e[t]; + } + } + return e; + }), + (s.hasScroll = function (e, t) { + var n = r(t), + s = t.style.overflowX, + i = t.style.overflowY; + return ( + (s !== i || ('hidden' !== i && 'visible' !== i)) && + ('scroll' === s || + 'scroll' === i || + n.innerHeight() < t.scrollHeight || + n.innerWidth() < t.scrollWidth) + ); + }), + (s.escapeMarkup = function (e) { + var t = { + '\\': '\', + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/', + }; + return 'string' != typeof e + ? e + : String(e).replace(/[&<>"'\/\\]/g, function (e) { + return t[e]; + }); + }), + (s.__cache = {}); + var n = 0; + return ( + (s.GetUniqueElementId = function (e) { + var t = e.getAttribute('data-select2-id'); + return ( + null != t || + ((t = e.id + ? 'select2-data-' + e.id + : 'select2-data-' + + (++n).toString() + + '-' + + s.generateChars(4)), + e.setAttribute('data-select2-id', t)), + t + ); + }), + (s.StoreData = function (e, t, n) { + e = s.GetUniqueElementId(e); + s.__cache[e] || (s.__cache[e] = {}), (s.__cache[e][t] = n); + }), + (s.GetData = function (e, t) { + var n = s.GetUniqueElementId(e); + return t + ? s.__cache[n] && null != s.__cache[n][t] + ? s.__cache[n][t] + : r(e).data(t) + : s.__cache[n]; + }), + (s.RemoveData = function (e) { + var t = s.GetUniqueElementId(e); + null != s.__cache[t] && delete s.__cache[t], + e.removeAttribute('data-select2-id'); + }), + (s.copyNonInternalCssClasses = function (e, t) { + var n = (n = e.getAttribute('class').trim().split(/\s+/)).filter( + function (e) { + return 0 === e.indexOf('select2-'); + }, + ), + t = (t = t.getAttribute('class').trim().split(/\s+/)).filter( + function (e) { + return 0 !== e.indexOf('select2-'); + }, + ), + t = n.concat(t); + e.setAttribute('class', t.join(' ')); + }), + s + ); + }), + u.define('select2/results', ['jquery', './utils'], function (d, p) { + function s(e, t, n) { + (this.$element = e), + (this.data = n), + (this.options = t), + s.__super__.constructor.call(this); + } + return ( + p.Extend(s, p.Observable), + (s.prototype.render = function () { + var e = d( + '
    ', + ); + return ( + this.options.get('multiple') && + e.attr('aria-multiselectable', 'true'), + (this.$results = e) + ); + }), + (s.prototype.clear = function () { + this.$results.empty(); + }), + (s.prototype.displayMessage = function (e) { + var t = this.options.get('escapeMarkup'); + this.clear(), this.hideLoading(); + var n = d( + '', + ), + s = this.options.get('translations').get(e.message); + n.append(t(s(e.args))), + (n[0].className += ' select2-results__message'), + this.$results.append(n); + }), + (s.prototype.hideMessages = function () { + this.$results.find('.select2-results__message').remove(); + }), + (s.prototype.append = function (e) { + this.hideLoading(); + var t = []; + if (null != e.results && 0 !== e.results.length) { + e.results = this.sort(e.results); + for (var n = 0; n < e.results.length; n++) { + var s = e.results[n], + s = this.option(s); + t.push(s); + } + this.$results.append(t); + } else + 0 === this.$results.children().length && + this.trigger('results:message', { message: 'noResults' }); + }), + (s.prototype.position = function (e, t) { + t.find('.select2-results').append(e); + }), + (s.prototype.sort = function (e) { + return this.options.get('sorter')(e); + }), + (s.prototype.highlightFirstItem = function () { + var e = this.$results.find('.select2-results__option--selectable'), + t = e.filter('.select2-results__option--selected'); + (0 < t.length ? t : e).first().trigger('mouseenter'), + this.ensureHighlightVisible(); + }), + (s.prototype.setClasses = function () { + var t = this; + this.data.current(function (e) { + var s = e.map(function (e) { + return e.id.toString(); + }); + t.$results + .find('.select2-results__option--selectable') + .each(function () { + var e = d(this), + t = p.GetData(this, 'data'), + n = '' + t.id; + (null != t.element && t.element.selected) || + (null == t.element && -1 < s.indexOf(n)) + ? (this.classList.add('select2-results__option--selected'), + e.attr('aria-selected', 'true')) + : (this.classList.remove( + 'select2-results__option--selected', + ), + e.attr('aria-selected', 'false')); + }); + }); + }), + (s.prototype.showLoading = function (e) { + this.hideLoading(); + (e = { + disabled: !0, + loading: !0, + text: this.options.get('translations').get('searching')(e), + }), + (e = this.option(e)); + (e.className += ' loading-results'), this.$results.prepend(e); + }), + (s.prototype.hideLoading = function () { + this.$results.find('.loading-results').remove(); + }), + (s.prototype.option = function (e) { + var t = document.createElement('li'); + t.classList.add('select2-results__option'), + t.classList.add('select2-results__option--selectable'); + var n, + s = { role: 'option' }, + i = + window.Element.prototype.matches || + window.Element.prototype.msMatchesSelector || + window.Element.prototype.webkitMatchesSelector; + for (n in (((null != e.element && i.call(e.element, ':disabled')) || + (null == e.element && e.disabled)) && + ((s['aria-disabled'] = 'true'), + t.classList.remove('select2-results__option--selectable'), + t.classList.add('select2-results__option--disabled')), + null == e.id && + t.classList.remove('select2-results__option--selectable'), + null != e._resultId && (t.id = e._resultId), + e.title && (t.title = e.title), + e.children && + ((s.role = 'group'), + (s['aria-label'] = e.text), + t.classList.remove('select2-results__option--selectable'), + t.classList.add('select2-results__option--group')), + s)) { + var r = s[n]; + t.setAttribute(n, r); + } + if (e.children) { + var o = d(t), + a = document.createElement('strong'); + (a.className = 'select2-results__group'), this.template(e, a); + for (var l = [], c = 0; c < e.children.length; c++) { + var u = e.children[c], + u = this.option(u); + l.push(u); + } + i = d('
      ', { + class: + 'select2-results__options select2-results__options--nested', + role: 'none', + }); + i.append(l), o.append(a), o.append(i); + } else this.template(e, t); + return p.StoreData(t, 'data', e), t; + }), + (s.prototype.bind = function (t, e) { + var i = this, + n = t.id + '-results'; + this.$results.attr('id', n), + t.on('results:all', function (e) { + i.clear(), + i.append(e.data), + t.isOpen() && (i.setClasses(), i.highlightFirstItem()); + }), + t.on('results:append', function (e) { + i.append(e.data), t.isOpen() && i.setClasses(); + }), + t.on('query', function (e) { + i.hideMessages(), i.showLoading(e); + }), + t.on('select', function () { + t.isOpen() && + (i.setClasses(), + i.options.get('scrollAfterSelect') && i.highlightFirstItem()); + }), + t.on('unselect', function () { + t.isOpen() && + (i.setClasses(), + i.options.get('scrollAfterSelect') && i.highlightFirstItem()); + }), + t.on('open', function () { + i.$results.attr('aria-expanded', 'true'), + i.$results.attr('aria-hidden', 'false'), + i.setClasses(), + i.ensureHighlightVisible(); + }), + t.on('close', function () { + i.$results.attr('aria-expanded', 'false'), + i.$results.attr('aria-hidden', 'true'), + i.$results.removeAttr('aria-activedescendant'); + }), + t.on('results:toggle', function () { + var e = i.getHighlightedResults(); + 0 !== e.length && e.trigger('mouseup'); + }), + t.on('results:select', function () { + var e, + t = i.getHighlightedResults(); + 0 !== t.length && + ((e = p.GetData(t[0], 'data')), + t.hasClass('select2-results__option--selected') + ? i.trigger('close', {}) + : i.trigger('select', { data: e })); + }), + t.on('results:previous', function () { + var e, + t = i.getHighlightedResults(), + n = i.$results.find('.select2-results__option--selectable'), + s = n.index(t); + s <= 0 || + ((e = s - 1), + 0 === t.length && (e = 0), + (s = n.eq(e)).trigger('mouseenter'), + (t = i.$results.offset().top), + (n = s.offset().top), + (s = i.$results.scrollTop() + (n - t)), + 0 === e + ? i.$results.scrollTop(0) + : n - t < 0 && i.$results.scrollTop(s)); + }), + t.on('results:next', function () { + var e, + t = i.getHighlightedResults(), + n = i.$results.find('.select2-results__option--selectable'), + s = n.index(t) + 1; + s >= n.length || + ((e = n.eq(s)).trigger('mouseenter'), + (t = i.$results.offset().top + i.$results.outerHeight(!1)), + (n = e.offset().top + e.outerHeight(!1)), + (e = i.$results.scrollTop() + n - t), + 0 === s + ? i.$results.scrollTop(0) + : t < n && i.$results.scrollTop(e)); + }), + t.on('results:focus', function (e) { + e.element[0].classList.add( + 'select2-results__option--highlighted', + ), + e.element[0].setAttribute('aria-selected', 'true'); + }), + t.on('results:message', function (e) { + i.displayMessage(e); + }), + d.fn.mousewheel && + this.$results.on('mousewheel', function (e) { + var t = i.$results.scrollTop(), + n = i.$results.get(0).scrollHeight - t + e.deltaY, + t = 0 < e.deltaY && t - e.deltaY <= 0, + n = e.deltaY < 0 && n <= i.$results.height(); + t + ? (i.$results.scrollTop(0), + e.preventDefault(), + e.stopPropagation()) + : n && + (i.$results.scrollTop( + i.$results.get(0).scrollHeight - i.$results.height(), + ), + e.preventDefault(), + e.stopPropagation()); + }), + this.$results.on( + 'mouseup', + '.select2-results__option--selectable', + function (e) { + var t = d(this), + n = p.GetData(this, 'data'); + t.hasClass('select2-results__option--selected') + ? i.options.get('multiple') + ? i.trigger('unselect', { originalEvent: e, data: n }) + : i.trigger('close', {}) + : i.trigger('select', { originalEvent: e, data: n }); + }, + ), + this.$results.on( + 'mouseenter', + '.select2-results__option--selectable', + function (e) { + var t = p.GetData(this, 'data'); + i + .getHighlightedResults() + .removeClass('select2-results__option--highlighted') + .attr('aria-selected', 'false'), + i.trigger('results:focus', { data: t, element: d(this) }); + }, + ); + }), + (s.prototype.getHighlightedResults = function () { + return this.$results.find('.select2-results__option--highlighted'); + }), + (s.prototype.destroy = function () { + this.$results.remove(); + }), + (s.prototype.ensureHighlightVisible = function () { + var e, + t, + n, + s, + i = this.getHighlightedResults(); + 0 !== i.length && + ((e = this.$results + .find('.select2-results__option--selectable') + .index(i)), + (s = this.$results.offset().top), + (t = i.offset().top), + (n = this.$results.scrollTop() + (t - s)), + (s = t - s), + (n -= 2 * i.outerHeight(!1)), + e <= 2 + ? this.$results.scrollTop(0) + : (s > this.$results.outerHeight() || s < 0) && + this.$results.scrollTop(n)); + }), + (s.prototype.template = function (e, t) { + var n = this.options.get('templateResult'), + s = this.options.get('escapeMarkup'), + e = n(e, t); + null == e + ? (t.style.display = 'none') + : 'string' == typeof e + ? (t.innerHTML = s(e)) + : d(t).append(e); + }), + s + ); + }), + u.define('select2/keys', [], function () { + return { + BACKSPACE: 8, + TAB: 9, + ENTER: 13, + SHIFT: 16, + CTRL: 17, + ALT: 18, + ESC: 27, + SPACE: 32, + PAGE_UP: 33, + PAGE_DOWN: 34, + END: 35, + HOME: 36, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40, + DELETE: 46, + }; + }), + u.define( + 'select2/selection/base', + ['jquery', '../utils', '../keys'], + function (n, s, i) { + function r(e, t) { + (this.$element = e), + (this.options = t), + r.__super__.constructor.call(this); + } + return ( + s.Extend(r, s.Observable), + (r.prototype.render = function () { + var e = n( + '', + ); + return ( + (this._tabindex = 0), + null != s.GetData(this.$element[0], 'old-tabindex') + ? (this._tabindex = s.GetData( + this.$element[0], + 'old-tabindex', + )) + : null != this.$element.attr('tabindex') && + (this._tabindex = this.$element.attr('tabindex')), + e.attr('title', this.$element.attr('title')), + e.attr('tabindex', this._tabindex), + e.attr('aria-disabled', 'false'), + (this.$selection = e) + ); + }), + (r.prototype.bind = function (e, t) { + var n = this, + s = e.id + '-results'; + (this.container = e), + this.$selection.on('focus', function (e) { + n.trigger('focus', e); + }), + this.$selection.on('blur', function (e) { + n._handleBlur(e); + }), + this.$selection.on('keydown', function (e) { + n.trigger('keypress', e), + e.which === i.SPACE && e.preventDefault(); + }), + e.on('results:focus', function (e) { + n.$selection.attr('aria-activedescendant', e.data._resultId); + }), + e.on('selection:update', function (e) { + n.update(e.data); + }), + e.on('open', function () { + n.$selection.attr('aria-expanded', 'true'), + n.$selection.attr('aria-owns', s), + n._attachCloseHandler(e); + }), + e.on('close', function () { + n.$selection.attr('aria-expanded', 'false'), + n.$selection.removeAttr('aria-activedescendant'), + n.$selection.removeAttr('aria-owns'), + n.$selection.trigger('focus'), + n._detachCloseHandler(e); + }), + e.on('enable', function () { + n.$selection.attr('tabindex', n._tabindex), + n.$selection.attr('aria-disabled', 'false'); + }), + e.on('disable', function () { + n.$selection.attr('tabindex', '-1'), + n.$selection.attr('aria-disabled', 'true'); + }); + }), + (r.prototype._handleBlur = function (e) { + var t = this; + window.setTimeout(function () { + document.activeElement == t.$selection[0] || + n.contains(t.$selection[0], document.activeElement) || + t.trigger('blur', e); + }, 1); + }), + (r.prototype._attachCloseHandler = function (e) { + n(document.body).on('mousedown.select2.' + e.id, function (e) { + var t = n(e.target).closest('.select2'); + n('.select2.select2-container--open').each(function () { + this != t[0] && s.GetData(this, 'element').select2('close'); + }); + }); + }), + (r.prototype._detachCloseHandler = function (e) { + n(document.body).off('mousedown.select2.' + e.id); + }), + (r.prototype.position = function (e, t) { + t.find('.selection').append(e); + }), + (r.prototype.destroy = function () { + this._detachCloseHandler(this.container); + }), + (r.prototype.update = function (e) { + throw new Error( + 'The `update` method must be defined in child classes.', + ); + }), + (r.prototype.isEnabled = function () { + return !this.isDisabled(); + }), + (r.prototype.isDisabled = function () { + return this.options.get('disabled'); + }), + r + ); + }, + ), + u.define( + 'select2/selection/single', + ['jquery', './base', '../utils', '../keys'], + function (e, t, n, s) { + function i() { + i.__super__.constructor.apply(this, arguments); + } + return ( + n.Extend(i, t), + (i.prototype.render = function () { + var e = i.__super__.render.call(this); + return ( + e[0].classList.add('select2-selection--single'), + e.html( + '', + ), + e + ); + }), + (i.prototype.bind = function (t, e) { + var n = this; + i.__super__.bind.apply(this, arguments); + var s = t.id + '-container'; + this.$selection + .find('.select2-selection__rendered') + .attr('id', s) + .attr('role', 'textbox') + .attr('aria-readonly', 'true'), + this.$selection.attr('aria-labelledby', s), + this.$selection.attr('aria-controls', s), + this.$selection.on('mousedown', function (e) { + 1 === e.which && n.trigger('toggle', { originalEvent: e }); + }), + this.$selection.on('focus', function (e) {}), + this.$selection.on('blur', function (e) {}), + t.on('focus', function (e) { + t.isOpen() || n.$selection.trigger('focus'); + }); + }), + (i.prototype.clear = function () { + var e = this.$selection.find('.select2-selection__rendered'); + e.empty(), e.removeAttr('title'); + }), + (i.prototype.display = function (e, t) { + var n = this.options.get('templateSelection'); + return this.options.get('escapeMarkup')(n(e, t)); + }), + (i.prototype.selectionContainer = function () { + return e(''); + }), + (i.prototype.update = function (e) { + var t, n; + 0 !== e.length + ? ((n = e[0]), + (t = this.$selection.find('.select2-selection__rendered')), + (e = this.display(n, t)), + t.empty().append(e), + (n = n.title || n.text) + ? t.attr('title', n) + : t.removeAttr('title')) + : this.clear(); + }), + i + ); + }, + ), + u.define( + 'select2/selection/multiple', + ['jquery', './base', '../utils'], + function (i, e, c) { + function r(e, t) { + r.__super__.constructor.apply(this, arguments); + } + return ( + c.Extend(r, e), + (r.prototype.render = function () { + var e = r.__super__.render.call(this); + return ( + e[0].classList.add('select2-selection--multiple'), + e.html('
        '), + e + ); + }), + (r.prototype.bind = function (e, t) { + var n = this; + r.__super__.bind.apply(this, arguments); + var s = e.id + '-container'; + this.$selection + .find('.select2-selection__rendered') + .attr('id', s), + this.$selection.on('click', function (e) { + n.trigger('toggle', { originalEvent: e }); + }), + this.$selection.on( + 'click', + '.select2-selection__choice__remove', + function (e) { + var t; + n.isDisabled() || + ((t = i(this).parent()), + (t = c.GetData(t[0], 'data')), + n.trigger('unselect', { originalEvent: e, data: t })); + }, + ), + this.$selection.on( + 'keydown', + '.select2-selection__choice__remove', + function (e) { + n.isDisabled() || e.stopPropagation(); + }, + ); + }), + (r.prototype.clear = function () { + var e = this.$selection.find('.select2-selection__rendered'); + e.empty(), e.removeAttr('title'); + }), + (r.prototype.display = function (e, t) { + var n = this.options.get('templateSelection'); + return this.options.get('escapeMarkup')(n(e, t)); + }), + (r.prototype.selectionContainer = function () { + return i( + '
      • ', + ); + }), + (r.prototype.update = function (e) { + if ((this.clear(), 0 !== e.length)) { + for ( + var t = [], + n = + this.$selection + .find('.select2-selection__rendered') + .attr('id') + '-choice-', + s = 0; + s < e.length; + s++ + ) { + var i = e[s], + r = this.selectionContainer(), + o = this.display(i, r), + a = n + c.generateChars(4) + '-'; + i.id ? (a += i.id) : (a += c.generateChars(4)), + r + .find('.select2-selection__choice__display') + .append(o) + .attr('id', a); + var l = i.title || i.text; + l && r.attr('title', l); + (o = this.options.get('translations').get('removeItem')), + (l = r.find('.select2-selection__choice__remove')); + l.attr('title', o()), + l.attr('aria-label', o()), + l.attr('aria-describedby', a), + c.StoreData(r[0], 'data', i), + t.push(r); + } + this.$selection.find('.select2-selection__rendered').append(t); + } + }), + r + ); + }, + ), + u.define('select2/selection/placeholder', [], function () { + function e(e, t, n) { + (this.placeholder = this.normalizePlaceholder(n.get('placeholder'))), + e.call(this, t, n); + } + return ( + (e.prototype.normalizePlaceholder = function (e, t) { + return 'string' == typeof t && (t = { id: '', text: t }), t; + }), + (e.prototype.createPlaceholder = function (e, t) { + var n = this.selectionContainer(); + n.html(this.display(t)), + n[0].classList.add('select2-selection__placeholder'), + n[0].classList.remove('select2-selection__choice'); + t = t.title || t.text || n.text(); + return ( + this.$selection + .find('.select2-selection__rendered') + .attr('title', t), + n + ); + }), + (e.prototype.update = function (e, t) { + var n = 1 == t.length && t[0].id != this.placeholder.id; + if (1 < t.length || n) return e.call(this, t); + this.clear(); + t = this.createPlaceholder(this.placeholder); + this.$selection.find('.select2-selection__rendered').append(t); + }), + e + ); + }), + u.define( + 'select2/selection/allowClear', + ['jquery', '../keys', '../utils'], + function (i, s, a) { + function e() {} + return ( + (e.prototype.bind = function (e, t, n) { + var s = this; + e.call(this, t, n), + null == this.placeholder && + this.options.get('debug') && + window.console && + console.error && + console.error( + 'Select2: The `allowClear` option should be used in combination with the `placeholder` option.', + ), + this.$selection.on( + 'mousedown', + '.select2-selection__clear', + function (e) { + s._handleClear(e); + }, + ), + t.on('keypress', function (e) { + s._handleKeyboardClear(e, t); + }); + }), + (e.prototype._handleClear = function (e, t) { + if (!this.isDisabled()) { + var n = this.$selection.find('.select2-selection__clear'); + if (0 !== n.length) { + t.stopPropagation(); + var s = a.GetData(n[0], 'data'), + i = this.$element.val(); + this.$element.val(this.placeholder.id); + var r = { data: s }; + if ((this.trigger('clear', r), r.prevented)) + this.$element.val(i); + else { + for (var o = 0; o < s.length; o++) + if ( + ((r = { data: s[o] }), + this.trigger('unselect', r), + r.prevented) + ) + return void this.$element.val(i); + this.$element.trigger('input').trigger('change'), + this.trigger('toggle', {}); + } + } + } + }), + (e.prototype._handleKeyboardClear = function (e, t, n) { + n.isOpen() || + (t.which != s.DELETE && t.which != s.BACKSPACE) || + this._handleClear(t); + }), + (e.prototype.update = function (e, t) { + var n, s; + e.call(this, t), + this.$selection.find('.select2-selection__clear').remove(), + this.$selection[0].classList.remove( + 'select2-selection--clearable', + ), + 0 < + this.$selection.find('.select2-selection__placeholder') + .length || + 0 === t.length || + ((n = this.$selection + .find('.select2-selection__rendered') + .attr('id')), + (s = this.options.get('translations').get('removeAllItems')), + (e = i( + '', + )).attr('title', s()), + e.attr('aria-label', s()), + e.attr('aria-describedby', n), + a.StoreData(e[0], 'data', t), + this.$selection.prepend(e), + this.$selection[0].classList.add( + 'select2-selection--clearable', + )); + }), + e + ); + }, + ), + u.define( + 'select2/selection/search', + ['jquery', '../utils', '../keys'], + function (s, a, l) { + function e(e, t, n) { + e.call(this, t, n); + } + return ( + (e.prototype.render = function (e) { + var t = this.options.get('translations').get('search'), + n = s( + '', + ); + (this.$searchContainer = n), + (this.$search = n.find('textarea')), + this.$search.prop( + 'autocomplete', + this.options.get('autocomplete'), + ), + this.$search.attr('aria-label', t()); + e = e.call(this); + return ( + this._transferTabIndex(), e.append(this.$searchContainer), e + ); + }), + (e.prototype.bind = function (e, t, n) { + var s = this, + i = t.id + '-results', + r = t.id + '-container'; + e.call(this, t, n), + s.$search.attr('aria-describedby', r), + t.on('open', function () { + s.$search.attr('aria-controls', i), + s.$search.trigger('focus'); + }), + t.on('close', function () { + s.$search.val(''), + s.resizeSearch(), + s.$search.removeAttr('aria-controls'), + s.$search.removeAttr('aria-activedescendant'), + s.$search.trigger('focus'); + }), + t.on('enable', function () { + s.$search.prop('disabled', !1), s._transferTabIndex(); + }), + t.on('disable', function () { + s.$search.prop('disabled', !0); + }), + t.on('focus', function (e) { + s.$search.trigger('focus'); + }), + t.on('results:focus', function (e) { + e.data._resultId + ? s.$search.attr('aria-activedescendant', e.data._resultId) + : s.$search.removeAttr('aria-activedescendant'); + }), + this.$selection.on( + 'focusin', + '.select2-search--inline', + function (e) { + s.trigger('focus', e); + }, + ), + this.$selection.on( + 'focusout', + '.select2-search--inline', + function (e) { + s._handleBlur(e); + }, + ), + this.$selection.on( + 'keydown', + '.select2-search--inline', + function (e) { + var t; + e.stopPropagation(), + s.trigger('keypress', e), + (s._keyUpPrevented = e.isDefaultPrevented()), + e.which !== l.BACKSPACE || + '' !== s.$search.val() || + (0 < + (t = s.$selection + .find('.select2-selection__choice') + .last()).length && + ((t = a.GetData(t[0], 'data')), + s.searchRemoveChoice(t), + e.preventDefault())); + }, + ), + this.$selection.on( + 'click', + '.select2-search--inline', + function (e) { + s.$search.val() && e.stopPropagation(); + }, + ); + var t = document.documentMode, + o = t && t <= 11; + this.$selection.on( + 'input.searchcheck', + '.select2-search--inline', + function (e) { + o + ? s.$selection.off('input.search input.searchcheck') + : s.$selection.off('keyup.search'); + }, + ), + this.$selection.on( + 'keyup.search input.search', + '.select2-search--inline', + function (e) { + var t; + o && 'input' === e.type + ? s.$selection.off('input.search input.searchcheck') + : (t = e.which) != l.SHIFT && + t != l.CTRL && + t != l.ALT && + t != l.TAB && + s.handleSearch(e); + }, + ); + }), + (e.prototype._transferTabIndex = function (e) { + this.$search.attr('tabindex', this.$selection.attr('tabindex')), + this.$selection.attr('tabindex', '-1'); + }), + (e.prototype.createPlaceholder = function (e, t) { + this.$search.attr('placeholder', t.text); + }), + (e.prototype.update = function (e, t) { + var n = this.$search[0] == document.activeElement; + this.$search.attr('placeholder', ''), + e.call(this, t), + this.resizeSearch(), + n && this.$search.trigger('focus'); + }), + (e.prototype.handleSearch = function () { + var e; + this.resizeSearch(), + this._keyUpPrevented || + ((e = this.$search.val()), + this.trigger('query', { term: e })), + (this._keyUpPrevented = !1); + }), + (e.prototype.searchRemoveChoice = function (e, t) { + this.trigger('unselect', { data: t }), + this.$search.val(t.text), + this.handleSearch(); + }), + (e.prototype.resizeSearch = function () { + this.$search.css('width', '25px'); + var e = '100%'; + '' === this.$search.attr('placeholder') && + (e = 0.75 * (this.$search.val().length + 1) + 'em'), + this.$search.css('width', e); + }), + e + ); + }, + ), + u.define('select2/selection/selectionCss', ['../utils'], function (n) { + function e() {} + return ( + (e.prototype.render = function (e) { + var t = e.call(this), + e = this.options.get('selectionCssClass') || ''; + return ( + -1 !== e.indexOf(':all:') && + ((e = e.replace(':all:', '')), + n.copyNonInternalCssClasses(t[0], this.$element[0])), + t.addClass(e), + t + ); + }), + e + ); + }), + u.define('select2/selection/eventRelay', ['jquery'], function (o) { + function e() {} + return ( + (e.prototype.bind = function (e, t, n) { + var s = this, + i = [ + 'open', + 'opening', + 'close', + 'closing', + 'select', + 'selecting', + 'unselect', + 'unselecting', + 'clear', + 'clearing', + ], + r = [ + 'opening', + 'closing', + 'selecting', + 'unselecting', + 'clearing', + ]; + e.call(this, t, n), + t.on('*', function (e, t) { + var n; + -1 !== i.indexOf(e) && + ((t = t || {}), + (n = o.Event('select2:' + e, { params: t })), + s.$element.trigger(n), + -1 !== r.indexOf(e) && + (t.prevented = n.isDefaultPrevented())); + }); + }), + e + ); + }), + u.define('select2/translation', ['jquery', 'require'], function (t, n) { + function s(e) { + this.dict = e || {}; + } + return ( + (s.prototype.all = function () { + return this.dict; + }), + (s.prototype.get = function (e) { + return this.dict[e]; + }), + (s.prototype.extend = function (e) { + this.dict = t.extend({}, e.all(), this.dict); + }), + (s._cache = {}), + (s.loadPath = function (e) { + var t; + return ( + e in s._cache || ((t = n(e)), (s._cache[e] = t)), + new s(s._cache[e]) + ); + }), + s + ); + }), + u.define('select2/diacritics', [], function () { + return { + 'Ⓐ': 'A', + A: 'A', + À: 'A', + Á: 'A', + Â: 'A', + Ầ: 'A', + Ấ: 'A', + Ẫ: 'A', + Ẩ: 'A', + Ã: 'A', + Ā: 'A', + Ă: 'A', + Ằ: 'A', + Ắ: 'A', + Ẵ: 'A', + Ẳ: 'A', + Ȧ: 'A', + Ǡ: 'A', + Ä: 'A', + Ǟ: 'A', + Ả: 'A', + Å: 'A', + Ǻ: 'A', + Ǎ: 'A', + Ȁ: 'A', + Ȃ: 'A', + Ạ: 'A', + Ậ: 'A', + Ặ: 'A', + Ḁ: 'A', + Ą: 'A', + Ⱥ: 'A', + Ɐ: 'A', + Ꜳ: 'AA', + Æ: 'AE', + Ǽ: 'AE', + Ǣ: 'AE', + Ꜵ: 'AO', + Ꜷ: 'AU', + Ꜹ: 'AV', + Ꜻ: 'AV', + Ꜽ: 'AY', + 'Ⓑ': 'B', + B: 'B', + Ḃ: 'B', + Ḅ: 'B', + Ḇ: 'B', + Ƀ: 'B', + Ƃ: 'B', + Ɓ: 'B', + 'Ⓒ': 'C', + C: 'C', + Ć: 'C', + Ĉ: 'C', + Ċ: 'C', + Č: 'C', + Ç: 'C', + Ḉ: 'C', + Ƈ: 'C', + Ȼ: 'C', + Ꜿ: 'C', + 'Ⓓ': 'D', + D: 'D', + Ḋ: 'D', + Ď: 'D', + Ḍ: 'D', + Ḑ: 'D', + Ḓ: 'D', + Ḏ: 'D', + Đ: 'D', + Ƌ: 'D', + Ɗ: 'D', + Ɖ: 'D', + Ꝺ: 'D', + DZ: 'DZ', + DŽ: 'DZ', + Dz: 'Dz', + Dž: 'Dz', + 'Ⓔ': 'E', + E: 'E', + È: 'E', + É: 'E', + Ê: 'E', + Ề: 'E', + Ế: 'E', + Ễ: 'E', + Ể: 'E', + Ẽ: 'E', + Ē: 'E', + Ḕ: 'E', + Ḗ: 'E', + Ĕ: 'E', + Ė: 'E', + Ë: 'E', + Ẻ: 'E', + Ě: 'E', + Ȅ: 'E', + Ȇ: 'E', + Ẹ: 'E', + Ệ: 'E', + Ȩ: 'E', + Ḝ: 'E', + Ę: 'E', + Ḙ: 'E', + Ḛ: 'E', + Ɛ: 'E', + Ǝ: 'E', + 'Ⓕ': 'F', + F: 'F', + Ḟ: 'F', + Ƒ: 'F', + Ꝼ: 'F', + 'Ⓖ': 'G', + G: 'G', + Ǵ: 'G', + Ĝ: 'G', + Ḡ: 'G', + Ğ: 'G', + Ġ: 'G', + Ǧ: 'G', + Ģ: 'G', + Ǥ: 'G', + Ɠ: 'G', + Ꞡ: 'G', + Ᵹ: 'G', + Ꝿ: 'G', + 'Ⓗ': 'H', + H: 'H', + Ĥ: 'H', + Ḣ: 'H', + Ḧ: 'H', + Ȟ: 'H', + Ḥ: 'H', + Ḩ: 'H', + Ḫ: 'H', + Ħ: 'H', + Ⱨ: 'H', + Ⱶ: 'H', + Ɥ: 'H', + 'Ⓘ': 'I', + I: 'I', + Ì: 'I', + Í: 'I', + Î: 'I', + Ĩ: 'I', + Ī: 'I', + Ĭ: 'I', + İ: 'I', + Ï: 'I', + Ḯ: 'I', + Ỉ: 'I', + Ǐ: 'I', + Ȉ: 'I', + Ȋ: 'I', + Ị: 'I', + Į: 'I', + Ḭ: 'I', + Ɨ: 'I', + 'Ⓙ': 'J', + J: 'J', + Ĵ: 'J', + Ɉ: 'J', + 'Ⓚ': 'K', + K: 'K', + Ḱ: 'K', + Ǩ: 'K', + Ḳ: 'K', + Ķ: 'K', + Ḵ: 'K', + Ƙ: 'K', + Ⱪ: 'K', + Ꝁ: 'K', + Ꝃ: 'K', + Ꝅ: 'K', + Ꞣ: 'K', + 'Ⓛ': 'L', + L: 'L', + Ŀ: 'L', + Ĺ: 'L', + Ľ: 'L', + Ḷ: 'L', + Ḹ: 'L', + Ļ: 'L', + Ḽ: 'L', + Ḻ: 'L', + Ł: 'L', + Ƚ: 'L', + Ɫ: 'L', + Ⱡ: 'L', + Ꝉ: 'L', + Ꝇ: 'L', + Ꞁ: 'L', + LJ: 'LJ', + Lj: 'Lj', + 'Ⓜ': 'M', + M: 'M', + Ḿ: 'M', + Ṁ: 'M', + Ṃ: 'M', + Ɱ: 'M', + Ɯ: 'M', + 'Ⓝ': 'N', + N: 'N', + Ǹ: 'N', + Ń: 'N', + Ñ: 'N', + Ṅ: 'N', + Ň: 'N', + Ṇ: 'N', + Ņ: 'N', + Ṋ: 'N', + Ṉ: 'N', + Ƞ: 'N', + Ɲ: 'N', + Ꞑ: 'N', + Ꞥ: 'N', + NJ: 'NJ', + Nj: 'Nj', + 'Ⓞ': 'O', + O: 'O', + Ò: 'O', + Ó: 'O', + Ô: 'O', + Ồ: 'O', + Ố: 'O', + Ỗ: 'O', + Ổ: 'O', + Õ: 'O', + Ṍ: 'O', + Ȭ: 'O', + Ṏ: 'O', + Ō: 'O', + Ṑ: 'O', + Ṓ: 'O', + Ŏ: 'O', + Ȯ: 'O', + Ȱ: 'O', + Ö: 'O', + Ȫ: 'O', + Ỏ: 'O', + Ő: 'O', + Ǒ: 'O', + Ȍ: 'O', + Ȏ: 'O', + Ơ: 'O', + Ờ: 'O', + Ớ: 'O', + Ỡ: 'O', + Ở: 'O', + Ợ: 'O', + Ọ: 'O', + Ộ: 'O', + Ǫ: 'O', + Ǭ: 'O', + Ø: 'O', + Ǿ: 'O', + Ɔ: 'O', + Ɵ: 'O', + Ꝋ: 'O', + Ꝍ: 'O', + Œ: 'OE', + Ƣ: 'OI', + Ꝏ: 'OO', + Ȣ: 'OU', + 'Ⓟ': 'P', + P: 'P', + Ṕ: 'P', + Ṗ: 'P', + Ƥ: 'P', + Ᵽ: 'P', + Ꝑ: 'P', + Ꝓ: 'P', + Ꝕ: 'P', + 'Ⓠ': 'Q', + Q: 'Q', + Ꝗ: 'Q', + Ꝙ: 'Q', + Ɋ: 'Q', + 'Ⓡ': 'R', + R: 'R', + Ŕ: 'R', + Ṙ: 'R', + Ř: 'R', + Ȑ: 'R', + Ȓ: 'R', + Ṛ: 'R', + Ṝ: 'R', + Ŗ: 'R', + Ṟ: 'R', + Ɍ: 'R', + Ɽ: 'R', + Ꝛ: 'R', + Ꞧ: 'R', + Ꞃ: 'R', + 'Ⓢ': 'S', + S: 'S', + ẞ: 'S', + Ś: 'S', + Ṥ: 'S', + Ŝ: 'S', + Ṡ: 'S', + Š: 'S', + Ṧ: 'S', + Ṣ: 'S', + Ṩ: 'S', + Ș: 'S', + Ş: 'S', + Ȿ: 'S', + Ꞩ: 'S', + Ꞅ: 'S', + 'Ⓣ': 'T', + T: 'T', + Ṫ: 'T', + Ť: 'T', + Ṭ: 'T', + Ț: 'T', + Ţ: 'T', + Ṱ: 'T', + Ṯ: 'T', + Ŧ: 'T', + Ƭ: 'T', + Ʈ: 'T', + Ⱦ: 'T', + Ꞇ: 'T', + Ꜩ: 'TZ', + 'Ⓤ': 'U', + U: 'U', + Ù: 'U', + Ú: 'U', + Û: 'U', + Ũ: 'U', + Ṹ: 'U', + Ū: 'U', + Ṻ: 'U', + Ŭ: 'U', + Ü: 'U', + Ǜ: 'U', + Ǘ: 'U', + Ǖ: 'U', + Ǚ: 'U', + Ủ: 'U', + Ů: 'U', + Ű: 'U', + Ǔ: 'U', + Ȕ: 'U', + Ȗ: 'U', + Ư: 'U', + Ừ: 'U', + Ứ: 'U', + Ữ: 'U', + Ử: 'U', + Ự: 'U', + Ụ: 'U', + Ṳ: 'U', + Ų: 'U', + Ṷ: 'U', + Ṵ: 'U', + Ʉ: 'U', + 'Ⓥ': 'V', + V: 'V', + Ṽ: 'V', + Ṿ: 'V', + Ʋ: 'V', + Ꝟ: 'V', + Ʌ: 'V', + Ꝡ: 'VY', + 'Ⓦ': 'W', + W: 'W', + Ẁ: 'W', + Ẃ: 'W', + Ŵ: 'W', + Ẇ: 'W', + Ẅ: 'W', + Ẉ: 'W', + Ⱳ: 'W', + 'Ⓧ': 'X', + X: 'X', + Ẋ: 'X', + Ẍ: 'X', + 'Ⓨ': 'Y', + Y: 'Y', + Ỳ: 'Y', + Ý: 'Y', + Ŷ: 'Y', + Ỹ: 'Y', + Ȳ: 'Y', + Ẏ: 'Y', + Ÿ: 'Y', + Ỷ: 'Y', + Ỵ: 'Y', + Ƴ: 'Y', + Ɏ: 'Y', + Ỿ: 'Y', + 'Ⓩ': 'Z', + Z: 'Z', + Ź: 'Z', + Ẑ: 'Z', + Ż: 'Z', + Ž: 'Z', + Ẓ: 'Z', + Ẕ: 'Z', + Ƶ: 'Z', + Ȥ: 'Z', + Ɀ: 'Z', + Ⱬ: 'Z', + Ꝣ: 'Z', + 'ⓐ': 'a', + a: 'a', + ẚ: 'a', + à: 'a', + á: 'a', + â: 'a', + ầ: 'a', + ấ: 'a', + ẫ: 'a', + ẩ: 'a', + ã: 'a', + ā: 'a', + ă: 'a', + ằ: 'a', + ắ: 'a', + ẵ: 'a', + ẳ: 'a', + ȧ: 'a', + ǡ: 'a', + ä: 'a', + ǟ: 'a', + ả: 'a', + å: 'a', + ǻ: 'a', + ǎ: 'a', + ȁ: 'a', + ȃ: 'a', + ạ: 'a', + ậ: 'a', + ặ: 'a', + ḁ: 'a', + ą: 'a', + ⱥ: 'a', + ɐ: 'a', + ꜳ: 'aa', + æ: 'ae', + ǽ: 'ae', + ǣ: 'ae', + ꜵ: 'ao', + ꜷ: 'au', + ꜹ: 'av', + ꜻ: 'av', + ꜽ: 'ay', + 'ⓑ': 'b', + b: 'b', + ḃ: 'b', + ḅ: 'b', + ḇ: 'b', + ƀ: 'b', + ƃ: 'b', + ɓ: 'b', + 'ⓒ': 'c', + c: 'c', + ć: 'c', + ĉ: 'c', + ċ: 'c', + č: 'c', + ç: 'c', + ḉ: 'c', + ƈ: 'c', + ȼ: 'c', + ꜿ: 'c', + ↄ: 'c', + 'ⓓ': 'd', + d: 'd', + ḋ: 'd', + ď: 'd', + ḍ: 'd', + ḑ: 'd', + ḓ: 'd', + ḏ: 'd', + đ: 'd', + ƌ: 'd', + ɖ: 'd', + ɗ: 'd', + ꝺ: 'd', + dz: 'dz', + dž: 'dz', + 'ⓔ': 'e', + e: 'e', + è: 'e', + é: 'e', + ê: 'e', + ề: 'e', + ế: 'e', + ễ: 'e', + ể: 'e', + ẽ: 'e', + ē: 'e', + ḕ: 'e', + ḗ: 'e', + ĕ: 'e', + ė: 'e', + ë: 'e', + ẻ: 'e', + ě: 'e', + ȅ: 'e', + ȇ: 'e', + ẹ: 'e', + ệ: 'e', + ȩ: 'e', + ḝ: 'e', + ę: 'e', + ḙ: 'e', + ḛ: 'e', + ɇ: 'e', + ɛ: 'e', + ǝ: 'e', + 'ⓕ': 'f', + f: 'f', + ḟ: 'f', + ƒ: 'f', + ꝼ: 'f', + 'ⓖ': 'g', + g: 'g', + ǵ: 'g', + ĝ: 'g', + ḡ: 'g', + ğ: 'g', + ġ: 'g', + ǧ: 'g', + ģ: 'g', + ǥ: 'g', + ɠ: 'g', + ꞡ: 'g', + ᵹ: 'g', + ꝿ: 'g', + 'ⓗ': 'h', + h: 'h', + ĥ: 'h', + ḣ: 'h', + ḧ: 'h', + ȟ: 'h', + ḥ: 'h', + ḩ: 'h', + ḫ: 'h', + ẖ: 'h', + ħ: 'h', + ⱨ: 'h', + ⱶ: 'h', + ɥ: 'h', + ƕ: 'hv', + 'ⓘ': 'i', + i: 'i', + ì: 'i', + í: 'i', + î: 'i', + ĩ: 'i', + ī: 'i', + ĭ: 'i', + ï: 'i', + ḯ: 'i', + ỉ: 'i', + ǐ: 'i', + ȉ: 'i', + ȋ: 'i', + ị: 'i', + į: 'i', + ḭ: 'i', + ɨ: 'i', + ı: 'i', + 'ⓙ': 'j', + j: 'j', + ĵ: 'j', + ǰ: 'j', + ɉ: 'j', + 'ⓚ': 'k', + k: 'k', + ḱ: 'k', + ǩ: 'k', + ḳ: 'k', + ķ: 'k', + ḵ: 'k', + ƙ: 'k', + ⱪ: 'k', + ꝁ: 'k', + ꝃ: 'k', + ꝅ: 'k', + ꞣ: 'k', + 'ⓛ': 'l', + l: 'l', + ŀ: 'l', + ĺ: 'l', + ľ: 'l', + ḷ: 'l', + ḹ: 'l', + ļ: 'l', + ḽ: 'l', + ḻ: 'l', + ſ: 'l', + ł: 'l', + ƚ: 'l', + ɫ: 'l', + ⱡ: 'l', + ꝉ: 'l', + ꞁ: 'l', + ꝇ: 'l', + lj: 'lj', + 'ⓜ': 'm', + m: 'm', + ḿ: 'm', + ṁ: 'm', + ṃ: 'm', + ɱ: 'm', + ɯ: 'm', + 'ⓝ': 'n', + n: 'n', + ǹ: 'n', + ń: 'n', + ñ: 'n', + ṅ: 'n', + ň: 'n', + ṇ: 'n', + ņ: 'n', + ṋ: 'n', + ṉ: 'n', + ƞ: 'n', + ɲ: 'n', + ʼn: 'n', + ꞑ: 'n', + ꞥ: 'n', + nj: 'nj', + 'ⓞ': 'o', + o: 'o', + ò: 'o', + ó: 'o', + ô: 'o', + ồ: 'o', + ố: 'o', + ỗ: 'o', + ổ: 'o', + õ: 'o', + ṍ: 'o', + ȭ: 'o', + ṏ: 'o', + ō: 'o', + ṑ: 'o', + ṓ: 'o', + ŏ: 'o', + ȯ: 'o', + ȱ: 'o', + ö: 'o', + ȫ: 'o', + ỏ: 'o', + ő: 'o', + ǒ: 'o', + ȍ: 'o', + ȏ: 'o', + ơ: 'o', + ờ: 'o', + ớ: 'o', + ỡ: 'o', + ở: 'o', + ợ: 'o', + ọ: 'o', + ộ: 'o', + ǫ: 'o', + ǭ: 'o', + ø: 'o', + ǿ: 'o', + ɔ: 'o', + ꝋ: 'o', + ꝍ: 'o', + ɵ: 'o', + œ: 'oe', + ƣ: 'oi', + ȣ: 'ou', + ꝏ: 'oo', + 'ⓟ': 'p', + p: 'p', + ṕ: 'p', + ṗ: 'p', + ƥ: 'p', + ᵽ: 'p', + ꝑ: 'p', + ꝓ: 'p', + ꝕ: 'p', + 'ⓠ': 'q', + q: 'q', + ɋ: 'q', + ꝗ: 'q', + ꝙ: 'q', + 'ⓡ': 'r', + r: 'r', + ŕ: 'r', + ṙ: 'r', + ř: 'r', + ȑ: 'r', + ȓ: 'r', + ṛ: 'r', + ṝ: 'r', + ŗ: 'r', + ṟ: 'r', + ɍ: 'r', + ɽ: 'r', + ꝛ: 'r', + ꞧ: 'r', + ꞃ: 'r', + 'ⓢ': 's', + s: 's', + ß: 's', + ś: 's', + ṥ: 's', + ŝ: 's', + ṡ: 's', + š: 's', + ṧ: 's', + ṣ: 's', + ṩ: 's', + ș: 's', + ş: 's', + ȿ: 's', + ꞩ: 's', + ꞅ: 's', + ẛ: 's', + 'ⓣ': 't', + t: 't', + ṫ: 't', + ẗ: 't', + ť: 't', + ṭ: 't', + ț: 't', + ţ: 't', + ṱ: 't', + ṯ: 't', + ŧ: 't', + ƭ: 't', + ʈ: 't', + ⱦ: 't', + ꞇ: 't', + ꜩ: 'tz', + 'ⓤ': 'u', + u: 'u', + ù: 'u', + ú: 'u', + û: 'u', + ũ: 'u', + ṹ: 'u', + ū: 'u', + ṻ: 'u', + ŭ: 'u', + ü: 'u', + ǜ: 'u', + ǘ: 'u', + ǖ: 'u', + ǚ: 'u', + ủ: 'u', + ů: 'u', + ű: 'u', + ǔ: 'u', + ȕ: 'u', + ȗ: 'u', + ư: 'u', + ừ: 'u', + ứ: 'u', + ữ: 'u', + ử: 'u', + ự: 'u', + ụ: 'u', + ṳ: 'u', + ų: 'u', + ṷ: 'u', + ṵ: 'u', + ʉ: 'u', + 'ⓥ': 'v', + v: 'v', + ṽ: 'v', + ṿ: 'v', + ʋ: 'v', + ꝟ: 'v', + ʌ: 'v', + ꝡ: 'vy', + 'ⓦ': 'w', + w: 'w', + ẁ: 'w', + ẃ: 'w', + ŵ: 'w', + ẇ: 'w', + ẅ: 'w', + ẘ: 'w', + ẉ: 'w', + ⱳ: 'w', + 'ⓧ': 'x', + x: 'x', + ẋ: 'x', + ẍ: 'x', + 'ⓨ': 'y', + y: 'y', + ỳ: 'y', + ý: 'y', + ŷ: 'y', + ỹ: 'y', + ȳ: 'y', + ẏ: 'y', + ÿ: 'y', + ỷ: 'y', + ẙ: 'y', + ỵ: 'y', + ƴ: 'y', + ɏ: 'y', + ỿ: 'y', + 'ⓩ': 'z', + z: 'z', + ź: 'z', + ẑ: 'z', + ż: 'z', + ž: 'z', + ẓ: 'z', + ẕ: 'z', + ƶ: 'z', + ȥ: 'z', + ɀ: 'z', + ⱬ: 'z', + ꝣ: 'z', + Ά: 'Α', + Έ: 'Ε', + Ή: 'Η', + Ί: 'Ι', + Ϊ: 'Ι', + Ό: 'Ο', + Ύ: 'Υ', + Ϋ: 'Υ', + Ώ: 'Ω', + ά: 'α', + έ: 'ε', + ή: 'η', + ί: 'ι', + ϊ: 'ι', + ΐ: 'ι', + ό: 'ο', + ύ: 'υ', + ϋ: 'υ', + ΰ: 'υ', + ώ: 'ω', + ς: 'σ', + '’': "'", + }; + }), + u.define('select2/data/base', ['../utils'], function (n) { + function s(e, t) { + s.__super__.constructor.call(this); + } + return ( + n.Extend(s, n.Observable), + (s.prototype.current = function (e) { + throw new Error( + 'The `current` method must be defined in child classes.', + ); + }), + (s.prototype.query = function (e, t) { + throw new Error( + 'The `query` method must be defined in child classes.', + ); + }), + (s.prototype.bind = function (e, t) {}), + (s.prototype.destroy = function () {}), + (s.prototype.generateResultId = function (e, t) { + e = e.id + '-result-'; + return ( + (e += n.generateChars(4)), + null != t.id + ? (e += '-' + t.id.toString()) + : (e += '-' + n.generateChars(4)), + e + ); + }), + s + ); + }), + u.define( + 'select2/data/select', + ['./base', '../utils', 'jquery'], + function (e, a, l) { + function n(e, t) { + (this.$element = e), + (this.options = t), + n.__super__.constructor.call(this); + } + return ( + a.Extend(n, e), + (n.prototype.current = function (e) { + var t = this; + e( + Array.prototype.map.call( + this.$element[0].querySelectorAll(':checked'), + function (e) { + return t.item(l(e)); + }, + ), + ); + }), + (n.prototype.select = function (i) { + var e, + r = this; + if ( + ((i.selected = !0), + null != i.element && + 'option' === i.element.tagName.toLowerCase()) + ) + return ( + (i.element.selected = !0), + void this.$element.trigger('input').trigger('change') + ); + this.$element.prop('multiple') + ? this.current(function (e) { + var t = []; + (i = [i]).push.apply(i, e); + for (var n = 0; n < i.length; n++) { + var s = i[n].id; + -1 === t.indexOf(s) && t.push(s); + } + r.$element.val(t), + r.$element.trigger('input').trigger('change'); + }) + : ((e = i.id), + this.$element.val(e), + this.$element.trigger('input').trigger('change')); + }), + (n.prototype.unselect = function (i) { + var r = this; + if (this.$element.prop('multiple')) { + if ( + ((i.selected = !1), + null != i.element && + 'option' === i.element.tagName.toLowerCase()) + ) + return ( + (i.element.selected = !1), + void this.$element.trigger('input').trigger('change') + ); + this.current(function (e) { + for (var t = [], n = 0; n < e.length; n++) { + var s = e[n].id; + s !== i.id && -1 === t.indexOf(s) && t.push(s); + } + r.$element.val(t), + r.$element.trigger('input').trigger('change'); + }); + } + }), + (n.prototype.bind = function (e, t) { + var n = this; + (this.container = e).on('select', function (e) { + n.select(e.data); + }), + e.on('unselect', function (e) { + n.unselect(e.data); + }); + }), + (n.prototype.destroy = function () { + this.$element.find('*').each(function () { + a.RemoveData(this); + }); + }), + (n.prototype.query = function (t, e) { + var n = [], + s = this; + this.$element.children().each(function () { + var e; + ('option' !== this.tagName.toLowerCase() && + 'optgroup' !== this.tagName.toLowerCase()) || + ((e = l(this)), + (e = s.item(e)), + null !== (e = s.matches(t, e)) && n.push(e)); + }), + e({ results: n }); + }), + (n.prototype.addOptions = function (e) { + this.$element.append(e); + }), + (n.prototype.option = function (e) { + var t; + e.children + ? ((t = document.createElement('optgroup')).label = e.text) + : void 0 !== (t = document.createElement('option')).textContent + ? (t.textContent = e.text) + : (t.innerText = e.text), + void 0 !== e.id && (t.value = e.id), + e.disabled && (t.disabled = !0), + e.selected && (t.selected = !0), + e.title && (t.title = e.title); + e = this._normalizeItem(e); + return (e.element = t), a.StoreData(t, 'data', e), l(t); + }), + (n.prototype.item = function (e) { + var t = {}; + if (null != (t = a.GetData(e[0], 'data'))) return t; + var n = e[0]; + if ('option' === n.tagName.toLowerCase()) + t = { + id: e.val(), + text: e.text(), + disabled: e.prop('disabled'), + selected: e.prop('selected'), + title: e.prop('title'), + }; + else if ('optgroup' === n.tagName.toLowerCase()) { + t = { + text: e.prop('label'), + children: [], + title: e.prop('title'), + }; + for ( + var s = e.children('option'), i = [], r = 0; + r < s.length; + r++ + ) { + var o = l(s[r]), + o = this.item(o); + i.push(o); + } + t.children = i; + } + return ( + ((t = this._normalizeItem(t)).element = e[0]), + a.StoreData(e[0], 'data', t), + t + ); + }), + (n.prototype._normalizeItem = function (e) { + e !== Object(e) && (e = { id: e, text: e }); + return ( + null != (e = l.extend({}, { text: '' }, e)).id && + (e.id = e.id.toString()), + null != e.text && (e.text = e.text.toString()), + null == e._resultId && + e.id && + null != this.container && + (e._resultId = this.generateResultId(this.container, e)), + l.extend({}, { selected: !1, disabled: !1 }, e) + ); + }), + (n.prototype.matches = function (e, t) { + return this.options.get('matcher')(e, t); + }), + n + ); + }, + ), + u.define( + 'select2/data/array', + ['./select', '../utils', 'jquery'], + function (e, t, c) { + function s(e, t) { + (this._dataToConvert = t.get('data') || []), + s.__super__.constructor.call(this, e, t); + } + return ( + t.Extend(s, e), + (s.prototype.bind = function (e, t) { + s.__super__.bind.call(this, e, t), + this.addOptions(this.convertToOptions(this._dataToConvert)); + }), + (s.prototype.select = function (n) { + var e = this.$element.find('option').filter(function (e, t) { + return t.value == n.id.toString(); + }); + 0 === e.length && ((e = this.option(n)), this.addOptions(e)), + s.__super__.select.call(this, n); + }), + (s.prototype.convertToOptions = function (e) { + var t = this, + n = this.$element.find('option'), + s = n + .map(function () { + return t.item(c(this)).id; + }) + .get(), + i = []; + for (var r = 0; r < e.length; r++) { + var o, + a, + l = this._normalizeItem(e[r]); + 0 <= s.indexOf(l.id) + ? ((o = n.filter( + (function (e) { + return function () { + return c(this).val() == e.id; + }; + })(l), + )), + (a = this.item(o)), + (a = c.extend(!0, {}, l, a)), + (a = this.option(a)), + o.replaceWith(a)) + : ((a = this.option(l)), + l.children && + ((l = this.convertToOptions(l.children)), a.append(l)), + i.push(a)); + } + return i; + }), + s + ); + }, + ), + u.define( + 'select2/data/ajax', + ['./array', '../utils', 'jquery'], + function (e, t, r) { + function n(e, t) { + (this.ajaxOptions = this._applyDefaults(t.get('ajax'))), + null != this.ajaxOptions.processResults && + (this.processResults = this.ajaxOptions.processResults), + n.__super__.constructor.call(this, e, t); + } + return ( + t.Extend(n, e), + (n.prototype._applyDefaults = function (e) { + var t = { + data: function (e) { + return r.extend({}, e, { q: e.term }); + }, + transport: function (e, t, n) { + e = r.ajax(e); + return e.then(t), e.fail(n), e; + }, + }; + return r.extend({}, t, e, !0); + }), + (n.prototype.processResults = function (e) { + return e; + }), + (n.prototype.query = function (t, n) { + var s = this; + null != this._request && + ('function' == typeof this._request.abort && + this._request.abort(), + (this._request = null)); + var i = r.extend({ type: 'GET' }, this.ajaxOptions); + function e() { + var e = i.transport( + i, + function (e) { + e = s.processResults(e, t); + s.options.get('debug') && + window.console && + console.error && + ((e && e.results && Array.isArray(e.results)) || + console.error( + 'Select2: The AJAX results did not return an array in the `results` key of the response.', + )), + n(e); + }, + function () { + ('status' in e && (0 === e.status || '0' === e.status)) || + s.trigger('results:message', { message: 'errorLoading' }); + }, + ); + s._request = e; + } + 'function' == typeof i.url && + (i.url = i.url.call(this.$element, t)), + 'function' == typeof i.data && + (i.data = i.data.call(this.$element, t)), + this.ajaxOptions.delay && null != t.term + ? (this._queryTimeout && + window.clearTimeout(this._queryTimeout), + (this._queryTimeout = window.setTimeout( + e, + this.ajaxOptions.delay, + ))) + : e(); + }), + n + ); + }, + ), + u.define('select2/data/tags', ['jquery'], function (t) { + function e(e, t, n) { + var s = n.get('tags'), + i = n.get('createTag'); + void 0 !== i && (this.createTag = i); + i = n.get('insertTag'); + if ( + (void 0 !== i && (this.insertTag = i), + e.call(this, t, n), + Array.isArray(s)) + ) + for (var r = 0; r < s.length; r++) { + var o = s[r], + o = this._normalizeItem(o), + o = this.option(o); + this.$element.append(o); + } + } + return ( + (e.prototype.query = function (e, c, u) { + var d = this; + this._removeOldTags(), + null != c.term && null == c.page + ? e.call(this, c, function e(t, n) { + for (var s = t.results, i = 0; i < s.length; i++) { + var r = s[i], + o = + null != r.children && !e({ results: r.children }, !0); + if ( + (r.text || '').toUpperCase() === + (c.term || '').toUpperCase() || + o + ) + return !n && ((t.data = s), void u(t)); + } + if (n) return !0; + var a, + l = d.createTag(c); + null != l && + ((a = d.option(l)).attr('data-select2-tag', 'true'), + d.addOptions([a]), + d.insertTag(s, l)), + (t.results = s), + u(t); + }) + : e.call(this, c, u); + }), + (e.prototype.createTag = function (e, t) { + if (null == t.term) return null; + t = t.term.trim(); + return '' === t ? null : { id: t, text: t }; + }), + (e.prototype.insertTag = function (e, t, n) { + t.unshift(n); + }), + (e.prototype._removeOldTags = function (e) { + this.$element.find('option[data-select2-tag]').each(function () { + this.selected || t(this).remove(); + }); + }), + e + ); + }), + u.define('select2/data/tokenizer', ['jquery'], function (c) { + function e(e, t, n) { + var s = n.get('tokenizer'); + void 0 !== s && (this.tokenizer = s), e.call(this, t, n); + } + return ( + (e.prototype.bind = function (e, t, n) { + e.call(this, t, n), + (this.$search = + t.dropdown.$search || + t.selection.$search || + n.find('.select2-search__field')); + }), + (e.prototype.query = function (e, t, n) { + var s = this; + t.term = t.term || ''; + var i = this.tokenizer(t, this.options, function (e) { + var t, + n = s._normalizeItem(e); + s.$element.find('option').filter(function () { + return c(this).val() === n.id; + }).length || + ((t = s.option(n)).attr('data-select2-tag', !0), + s._removeOldTags(), + s.addOptions([t])), + (t = n), + s.trigger('select', { data: t }); + }); + i.term !== t.term && + (this.$search.length && + (this.$search.val(i.term), this.$search.trigger('focus')), + (t.term = i.term)), + e.call(this, t, n); + }), + (e.prototype.tokenizer = function (e, t, n, s) { + for ( + var i = n.get('tokenSeparators') || [], + r = t.term, + o = 0, + a = + this.createTag || + function (e) { + return { id: e.term, text: e.term }; + }; + o < r.length; + + ) { + var l = r[o]; + -1 !== i.indexOf(l) + ? ((l = r.substr(0, o)), + null != (l = a(c.extend({}, t, { term: l }))) + ? (s(l), (r = r.substr(o + 1) || ''), (o = 0)) + : o++) + : o++; + } + return { term: r }; + }), + e + ); + }), + u.define('select2/data/minimumInputLength', [], function () { + function e(e, t, n) { + (this.minimumInputLength = n.get('minimumInputLength')), + e.call(this, t, n); + } + return ( + (e.prototype.query = function (e, t, n) { + (t.term = t.term || ''), + t.term.length < this.minimumInputLength + ? this.trigger('results:message', { + message: 'inputTooShort', + args: { + minimum: this.minimumInputLength, + input: t.term, + params: t, + }, + }) + : e.call(this, t, n); + }), + e + ); + }), + u.define('select2/data/maximumInputLength', [], function () { + function e(e, t, n) { + (this.maximumInputLength = n.get('maximumInputLength')), + e.call(this, t, n); + } + return ( + (e.prototype.query = function (e, t, n) { + (t.term = t.term || ''), + 0 < this.maximumInputLength && + t.term.length > this.maximumInputLength + ? this.trigger('results:message', { + message: 'inputTooLong', + args: { + maximum: this.maximumInputLength, + input: t.term, + params: t, + }, + }) + : e.call(this, t, n); + }), + e + ); + }), + u.define('select2/data/maximumSelectionLength', [], function () { + function e(e, t, n) { + (this.maximumSelectionLength = n.get('maximumSelectionLength')), + e.call(this, t, n); + } + return ( + (e.prototype.bind = function (e, t, n) { + var s = this; + e.call(this, t, n), + t.on('select', function () { + s._checkIfMaximumSelected(); + }); + }), + (e.prototype.query = function (e, t, n) { + var s = this; + this._checkIfMaximumSelected(function () { + e.call(s, t, n); + }); + }), + (e.prototype._checkIfMaximumSelected = function (e, t) { + var n = this; + this.current(function (e) { + e = null != e ? e.length : 0; + 0 < n.maximumSelectionLength && e >= n.maximumSelectionLength + ? n.trigger('results:message', { + message: 'maximumSelected', + args: { maximum: n.maximumSelectionLength }, + }) + : t && t(); + }); + }), + e + ); + }), + u.define('select2/dropdown', ['jquery', './utils'], function (t, e) { + function n(e, t) { + (this.$element = e), + (this.options = t), + n.__super__.constructor.call(this); + } + return ( + e.Extend(n, e.Observable), + (n.prototype.render = function () { + var e = t( + '', + ); + return e.attr('dir', this.options.get('dir')), (this.$dropdown = e); + }), + (n.prototype.bind = function () {}), + (n.prototype.position = function (e, t) {}), + (n.prototype.destroy = function () { + this.$dropdown.remove(); + }), + n + ); + }), + u.define('select2/dropdown/search', ['jquery'], function (r) { + function e() {} + return ( + (e.prototype.render = function (e) { + var t = e.call(this), + n = this.options.get('translations').get('search'), + e = r( + '', + ); + return ( + (this.$searchContainer = e), + (this.$search = e.find('input')), + this.$search.prop( + 'autocomplete', + this.options.get('autocomplete'), + ), + this.$search.attr('aria-label', n()), + t.prepend(e), + t + ); + }), + (e.prototype.bind = function (e, t, n) { + var s = this, + i = t.id + '-results'; + e.call(this, t, n), + this.$search.on('keydown', function (e) { + s.trigger('keypress', e), + (s._keyUpPrevented = e.isDefaultPrevented()); + }), + this.$search.on('input', function (e) { + r(this).off('keyup'); + }), + this.$search.on('keyup input', function (e) { + s.handleSearch(e); + }), + t.on('open', function () { + s.$search.attr('tabindex', 0), + s.$search.attr('aria-controls', i), + s.$search.trigger('focus'), + window.setTimeout(function () { + s.$search.trigger('focus'); + }, 0); + }), + t.on('close', function () { + s.$search.attr('tabindex', -1), + s.$search.removeAttr('aria-controls'), + s.$search.removeAttr('aria-activedescendant'), + s.$search.val(''), + s.$search.trigger('blur'); + }), + t.on('focus', function () { + t.isOpen() || s.$search.trigger('focus'); + }), + t.on('results:all', function (e) { + (null != e.query.term && '' !== e.query.term) || + (s.showSearch(e) + ? s.$searchContainer[0].classList.remove( + 'select2-search--hide', + ) + : s.$searchContainer[0].classList.add( + 'select2-search--hide', + )); + }), + t.on('results:focus', function (e) { + e.data._resultId + ? s.$search.attr('aria-activedescendant', e.data._resultId) + : s.$search.removeAttr('aria-activedescendant'); + }); + }), + (e.prototype.handleSearch = function (e) { + var t; + this._keyUpPrevented || + ((t = this.$search.val()), this.trigger('query', { term: t })), + (this._keyUpPrevented = !1); + }), + (e.prototype.showSearch = function (e, t) { + return !0; + }), + e + ); + }), + u.define('select2/dropdown/hidePlaceholder', [], function () { + function e(e, t, n, s) { + (this.placeholder = this.normalizePlaceholder(n.get('placeholder'))), + e.call(this, t, n, s); + } + return ( + (e.prototype.append = function (e, t) { + (t.results = this.removePlaceholder(t.results)), e.call(this, t); + }), + (e.prototype.normalizePlaceholder = function (e, t) { + return 'string' == typeof t && (t = { id: '', text: t }), t; + }), + (e.prototype.removePlaceholder = function (e, t) { + for (var n = t.slice(0), s = t.length - 1; 0 <= s; s--) { + var i = t[s]; + this.placeholder.id === i.id && n.splice(s, 1); + } + return n; + }), + e + ); + }), + u.define('select2/dropdown/infiniteScroll', ['jquery'], function (n) { + function e(e, t, n, s) { + (this.lastParams = {}), + e.call(this, t, n, s), + (this.$loadingMore = this.createLoadingMore()), + (this.loading = !1); + } + return ( + (e.prototype.append = function (e, t) { + this.$loadingMore.remove(), + (this.loading = !1), + e.call(this, t), + this.showLoadingMore(t) && + (this.$results.append(this.$loadingMore), + this.loadMoreIfNeeded()); + }), + (e.prototype.bind = function (e, t, n) { + var s = this; + e.call(this, t, n), + t.on('query', function (e) { + (s.lastParams = e), (s.loading = !0); + }), + t.on('query:append', function (e) { + (s.lastParams = e), (s.loading = !0); + }), + this.$results.on('scroll', this.loadMoreIfNeeded.bind(this)); + }), + (e.prototype.loadMoreIfNeeded = function () { + var e = n.contains(document.documentElement, this.$loadingMore[0]); + !this.loading && + e && + ((e = this.$results.offset().top + this.$results.outerHeight(!1)), + this.$loadingMore.offset().top + + this.$loadingMore.outerHeight(!1) <= + e + 50 && this.loadMore()); + }), + (e.prototype.loadMore = function () { + this.loading = !0; + var e = n.extend({}, { page: 1 }, this.lastParams); + e.page++, this.trigger('query:append', e); + }), + (e.prototype.showLoadingMore = function (e, t) { + return t.pagination && t.pagination.more; + }), + (e.prototype.createLoadingMore = function () { + var e = n( + '
      • ', + ), + t = this.options.get('translations').get('loadingMore'); + return e.html(t(this.lastParams)), e; + }), + e + ); + }), + u.define( + 'select2/dropdown/attachBody', + ['jquery', '../utils'], + function (u, o) { + function e(e, t, n) { + (this.$dropdownParent = u( + n.get('dropdownParent') || document.body, + )), + e.call(this, t, n); + } + return ( + (e.prototype.bind = function (e, t, n) { + var s = this; + e.call(this, t, n), + t.on('open', function () { + s._showDropdown(), + s._attachPositioningHandler(t), + s._bindContainerResultHandlers(t); + }), + t.on('close', function () { + s._hideDropdown(), s._detachPositioningHandler(t); + }), + this.$dropdownContainer.on('mousedown', function (e) { + e.stopPropagation(); + }); + }), + (e.prototype.destroy = function (e) { + e.call(this), this.$dropdownContainer.remove(); + }), + (e.prototype.position = function (e, t, n) { + t.attr('class', n.attr('class')), + t[0].classList.remove('select2'), + t[0].classList.add('select2-container--open'), + t.css({ position: 'absolute', top: -999999 }), + (this.$container = n); + }), + (e.prototype.render = function (e) { + var t = u(''), + e = e.call(this); + return t.append(e), (this.$dropdownContainer = t); + }), + (e.prototype._hideDropdown = function (e) { + this.$dropdownContainer.detach(); + }), + (e.prototype._bindContainerResultHandlers = function (e, t) { + var n; + this._containerResultsHandlersBound || + ((n = this), + t.on('results:all', function () { + n._positionDropdown(), n._resizeDropdown(); + }), + t.on('results:append', function () { + n._positionDropdown(), n._resizeDropdown(); + }), + t.on('results:message', function () { + n._positionDropdown(), n._resizeDropdown(); + }), + t.on('select', function () { + n._positionDropdown(), n._resizeDropdown(); + }), + t.on('unselect', function () { + n._positionDropdown(), n._resizeDropdown(); + }), + (this._containerResultsHandlersBound = !0)); + }), + (e.prototype._attachPositioningHandler = function (e, t) { + var n = this, + s = 'scroll.select2.' + t.id, + i = 'resize.select2.' + t.id, + r = 'orientationchange.select2.' + t.id, + t = this.$container.parents().filter(o.hasScroll); + t.each(function () { + o.StoreData(this, 'select2-scroll-position', { + x: u(this).scrollLeft(), + y: u(this).scrollTop(), + }); + }), + t.on(s, function (e) { + var t = o.GetData(this, 'select2-scroll-position'); + u(this).scrollTop(t.y); + }), + u(window).on(s + ' ' + i + ' ' + r, function (e) { + n._positionDropdown(), n._resizeDropdown(); + }); + }), + (e.prototype._detachPositioningHandler = function (e, t) { + var n = 'scroll.select2.' + t.id, + s = 'resize.select2.' + t.id, + t = 'orientationchange.select2.' + t.id; + this.$container.parents().filter(o.hasScroll).off(n), + u(window).off(n + ' ' + s + ' ' + t); + }), + (e.prototype._positionDropdown = function () { + var e = u(window), + t = this.$dropdown[0].classList.contains( + 'select2-dropdown--above', + ), + n = this.$dropdown[0].classList.contains( + 'select2-dropdown--below', + ), + s = null, + i = this.$container.offset(); + i.bottom = i.top + this.$container.outerHeight(!1); + var r = { height: this.$container.outerHeight(!1) }; + (r.top = i.top), (r.bottom = i.top + r.height); + var o = this.$dropdown.outerHeight(!1), + a = e.scrollTop(), + l = e.scrollTop() + e.height(), + c = a < i.top - o, + e = l > i.bottom + o, + a = { left: i.left, top: r.bottom }, + l = this.$dropdownParent; + 'static' === l.css('position') && (l = l.offsetParent()); + i = { top: 0, left: 0 }; + (u.contains(document.body, l[0]) || l[0].isConnected) && + (i = l.offset()), + (a.top -= i.top), + (a.left -= i.left), + t || n || (s = 'below'), + e || !c || t ? !c && e && t && (s = 'below') : (s = 'above'), + ('above' == s || (t && 'below' !== s)) && + (a.top = r.top - i.top - o), + null != s && + (this.$dropdown[0].classList.remove( + 'select2-dropdown--below', + ), + this.$dropdown[0].classList.remove('select2-dropdown--above'), + this.$dropdown[0].classList.add('select2-dropdown--' + s), + this.$container[0].classList.remove( + 'select2-container--below', + ), + this.$container[0].classList.remove( + 'select2-container--above', + ), + this.$container[0].classList.add('select2-container--' + s)), + this.$dropdownContainer.css(a); + }), + (e.prototype._resizeDropdown = function () { + var e = { width: this.$container.outerWidth(!1) + 'px' }; + this.options.get('dropdownAutoWidth') && + ((e.minWidth = e.width), + (e.position = 'relative'), + (e.width = 'auto')), + this.$dropdown.css(e); + }), + (e.prototype._showDropdown = function (e) { + this.$dropdownContainer.appendTo(this.$dropdownParent), + this._positionDropdown(), + this._resizeDropdown(); + }), + e + ); + }, + ), + u.define('select2/dropdown/minimumResultsForSearch', [], function () { + function e(e, t, n, s) { + (this.minimumResultsForSearch = n.get('minimumResultsForSearch')), + this.minimumResultsForSearch < 0 && + (this.minimumResultsForSearch = 1 / 0), + e.call(this, t, n, s); + } + return ( + (e.prototype.showSearch = function (e, t) { + return ( + !( + (function e(t) { + for (var n = 0, s = 0; s < t.length; s++) { + var i = t[s]; + i.children ? (n += e(i.children)) : n++; + } + return n; + })(t.data.results) < this.minimumResultsForSearch + ) && e.call(this, t) + ); + }), + e + ); + }), + u.define('select2/dropdown/selectOnClose', ['../utils'], function (s) { + function e() {} + return ( + (e.prototype.bind = function (e, t, n) { + var s = this; + e.call(this, t, n), + t.on('close', function (e) { + s._handleSelectOnClose(e); + }); + }), + (e.prototype._handleSelectOnClose = function (e, t) { + if (t && null != t.originalSelect2Event) { + var n = t.originalSelect2Event; + if ('select' === n._type || 'unselect' === n._type) return; + } + n = this.getHighlightedResults(); + n.length < 1 || + (null != (n = s.GetData(n[0], 'data')).element && + n.element.selected) || + (null == n.element && n.selected) || + this.trigger('select', { data: n }); + }), + e + ); + }), + u.define('select2/dropdown/closeOnSelect', [], function () { + function e() {} + return ( + (e.prototype.bind = function (e, t, n) { + var s = this; + e.call(this, t, n), + t.on('select', function (e) { + s._selectTriggered(e); + }), + t.on('unselect', function (e) { + s._selectTriggered(e); + }); + }), + (e.prototype._selectTriggered = function (e, t) { + var n = t.originalEvent; + (n && (n.ctrlKey || n.metaKey)) || + this.trigger('close', { + originalEvent: n, + originalSelect2Event: t, + }); + }), + e + ); + }), + u.define('select2/dropdown/dropdownCss', ['../utils'], function (n) { + function e() {} + return ( + (e.prototype.render = function (e) { + var t = e.call(this), + e = this.options.get('dropdownCssClass') || ''; + return ( + -1 !== e.indexOf(':all:') && + ((e = e.replace(':all:', '')), + n.copyNonInternalCssClasses(t[0], this.$element[0])), + t.addClass(e), + t + ); + }), + e + ); + }), + u.define( + 'select2/dropdown/tagsSearchHighlight', + ['../utils'], + function (s) { + function e() {} + return ( + (e.prototype.highlightFirstItem = function (e) { + var t = this.$results.find( + '.select2-results__option--selectable:not(.select2-results__option--selected)', + ); + if (0 < t.length) { + var n = t.first(), + t = s.GetData(n[0], 'data').element; + if ( + t && + t.getAttribute && + 'true' === t.getAttribute('data-select2-tag') + ) + return void n.trigger('mouseenter'); + } + e.call(this); + }), + e + ); + }, + ), + u.define('select2/i18n/en', [], function () { + return { + errorLoading: function () { + return 'The results could not be loaded.'; + }, + inputTooLong: function (e) { + var t = e.input.length - e.maximum, + e = 'Please delete ' + t + ' character'; + return 1 != t && (e += 's'), e; + }, + inputTooShort: function (e) { + return ( + 'Please enter ' + + (e.minimum - e.input.length) + + ' or more characters' + ); + }, + loadingMore: function () { + return 'Loading more results…'; + }, + maximumSelected: function (e) { + var t = 'You can only select ' + e.maximum + ' item'; + return 1 != e.maximum && (t += 's'), t; + }, + noResults: function () { + return 'No results found'; + }, + searching: function () { + return 'Searching…'; + }, + removeAllItems: function () { + return 'Remove all items'; + }, + removeItem: function () { + return 'Remove item'; + }, + search: function () { + return 'Search'; + }, + }; + }), + u.define( + 'select2/defaults', + [ + 'jquery', + './results', + './selection/single', + './selection/multiple', + './selection/placeholder', + './selection/allowClear', + './selection/search', + './selection/selectionCss', + './selection/eventRelay', + './utils', + './translation', + './diacritics', + './data/select', + './data/array', + './data/ajax', + './data/tags', + './data/tokenizer', + './data/minimumInputLength', + './data/maximumInputLength', + './data/maximumSelectionLength', + './dropdown', + './dropdown/search', + './dropdown/hidePlaceholder', + './dropdown/infiniteScroll', + './dropdown/attachBody', + './dropdown/minimumResultsForSearch', + './dropdown/selectOnClose', + './dropdown/closeOnSelect', + './dropdown/dropdownCss', + './dropdown/tagsSearchHighlight', + './i18n/en', + ], + function ( + l, + r, + o, + a, + c, + u, + d, + p, + h, + f, + g, + t, + m, + y, + v, + _, + b, + $, + w, + x, + A, + D, + S, + E, + O, + C, + L, + T, + q, + I, + e, + ) { + function n() { + this.reset(); + } + return ( + (n.prototype.apply = function (e) { + var t; + null == (e = l.extend(!0, {}, this.defaults, e)).dataAdapter && + (null != e.ajax + ? (e.dataAdapter = v) + : null != e.data + ? (e.dataAdapter = y) + : (e.dataAdapter = m), + 0 < e.minimumInputLength && + (e.dataAdapter = f.Decorate(e.dataAdapter, $)), + 0 < e.maximumInputLength && + (e.dataAdapter = f.Decorate(e.dataAdapter, w)), + 0 < e.maximumSelectionLength && + (e.dataAdapter = f.Decorate(e.dataAdapter, x)), + e.tags && (e.dataAdapter = f.Decorate(e.dataAdapter, _)), + (null == e.tokenSeparators && null == e.tokenizer) || + (e.dataAdapter = f.Decorate(e.dataAdapter, b))), + null == e.resultsAdapter && + ((e.resultsAdapter = r), + null != e.ajax && + (e.resultsAdapter = f.Decorate(e.resultsAdapter, E)), + null != e.placeholder && + (e.resultsAdapter = f.Decorate(e.resultsAdapter, S)), + e.selectOnClose && + (e.resultsAdapter = f.Decorate(e.resultsAdapter, L)), + e.tags && + (e.resultsAdapter = f.Decorate(e.resultsAdapter, I))), + null == e.dropdownAdapter && + (e.multiple + ? (e.dropdownAdapter = A) + : ((t = f.Decorate(A, D)), (e.dropdownAdapter = t)), + 0 !== e.minimumResultsForSearch && + (e.dropdownAdapter = f.Decorate(e.dropdownAdapter, C)), + e.closeOnSelect && + (e.dropdownAdapter = f.Decorate(e.dropdownAdapter, T)), + null != e.dropdownCssClass && + (e.dropdownAdapter = f.Decorate(e.dropdownAdapter, q)), + (e.dropdownAdapter = f.Decorate(e.dropdownAdapter, O))), + null == e.selectionAdapter && + (e.multiple + ? (e.selectionAdapter = a) + : (e.selectionAdapter = o), + null != e.placeholder && + (e.selectionAdapter = f.Decorate(e.selectionAdapter, c)), + e.allowClear && + (e.selectionAdapter = f.Decorate(e.selectionAdapter, u)), + e.multiple && + (e.selectionAdapter = f.Decorate(e.selectionAdapter, d)), + null != e.selectionCssClass && + (e.selectionAdapter = f.Decorate(e.selectionAdapter, p)), + (e.selectionAdapter = f.Decorate(e.selectionAdapter, h))), + (e.language = this._resolveLanguage(e.language)), + e.language.push('en'); + for (var n = [], s = 0; s < e.language.length; s++) { + var i = e.language[s]; + -1 === n.indexOf(i) && n.push(i); + } + return ( + (e.language = n), + (e.translations = this._processTranslations( + e.language, + e.debug, + )), + e + ); + }), + (n.prototype.reset = function () { + function a(e) { + return e.replace(/[^\u0000-\u007E]/g, function (e) { + return t[e] || e; + }); + } + this.defaults = { + amdLanguageBase: './i18n/', + autocomplete: 'off', + closeOnSelect: !0, + debug: !1, + dropdownAutoWidth: !1, + escapeMarkup: f.escapeMarkup, + language: {}, + matcher: function e(t, n) { + if (null == t.term || '' === t.term.trim()) return n; + if (n.children && 0 < n.children.length) { + for ( + var s = l.extend(!0, {}, n), i = n.children.length - 1; + 0 <= i; + i-- + ) + null == e(t, n.children[i]) && s.children.splice(i, 1); + return 0 < s.children.length ? s : e(t, s); + } + var r = a(n.text).toUpperCase(), + o = a(t.term).toUpperCase(); + return -1 < r.indexOf(o) ? n : null; + }, + minimumInputLength: 0, + maximumInputLength: 0, + maximumSelectionLength: 0, + minimumResultsForSearch: 0, + selectOnClose: !1, + scrollAfterSelect: !1, + sorter: function (e) { + return e; + }, + templateResult: function (e) { + return e.text; + }, + templateSelection: function (e) { + return e.text; + }, + theme: 'default', + width: 'resolve', + }; + }), + (n.prototype.applyFromElement = function (e, t) { + var n = e.language, + s = this.defaults.language, + i = t.prop('lang'), + t = t.closest('[lang]').prop('lang'), + t = Array.prototype.concat.call( + this._resolveLanguage(i), + this._resolveLanguage(n), + this._resolveLanguage(s), + this._resolveLanguage(t), + ); + return (e.language = t), e; + }), + (n.prototype._resolveLanguage = function (e) { + if (!e) return []; + if (l.isEmptyObject(e)) return []; + if (l.isPlainObject(e)) return [e]; + for ( + var t, n = Array.isArray(e) ? e : [e], s = [], i = 0; + i < n.length; + i++ + ) + s.push(n[i]), + 'string' == typeof n[i] && + 0 < n[i].indexOf('-') && + ((t = n[i].split('-')[0]), s.push(t)); + return s; + }), + (n.prototype._processTranslations = function (e, t) { + for (var n = new g(), s = 0; s < e.length; s++) { + var i = new g(), + r = e[s]; + if ('string' == typeof r) + try { + i = g.loadPath(r); + } catch (e) { + try { + (r = this.defaults.amdLanguageBase + r), + (i = g.loadPath(r)); + } catch (e) { + t && + window.console && + console.warn && + console.warn( + 'Select2: The language file for "' + + r + + '" could not be automatically loaded. A fallback will be used instead.', + ); + } + } + else i = l.isPlainObject(r) ? new g(r) : r; + n.extend(i); + } + return n; + }), + (n.prototype.set = function (e, t) { + var n = {}; + n[l.camelCase(e)] = t; + n = f._convertData(n); + l.extend(!0, this.defaults, n); + }), + new n() + ); + }, + ), + u.define( + 'select2/options', + ['jquery', './defaults', './utils'], + function (c, n, u) { + function e(e, t) { + (this.options = e), + null != t && this.fromElement(t), + null != t && (this.options = n.applyFromElement(this.options, t)), + (this.options = n.apply(this.options)); + } + return ( + (e.prototype.fromElement = function (e) { + var t = ['select2']; + null == this.options.multiple && + (this.options.multiple = e.prop('multiple')), + null == this.options.disabled && + (this.options.disabled = e.prop('disabled')), + null == this.options.autocomplete && + e.prop('autocomplete') && + (this.options.autocomplete = e.prop('autocomplete')), + null == this.options.dir && + (e.prop('dir') + ? (this.options.dir = e.prop('dir')) + : e.closest('[dir]').prop('dir') + ? (this.options.dir = e.closest('[dir]').prop('dir')) + : (this.options.dir = 'ltr')), + e.prop('disabled', this.options.disabled), + e.prop('multiple', this.options.multiple), + u.GetData(e[0], 'select2Tags') && + (this.options.debug && + window.console && + console.warn && + console.warn( + 'Select2: The `data-select2-tags` attribute has been changed to use the `data-data` and `data-tags="true"` attributes and will be removed in future versions of Select2.', + ), + u.StoreData(e[0], 'data', u.GetData(e[0], 'select2Tags')), + u.StoreData(e[0], 'tags', !0)), + u.GetData(e[0], 'ajaxUrl') && + (this.options.debug && + window.console && + console.warn && + console.warn( + 'Select2: The `data-ajax-url` attribute has been changed to `data-ajax--url` and support for the old attribute will be removed in future versions of Select2.', + ), + e.attr('ajax--url', u.GetData(e[0], 'ajaxUrl')), + u.StoreData(e[0], 'ajax-Url', u.GetData(e[0], 'ajaxUrl'))); + var n = {}; + function s(e, t) { + return t.toUpperCase(); + } + for (var i = 0; i < e[0].attributes.length; i++) { + var r = e[0].attributes[i].name, + o = 'data-'; + r.substr(0, o.length) == o && + ((r = r.substring(o.length)), + (o = u.GetData(e[0], r)), + (n[r.replace(/-([a-z])/g, s)] = o)); + } + c.fn.jquery && + '1.' == c.fn.jquery.substr(0, 2) && + e[0].dataset && + (n = c.extend(!0, {}, e[0].dataset, n)); + var a, + l = c.extend(!0, {}, u.GetData(e[0]), n); + for (a in (l = u._convertData(l))) + -1 < t.indexOf(a) || + (c.isPlainObject(this.options[a]) + ? c.extend(this.options[a], l[a]) + : (this.options[a] = l[a])); + return this; + }), + (e.prototype.get = function (e) { + return this.options[e]; + }), + (e.prototype.set = function (e, t) { + this.options[e] = t; + }), + e + ); + }, + ), + u.define( + 'select2/core', + ['jquery', './options', './utils', './keys'], + function (t, i, r, s) { + var o = function (e, t) { + null != r.GetData(e[0], 'select2') && + r.GetData(e[0], 'select2').destroy(), + (this.$element = e), + (this.id = this._generateId(e)), + (t = t || {}), + (this.options = new i(t, e)), + o.__super__.constructor.call(this); + var n = e.attr('tabindex') || 0; + r.StoreData(e[0], 'old-tabindex', n), e.attr('tabindex', '-1'); + t = this.options.get('dataAdapter'); + this.dataAdapter = new t(e, this.options); + n = this.render(); + this._placeContainer(n); + t = this.options.get('selectionAdapter'); + (this.selection = new t(e, this.options)), + (this.$selection = this.selection.render()), + this.selection.position(this.$selection, n); + t = this.options.get('dropdownAdapter'); + (this.dropdown = new t(e, this.options)), + (this.$dropdown = this.dropdown.render()), + this.dropdown.position(this.$dropdown, n); + n = this.options.get('resultsAdapter'); + (this.results = new n(e, this.options, this.dataAdapter)), + (this.$results = this.results.render()), + this.results.position(this.$results, this.$dropdown); + var s = this; + this._bindAdapters(), + this._registerDomEvents(), + this._registerDataEvents(), + this._registerSelectionEvents(), + this._registerDropdownEvents(), + this._registerResultsEvents(), + this._registerEvents(), + this.dataAdapter.current(function (e) { + s.trigger('selection:update', { data: e }); + }), + e[0].classList.add('select2-hidden-accessible'), + e.attr('aria-hidden', 'true'), + this._syncAttributes(), + r.StoreData(e[0], 'select2', this), + e.data('select2', this); + }; + return ( + r.Extend(o, r.Observable), + (o.prototype._generateId = function (e) { + return ( + 'select2-' + + (null != e.attr('id') + ? e.attr('id') + : null != e.attr('name') + ? e.attr('name') + '-' + r.generateChars(2) + : r.generateChars(4) + ).replace(/(:|\.|\[|\]|,)/g, '') + ); + }), + (o.prototype._placeContainer = function (e) { + e.insertAfter(this.$element); + var t = this._resolveWidth( + this.$element, + this.options.get('width'), + ); + null != t && e.css('width', t); + }), + (o.prototype._resolveWidth = function (e, t) { + var n = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i; + if ('resolve' == t) { + var s = this._resolveWidth(e, 'style'); + return null != s ? s : this._resolveWidth(e, 'element'); + } + if ('element' == t) { + s = e.outerWidth(!1); + return s <= 0 ? 'auto' : s + 'px'; + } + if ('style' != t) + return 'computedstyle' != t + ? t + : window.getComputedStyle(e[0]).width; + e = e.attr('style'); + if ('string' != typeof e) return null; + for (var i = e.split(';'), r = 0, o = i.length; r < o; r += 1) { + var a = i[r].replace(/\s/g, '').match(n); + if (null !== a && 1 <= a.length) return a[1]; + } + return null; + }), + (o.prototype._bindAdapters = function () { + this.dataAdapter.bind(this, this.$container), + this.selection.bind(this, this.$container), + this.dropdown.bind(this, this.$container), + this.results.bind(this, this.$container); + }), + (o.prototype._registerDomEvents = function () { + var t = this; + this.$element.on('change.select2', function () { + t.dataAdapter.current(function (e) { + t.trigger('selection:update', { data: e }); + }); + }), + this.$element.on('focus.select2', function (e) { + t.trigger('focus', e); + }), + (this._syncA = r.bind(this._syncAttributes, this)), + (this._syncS = r.bind(this._syncSubtree, this)), + (this._observer = new window.MutationObserver(function (e) { + t._syncA(), t._syncS(e); + })), + this._observer.observe(this.$element[0], { + attributes: !0, + childList: !0, + subtree: !1, + }); + }), + (o.prototype._registerDataEvents = function () { + var n = this; + this.dataAdapter.on('*', function (e, t) { + n.trigger(e, t); + }); + }), + (o.prototype._registerSelectionEvents = function () { + var n = this, + s = ['toggle', 'focus']; + this.selection.on('toggle', function () { + n.toggleDropdown(); + }), + this.selection.on('focus', function (e) { + n.focus(e); + }), + this.selection.on('*', function (e, t) { + -1 === s.indexOf(e) && n.trigger(e, t); + }); + }), + (o.prototype._registerDropdownEvents = function () { + var n = this; + this.dropdown.on('*', function (e, t) { + n.trigger(e, t); + }); + }), + (o.prototype._registerResultsEvents = function () { + var n = this; + this.results.on('*', function (e, t) { + n.trigger(e, t); + }); + }), + (o.prototype._registerEvents = function () { + var n = this; + this.on('open', function () { + n.$container[0].classList.add('select2-container--open'); + }), + this.on('close', function () { + n.$container[0].classList.remove('select2-container--open'); + }), + this.on('enable', function () { + n.$container[0].classList.remove( + 'select2-container--disabled', + ); + }), + this.on('disable', function () { + n.$container[0].classList.add('select2-container--disabled'); + }), + this.on('blur', function () { + n.$container[0].classList.remove('select2-container--focus'); + }), + this.on('query', function (t) { + n.isOpen() || n.trigger('open', {}), + this.dataAdapter.query(t, function (e) { + n.trigger('results:all', { data: e, query: t }); + }); + }), + this.on('query:append', function (t) { + this.dataAdapter.query(t, function (e) { + n.trigger('results:append', { data: e, query: t }); + }); + }), + this.on('keypress', function (e) { + var t = e.which; + n.isOpen() + ? t === s.ESC || (t === s.UP && e.altKey) + ? (n.close(e), e.preventDefault()) + : t === s.ENTER || t === s.TAB + ? (n.trigger('results:select', {}), e.preventDefault()) + : t === s.SPACE && e.ctrlKey + ? (n.trigger('results:toggle', {}), e.preventDefault()) + : t === s.UP + ? (n.trigger('results:previous', {}), e.preventDefault()) + : t === s.DOWN && + (n.trigger('results:next', {}), e.preventDefault()) + : (t === s.ENTER || + t === s.SPACE || + (t === s.DOWN && e.altKey)) && + (n.open(), e.preventDefault()); + }); + }), + (o.prototype._syncAttributes = function () { + this.options.set('disabled', this.$element.prop('disabled')), + this.isDisabled() + ? (this.isOpen() && this.close(), this.trigger('disable', {})) + : this.trigger('enable', {}); + }), + (o.prototype._isChangeMutation = function (e) { + var t = this; + if (e.addedNodes && 0 < e.addedNodes.length) { + for (var n = 0; n < e.addedNodes.length; n++) + if (e.addedNodes[n].selected) return !0; + } else { + if (e.removedNodes && 0 < e.removedNodes.length) return !0; + if (Array.isArray(e)) + return e.some(function (e) { + return t._isChangeMutation(e); + }); + } + return !1; + }), + (o.prototype._syncSubtree = function (e) { + var e = this._isChangeMutation(e), + t = this; + e && + this.dataAdapter.current(function (e) { + t.trigger('selection:update', { data: e }); + }); + }), + (o.prototype.trigger = function (e, t) { + var n = o.__super__.trigger, + s = { + open: 'opening', + close: 'closing', + select: 'selecting', + unselect: 'unselecting', + clear: 'clearing', + }; + if ((void 0 === t && (t = {}), e in s)) { + var i = s[e], + s = { prevented: !1, name: e, args: t }; + if ((n.call(this, i, s), s.prevented)) + return void (t.prevented = !0); + } + n.call(this, e, t); + }), + (o.prototype.toggleDropdown = function () { + this.isDisabled() || (this.isOpen() ? this.close() : this.open()); + }), + (o.prototype.open = function () { + this.isOpen() || this.isDisabled() || this.trigger('query', {}); + }), + (o.prototype.close = function (e) { + this.isOpen() && this.trigger('close', { originalEvent: e }); + }), + (o.prototype.isEnabled = function () { + return !this.isDisabled(); + }), + (o.prototype.isDisabled = function () { + return this.options.get('disabled'); + }), + (o.prototype.isOpen = function () { + return this.$container[0].classList.contains( + 'select2-container--open', + ); + }), + (o.prototype.hasFocus = function () { + return this.$container[0].classList.contains( + 'select2-container--focus', + ); + }), + (o.prototype.focus = function (e) { + this.hasFocus() || + (this.$container[0].classList.add('select2-container--focus'), + this.trigger('focus', {})); + }), + (o.prototype.enable = function (e) { + this.options.get('debug') && + window.console && + console.warn && + console.warn( + 'Select2: The `select2("enable")` method has been deprecated and will be removed in later Select2 versions. Use $element.prop("disabled") instead.', + ), + (null != e && 0 !== e.length) || (e = [!0]); + e = !e[0]; + this.$element.prop('disabled', e); + }), + (o.prototype.data = function () { + this.options.get('debug') && + 0 < arguments.length && + window.console && + console.warn && + console.warn( + 'Select2: Data can no longer be set using `select2("data")`. You should consider setting the value instead using `$element.val()`.', + ); + var t = []; + return ( + this.dataAdapter.current(function (e) { + t = e; + }), + t + ); + }), + (o.prototype.val = function (e) { + if ( + (this.options.get('debug') && + window.console && + console.warn && + console.warn( + 'Select2: The `select2("val")` method has been deprecated and will be removed in later Select2 versions. Use $element.val() instead.', + ), + null == e || 0 === e.length) + ) + return this.$element.val(); + e = e[0]; + Array.isArray(e) && + (e = e.map(function (e) { + return e.toString(); + })), + this.$element.val(e).trigger('input').trigger('change'); + }), + (o.prototype.destroy = function () { + r.RemoveData(this.$container[0]), + this.$container.remove(), + this._observer.disconnect(), + (this._observer = null), + (this._syncA = null), + (this._syncS = null), + this.$element.off('.select2'), + this.$element.attr( + 'tabindex', + r.GetData(this.$element[0], 'old-tabindex'), + ), + this.$element[0].classList.remove('select2-hidden-accessible'), + this.$element.attr('aria-hidden', 'false'), + r.RemoveData(this.$element[0]), + this.$element.removeData('select2'), + this.dataAdapter.destroy(), + this.selection.destroy(), + this.dropdown.destroy(), + this.results.destroy(), + (this.dataAdapter = null), + (this.selection = null), + (this.dropdown = null), + (this.results = null); + }), + (o.prototype.render = function () { + var e = t( + '', + ); + return ( + e.attr('dir', this.options.get('dir')), + (this.$container = e), + this.$container[0].classList.add( + 'select2-container--' + this.options.get('theme'), + ), + r.StoreData(e[0], 'element', this.$element), + e + ); + }), + o + ); + }, + ), + u.define('jquery-mousewheel', ['jquery'], function (e) { + return e; + }), + u.define( + 'jquery.select2', + [ + 'jquery', + 'jquery-mousewheel', + './select2/core', + './select2/defaults', + './select2/utils', + ], + function (i, e, r, t, o) { + var a; + return ( + null == i.fn.select2 && + ((a = ['open', 'close', 'destroy']), + (i.fn.select2 = function (t) { + if ('object' == typeof (t = t || {})) + return ( + this.each(function () { + var e = i.extend(!0, {}, t); + new r(i(this), e); + }), + this + ); + if ('string' != typeof t) + throw new Error('Invalid arguments for Select2: ' + t); + var n, + s = Array.prototype.slice.call(arguments, 1); + return ( + this.each(function () { + var e = o.GetData(this, 'select2'); + null == e && + window.console && + console.error && + console.error( + "The select2('" + + t + + "') method was called on an element that is not using Select2.", + ), + (n = e[t].apply(e, s)); + }), + -1 < a.indexOf(t) ? this : n + ); + })), + null == i.fn.select2.defaults && (i.fn.select2.defaults = t), + r + ); + }, + ), + { define: u.define, require: u.require }); + function b(e, t) { + return i.call(e, t); + } + function l(e, t) { + var n, + s, + i, + r, + o, + a, + l, + c, + u, + d, + p = t && t.split('/'), + h = y.map, + f = (h && h['*']) || {}; + if (e) { + for ( + t = (e = e.split('/')).length - 1, + y.nodeIdCompat && _.test(e[t]) && (e[t] = e[t].replace(_, '')), + '.' === e[0].charAt(0) && + p && + (e = p.slice(0, p.length - 1).concat(e)), + c = 0; + c < e.length; + c++ + ) + '.' === (d = e[c]) + ? (e.splice(c, 1), --c) + : '..' === d && + (0 === c || + (1 === c && '..' === e[2]) || + '..' === e[c - 1] || + (0 < c && (e.splice(c - 1, 2), (c -= 2)))); + e = e.join('/'); + } + if ((p || f) && h) { + for (c = (n = e.split('/')).length; 0 < c; --c) { + if (((s = n.slice(0, c).join('/')), p)) + for (u = p.length; 0 < u; --u) + if (((i = h[p.slice(0, u).join('/')]), (i = i && i[s]))) { + (r = i), (o = c); + break; + } + if (r) break; + !a && f && f[s] && ((a = f[s]), (l = c)); + } + !r && a && ((r = a), (o = l)), + r && (n.splice(0, o, r), (e = n.join('/'))); + } + return e; + } + function w(t, n) { + return function () { + var e = a.call(arguments, 0); + return ( + 'string' != typeof e[0] && 1 === e.length && e.push(null), + o.apply(p, e.concat([t, n])) + ); + }; + } + function x(e) { + var t; + if ( + (b(m, e) && ((t = m[e]), delete m[e], (v[e] = !0), r.apply(p, t)), + !b(g, e) && !b(v, e)) + ) + throw new Error('No ' + e); + return g[e]; + } + function c(e) { + var t, + n = e ? e.indexOf('!') : -1; + return ( + -1 < n && ((t = e.substring(0, n)), (e = e.substring(n + 1, e.length))), + [t, e] + ); + } + function A(e) { + return e ? c(e) : []; + } + var u = s.require('jquery.select2'); + return (t.fn.select2.amd = s), u; + }); + \ No newline at end of file diff --git a/public/js/setting.js b/public/js/setting.js new file mode 100644 index 0000000..e69de29 diff --git a/public/js/signature.js b/public/js/signature.js new file mode 100644 index 0000000..fc6b82a --- /dev/null +++ b/public/js/signature.js @@ -0,0 +1,48 @@ +var canvas = document.getElementById('signature-pad'); + +// Adjust canvas coordinate space taking into account pixel ratio, +// to make it look crisp on mobile devices. +// This also causes canvas to be cleared. + +function resizeCanvas() { + // When zoomed out to less than 100%, for some very strange reason, + // some browsers report devicePixelRatio as less than 1 + // and only part of the canvas is cleared then. + var ratio = Math.max(window.devicePixelRatio || 1, 1); + canvas.width = canvas.offsetWidth * ratio; + canvas.height = canvas.offsetHeight * ratio; + canvas.getContext('2d').scale(ratio, ratio); +} + +if (canvas) { + window.onresize = resizeCanvas; + resizeCanvas(); +} + +var signaturePad = new SignaturePad(canvas, { + backgroundColor: 'rgb(255, 255, 255)', // necessary for saving image as JPEG; can be removed is only saving as PNG or SVG +}); + +document.getElementById('save-png').addEventListener('click', function () { + if (signaturePad.isEmpty()) { + return alert('Please provide a signature first.'); + } + + var data = signaturePad.toDataURL('image/png'); + console.log(data); +}); + +document.getElementById('clear').addEventListener('click', function () { + signaturePad.clear(); +}); + +document.getElementById('draw').addEventListener('click', function () { + var ctx = canvas.getContext('2d'); + console.log(ctx.globalCompositeOperation); + ctx.globalCompositeOperation = 'source-over'; // default value +}); + +document.getElementById('erase').addEventListener('click', function () { + var ctx = canvas.getContext('2d'); + ctx.globalCompositeOperation = 'destination-out'; +}); diff --git a/public/js/suneditor.js b/public/js/suneditor.js new file mode 100644 index 0000000..96abeb7 --- /dev/null +++ b/public/js/suneditor.js @@ -0,0 +1,24 @@ +if (document.getElementById('mkd-suneditor')) { + SUNEDITOR.create(document.getElementById('mkd-suneditor') || 'mkd-suneditor', { + // All of the plugins are loaded in the "window.SUNEDITOR" object in dist/suneditor.min.js file + // Insert options + // Language global object (default: en) + height: 500, + width: '100%', + buttonList: [ + // Default + ['undo', 'redo'], + ['font', 'fontSize', 'formatBlock'], + ['paragraphStyle', 'blockquote'], + ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'], + ['fontColor', 'hiliteColor', 'textStyle'], + ['removeFormat'], + ['outdent', 'indent'], + ['align', 'horizontalRule', 'list', 'lineHeight'], + ['table', 'link', 'image', 'video', 'audio'], + ['imageGallery'], + ['fullScreen', 'showBlocks', 'codeView'], + ['preview', 'print'], + ], + }); +} diff --git a/public/modules/css/barcode.css b/public/modules/css/barcode.css new file mode 100644 index 0000000..25e32a0 --- /dev/null +++ b/public/modules/css/barcode.css @@ -0,0 +1,255 @@ +#container { + width: 640px; + margin: 20px auto; + padding: 10px; +} + +#interactive.viewport { + width: 640px; + height: 480px; +} + +#interactive.viewport canvas, +video { + float: left; + width: 640px; + height: 480px; +} + +#interactive.viewport canvas.drawingBuffer, +video.drawingBuffer { + margin-left: -640px; +} + +.controls fieldset { + border: none; + margin: 0; + padding: 0; +} + +.controls .input-group { + float: left; +} + +.controls .input-group input, +.controls .input-group button { + display: block; +} + +.controls .reader-config-group { + float: right; +} + +.controls .reader-config-group label { + display: block; +} + +.controls .reader-config-group label span { + width: 9rem; + display: inline-block; + text-align: right; +} + +.controls:after { + content: ''; + display: block; + clear: both; +} + +#result_strip { + margin: 10px 0; + border-top: 1px solid #eee; + border-bottom: 1px solid #eee; + padding: 10px 0; +} + +#result_strip > ul { + padding: 0; + margin: 0; + list-style-type: none; + width: auto; + overflow-x: auto; + overflow-y: hidden; + white-space: nowrap; +} + +#result_strip > ul > li { + display: inline-block; + vertical-align: middle; + width: 160px; +} + +#result_strip > ul > li .thumbnail { + padding: 5px; + margin: 4px; + border: 1px dashed #ccc; +} + +#result_strip > ul > li .thumbnail img { + max-width: 140px; +} + +#result_strip > ul > li .thumbnail .caption { + white-space: normal; +} + +#result_strip > ul > li .thumbnail .caption h4 { + text-align: center; + word-wrap: break-word; + height: 40px; + margin: 0px; +} + +#result_strip > ul:after { + content: ''; + display: table; + clear: both; +} + +.scanner-overlay { + display: none; + width: 640px; + height: 510px; + position: absolute; + padding: 20px; + top: 50%; + margin-top: -275px; + left: 50%; + margin-left: -340px; + background-color: #fff; + -moz-box-shadow: #333333 0px 4px 10px; + -webkit-box-shadow: #333333 0px 4px 10px; + box-shadow: #333333 0px 4px 10px; +} + +.scanner-overlay > .header { + position: relative; + margin-bottom: 14px; +} + +.scanner-overlay > .header h4, +.scanner-overlay > .header .close { + line-height: 16px; +} + +.scanner-overlay > .header h4 { + margin: 0px; + padding: 0px; +} + +.scanner-overlay > .header .close { + position: absolute; + right: 0px; + top: 0px; + height: 16px; + width: 16px; + text-align: center; + font-weight: bold; + font-size: 14px; + cursor: pointer; +} + +i.icon-24-scan { + width: 24px; + height: 24px; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QzFFMjMzNTBFNjcwMTFFMkIzMERGOUMzMzEzM0E1QUMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QzFFMjMzNTFFNjcwMTFFMkIzMERGOUMzMzEzM0E1QUMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDMUUyMzM0RUU2NzAxMUUyQjMwREY5QzMzMTMzQTVBQyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDMUUyMzM0RkU2NzAxMUUyQjMwREY5QzMzMTMzQTVBQyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PtQr90wAAAUuSURBVHjanFVLbFRVGP7ua97T9DGPthbamAYYBNSMVbBpjCliWWGIEBMWsnDJxkh8RDeEDW5MDGticMmGBWnSlRSCwgLFNkqmmrRIqzjTznTazkxn5s7c6/efzm0G0Jhwkj/nP+d/nv91tIWFBTQaDQWapkGW67p4ltUub5qmAi0UCqF/a/U2m81tpmddotwwDGSz2dzi4uKSaOucnJycGhsbe1XXdQiIIcdxEAgEtgXq9brySHCht79UXi/8QheawN27d385fPjwuEl6XyKR6LdtW7t06RLK5TKOHj2K/fv3Q87Dw8OYn5/HiRMnMDs7i5mZGQwODiqlPp8PuVwO6XRaOXb16lXl1OnTp5FMJvtosF8M+MWLarWqGJaWlpBKpRRcu3YN4+PjmJ6exsTEhDJw5coVjI6OKgPhcBiZTAbxeBx+vx+XL19Gd3c3Tp48Ka9zqDYgBlTQxYNgMIhIJKLCILkQb+TZsgvdsiyFi+feWRR7oRNZyanQtvW2V4DEUUBiK2eJpeDirSyhCe7F2QPh8fiEp72i9PbsC5G52DbiKZA771yr1dTuGfJ4PQNPFoAyQNR1aNEmsS5eyB3PgjeooMZd2AWvNmzYci/Gea7TeFOcI93jV/K67noGmi4vdRI9gPSDeMLSdKUBZZczlWm1rTtHjLZ24d+WER2tc8N1m+Y+ID74wx0zGYvhg9UNrJdtHJyZRdQfwPsrq9g99xsGlgsYmr6BNzO/IVwsYfjBQ6XYz6JI/72MV366B5/lw0elOkJWGUM3bmKtWjXSLuLaBWhnPnnp0FfoiFi4+TMfVAb2poBkDLjO845uYLEAjL4ALGWBP5YAOsP4AJYBFDaB1HOSVWD2PuV95H2RdV93Lv74/cf6p6Zxq/h6OofeOPJBC39JtONdwOAAViOs4p4OFGTf0Uc8iiyrr9YdQrUnDLsngrVOC0jQib44HlF2RafRZBz1Qy+vfhgK3NJZBlrm+LEm9qWwzFgLU7Ozg0JxZP06jQSRpQ7EerAWDSt6PuhHPmChEAog56fCLvJT5hHTm3OZkz3DyLx7XNWTGEA1GkV14gjWgwbW0ESVjYRwCOuai03L5E7OUBAV4kXSS4auoGIaKOma4m8EA5R1sMEGLh95C+XuLph0WJWpxepYYLtfT0RRgY1KgNODY6BoaChRuEhDCIZQYseuki5KN6hcQHiq7OZNv4/Zq2O6P4Lfkwn46vZjjaYZrIpvWbpzjLErrc4xUGE4avRedpYJalRcIl5hQius/SrPm9xrNOQYJhao6BvNUeWqtY8KaWuNjHOFAr7mM9f4NA4UbKysoUJ8PV9UzVOx6wxDDWUOxnK1pmCD07fOMAvtIsM3l89Dl3HRGhVma9AZMqjOnz2LQqWCxs6dqr3T7x1DTzKJaG8SekcHhg4cgI/56uKdlKnBV/WndqN3YAB/7tyBd3oT6GBIOzs7kc/nDfFdDFT5bS73cp06dQoaPa/Rw/rtO/resTHxxE2m9rCrbSR27UJCcMf1BpiA5rAAGgdfc868fUR1sMwj0cm9Iu9IctweisViB3hhKTHDcHc5jv/LspbyaZrR1OD82/fIlOkuB9LnEWRmDX2TsddUPg3D5gvuc0je0rZaD5EW6G3yjS+A3eeBEWq3XW/Abw1HhUspXADufQb86oW7tZytkYCN//3hHwBvDALPi8EnSOYK8DAOfCc2h4aGcO7cuafkzampqf9UripH12/DtOZbx8ciVGzYy5OO40o25ascGRl5Ssc/AgwAjW3JwqIUjSYAAAAASUVORK5CYII='); + display: inline-block; + background-repeat: no-repeat; + line-height: 24px; + margin-top: 1px; + vertical-align: text-top; +} + +@media (max-width: 603px) { + #container { + width: 300px; + margin: 10px auto; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; + } + + #container form.voucher-form input.voucher-code { + width: 180px; + } +} +@media (max-width: 603px) { + .reader-config-group { + width: 100%; + } + + .reader-config-group label > span { + width: 50%; + } + + .reader-config-group label > select, + .reader-config-group label > input { + max-width: calc(50% - 2px); + } + + #interactive.viewport { + width: 300px; + height: 300px; + overflow: hidden; + } + + #interactive.viewport canvas, + video { + margin-top: -50px; + width: 300px; + height: 400px; + } + + #interactive.viewport canvas.drawingBuffer, + video.drawingBuffer { + margin-left: -300px; + } + + #result_strip { + margin-top: 5px; + padding-top: 5px; + } + + #result_strip ul.thumbnails > li { + width: 150px; + } + + #result_strip ul.thumbnails > li .thumbnail .imgWrapper { + width: 130px; + height: 130px; + overflow: hidden; + } + + #result_strip ul.thumbnails > li .thumbnail .imgWrapper img { + margin-top: -25px; + width: 130px; + height: 180px; + } +} +@media (max-width: 603px) { + .overlay.scanner { + width: 640px; + height: 510px; + padding: 20px; + margin-top: -275px; + margin-left: -340px; + background-color: #fff; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; + } + + .overlay.scanner > .header { + margin-bottom: 14px; + } + + .overlay.scanner > .header h4, + .overlay.scanner > .header .close { + line-height: 16px; + } + + .overlay.scanner > .header .close { + height: 16px; + width: 16px; + } +} diff --git a/public/modules/css/qrcode.css b/public/modules/css/qrcode.css new file mode 100644 index 0000000..e9de1ef --- /dev/null +++ b/public/modules/css/qrcode.css @@ -0,0 +1,33 @@ +#qr-container { + text-align: center; + margin: 10px; + max-width: 400px; +} + +#qr-canvas { + margin: auto; + max-width: 400px; +} + +#qr-canvas-container { + max-width: 400px; +} + +#btn-scan-qr { + cursor: pointer; + font-size: 80px; +} + +#btn-scan-qr img { + height: 10em; + padding: 15px; + margin: 15px; + background: white; +} + +#qr-result { + font-size: 1.2em; + margin: 20px auto; + padding: 20px; + max-width: 700px; +} diff --git a/public/modules/css/signature.css b/public/modules/css/signature.css new file mode 100644 index 0000000..df3c3fa --- /dev/null +++ b/public/modules/css/signature.css @@ -0,0 +1,18 @@ +.signature-wrapper { + position: relative; + width: 400px; + height: 200px; + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.signature-pad { + position: absolute; + left: 0; + top: 0; + width: 400px; + height: 200px; + background-color: white; +} diff --git a/public/modules/css/suneditor.css b/public/modules/css/suneditor.css new file mode 100644 index 0000000..f258085 --- /dev/null +++ b/public/modules/css/suneditor.css @@ -0,0 +1 @@ +@import 'https://cdn.jsdelivr.net/npm/suneditor@latest/dist/css/suneditor.min.css'; diff --git a/public/modules/css/uppload.css b/public/modules/css/uppload.css new file mode 100644 index 0000000..401367a --- /dev/null +++ b/public/modules/css/uppload.css @@ -0,0 +1,2 @@ +@import "https://unpkg.com/uppload/dist/uppload.css"; +@import "https://unpkg.com/uppload/dist/themes/light.css"; \ No newline at end of file diff --git a/public/modules/doc.readme b/public/modules/doc.readme new file mode 100644 index 0000000..cc8bf2f --- /dev/null +++ b/public/modules/doc.readme @@ -0,0 +1,31 @@ +Upload example + + +Signature example +
        + +
        + + + +Suneditor example + + +QRCode scanner example + + +Barcode example +
        +
        +
        \ No newline at end of file diff --git a/public/modules/js/uppload.js b/public/modules/js/uppload.js new file mode 100644 index 0000000..18344d3 --- /dev/null +++ b/public/modules/js/uppload.js @@ -0,0 +1,113 @@ +const { + Uppload, + Instagram, + Facebook, + Camera, + URL, + Local, + GIPHY, + Unsplash, + Pixabay, + Pexels, + Screenshot, + Crop, + Rotate, + Flip, + Blur, + Flickr, + NineGag, + Pinterest, + en, + DeviantArt, + ArtStation, + Twitter, + Flipboard, + Fotki, + LinkedIn, + Reddit, + Tumblr, + WeHeartIt, + Brightness, + Contrast, + Grayscale, + HueRotate, + Invert, + Saturate, + Sepia, + xhrUploader, +} = require('uppload'); + +let uploadButtons = [], + hiddenInputElement, + shownMedia; +document.querySelectorAll('button.mkd-uppload-image-button').forEach(function (btn) { + uploadButtons.push(btn); + btn.addEventListener('click', function () { + hiddenInputElement = document.getElementById(`file_${this.dataset.uploadFor}`); + shownMedia = document.getElementById(`media_${this.dataset.uploadFor}`); + }); +}); +const uploader = new Uppload({ + call: uploadButtons, + lang: en, + uploader: xhrUploader({ + endpoint: '/v1/upload/file', + fileKeyName: 'file', + responseFunction: (responseText) => { + const data = JSON.parse(responseText); + console.log('data', data); + hiddenInputElement.value = data.id; + + if (shownMedia) { + shownMedia.src = data.url; + if (shownMedia.nodeName == 'SOURCE') { + const videoPlaying = shownMedia.parentNode; + videoPlaying.load(); + videoPlaying.play(); + } + } + }, + }), +}); + +// These are our public demo API keys +// You should create your own (free!) account on these services and use your own API keys + +uploader.use([ + new Local({ + mimeTypes: ['image/jpeg', 'image/jpg', 'image/png', 'video/mp4', 'video/ogg'], + }), + new Camera(), + new Instagram(), + new URL(), + new Facebook(), + new Screenshot(), + new Pinterest(), + new Flickr(), + new Twitter(), + new NineGag(), + new DeviantArt(), + new ArtStation(), + new Flipboard(), + new Fotki(), + new LinkedIn(), + new Reddit(), + new Tumblr(), + new WeHeartIt(), +]); + +uploader.use([ + new Crop({ + aspectRatio: 1, + }), + new Rotate(), + new Blur(), + new Brightness(), + new Flip(), + new Contrast(), + new Grayscale(), + new HueRotate(), + new Invert(), + new Saturate(), + new Sepia(), +]); diff --git a/public/modules/scripts/camera.script b/public/modules/scripts/camera.script new file mode 100644 index 0000000..335d5d7 --- /dev/null +++ b/public/modules/scripts/camera.script @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/modules/scripts/qrcode.script b/public/modules/scripts/qrcode.script new file mode 100644 index 0000000..580696f --- /dev/null +++ b/public/modules/scripts/qrcode.script @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/modules/scripts/signature.script b/public/modules/scripts/signature.script new file mode 100644 index 0000000..7bdff9f --- /dev/null +++ b/public/modules/scripts/signature.script @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/modules/scripts/suneditor.script b/public/modules/scripts/suneditor.script new file mode 100644 index 0000000..2a1d2de --- /dev/null +++ b/public/modules/scripts/suneditor.script @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/public/quiz-test.html b/public/quiz-test.html new file mode 100644 index 0000000..b09189a --- /dev/null +++ b/public/quiz-test.html @@ -0,0 +1,301 @@ + + + + + + + + + + Quiz + + + +
        +
        +
        +

        Create Yours

        +
        TEST SKIN CARE QUIZ
        +
        +
        +
        +

        + Let’s start our journey + just for you. +

        +

        + We are experts on skin and skincare actives.. +

        + +
        +
        + +
        +
        +
        +
        + +
        +
        +
        + +
        +
        +
        + +
        +
        +
        + + + +
        +
        +

        + +

        +
        +
        +
        +

        + +

        +
        +
        +

        + +

        +
        +
        + +
        +
        + +
        + +
        +
        +
        + +
        +
        + +
        + +
        +
        +
        + +
        +
        + +
        +
        + +
        +
        +
        + +
        +
        +
        + +
        +
        +
        + + +
        +
        + +
        +
        +
        +
        + +
        +
        + +
        +
        + +
        +
        + + +
        +
        + +
        +
        +
        +
        +
        + +
        +
        +
        + + + +
        +
        +
        + +

        + +

        +
        +
        +
        +
        + +
        +
        +
        + + + +
        +
        +
        +
        + +
        +
        + +
        +
        +
        +
        +
        Environmental Profile
        +
        +
        + Humidity: + +
        +
        + Temperature: + +
        +
        + Sun: + +
        +
        + Pollution: + +
        +
        +
        +
        +
        + +
        +
        +
        +
        + image missing +
        +
        +

        Preparing your custom formula...

        +
        +
        +
        +
        + +
        +
        +
        + +
        +
        +
        +
        +
        + +
        +
        +
        +

        Your Skin Profile is Complete!

        +
        +
        +

        + Based on what you’ve shared, your skin is pretty nicely balanced. We’ll look to reduce your pores, protecting you from pollution and sealing out toxins. We’ll also target your + blackheads and tone out your skin for a nice, even look. +

        +
        +
        + +
        +
        +
        +
        +
        +
        +
        +

        About these results

        +
        +
        +

        These results tell us exactly how much support you need in which areas - Your custom forumlas will be tailored to these measurements.

        +
        +
        + +
        +
        +
        +
        +
        + +
        +
        +
        +
        +
        + +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        + + + + + + diff --git a/public/uploads/.gitkeep b/public/uploads/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/uploads/1640963582601-Acai.jpg b/public/uploads/1640963582601-Acai.jpg new file mode 100644 index 0000000..922eebe Binary files /dev/null and b/public/uploads/1640963582601-Acai.jpg differ diff --git a/public/uploads/1640964134964-Acai.jpg b/public/uploads/1640964134964-Acai.jpg new file mode 100644 index 0000000..922eebe Binary files /dev/null and b/public/uploads/1640964134964-Acai.jpg differ diff --git a/public/uploads/1640964227759-Blank.jpg b/public/uploads/1640964227759-Blank.jpg new file mode 100644 index 0000000..374592b Binary files /dev/null and b/public/uploads/1640964227759-Blank.jpg differ diff --git a/public/uploads/1640964242741-Chia.jpg b/public/uploads/1640964242741-Chia.jpg new file mode 100644 index 0000000..5afa63e Binary files /dev/null and b/public/uploads/1640964242741-Chia.jpg differ diff --git a/public/uploads/1640964255698-Cogon Grass.jpg b/public/uploads/1640964255698-Cogon Grass.jpg new file mode 100644 index 0000000..0c6edb4 Binary files /dev/null and b/public/uploads/1640964255698-Cogon Grass.jpg differ diff --git a/public/uploads/1640964272190-Cucumber.jpg b/public/uploads/1640964272190-Cucumber.jpg new file mode 100644 index 0000000..708ea58 Binary files /dev/null and b/public/uploads/1640964272190-Cucumber.jpg differ diff --git a/public/uploads/1640964466940-Blank.jpg b/public/uploads/1640964466940-Blank.jpg new file mode 100644 index 0000000..374592b Binary files /dev/null and b/public/uploads/1640964466940-Blank.jpg differ diff --git a/public/uploads/1640964479508-Chia.jpg b/public/uploads/1640964479508-Chia.jpg new file mode 100644 index 0000000..5afa63e Binary files /dev/null and b/public/uploads/1640964479508-Chia.jpg differ diff --git a/public/uploads/1640965510067-affordable-skincare-singapore.png b/public/uploads/1640965510067-affordable-skincare-singapore.png new file mode 100644 index 0000000..1a436a7 Binary files /dev/null and b/public/uploads/1640965510067-affordable-skincare-singapore.png differ diff --git a/public/uploads/1640965875683-affordable-skincare-singapore.png b/public/uploads/1640965875683-affordable-skincare-singapore.png new file mode 100644 index 0000000..0404cb6 Binary files /dev/null and b/public/uploads/1640965875683-affordable-skincare-singapore.png differ diff --git a/public/uploads/1641325210686-affordable-skincare-singapore.png b/public/uploads/1641325210686-affordable-skincare-singapore.png new file mode 100644 index 0000000..3135a04 Binary files /dev/null and b/public/uploads/1641325210686-affordable-skincare-singapore.png differ diff --git a/public/uploads/1642095020510-6 Glasses of Water-sl.png b/public/uploads/1642095020510-6 Glasses of Water-sl.png new file mode 100644 index 0000000..c820bc0 Binary files /dev/null and b/public/uploads/1642095020510-6 Glasses of Water-sl.png differ diff --git a/public/uploads/1642095053658-2.5 Glasses of Water -sl.png b/public/uploads/1642095053658-2.5 Glasses of Water -sl.png new file mode 100644 index 0000000..f9401aa Binary files /dev/null and b/public/uploads/1642095053658-2.5 Glasses of Water -sl.png differ diff --git a/public/uploads/1642098020219-2 Blotchiness.png b/public/uploads/1642098020219-2 Blotchiness.png new file mode 100644 index 0000000..599ab4c Binary files /dev/null and b/public/uploads/1642098020219-2 Blotchiness.png differ diff --git a/public/uploads/1642098049111-3 Blotchiness.png b/public/uploads/1642098049111-3 Blotchiness.png new file mode 100644 index 0000000..2feed52 Binary files /dev/null and b/public/uploads/1642098049111-3 Blotchiness.png differ diff --git a/public/uploads/1642098073770-4 Blotchiness.png b/public/uploads/1642098073770-4 Blotchiness.png new file mode 100644 index 0000000..4e2dfa9 Binary files /dev/null and b/public/uploads/1642098073770-4 Blotchiness.png differ diff --git a/public/uploads/1642103670252-5 Very Oily.png b/public/uploads/1642103670252-5 Very Oily.png new file mode 100644 index 0000000..fc980d8 Binary files /dev/null and b/public/uploads/1642103670252-5 Very Oily.png differ diff --git a/public/uploads/1642103710346-4 Oily.png b/public/uploads/1642103710346-4 Oily.png new file mode 100644 index 0000000..9e67ff6 Binary files /dev/null and b/public/uploads/1642103710346-4 Oily.png differ diff --git a/public/uploads/1642103734937-3 Combo.png b/public/uploads/1642103734937-3 Combo.png new file mode 100644 index 0000000..d64a99b Binary files /dev/null and b/public/uploads/1642103734937-3 Combo.png differ diff --git a/public/uploads/1642103756362-2 Dry.png b/public/uploads/1642103756362-2 Dry.png new file mode 100644 index 0000000..27c7461 Binary files /dev/null and b/public/uploads/1642103756362-2 Dry.png differ diff --git a/public/uploads/1642103776244-1 Very Dry.png b/public/uploads/1642103776244-1 Very Dry.png new file mode 100644 index 0000000..210eafa Binary files /dev/null and b/public/uploads/1642103776244-1 Very Dry.png differ diff --git a/public/uploads/1642103863474-5 Very Oily.png b/public/uploads/1642103863474-5 Very Oily.png new file mode 100644 index 0000000..fc980d8 Binary files /dev/null and b/public/uploads/1642103863474-5 Very Oily.png differ diff --git a/public/uploads/1642103900672-3 Combo.png b/public/uploads/1642103900672-3 Combo.png new file mode 100644 index 0000000..d64a99b Binary files /dev/null and b/public/uploads/1642103900672-3 Combo.png differ diff --git a/public/uploads/1642106832840-2 mildly Sensitive.png b/public/uploads/1642106832840-2 mildly Sensitive.png new file mode 100644 index 0000000..8abe744 Binary files /dev/null and b/public/uploads/1642106832840-2 mildly Sensitive.png differ diff --git a/public/uploads/1642106921592-2 mildly Sensitive.png b/public/uploads/1642106921592-2 mildly Sensitive.png new file mode 100644 index 0000000..dcc7d73 Binary files /dev/null and b/public/uploads/1642106921592-2 mildly Sensitive.png differ diff --git a/public/uploads/1642107107486-3 Moderately Sensitive.png b/public/uploads/1642107107486-3 Moderately Sensitive.png new file mode 100644 index 0000000..715b653 Binary files /dev/null and b/public/uploads/1642107107486-3 Moderately Sensitive.png differ diff --git a/public/uploads/1642107296761-4 Sensitive.png b/public/uploads/1642107296761-4 Sensitive.png new file mode 100644 index 0000000..dc4841e Binary files /dev/null and b/public/uploads/1642107296761-4 Sensitive.png differ diff --git a/public/uploads/1644264414098-No Wrinkles.png b/public/uploads/1644264414098-No Wrinkles.png new file mode 100644 index 0000000..94f5ec6 Binary files /dev/null and b/public/uploads/1644264414098-No Wrinkles.png differ diff --git a/public/uploads/1644264577717-Cover Image - No Wrinkles.png b/public/uploads/1644264577717-Cover Image - No Wrinkles.png new file mode 100644 index 0000000..72b2a95 Binary files /dev/null and b/public/uploads/1644264577717-Cover Image - No Wrinkles.png differ diff --git a/public/uploads/1645467318181-1 Low Res.png b/public/uploads/1645467318181-1 Low Res.png new file mode 100644 index 0000000..a5e35cf Binary files /dev/null and b/public/uploads/1645467318181-1 Low Res.png differ diff --git a/public/uploads/1645467407794-1 Low Res.png b/public/uploads/1645467407794-1 Low Res.png new file mode 100644 index 0000000..a5e35cf Binary files /dev/null and b/public/uploads/1645467407794-1 Low Res.png differ diff --git a/public/uploads/1645467426080-2 Low Res.png b/public/uploads/1645467426080-2 Low Res.png new file mode 100644 index 0000000..791fb57 Binary files /dev/null and b/public/uploads/1645467426080-2 Low Res.png differ diff --git a/public/uploads/1645467438524-3 Low Res.png b/public/uploads/1645467438524-3 Low Res.png new file mode 100644 index 0000000..fc93f02 Binary files /dev/null and b/public/uploads/1645467438524-3 Low Res.png differ diff --git a/public/uploads/1645467453261-3 Low Res.png b/public/uploads/1645467453261-3 Low Res.png new file mode 100644 index 0000000..fc93f02 Binary files /dev/null and b/public/uploads/1645467453261-3 Low Res.png differ diff --git a/public/uploads/1645467469837-1 Low Res.png b/public/uploads/1645467469837-1 Low Res.png new file mode 100644 index 0000000..a5e35cf Binary files /dev/null and b/public/uploads/1645467469837-1 Low Res.png differ diff --git a/public/uploads/1645467481480-2 Low Res.png b/public/uploads/1645467481480-2 Low Res.png new file mode 100644 index 0000000..791fb57 Binary files /dev/null and b/public/uploads/1645467481480-2 Low Res.png differ diff --git a/public/uploads/1645467492327-3 Low Res.png b/public/uploads/1645467492327-3 Low Res.png new file mode 100644 index 0000000..fc93f02 Binary files /dev/null and b/public/uploads/1645467492327-3 Low Res.png differ diff --git a/public/uploads/1645467504528-4 Low Res.png b/public/uploads/1645467504528-4 Low Res.png new file mode 100644 index 0000000..058518b Binary files /dev/null and b/public/uploads/1645467504528-4 Low Res.png differ diff --git a/public/uploads/1645467517361-5 Low Res.png b/public/uploads/1645467517361-5 Low Res.png new file mode 100644 index 0000000..4361e3a Binary files /dev/null and b/public/uploads/1645467517361-5 Low Res.png differ diff --git a/public/uploads/1645467530448-6 Low Res.png b/public/uploads/1645467530448-6 Low Res.png new file mode 100644 index 0000000..1adf6de Binary files /dev/null and b/public/uploads/1645467530448-6 Low Res.png differ diff --git a/public/uploads/1645467543957-7 Low Res.png b/public/uploads/1645467543957-7 Low Res.png new file mode 100644 index 0000000..387a8a7 Binary files /dev/null and b/public/uploads/1645467543957-7 Low Res.png differ diff --git a/public/uploads/1645467561363-8 Low Res.png b/public/uploads/1645467561363-8 Low Res.png new file mode 100644 index 0000000..93e14d4 Binary files /dev/null and b/public/uploads/1645467561363-8 Low Res.png differ diff --git a/public/uploads/1645467573529-9 Low Res.png b/public/uploads/1645467573529-9 Low Res.png new file mode 100644 index 0000000..fe96b4a Binary files /dev/null and b/public/uploads/1645467573529-9 Low Res.png differ diff --git a/public/uploads/1645467588458-10 Low Res.png b/public/uploads/1645467588458-10 Low Res.png new file mode 100644 index 0000000..0f0cf5a Binary files /dev/null and b/public/uploads/1645467588458-10 Low Res.png differ diff --git a/public/uploads/1645467602697-11 Low Res.png b/public/uploads/1645467602697-11 Low Res.png new file mode 100644 index 0000000..1d58e53 Binary files /dev/null and b/public/uploads/1645467602697-11 Low Res.png differ diff --git a/public/uploads/1645467615895-12 Low Res.png b/public/uploads/1645467615895-12 Low Res.png new file mode 100644 index 0000000..fea8706 Binary files /dev/null and b/public/uploads/1645467615895-12 Low Res.png differ diff --git a/public/uploads/1645467628895-13 Low Res.png b/public/uploads/1645467628895-13 Low Res.png new file mode 100644 index 0000000..19a88f1 Binary files /dev/null and b/public/uploads/1645467628895-13 Low Res.png differ diff --git a/public/uploads/1645467642940-14 Low Res.png b/public/uploads/1645467642940-14 Low Res.png new file mode 100644 index 0000000..a692c19 Binary files /dev/null and b/public/uploads/1645467642940-14 Low Res.png differ diff --git a/public/uploads/1645467656372-15 Low Res.png b/public/uploads/1645467656372-15 Low Res.png new file mode 100644 index 0000000..e2f7f7b Binary files /dev/null and b/public/uploads/1645467656372-15 Low Res.png differ diff --git a/public/uploads/placeholder.jpg b/public/uploads/placeholder.jpg new file mode 100644 index 0000000..cce381e Binary files /dev/null and b/public/uploads/placeholder.jpg differ diff --git a/resolvers/.gitkeep b/resolvers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resolvers/all/.gitkeep b/resolvers/all/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resolvers/all/allActive.js b/resolvers/all/allActive.js new file mode 100644 index 0000000..7281ee6 --- /dev/null +++ b/resolvers/all/allActive.js @@ -0,0 +1,56 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * active Resolve All + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const { ApolloError } = require('apollo-server-express'); +const Sequelize = require('sequelize'); +const { last } = require('lodash'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, { first, after }, { db, credential }, info) => { + //Check Auth if user allowed + try { + const attributes = db.active.intersection(graphqlFields(info).edges.node); + + const options = { + where: {}, + limit: first, + attributes, + }; + + if (after) { + options.where = { + id: { + [Sequelize.Op.gt]: after, + }, + }; + } + + const { count, rows } = await db.active.findAndCountAll(options); + + const edges = rows.map((active) => ({ + cursor: active.id, + node: active, + })); + + const pageInfo = { + endCursor: last(edges)?.cursor, + hasNextPage: 0 < count - first, + }; + + return { + edges, + pageInfo, + }; + + } catch (error) { + console.log('active -> error', error); + return new ApolloError('InternalServerError'); + } +} diff --git a/resolvers/all/allActivityLog.js b/resolvers/all/allActivityLog.js new file mode 100644 index 0000000..6540def --- /dev/null +++ b/resolvers/all/allActivityLog.js @@ -0,0 +1,56 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * activity_log Resolve All + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const { ApolloError } = require('apollo-server-express'); +const Sequelize = require('sequelize'); +const { last } = require('lodash'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, { first, after }, { db, credential }, info) => { + //Check Auth if user allowed + try { + const attributes = db.activity_log.intersection(graphqlFields(info).edges.node); + + const options = { + where: {}, + limit: first, + attributes, + }; + + if (after) { + options.where = { + id: { + [Sequelize.Op.gt]: after, + }, + }; + } + + const { count, rows } = await db.activity_log.findAndCountAll(options); + + const edges = rows.map((activity_log) => ({ + cursor: activity_log.id, + node: activity_log, + })); + + const pageInfo = { + endCursor: last(edges)?.cursor, + hasNextPage: 0 < count - first, + }; + + return { + edges, + pageInfo, + }; + + } catch (error) { + console.log('activity_log -> error', error); + return new ApolloError('InternalServerError'); + } +} diff --git a/resolvers/all/allAnswer.js b/resolvers/all/allAnswer.js new file mode 100644 index 0000000..c863560 --- /dev/null +++ b/resolvers/all/allAnswer.js @@ -0,0 +1,56 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * answer Resolve All + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const { ApolloError } = require('apollo-server-express'); +const Sequelize = require('sequelize'); +const { last } = require('lodash'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, { first, after }, { db, credential }, info) => { + //Check Auth if user allowed + try { + const attributes = db.answer.intersection(graphqlFields(info).edges.node); + + const options = { + where: {}, + limit: first, + attributes, + }; + + if (after) { + options.where = { + id: { + [Sequelize.Op.gt]: after, + }, + }; + } + + const { count, rows } = await db.answer.findAndCountAll(options); + + const edges = rows.map((answer) => ({ + cursor: answer.id, + node: answer, + })); + + const pageInfo = { + endCursor: last(edges)?.cursor, + hasNextPage: 0 < count - first, + }; + + return { + edges, + pageInfo, + }; + + } catch (error) { + console.log('answer -> error', error); + return new ApolloError('InternalServerError'); + } +} diff --git a/resolvers/all/allCredential.js b/resolvers/all/allCredential.js new file mode 100644 index 0000000..059fb63 --- /dev/null +++ b/resolvers/all/allCredential.js @@ -0,0 +1,56 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * credential Resolve All + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const { ApolloError } = require('apollo-server-express'); +const Sequelize = require('sequelize'); +const { last } = require('lodash'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, { first, after }, { db, credential }, info) => { + //Check Auth if user allowed + try { + const attributes = db.credential.intersection(graphqlFields(info).edges.node); + + const options = { + where: {}, + limit: first, + attributes, + }; + + if (after) { + options.where = { + id: { + [Sequelize.Op.gt]: after, + }, + }; + } + + const { count, rows } = await db.credential.findAndCountAll(options); + + const edges = rows.map((credential) => ({ + cursor: credential.id, + node: credential, + })); + + const pageInfo = { + endCursor: last(edges)?.cursor, + hasNextPage: 0 < count - first, + }; + + return { + edges, + pageInfo, + }; + + } catch (error) { + console.log('credential -> error', error); + return new ApolloError('InternalServerError'); + } +} diff --git a/resolvers/all/allImage.js b/resolvers/all/allImage.js new file mode 100644 index 0000000..f814bb3 --- /dev/null +++ b/resolvers/all/allImage.js @@ -0,0 +1,56 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * image Resolve All + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const { ApolloError } = require('apollo-server-express'); +const Sequelize = require('sequelize'); +const { last } = require('lodash'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, { first, after }, { db, credential }, info) => { + //Check Auth if user allowed + try { + const attributes = db.image.intersection(graphqlFields(info).edges.node); + + const options = { + where: {}, + limit: first, + attributes, + }; + + if (after) { + options.where = { + id: { + [Sequelize.Op.gt]: after, + }, + }; + } + + const { count, rows } = await db.image.findAndCountAll(options); + + const edges = rows.map((image) => ({ + cursor: image.id, + node: image, + })); + + const pageInfo = { + endCursor: last(edges)?.cursor, + hasNextPage: 0 < count - first, + }; + + return { + edges, + pageInfo, + }; + + } catch (error) { + console.log('image -> error', error); + return new ApolloError('InternalServerError'); + } +} diff --git a/resolvers/all/allOutputVariable.js b/resolvers/all/allOutputVariable.js new file mode 100644 index 0000000..4067ed3 --- /dev/null +++ b/resolvers/all/allOutputVariable.js @@ -0,0 +1,56 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * output_variable Resolve All + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const { ApolloError } = require('apollo-server-express'); +const Sequelize = require('sequelize'); +const { last } = require('lodash'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, { first, after }, { db, credential }, info) => { + //Check Auth if user allowed + try { + const attributes = db.output_variable.intersection(graphqlFields(info).edges.node); + + const options = { + where: {}, + limit: first, + attributes, + }; + + if (after) { + options.where = { + id: { + [Sequelize.Op.gt]: after, + }, + }; + } + + const { count, rows } = await db.output_variable.findAndCountAll(options); + + const edges = rows.map((output_variable) => ({ + cursor: output_variable.id, + node: output_variable, + })); + + const pageInfo = { + endCursor: last(edges)?.cursor, + hasNextPage: 0 < count - first, + }; + + return { + edges, + pageInfo, + }; + + } catch (error) { + console.log('output_variable -> error', error); + return new ApolloError('InternalServerError'); + } +} diff --git a/resolvers/all/allProfileHeader.js b/resolvers/all/allProfileHeader.js new file mode 100644 index 0000000..83674e5 --- /dev/null +++ b/resolvers/all/allProfileHeader.js @@ -0,0 +1,56 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * profile_header Resolve All + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const { ApolloError } = require('apollo-server-express'); +const Sequelize = require('sequelize'); +const { last } = require('lodash'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, { first, after }, { db, credential }, info) => { + //Check Auth if user allowed + try { + const attributes = db.profile_header.intersection(graphqlFields(info).edges.node); + + const options = { + where: {}, + limit: first, + attributes, + }; + + if (after) { + options.where = { + id: { + [Sequelize.Op.gt]: after, + }, + }; + } + + const { count, rows } = await db.profile_header.findAndCountAll(options); + + const edges = rows.map((profile_header) => ({ + cursor: profile_header.id, + node: profile_header, + })); + + const pageInfo = { + endCursor: last(edges)?.cursor, + hasNextPage: 0 < count - first, + }; + + return { + edges, + pageInfo, + }; + + } catch (error) { + console.log('profile_header -> error', error); + return new ApolloError('InternalServerError'); + } +} diff --git a/resolvers/all/allQuestion.js b/resolvers/all/allQuestion.js new file mode 100644 index 0000000..d20dde5 --- /dev/null +++ b/resolvers/all/allQuestion.js @@ -0,0 +1,56 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * question Resolve All + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const { ApolloError } = require('apollo-server-express'); +const Sequelize = require('sequelize'); +const { last } = require('lodash'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, { first, after }, { db, credential }, info) => { + //Check Auth if user allowed + try { + const attributes = db.question.intersection(graphqlFields(info).edges.node); + + const options = { + where: {}, + limit: first, + attributes, + }; + + if (after) { + options.where = { + id: { + [Sequelize.Op.gt]: after, + }, + }; + } + + const { count, rows } = await db.question.findAndCountAll(options); + + const edges = rows.map((question) => ({ + cursor: question.id, + node: question, + })); + + const pageInfo = { + endCursor: last(edges)?.cursor, + hasNextPage: 0 < count - first, + }; + + return { + edges, + pageInfo, + }; + + } catch (error) { + console.log('question -> error', error); + return new ApolloError('InternalServerError'); + } +} diff --git a/resolvers/all/allQuiz.js b/resolvers/all/allQuiz.js new file mode 100644 index 0000000..74b308b --- /dev/null +++ b/resolvers/all/allQuiz.js @@ -0,0 +1,56 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * quiz Resolve All + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const { ApolloError } = require('apollo-server-express'); +const Sequelize = require('sequelize'); +const { last } = require('lodash'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, { first, after }, { db, credential }, info) => { + //Check Auth if user allowed + try { + const attributes = db.quiz.intersection(graphqlFields(info).edges.node); + + const options = { + where: {}, + limit: first, + attributes, + }; + + if (after) { + options.where = { + id: { + [Sequelize.Op.gt]: after, + }, + }; + } + + const { count, rows } = await db.quiz.findAndCountAll(options); + + const edges = rows.map((quiz) => ({ + cursor: quiz.id, + node: quiz, + })); + + const pageInfo = { + endCursor: last(edges)?.cursor, + hasNextPage: 0 < count - first, + }; + + return { + edges, + pageInfo, + }; + + } catch (error) { + console.log('quiz -> error', error); + return new ApolloError('InternalServerError'); + } +} diff --git a/resolvers/all/allReferLog.js b/resolvers/all/allReferLog.js new file mode 100644 index 0000000..4512cad --- /dev/null +++ b/resolvers/all/allReferLog.js @@ -0,0 +1,56 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * refer_log Resolve All + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const { ApolloError } = require('apollo-server-express'); +const Sequelize = require('sequelize'); +const { last } = require('lodash'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, { first, after }, { db, credential }, info) => { + //Check Auth if user allowed + try { + const attributes = db.refer_log.intersection(graphqlFields(info).edges.node); + + const options = { + where: {}, + limit: first, + attributes, + }; + + if (after) { + options.where = { + id: { + [Sequelize.Op.gt]: after, + }, + }; + } + + const { count, rows } = await db.refer_log.findAndCountAll(options); + + const edges = rows.map((refer_log) => ({ + cursor: refer_log.id, + node: refer_log, + })); + + const pageInfo = { + endCursor: last(edges)?.cursor, + hasNextPage: 0 < count - first, + }; + + return { + edges, + pageInfo, + }; + + } catch (error) { + console.log('refer_log -> error', error); + return new ApolloError('InternalServerError'); + } +} diff --git a/resolvers/all/allRule.js b/resolvers/all/allRule.js new file mode 100644 index 0000000..9592815 --- /dev/null +++ b/resolvers/all/allRule.js @@ -0,0 +1,56 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * rule Resolve All + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const { ApolloError } = require('apollo-server-express'); +const Sequelize = require('sequelize'); +const { last } = require('lodash'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, { first, after }, { db, credential }, info) => { + //Check Auth if user allowed + try { + const attributes = db.rule.intersection(graphqlFields(info).edges.node); + + const options = { + where: {}, + limit: first, + attributes, + }; + + if (after) { + options.where = { + id: { + [Sequelize.Op.gt]: after, + }, + }; + } + + const { count, rows } = await db.rule.findAndCountAll(options); + + const edges = rows.map((rule) => ({ + cursor: rule.id, + node: rule, + })); + + const pageInfo = { + endCursor: last(edges)?.cursor, + hasNextPage: 0 < count - first, + }; + + return { + edges, + pageInfo, + }; + + } catch (error) { + console.log('rule -> error', error); + return new ApolloError('InternalServerError'); + } +} diff --git a/resolvers/all/allRules.js b/resolvers/all/allRules.js new file mode 100644 index 0000000..fe3fd51 --- /dev/null +++ b/resolvers/all/allRules.js @@ -0,0 +1,56 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * rules Resolve All + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const { ApolloError } = require('apollo-server-express'); +const Sequelize = require('sequelize'); +const { last } = require('lodash'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, { first, after }, { db, credential }, info) => { + //Check Auth if user allowed + try { + const attributes = db.rules.intersection(graphqlFields(info).edges.node); + + const options = { + where: {}, + limit: first, + attributes, + }; + + if (after) { + options.where = { + id: { + [Sequelize.Op.gt]: after, + }, + }; + } + + const { count, rows } = await db.rules.findAndCountAll(options); + + const edges = rows.map((rules) => ({ + cursor: rules.id, + node: rules, + })); + + const pageInfo = { + endCursor: last(edges)?.cursor, + hasNextPage: 0 < count - first, + }; + + return { + edges, + pageInfo, + }; + + } catch (error) { + console.log('rules -> error', error); + return new ApolloError('InternalServerError'); + } +} diff --git a/resolvers/all/allUser.js b/resolvers/all/allUser.js new file mode 100644 index 0000000..4b18e23 --- /dev/null +++ b/resolvers/all/allUser.js @@ -0,0 +1,56 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * user Resolve All + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const { ApolloError } = require('apollo-server-express'); +const Sequelize = require('sequelize'); +const { last } = require('lodash'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, { first, after }, { db, credential }, info) => { + //Check Auth if user allowed + try { + const attributes = db.user.intersection(graphqlFields(info).edges.node); + + const options = { + where: {}, + limit: first, + attributes, + }; + + if (after) { + options.where = { + id: { + [Sequelize.Op.gt]: after, + }, + }; + } + + const { count, rows } = await db.user.findAndCountAll(options); + + const edges = rows.map((user) => ({ + cursor: user.id, + node: user, + })); + + const pageInfo = { + endCursor: last(edges)?.cursor, + hasNextPage: 0 < count - first, + }; + + return { + edges, + pageInfo, + }; + + } catch (error) { + console.log('user -> error', error); + return new ApolloError('InternalServerError'); + } +} diff --git a/resolvers/create/.gitkeep b/resolvers/create/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resolvers/create/createActive.js b/resolvers/create/createActive.js new file mode 100644 index 0000000..69aa03c --- /dev/null +++ b/resolvers/create/createActive.js @@ -0,0 +1,36 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * active Resolve Add + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + + + return await db.active.insert({ },{returnAllFields: true}); + } catch (error) { + console.log('create_active -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/create/createActivityLog.js b/resolvers/create/createActivityLog.js new file mode 100644 index 0000000..61f66c7 --- /dev/null +++ b/resolvers/create/createActivityLog.js @@ -0,0 +1,36 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * activity_log Resolve Add + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { name } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + + + return await db.activity_log.insert({ name },{returnAllFields: true}); + } catch (error) { + console.log('create_activity_log -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/create/createAnswer.js b/resolvers/create/createAnswer.js new file mode 100644 index 0000000..db33a68 --- /dev/null +++ b/resolvers/create/createAnswer.js @@ -0,0 +1,36 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * answer Resolve Add + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + + + return await db.answer.insert({ },{returnAllFields: true}); + } catch (error) { + console.log('create_answer -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/create/createCredential.js b/resolvers/create/createCredential.js new file mode 100644 index 0000000..dc8fe0f --- /dev/null +++ b/resolvers/create/createCredential.js @@ -0,0 +1,40 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * credential Resolve Add + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { email, + password } = args; + const v = new Validator({ email: args.email, + password: args.password}, { email: "required|valid_email", + password: "required" }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + + + return await db.credential.insert({ email, + password },{returnAllFields: true}); + } catch (error) { + console.log('create_credential -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/create/createImage.js b/resolvers/create/createImage.js new file mode 100644 index 0000000..112bab9 --- /dev/null +++ b/resolvers/create/createImage.js @@ -0,0 +1,38 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * image Resolve Add + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { url, + caption } = args; + const v = new Validator({ url: args.url}, { url: "required" }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + + + return await db.image.insert({ url, + caption },{returnAllFields: true}); + } catch (error) { + console.log('create_image -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/create/createOutputVariable.js b/resolvers/create/createOutputVariable.js new file mode 100644 index 0000000..8077508 --- /dev/null +++ b/resolvers/create/createOutputVariable.js @@ -0,0 +1,36 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * output_variable Resolve Add + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + + + return await db.output_variable.insert({ },{returnAllFields: true}); + } catch (error) { + console.log('create_output_variable -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/create/createProfileHeader.js b/resolvers/create/createProfileHeader.js new file mode 100644 index 0000000..f94f266 --- /dev/null +++ b/resolvers/create/createProfileHeader.js @@ -0,0 +1,36 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * profile_header Resolve Add + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + + + return await db.profile_header.insert({ },{returnAllFields: true}); + } catch (error) { + console.log('create_profile_header -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/create/createQuestion.js b/resolvers/create/createQuestion.js new file mode 100644 index 0000000..c17c4ce --- /dev/null +++ b/resolvers/create/createQuestion.js @@ -0,0 +1,36 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * question Resolve Add + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + + + return await db.question.insert({ },{returnAllFields: true}); + } catch (error) { + console.log('create_question -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/create/createQuiz.js b/resolvers/create/createQuiz.js new file mode 100644 index 0000000..99b2d40 --- /dev/null +++ b/resolvers/create/createQuiz.js @@ -0,0 +1,36 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * quiz Resolve Add + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + + + return await db.quiz.insert({ },{returnAllFields: true}); + } catch (error) { + console.log('create_quiz -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/create/createReferLog.js b/resolvers/create/createReferLog.js new file mode 100644 index 0000000..e8bd777 --- /dev/null +++ b/resolvers/create/createReferLog.js @@ -0,0 +1,40 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * refer_log Resolve Add + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { user_id, + type } = args; + const v = new Validator({ user_id: args.user_id, + type: args.type}, { user_id: "required|integer", + type: "required|integer" }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + + + return await db.refer_log.insert({ user_id, + type },{returnAllFields: true}); + } catch (error) { + console.log('create_refer_log -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/create/createRule.js b/resolvers/create/createRule.js new file mode 100644 index 0000000..60d60bd --- /dev/null +++ b/resolvers/create/createRule.js @@ -0,0 +1,36 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * rule Resolve Add + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + + + return await db.rule.insert({ },{returnAllFields: true}); + } catch (error) { + console.log('create_rule -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/create/createRules.js b/resolvers/create/createRules.js new file mode 100644 index 0000000..8f024c6 --- /dev/null +++ b/resolvers/create/createRules.js @@ -0,0 +1,36 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * rules Resolve Add + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + + + return await db.rules.insert({ },{returnAllFields: true}); + } catch (error) { + console.log('create_rules -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/create/createUser.js b/resolvers/create/createUser.js new file mode 100644 index 0000000..0729a15 --- /dev/null +++ b/resolvers/create/createUser.js @@ -0,0 +1,62 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * user Resolve Add + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { role_id, + profile_id, + organization_id, + first_name, + last_name, + phone, + image, + refer, + stripe_uid, + paypal_uid, + expire_at, + status } = args; + const v = new Validator({ first_name: args.first_name, + last_name: args.last_name, + status: args.status}, { first_name: "required", + last_name: "required", + status: "required" }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + + + return await db.user.insert({ role_id, + profile_id, + organization_id, + first_name, + last_name, + phone, + image, + refer, + stripe_uid, + paypal_uid, + expire_at, + status },{returnAllFields: true}); + } catch (error) { + console.log('create_user -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/custom/.gitkeep b/resolvers/custom/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resolvers/delete/.gitkeep b/resolvers/delete/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resolvers/delete/deleteActive.js b/resolvers/delete/deleteActive.js new file mode 100644 index 0000000..255d679 --- /dev/null +++ b/resolvers/delete/deleteActive.js @@ -0,0 +1,23 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * active Resolve Delete + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError } = require('apollo-server-express'); + +module.exports = async (parent, args, {db}, info) => { + //Check Auth if user allowed + try { + + return await db.active.realDelete(args.id); + } catch (error) { + console.log('delete_active -> error', error); + return new ApolloError('InternalServerError'); + } +} \ No newline at end of file diff --git a/resolvers/delete/deleteActivityLog.js b/resolvers/delete/deleteActivityLog.js new file mode 100644 index 0000000..325aed2 --- /dev/null +++ b/resolvers/delete/deleteActivityLog.js @@ -0,0 +1,23 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * activity_log Resolve Delete + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError } = require('apollo-server-express'); + +module.exports = async (parent, args, {db}, info) => { + //Check Auth if user allowed + try { + + return await db.activity_log.realDelete(args.id); + } catch (error) { + console.log('delete_activity_log -> error', error); + return new ApolloError('InternalServerError'); + } +} \ No newline at end of file diff --git a/resolvers/delete/deleteAnswer.js b/resolvers/delete/deleteAnswer.js new file mode 100644 index 0000000..a6c9068 --- /dev/null +++ b/resolvers/delete/deleteAnswer.js @@ -0,0 +1,23 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * answer Resolve Delete + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError } = require('apollo-server-express'); + +module.exports = async (parent, args, {db}, info) => { + //Check Auth if user allowed + try { + + return await db.answer.realDelete(args.id); + } catch (error) { + console.log('delete_answer -> error', error); + return new ApolloError('InternalServerError'); + } +} \ No newline at end of file diff --git a/resolvers/delete/deleteCredential.js b/resolvers/delete/deleteCredential.js new file mode 100644 index 0000000..70224cc --- /dev/null +++ b/resolvers/delete/deleteCredential.js @@ -0,0 +1,23 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * credential Resolve Delete + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError } = require('apollo-server-express'); + +module.exports = async (parent, args, {db}, info) => { + //Check Auth if user allowed + try { + + return await db.credential.realDelete(args.id); + } catch (error) { + console.log('delete_credential -> error', error); + return new ApolloError('InternalServerError'); + } +} \ No newline at end of file diff --git a/resolvers/delete/deleteImage.js b/resolvers/delete/deleteImage.js new file mode 100644 index 0000000..082245c --- /dev/null +++ b/resolvers/delete/deleteImage.js @@ -0,0 +1,23 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * image Resolve Delete + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError } = require('apollo-server-express'); + +module.exports = async (parent, args, {db}, info) => { + //Check Auth if user allowed + try { + + return await db.image.realDelete(args.id); + } catch (error) { + console.log('delete_image -> error', error); + return new ApolloError('InternalServerError'); + } +} \ No newline at end of file diff --git a/resolvers/delete/deleteOutputVariable.js b/resolvers/delete/deleteOutputVariable.js new file mode 100644 index 0000000..74fe133 --- /dev/null +++ b/resolvers/delete/deleteOutputVariable.js @@ -0,0 +1,23 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * output_variable Resolve Delete + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError } = require('apollo-server-express'); + +module.exports = async (parent, args, {db}, info) => { + //Check Auth if user allowed + try { + + return await db.output_variable.realDelete(args.id); + } catch (error) { + console.log('delete_output_variable -> error', error); + return new ApolloError('InternalServerError'); + } +} \ No newline at end of file diff --git a/resolvers/delete/deleteProfileHeader.js b/resolvers/delete/deleteProfileHeader.js new file mode 100644 index 0000000..62417a8 --- /dev/null +++ b/resolvers/delete/deleteProfileHeader.js @@ -0,0 +1,23 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * profile_header Resolve Delete + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError } = require('apollo-server-express'); + +module.exports = async (parent, args, {db}, info) => { + //Check Auth if user allowed + try { + + return await db.profile_header.realDelete(args.id); + } catch (error) { + console.log('delete_profile_header -> error', error); + return new ApolloError('InternalServerError'); + } +} \ No newline at end of file diff --git a/resolvers/delete/deleteQuestion.js b/resolvers/delete/deleteQuestion.js new file mode 100644 index 0000000..8bc9fc6 --- /dev/null +++ b/resolvers/delete/deleteQuestion.js @@ -0,0 +1,23 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * question Resolve Delete + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError } = require('apollo-server-express'); + +module.exports = async (parent, args, {db}, info) => { + //Check Auth if user allowed + try { + + return await db.question.realDelete(args.id); + } catch (error) { + console.log('delete_question -> error', error); + return new ApolloError('InternalServerError'); + } +} \ No newline at end of file diff --git a/resolvers/delete/deleteQuiz.js b/resolvers/delete/deleteQuiz.js new file mode 100644 index 0000000..a650db6 --- /dev/null +++ b/resolvers/delete/deleteQuiz.js @@ -0,0 +1,23 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * quiz Resolve Delete + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError } = require('apollo-server-express'); + +module.exports = async (parent, args, {db}, info) => { + //Check Auth if user allowed + try { + + return await db.quiz.realDelete(args.id); + } catch (error) { + console.log('delete_quiz -> error', error); + return new ApolloError('InternalServerError'); + } +} \ No newline at end of file diff --git a/resolvers/delete/deleteReferLog.js b/resolvers/delete/deleteReferLog.js new file mode 100644 index 0000000..d352e4f --- /dev/null +++ b/resolvers/delete/deleteReferLog.js @@ -0,0 +1,23 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * refer_log Resolve Delete + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError } = require('apollo-server-express'); + +module.exports = async (parent, args, {db}, info) => { + //Check Auth if user allowed + try { + + return await db.refer_log.realDelete(args.id); + } catch (error) { + console.log('delete_refer_log -> error', error); + return new ApolloError('InternalServerError'); + } +} \ No newline at end of file diff --git a/resolvers/delete/deleteRule.js b/resolvers/delete/deleteRule.js new file mode 100644 index 0000000..16792b4 --- /dev/null +++ b/resolvers/delete/deleteRule.js @@ -0,0 +1,23 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * rule Resolve Delete + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError } = require('apollo-server-express'); + +module.exports = async (parent, args, {db}, info) => { + //Check Auth if user allowed + try { + + return await db.rule.realDelete(args.id); + } catch (error) { + console.log('delete_rule -> error', error); + return new ApolloError('InternalServerError'); + } +} \ No newline at end of file diff --git a/resolvers/delete/deleteRules.js b/resolvers/delete/deleteRules.js new file mode 100644 index 0000000..ce57d3c --- /dev/null +++ b/resolvers/delete/deleteRules.js @@ -0,0 +1,23 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * rules Resolve Delete + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError } = require('apollo-server-express'); + +module.exports = async (parent, args, {db}, info) => { + //Check Auth if user allowed + try { + + return await db.rules.realDelete(args.id); + } catch (error) { + console.log('delete_rules -> error', error); + return new ApolloError('InternalServerError'); + } +} \ No newline at end of file diff --git a/resolvers/delete/deleteUser.js b/resolvers/delete/deleteUser.js new file mode 100644 index 0000000..34f7503 --- /dev/null +++ b/resolvers/delete/deleteUser.js @@ -0,0 +1,23 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * user Resolve Delete + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError } = require('apollo-server-express'); + +module.exports = async (parent, args, {db}, info) => { + //Check Auth if user allowed + try { + + return await db.user.realDelete(args.id); + } catch (error) { + console.log('delete_user -> error', error); + return new ApolloError('InternalServerError'); + } +} \ No newline at end of file diff --git a/resolvers/index.js b/resolvers/index.js new file mode 100644 index 0000000..4d00ec0 --- /dev/null +++ b/resolvers/index.js @@ -0,0 +1,170 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: {{{year}}}*/ +/** + * Resolve Index + * @copyright {{{year}}} Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + const allUserResolver = require("./all/allUser"); + const singleUserResolver = require("./single/singleUser"); + const createUserResolver = require("./create/createUser"); + const updateUserResolver = require("./update/updateUser"); + const deleteUserResolver = require("./delete/deleteUser"); + const typeUserResolver = require("./type/typeUser"); + + + const allActivityLogResolver = require("./all/allActivityLog"); + const singleActivityLogResolver = require("./single/singleActivityLog"); + const createActivityLogResolver = require("./create/createActivityLog"); + const updateActivityLogResolver = require("./update/updateActivityLog"); + const deleteActivityLogResolver = require("./delete/deleteActivityLog"); + const typeActivityLogResolver = require("./type/typeActivityLog"); + + + const allReferLogResolver = require("./all/allReferLog"); + const singleReferLogResolver = require("./single/singleReferLog"); + const createReferLogResolver = require("./create/createReferLog"); + const updateReferLogResolver = require("./update/updateReferLog"); + const deleteReferLogResolver = require("./delete/deleteReferLog"); + const typeReferLogResolver = require("./type/typeReferLog"); + + + const allCredentialResolver = require("./all/allCredential"); + const singleCredentialResolver = require("./single/singleCredential"); + const createCredentialResolver = require("./create/createCredential"); + const updateCredentialResolver = require("./update/updateCredential"); + const deleteCredentialResolver = require("./delete/deleteCredential"); + const typeCredentialResolver = require("./type/typeCredential"); + + + const allImageResolver = require("./all/allImage"); + const singleImageResolver = require("./single/singleImage"); + const createImageResolver = require("./create/createImage"); + const updateImageResolver = require("./update/updateImage"); + const deleteImageResolver = require("./delete/deleteImage"); + const typeImageResolver = require("./type/typeImage"); + + + const allRuleResolver = require("./all/allRule"); + const singleRuleResolver = require("./single/singleRule"); + const createRuleResolver = require("./create/createRule"); + const updateRuleResolver = require("./update/updateRule"); + const deleteRuleResolver = require("./delete/deleteRule"); + const typeRuleResolver = require("./type/typeRule"); + + + const allQuizResolver = require("./all/allQuiz"); + const singleQuizResolver = require("./single/singleQuiz"); + const createQuizResolver = require("./create/createQuiz"); + const updateQuizResolver = require("./update/updateQuiz"); + const deleteQuizResolver = require("./delete/deleteQuiz"); + const typeQuizResolver = require("./type/typeQuiz"); + + + const allActiveResolver = require("./all/allActive"); + const singleActiveResolver = require("./single/singleActive"); + const createActiveResolver = require("./create/createActive"); + const updateActiveResolver = require("./update/updateActive"); + const deleteActiveResolver = require("./delete/deleteActive"); + const typeActiveResolver = require("./type/typeActive"); + + + const allOutputVariableResolver = require("./all/allOutputVariable"); + const singleOutputVariableResolver = require("./single/singleOutputVariable"); + const createOutputVariableResolver = require("./create/createOutputVariable"); + const updateOutputVariableResolver = require("./update/updateOutputVariable"); + const deleteOutputVariableResolver = require("./delete/deleteOutputVariable"); + const typeOutputVariableResolver = require("./type/typeOutputVariable"); + + + const allQuestionResolver = require("./all/allQuestion"); + const singleQuestionResolver = require("./single/singleQuestion"); + const createQuestionResolver = require("./create/createQuestion"); + const updateQuestionResolver = require("./update/updateQuestion"); + const deleteQuestionResolver = require("./delete/deleteQuestion"); + const typeQuestionResolver = require("./type/typeQuestion"); + + + const allAnswerResolver = require("./all/allAnswer"); + const singleAnswerResolver = require("./single/singleAnswer"); + const createAnswerResolver = require("./create/createAnswer"); + const updateAnswerResolver = require("./update/updateAnswer"); + const deleteAnswerResolver = require("./delete/deleteAnswer"); + const typeAnswerResolver = require("./type/typeAnswer"); + +module.exports = { + + Query: { + Users: allUserResolver, + User: singleUserResolver, + ActivityLogs: allActivityLogResolver, + ActivityLog: singleActivityLogResolver, + ReferLogs: allReferLogResolver, + ReferLog: singleReferLogResolver, + Credentials: allCredentialResolver, + Credential: singleCredentialResolver, + Images: allImageResolver, + Image: singleImageResolver, + Rules: allRuleResolver, + Rule: singleRuleResolver, + Quizs: allQuizResolver, + Quiz: singleQuizResolver, + Actives: allActiveResolver, + Active: singleActiveResolver, + OutputVariables: allOutputVariableResolver, + OutputVariable: singleOutputVariableResolver, + Questions: allQuestionResolver, + Question: singleQuestionResolver, + Answers: allAnswerResolver, + Answer: singleAnswerResolver + }, + Mutation: { + createUser: createUserResolver, + updateUser: updateUserResolver, + deleteUser: deleteUserResolver, + createActivityLog: createActivityLogResolver, + updateActivityLog: updateActivityLogResolver, + deleteActivityLog: deleteActivityLogResolver, + createReferLog: createReferLogResolver, + updateReferLog: updateReferLogResolver, + deleteReferLog: deleteReferLogResolver, + createCredential: createCredentialResolver, + updateCredential: updateCredentialResolver, + deleteCredential: deleteCredentialResolver, + createImage: createImageResolver, + updateImage: updateImageResolver, + deleteImage: deleteImageResolver, + createRule: createRuleResolver, + updateRule: updateRuleResolver, + deleteRule: deleteRuleResolver, + createQuiz: createQuizResolver, + updateQuiz: updateQuizResolver, + deleteQuiz: deleteQuizResolver, + createActive: createActiveResolver, + updateActive: updateActiveResolver, + deleteActive: deleteActiveResolver, + createOutputVariable: createOutputVariableResolver, + updateOutputVariable: updateOutputVariableResolver, + deleteOutputVariable: deleteOutputVariableResolver, + createQuestion: createQuestionResolver, + updateQuestion: updateQuestionResolver, + deleteQuestion: deleteQuestionResolver, + createAnswer: createAnswerResolver, + updateAnswer: updateAnswerResolver, + deleteAnswer: deleteAnswerResolver +}, + User: typeUserResolver, + ActivityLog: typeActivityLogResolver, + ReferLog: typeReferLogResolver, + Credential: typeCredentialResolver, + Image: typeImageResolver, + Rule: typeRuleResolver, + Quiz: typeQuizResolver, + Active: typeActiveResolver, + OutputVariable: typeOutputVariableResolver, + Question: typeQuestionResolver, + Answer: typeAnswerResolver +}; diff --git a/resolvers/relation/.gitkeep b/resolvers/relation/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resolvers/relation/relationImage.js b/resolvers/relation/relationImage.js new file mode 100644 index 0000000..923a71f --- /dev/null +++ b/resolvers/relation/relationImage.js @@ -0,0 +1,8 @@ +"use strict"; +module.exports = (parent, args, context, info) => { + if (parent.image) { + return parent.image; + } else { + return parent.getImage(); + } +}; diff --git a/resolvers/relation/relationOrganization.js b/resolvers/relation/relationOrganization.js new file mode 100644 index 0000000..601eae0 --- /dev/null +++ b/resolvers/relation/relationOrganization.js @@ -0,0 +1,8 @@ +"use strict"; +module.exports = (parent, args, context, info) => { + if (parent.organization) { + return parent.organization; + } else { + return parent.getOrganization(); + } +}; diff --git a/resolvers/relation/relationProfile.js b/resolvers/relation/relationProfile.js new file mode 100644 index 0000000..4bd4258 --- /dev/null +++ b/resolvers/relation/relationProfile.js @@ -0,0 +1,8 @@ +"use strict"; +module.exports = (parent, args, context, info) => { + if (parent.profile) { + return parent.profile; + } else { + return parent.getProfile(); + } +}; diff --git a/resolvers/relation/relationQuestion.js b/resolvers/relation/relationQuestion.js new file mode 100644 index 0000000..32ec7d0 --- /dev/null +++ b/resolvers/relation/relationQuestion.js @@ -0,0 +1,8 @@ +"use strict"; +module.exports = (parent, args, context, info) => { + if (parent.question) { + return parent.question; + } else { + return parent.getQuestion(); + } +}; diff --git a/resolvers/relation/relationQuiz.js b/resolvers/relation/relationQuiz.js new file mode 100644 index 0000000..275a88a --- /dev/null +++ b/resolvers/relation/relationQuiz.js @@ -0,0 +1,8 @@ +"use strict"; +module.exports = (parent, args, context, info) => { + if (parent.quiz) { + return parent.quiz; + } else { + return parent.getQuiz(); + } +}; diff --git a/resolvers/relation/relationReferrerUser.js b/resolvers/relation/relationReferrerUser.js new file mode 100644 index 0000000..c06f722 --- /dev/null +++ b/resolvers/relation/relationReferrerUser.js @@ -0,0 +1,8 @@ +"use strict"; +module.exports = (parent, args, context, info) => { + if (parent.referrer_user) { + return parent.referrer_user; + } else { + return parent.getReferrerUser(); + } +}; diff --git a/resolvers/relation/relationRole.js b/resolvers/relation/relationRole.js new file mode 100644 index 0000000..979b2a7 --- /dev/null +++ b/resolvers/relation/relationRole.js @@ -0,0 +1,8 @@ +"use strict"; +module.exports = (parent, args, context, info) => { + if (parent.role) { + return parent.role; + } else { + return parent.getRole(); + } +}; diff --git a/resolvers/relation/relationUser.js b/resolvers/relation/relationUser.js new file mode 100644 index 0000000..7c1bcbf --- /dev/null +++ b/resolvers/relation/relationUser.js @@ -0,0 +1,8 @@ +"use strict"; +module.exports = (parent, args, context, info) => { + if (parent.user) { + return parent.user; + } else { + return parent.getUser(); + } +}; diff --git a/resolvers/single/.gitkeep b/resolvers/single/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resolvers/single/singleActive.js b/resolvers/single/singleActive.js new file mode 100644 index 0000000..72490d6 --- /dev/null +++ b/resolvers/single/singleActive.js @@ -0,0 +1,25 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * active Resolve Single + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, {id}, {db}, info) => { + try { + const attributes = db.active.intersection(graphqlFields(info)); + + return await db.active.getByPK(id); + } catch (error) { + console.log('single_active -> error', error); + return new ApolloError('InternalServerError'); + } +}; \ No newline at end of file diff --git a/resolvers/single/singleActivityLog.js b/resolvers/single/singleActivityLog.js new file mode 100644 index 0000000..af30c9e --- /dev/null +++ b/resolvers/single/singleActivityLog.js @@ -0,0 +1,25 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * activity_log Resolve Single + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, {id}, {db}, info) => { + try { + const attributes = db.activity_log.intersection(graphqlFields(info)); + + return await db.activity_log.getByPK(id); + } catch (error) { + console.log('single_activity_log -> error', error); + return new ApolloError('InternalServerError'); + } +}; \ No newline at end of file diff --git a/resolvers/single/singleAnswer.js b/resolvers/single/singleAnswer.js new file mode 100644 index 0000000..71d1710 --- /dev/null +++ b/resolvers/single/singleAnswer.js @@ -0,0 +1,25 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * answer Resolve Single + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, {id}, {db}, info) => { + try { + const attributes = db.answer.intersection(graphqlFields(info)); + + return await db.answer.getByPK(id); + } catch (error) { + console.log('single_answer -> error', error); + return new ApolloError('InternalServerError'); + } +}; \ No newline at end of file diff --git a/resolvers/single/singleCredential.js b/resolvers/single/singleCredential.js new file mode 100644 index 0000000..7647034 --- /dev/null +++ b/resolvers/single/singleCredential.js @@ -0,0 +1,25 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * credential Resolve Single + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, {id}, {db}, info) => { + try { + const attributes = db.credential.intersection(graphqlFields(info)); + + return await db.credential.getByPK(id); + } catch (error) { + console.log('single_credential -> error', error); + return new ApolloError('InternalServerError'); + } +}; \ No newline at end of file diff --git a/resolvers/single/singleImage.js b/resolvers/single/singleImage.js new file mode 100644 index 0000000..bd2f7d0 --- /dev/null +++ b/resolvers/single/singleImage.js @@ -0,0 +1,25 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * image Resolve Single + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, {id}, {db}, info) => { + try { + const attributes = db.image.intersection(graphqlFields(info)); + + return await db.image.getByPK(id); + } catch (error) { + console.log('single_image -> error', error); + return new ApolloError('InternalServerError'); + } +}; \ No newline at end of file diff --git a/resolvers/single/singleOutputVariable.js b/resolvers/single/singleOutputVariable.js new file mode 100644 index 0000000..c626a73 --- /dev/null +++ b/resolvers/single/singleOutputVariable.js @@ -0,0 +1,25 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * output_variable Resolve Single + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, {id}, {db}, info) => { + try { + const attributes = db.output_variable.intersection(graphqlFields(info)); + + return await db.output_variable.getByPK(id); + } catch (error) { + console.log('single_output_variable -> error', error); + return new ApolloError('InternalServerError'); + } +}; \ No newline at end of file diff --git a/resolvers/single/singleProfileHeader.js b/resolvers/single/singleProfileHeader.js new file mode 100644 index 0000000..d3b55bc --- /dev/null +++ b/resolvers/single/singleProfileHeader.js @@ -0,0 +1,25 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * profile_header Resolve Single + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, {id}, {db}, info) => { + try { + const attributes = db.profile_header.intersection(graphqlFields(info)); + + return await db.profile_header.getByPK(id); + } catch (error) { + console.log('single_profile_header -> error', error); + return new ApolloError('InternalServerError'); + } +}; \ No newline at end of file diff --git a/resolvers/single/singleQuestion.js b/resolvers/single/singleQuestion.js new file mode 100644 index 0000000..c8c7643 --- /dev/null +++ b/resolvers/single/singleQuestion.js @@ -0,0 +1,25 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * question Resolve Single + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, {id}, {db}, info) => { + try { + const attributes = db.question.intersection(graphqlFields(info)); + + return await db.question.getByPK(id); + } catch (error) { + console.log('single_question -> error', error); + return new ApolloError('InternalServerError'); + } +}; \ No newline at end of file diff --git a/resolvers/single/singleQuiz.js b/resolvers/single/singleQuiz.js new file mode 100644 index 0000000..b1974f4 --- /dev/null +++ b/resolvers/single/singleQuiz.js @@ -0,0 +1,25 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * quiz Resolve Single + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, {id}, {db}, info) => { + try { + const attributes = db.quiz.intersection(graphqlFields(info)); + + return await db.quiz.getByPK(id); + } catch (error) { + console.log('single_quiz -> error', error); + return new ApolloError('InternalServerError'); + } +}; \ No newline at end of file diff --git a/resolvers/single/singleReferLog.js b/resolvers/single/singleReferLog.js new file mode 100644 index 0000000..ebf5427 --- /dev/null +++ b/resolvers/single/singleReferLog.js @@ -0,0 +1,25 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * refer_log Resolve Single + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, {id}, {db}, info) => { + try { + const attributes = db.refer_log.intersection(graphqlFields(info)); + + return await db.refer_log.getByPK(id); + } catch (error) { + console.log('single_refer_log -> error', error); + return new ApolloError('InternalServerError'); + } +}; \ No newline at end of file diff --git a/resolvers/single/singleRule.js b/resolvers/single/singleRule.js new file mode 100644 index 0000000..84f29bc --- /dev/null +++ b/resolvers/single/singleRule.js @@ -0,0 +1,25 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * rule Resolve Single + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, {id}, {db}, info) => { + try { + const attributes = db.rule.intersection(graphqlFields(info)); + + return await db.rule.getByPK(id); + } catch (error) { + console.log('single_rule -> error', error); + return new ApolloError('InternalServerError'); + } +}; \ No newline at end of file diff --git a/resolvers/single/singleRules.js b/resolvers/single/singleRules.js new file mode 100644 index 0000000..141f709 --- /dev/null +++ b/resolvers/single/singleRules.js @@ -0,0 +1,25 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * rules Resolve Single + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, {id}, {db}, info) => { + try { + const attributes = db.rules.intersection(graphqlFields(info)); + + return await db.rules.getByPK(id); + } catch (error) { + console.log('single_rules -> error', error); + return new ApolloError('InternalServerError'); + } +}; \ No newline at end of file diff --git a/resolvers/single/singleUser.js b/resolvers/single/singleUser.js new file mode 100644 index 0000000..feb5052 --- /dev/null +++ b/resolvers/single/singleUser.js @@ -0,0 +1,25 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * user Resolve Single + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + + +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = async (_, {id}, {db}, info) => { + try { + const attributes = db.user.intersection(graphqlFields(info)); + + return await db.user.getByPK(id); + } catch (error) { + console.log('single_user -> error', error); + return new ApolloError('InternalServerError'); + } +}; \ No newline at end of file diff --git a/resolvers/type/typeActive.js b/resolvers/type/typeActive.js new file mode 100644 index 0000000..2f1e3c3 --- /dev/null +++ b/resolvers/type/typeActive.js @@ -0,0 +1,6 @@ +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = { + +} \ No newline at end of file diff --git a/resolvers/type/typeActivityLog.js b/resolvers/type/typeActivityLog.js new file mode 100644 index 0000000..2f1e3c3 --- /dev/null +++ b/resolvers/type/typeActivityLog.js @@ -0,0 +1,6 @@ +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = { + +} \ No newline at end of file diff --git a/resolvers/type/typeAnswer.js b/resolvers/type/typeAnswer.js new file mode 100644 index 0000000..dbdb2b0 --- /dev/null +++ b/resolvers/type/typeAnswer.js @@ -0,0 +1,15 @@ +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = { + async question({ question_id }, _, { db }, info) { + try { + const attributes = db.question.intersection(graphqlFields(info)); + + return await db.question.getByPK(question_id, { attributes }); + } catch (error) { + console.log('question -> error', error); + return new ApolloError('InternalServerError'); + } + }, +} \ No newline at end of file diff --git a/resolvers/type/typeCredential.js b/resolvers/type/typeCredential.js new file mode 100644 index 0000000..0b9f491 --- /dev/null +++ b/resolvers/type/typeCredential.js @@ -0,0 +1,15 @@ +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = { + async user({ user_id }, _, { db }, info) { + try { + const attributes = db.user.intersection(graphqlFields(info)); + + return await db.user.getByPK(user_id, { attributes }); + } catch (error) { + console.log('user -> error', error); + return new ApolloError('InternalServerError'); + } + }, +} \ No newline at end of file diff --git a/resolvers/type/typeImage.js b/resolvers/type/typeImage.js new file mode 100644 index 0000000..0b9f491 --- /dev/null +++ b/resolvers/type/typeImage.js @@ -0,0 +1,15 @@ +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = { + async user({ user_id }, _, { db }, info) { + try { + const attributes = db.user.intersection(graphqlFields(info)); + + return await db.user.getByPK(user_id, { attributes }); + } catch (error) { + console.log('user -> error', error); + return new ApolloError('InternalServerError'); + } + }, +} \ No newline at end of file diff --git a/resolvers/type/typeOutputVariable.js b/resolvers/type/typeOutputVariable.js new file mode 100644 index 0000000..2f1e3c3 --- /dev/null +++ b/resolvers/type/typeOutputVariable.js @@ -0,0 +1,6 @@ +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = { + +} \ No newline at end of file diff --git a/resolvers/type/typeProfileHeader.js b/resolvers/type/typeProfileHeader.js new file mode 100644 index 0000000..2f1e3c3 --- /dev/null +++ b/resolvers/type/typeProfileHeader.js @@ -0,0 +1,6 @@ +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = { + +} \ No newline at end of file diff --git a/resolvers/type/typeQuestion.js b/resolvers/type/typeQuestion.js new file mode 100644 index 0000000..9c38078 --- /dev/null +++ b/resolvers/type/typeQuestion.js @@ -0,0 +1,15 @@ +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = { + async quiz({ quiz_id }, _, { db }, info) { + try { + const attributes = db.quiz.intersection(graphqlFields(info)); + + return await db.quiz.getByPK(quiz_id, { attributes }); + } catch (error) { + console.log('quiz -> error', error); + return new ApolloError('InternalServerError'); + } + }, +} \ No newline at end of file diff --git a/resolvers/type/typeQuiz.js b/resolvers/type/typeQuiz.js new file mode 100644 index 0000000..2f1e3c3 --- /dev/null +++ b/resolvers/type/typeQuiz.js @@ -0,0 +1,6 @@ +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = { + +} \ No newline at end of file diff --git a/resolvers/type/typeReferLog.js b/resolvers/type/typeReferLog.js new file mode 100644 index 0000000..0b9f491 --- /dev/null +++ b/resolvers/type/typeReferLog.js @@ -0,0 +1,15 @@ +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = { + async user({ user_id }, _, { db }, info) { + try { + const attributes = db.user.intersection(graphqlFields(info)); + + return await db.user.getByPK(user_id, { attributes }); + } catch (error) { + console.log('user -> error', error); + return new ApolloError('InternalServerError'); + } + }, +} \ No newline at end of file diff --git a/resolvers/type/typeRule.js b/resolvers/type/typeRule.js new file mode 100644 index 0000000..2f1e3c3 --- /dev/null +++ b/resolvers/type/typeRule.js @@ -0,0 +1,6 @@ +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = { + +} \ No newline at end of file diff --git a/resolvers/type/typeRules.js b/resolvers/type/typeRules.js new file mode 100644 index 0000000..2f1e3c3 --- /dev/null +++ b/resolvers/type/typeRules.js @@ -0,0 +1,6 @@ +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = { + +} \ No newline at end of file diff --git a/resolvers/type/typeUser.js b/resolvers/type/typeUser.js new file mode 100644 index 0000000..a6c2289 --- /dev/null +++ b/resolvers/type/typeUser.js @@ -0,0 +1,24 @@ +const { ApolloError } = require('apollo-server-express'); +const graphqlFields = require('graphql-fields'); + +module.exports = { + async profile({ profile_id }, _, { db }, info) { + try { + const attributes = db.profile.intersection(graphqlFields(info)); + + return await db.profile.getByPK(profile_id, { attributes }); + } catch (error) { + console.log('profile -> error', error); + return new ApolloError('InternalServerError'); + } + },async organization({ organization_id }, _, { db }, info) { + try { + const attributes = db.organization.intersection(graphqlFields(info)); + + return await db.organization.getByPK(organization_id, { attributes }); + } catch (error) { + console.log('organization -> error', error); + return new ApolloError('InternalServerError'); + } + }, +} \ No newline at end of file diff --git a/resolvers/update/.gitkeep b/resolvers/update/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resolvers/update/updateActive.js b/resolvers/update/updateActive.js new file mode 100644 index 0000000..0e34dc2 --- /dev/null +++ b/resolvers/update/updateActive.js @@ -0,0 +1,32 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * active Resolve Update + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + return await db.active.edit({ }, args.id); + } catch (error) { + console.log('update_active -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/update/updateActivityLog.js b/resolvers/update/updateActivityLog.js new file mode 100644 index 0000000..24ea43b --- /dev/null +++ b/resolvers/update/updateActivityLog.js @@ -0,0 +1,32 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * activity_log Resolve Update + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { name } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + return await db.activity_log.edit({ name }, args.id); + } catch (error) { + console.log('update_activity_log -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/update/updateAnswer.js b/resolvers/update/updateAnswer.js new file mode 100644 index 0000000..fe2e1b1 --- /dev/null +++ b/resolvers/update/updateAnswer.js @@ -0,0 +1,32 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * answer Resolve Update + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + return await db.answer.edit({ }, args.id); + } catch (error) { + console.log('update_answer -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/update/updateCredential.js b/resolvers/update/updateCredential.js new file mode 100644 index 0000000..3ffced0 --- /dev/null +++ b/resolvers/update/updateCredential.js @@ -0,0 +1,35 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * credential Resolve Update + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { email, + password } = args; + const v = new Validator({ email: args.email, + password: args.password}, { email: "required|valid_email" }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + return await db.credential.edit({ email, + password }, args.id); + } catch (error) { + console.log('update_credential -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/update/updateImage.js b/resolvers/update/updateImage.js new file mode 100644 index 0000000..87ddf3a --- /dev/null +++ b/resolvers/update/updateImage.js @@ -0,0 +1,34 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * image Resolve Update + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { url, + caption } = args; + const v = new Validator({ url: args.url}, { url: "required" }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + return await db.image.edit({ url, + caption }, args.id); + } catch (error) { + console.log('update_image -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/update/updateOutputVariable.js b/resolvers/update/updateOutputVariable.js new file mode 100644 index 0000000..feae468 --- /dev/null +++ b/resolvers/update/updateOutputVariable.js @@ -0,0 +1,32 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * output_variable Resolve Update + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + return await db.output_variable.edit({ }, args.id); + } catch (error) { + console.log('update_output_variable -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/update/updateProfileHeader.js b/resolvers/update/updateProfileHeader.js new file mode 100644 index 0000000..ccd0222 --- /dev/null +++ b/resolvers/update/updateProfileHeader.js @@ -0,0 +1,32 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * profile_header Resolve Update + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + return await db.profile_header.edit({ }, args.id); + } catch (error) { + console.log('update_profile_header -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/update/updateQuestion.js b/resolvers/update/updateQuestion.js new file mode 100644 index 0000000..b4133c0 --- /dev/null +++ b/resolvers/update/updateQuestion.js @@ -0,0 +1,32 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * question Resolve Update + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + return await db.question.edit({ }, args.id); + } catch (error) { + console.log('update_question -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/update/updateQuiz.js b/resolvers/update/updateQuiz.js new file mode 100644 index 0000000..b7740f6 --- /dev/null +++ b/resolvers/update/updateQuiz.js @@ -0,0 +1,32 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * quiz Resolve Update + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + return await db.quiz.edit({ }, args.id); + } catch (error) { + console.log('update_quiz -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/update/updateReferLog.js b/resolvers/update/updateReferLog.js new file mode 100644 index 0000000..8a0aba7 --- /dev/null +++ b/resolvers/update/updateReferLog.js @@ -0,0 +1,32 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * refer_log Resolve Update + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + return await db.refer_log.edit({ }, args.id); + } catch (error) { + console.log('update_refer_log -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/update/updateRule.js b/resolvers/update/updateRule.js new file mode 100644 index 0000000..c190ded --- /dev/null +++ b/resolvers/update/updateRule.js @@ -0,0 +1,32 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * rule Resolve Update + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + return await db.rule.edit({ }, args.id); + } catch (error) { + console.log('update_rule -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/update/updateRules.js b/resolvers/update/updateRules.js new file mode 100644 index 0000000..67deebe --- /dev/null +++ b/resolvers/update/updateRules.js @@ -0,0 +1,32 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * rules Resolve Update + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { } = args; + const v = new Validator({ }, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + return await db.rules.edit({ }, args.id); + } catch (error) { + console.log('update_rules -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/resolvers/update/updateUser.js b/resolvers/update/updateUser.js new file mode 100644 index 0000000..1261c91 --- /dev/null +++ b/resolvers/update/updateUser.js @@ -0,0 +1,56 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * user Resolve Update + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const { ApolloError ,UserInputError} = require('apollo-server-express'); +const { Validator } = require('node-input-validator'); + +module.exports = async (parent, args, {db}, info) => { + try { + const { role_id, + profile_id, + organization_id, + first_name, + last_name, + phone, + image, + refer, + stripe_uid, + paypal_uid, + expire_at, + status } = args; + const v = new Validator({ first_name: args.first_name, + last_name: args.last_name, + status: args.status}, { }); + + v.check().then(function (matched) { + if (!matched) { + Object.keys(v.errors).forEach((error) => { + return new UserInputError(v.errors[error].message); + }); + } + }); + return await db.user.edit({ role_id, + profile_id, + organization_id, + first_name, + last_name, + phone, + image, + refer, + stripe_uid, + paypal_uid, + expire_at, + status }, args.id); + } catch (error) { + console.log('update_user -> error', error); + return new ApolloError('InternalServerError'); + } +}; diff --git a/routes/admin/index.js b/routes/admin/index.js new file mode 100644 index 0000000..e8f5f29 --- /dev/null +++ b/routes/admin/index.js @@ -0,0 +1,6 @@ +const Login = require("./login"); +const Logout = require("./logout"); +const Profile = require("./profile"); + +module.exports = [Login,Logout,Profile] + \ No newline at end of file diff --git a/routes/admin/login.js b/routes/admin/login.js new file mode 100644 index 0000000..0b084c6 --- /dev/null +++ b/routes/admin/login.js @@ -0,0 +1,73 @@ +"use strict"; + +const ValidationService = require("../../services/ValidationService"); +const AuthService = require("../../services/AuthService"); +const JWTService = require("../../services/JwtService"); +const SessionService = require("../../services/SessionService"); +const db = require("../../models"); +const errors = require("../../core/errors"); +const app = require("express").Router(); +const role_id = 1; + +app.get("/admin/login", SessionService.preventAuthRoutes(role_id, "admin"), async function (req, res, next) { + const AuthViewModel = require("../../view_models/admin_auth_view_model"); + + const viewModel = new AuthViewModel(db.user, "Login"); + req.session.redirect_to = req.query.redirect_to; + + return res.render("admin/Login", viewModel); +}); + +app.post( + "/admin/login", + + ValidationService.validateInput( + { + email: "required|email", + password: "required|minLength:6", + }, + { + "email.required": "Email is required", + "email.email": "Invalid email", + "password.required": "Password is required.", + "password.minLength": "Password should be at least 6 characters long.", + } + ), + + async function (req, res, next) { + const role_id = 1; + const { email, password } = req.body; + + const AuthViewModel = require("../../view_models/admin_auth_view_model"); + + const viewModel = new AuthViewModel(db.user, "Login"); + + ValidationService.handleValidationErrorForViews(req, res, viewModel, "admin/Login", "login_fields", { email }); + + try { + const { credential, user } = await AuthService.login(email, password, role_id); + + const session = req.session; + + session.role = role_id; + session.user = user; + session.credential = credential; + + return session.save((error) => { + if (error) { + throw new Error(error); + } + if (session.redirect_to) { + return res.redirect(session.redirect_to); + } + return res.redirect("/admin/dashboard"); + }); + } catch (error) { + viewModel.error = error.message || "Something went wrong"; + viewModel.login_fields.email = email; + return res.render("admin/Login", viewModel); + } + } +); + +module.exports = app; diff --git a/routes/admin/logout.js b/routes/admin/logout.js new file mode 100644 index 0000000..a9db31f --- /dev/null +++ b/routes/admin/logout.js @@ -0,0 +1,13 @@ +'use strict'; +const app = require('express').Router(); + +app.get('/admin/logout', async function (req, res, next) { + req.session.destroy(function(err) { + req.session = {} + }) + + return res.redirect("/admin/login") +}); + + +module.exports = app; diff --git a/routes/admin/profile.js b/routes/admin/profile.js new file mode 100644 index 0000000..635be93 --- /dev/null +++ b/routes/admin/profile.js @@ -0,0 +1,188 @@ +"use strict"; + +const ValidationService = require("../../services/ValidationService"); +const AuthService = require("../../services/AuthService"); +const JWTService = require("../../services/JwtService"); +const SessionService = require("../../services/SessionService"); +const PasswordService = require("../../services/PasswordService"); +const db = require("../../models"); +const helpers = require("../../core/helpers"); +const { validateEmail } = require("../../core/utils"); +const app = require("express").Router(); + +const role_id = 1; + +app.get( + "/admin/profile", + SessionService.verifySessionMiddleware(role_id, "admin"), + + async function (req, res, next) { + const user = await db.user.getByPK(req.session.user); + const id = user.id; + + const AuthViewModel = require("../../view_models/admin_auth_view_model"); + + const viewModel = new AuthViewModel(db.user, "Profile"); + + viewModel._base_url = "/admin/profile"; + + if (!user || !user.id) { + viewModel.error = "User Not Found"; + return res.render("admin/Profile", viewModel); + } + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + try { + // TODO: make this responsive with no joins as well + const exists = await db.user.get_user_credential(id, db); + + if (!exists || +exists.status === 0) { + viewModel.error = "Profile Not Found"; + return res.render("admin/Profile", viewModel); + } + + const values = exists; + Object.keys(viewModel.form_fields).forEach((field) => { + if (field === "credential.email") { + viewModel.form_fields[field] = values["credential"]["email"]; + return; + } + if (field === "credential.password") { + viewModel.form_fields[field] = values["credential"]["password"]; + return; + } + viewModel.form_fields[field] = values[field]; + }); + viewModel.credential = db.credential; + + return res.render("admin/Profile", viewModel); + } catch (error) { + viewModel.error = "Something went wrong"; + return res.render("admin/Profile", viewModel); + } + } +); + +app.post( + "/admin/profile", + + SessionService.verifySessionMiddleware(role_id, "admin"), + + async function (req, res, next) { + let UserRef; + let CredentialRef; + + let User; + let Credential; + + const user = await db.user.getByPK(req.session.user); + + const AuthViewModel = require("../../view_models/admin_auth_view_model"); + + const viewModel = new AuthViewModel(db.user, "Profile"); + viewModel._base_url = "/admin/profile"; + + if (!user || !user.id) { + viewModel.error = "User Not Found"; + return res.render("admin/Profile", viewModel); + } + + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const { first_name, last_name, credential_email, credential_password, status } = req.body; + + var credentialFields = { + email: credential_email, + password: credential_password, + }; + + viewModel.form_fields = { + ...viewModel.form_fields, + first_name, + last_name, + "credential.email": credential_email, + "credential.password": credential_password, + status, + }; + + delete credentialFields.password; + delete viewModel.form_fields["credential.password"]; + + if (credential_password && credential_password !== "" && credential_password !== null && credential_password !== undefined) { + credentialFields.password = credential_password; + } + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render("admin/Profile", viewModel); + } + + CredentialRef = await db.credential.getByFields({ + user_id: user.id, + status: 1, + type: 0, + }); + + if (!CredentialRef) throw new Error("Email Address Not Found"); + + const credentialType = CredentialRef.type; + + UserRef = await db.user.getByFields({ + id: user.id, + status: 1, + }); + + if (!UserRef) throw new Error("Email Address Not Found"); + + if (credentialType == 0 && Object.entries(credentialFields).length > 0) { + if (credentialFields.email) { + if (!validateEmail(credentialFields.email)) { + viewModel.error = "Invalid email"; + return res.render("admin/Profile", viewModel); + } + + if (CredentialRef.email !== credentialFields.email) { + const userExists = await db.credential.getByField("email", credentialFields.email); + if (userExists) { + throw new Error("Email Address Already Exists"); + } + } + } + if (credentialFields.password) { + credentialFields.password = await PasswordService.hash(credentialFields.password); + } + + Credential = await db.credential.edit(credentialFields, CredentialRef.id); + } + User = await db.user.edit( + { + first_name, + last_name, + status, + }, + UserRef.id + ); + + viewModel.success = "Profile Updated Successfully"; + return res.render("admin/Profile", viewModel); + } catch (error) { + console.error(error); + try { + if (Credential && CredentialRef) { + await db.credential.edit(credentialFields, CredentialRef.id); + } + viewModel.error = error.message || "Something went wrong"; + return res.render("admin/Profile", viewModel); + } catch (error_2) {} + viewModel.error = error_2.message || "Something went wrong"; + return res.render("admin/Profile", viewModel); + } + } +); + +module.exports = app; diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 0000000..785285a --- /dev/null +++ b/routes/index.js @@ -0,0 +1,5 @@ +const AdminRoutes = require("./admin/index"); +const MemberRoutes = require("./member/index"); + + +module.exports = [AdminRoutes,MemberRoutes]; \ No newline at end of file diff --git a/routes/member/facebook.js b/routes/member/facebook.js new file mode 100644 index 0000000..35c26cd --- /dev/null +++ b/routes/member/facebook.js @@ -0,0 +1,80 @@ +const ValidationService = require('../../services/ValidationService'); +const AuthService = require('../../services/AuthService'); +const JWTService = require('../../services/JwtService'); +const SessionService = require('../../services/SessionService'); +const OAuthService = require('../../services/OAuthService'); +const db = require('../../models'); +const errors = require('../../core/errors'); +const app = require('express').Router(); + + +app.get('/member/facebook/initialize', async function (req, res) { + const role_id = 2 + try { + + const authenticationUrl = OAuthService.facebook.generateAuthURL({ + redirect_uri: process.env.DYNAMIC_CONFIG_FACEBOOK_REDIRECT_URI, + client_id: process.env.DYNAMIC_CONFIG_FACEBOOK_CLIENT_ID, + }); + + res.redirect(authenticationUrl); + } catch (error) { + viewModel.error = 'Something went wrong'; + return res.render('member/Login', viewModel); + } +}); + +app.get('/member/facebook', async function (req, res) { + const role_id = 2 + + const AuthViewModel = require('../../view_models/member_auth_view_model'); + const viewModel = new AuthViewModel(db.user, 'Facebook login'); + try { + const authToken = await OAuthService.facebook.generateAuthToken({ + redirect_uri: process.env.DYNAMIC_CONFIG_FACEBOOK_REDIRECT_URI, + client_id: process.env.DYNAMIC_CONFIG_FACEBOOK_CLIENT_ID, + client_id: process.env.DYNAMIC_CONFIG_FACEBOOK_CLIENT_ID, + client_secret: process.env.DYNAMIC_CONFIG_FACEBOOK_CLIENT_SECRET, + auth_code: req.query.code, + }); + + const facebookUser = await OAuthService.facebook.getUserInfo(authToken); + + // Facebook doesn't return email address sometime + // Allow email in the list of permissions in the frontend and access token will return email as well + + if (!facebookUser.email) { + throw new Error( + 'EMAIL_ASSOCIATED_WITH_FACEBOOK_COULD_NOT_BE_FOUND', + ); + } + + const payload = await OAuthService.authenticate({ + provider: 'f', + id: facebookUser.id, + email: facebookUser.email, + first_name: facebookUser.first_name, + last_name: facebookUser.last_name, + image: '', + role_id + }); + + const session = req.session; + session.role = role_id; + session.user = payload.user; + + return session.save((error) => { + if (error) { + throw new Error(error); + } + return res.redirect('/member/dashboard'); + }); + } catch (error) { + viewModel.error = error.message || "Something went wrong"; + return res.render('member/Login', viewModel); + } +}); + + + +module.exports = app; diff --git a/routes/member/forgot.js b/routes/member/forgot.js new file mode 100644 index 0000000..5cf0008 --- /dev/null +++ b/routes/member/forgot.js @@ -0,0 +1,217 @@ +'use strict'; + +const ValidationService = require('../../services/ValidationService') +const AuthService = require('../../services/AuthService'); +const JWTService = require('../../services/JwtService'); +const SessionService = require('../../services/SessionService'); +const db = require("../../models"); +const app = require('express').Router(); + +const role_id = 2 + +app.get('/member/forgot', +SessionService.preventAuthRoutes(role_id, 'member') +,async function (req, res, next) { + + + const AuthViewModel = require("../../view_models/member_auth_view_model") + + const viewModel =new AuthViewModel(db.user, "Forgot Password") + + return res.render("member/Forgot", viewModel) + + }); + +app.post('/member/forgot', + +ValidationService.validateInput({ + email:"required|email", +},{ + "email.required":"Email is required", + "email.email":"Invalid email", +}) +,async function (req, res, next) { + const role_id = 2 + const {email} = req.body; + + const AuthViewModel = require("../../view_models/member_auth_view_model") + + const viewModel =new AuthViewModel(db.user,"Forgot Password") + + + ValidationService.handleValidationErrorForViews( + req, + res, + viewModel, + 'member/Forgot', + 'forgot_fields', + { email }, + ); + + +try { + const accountExists = await viewModel.account_exists(email,{role_id}) + if(!accountExists){ + viewModel.error = "Account doesn't exists." + return res.render("member/Forgot",viewModel ) + } + + const user = await viewModel.get_associated_user(accountExists.user_id) + + if(!user){ + viewModel.error = "Account doesn't exists." + return res.render("member/Forgot",viewModel ) + } + + viewModel.initializeMailService(email) + const mailTemplate = await viewModel.getForgotPasswordMailTemplate('reset-password') + + if (!mailTemplate) { + throw new Error(); + } + + const token = viewModel.generateRandomToken() + + if (!token) { + throw new Error(); + } + + + const finalTemplate = viewModel.injectMailTemplate( + { + body: mailTemplate.html, + subject: mailTemplate.subject, + }, + { + email, + link: process.env.BASE_URL + '/member/reset', + reset_token: token, + }, + ) + + if (!finalTemplate) { + throw new Error(); + } + + await viewModel.saveTokenToDB(token, user.id) + + await viewModel.sendMail(finalTemplate) + + viewModel.success = "A password reset link is sent to your inbox." + return res.render("member/Login", viewModel) + +} catch (error) { + viewModel.error = "Something went wrong" + return res.render("member/Forgot",viewModel ) + +} +}); + + +app.get('/member/reset/:token', +SessionService.preventAuthRoutes(role_id, 'member') +, async function (req, res, next) { + + const token = req.params.token + if(!token){ + viewModel.error = "Invalid token" + return res.render("member/Login",viewModel) + } + const AuthViewModel = require("../../view_models/member_auth_view_model") + + const viewModel =new AuthViewModel(db.user, "Reset Password") + + viewModel.resetToken=token + + + + try { + const tokenValid = await viewModel.validateToken(token) + if(!tokenValid){ + viewModel.error = "Invalid token" + return res.render("member/Login",viewModel) + } + return res.render("member/Reset", viewModel) + + } catch (error) { + viewModel.error = "Something went wrong" + return res.render("member/Login",viewModel ) + + } + + }); + + app.post('/member/reset/:token', + +ValidationService.validateInput({ + password:"required|minLength:6", + confirm_password:"required|minLength:6", +},{ + "password.required":"Password is required.", + "confirm_password.required":"Password is required.", + "password.minLength":"Password should be at least 6 characters long.", + "confirm_password.minLength":"Password should be at least 6 characters long." + }) +,async function (req, res, next) { + const role_id = 2 + const token = req.params.token + const {password, confirm_password} = req.body; + + if(!token){ + viewModel.error = "Invalid token" + return res.render("member/Login",viewModel) + } + + if(password!==confirm_password){ + viewModel.error = "Passwords do not match" + return res.render("member/Reset",viewModel ) + } + const AuthViewModel = require("../../view_models/member_auth_view_model") + + const viewModel =new AuthViewModel(db.user,"Reset Password") + viewModel.resetToken = token; + + + + ValidationService.handleValidationErrorForViews( + req, + res, + viewModel, + 'member/Reset', + 'reset_fields', + { password, confirm_password }, + ); + + + +try { + const tokenValid = await viewModel.validateToken(token) + if(!tokenValid){ + viewModel.error = "Invalid token" + return res.render("member/Login",viewModel) + } + + const hashPassword =await viewModel.generate_hash(password) + if(!hashPassword){ + throw new Error() + } + const userCredential =await viewModel.getUserCredential(tokenValid.user_id) + + if(!userCredential){ + throw new Error() + } + await viewModel.updatePassword(hashPassword, userCredential.id) + + viewModel.success="Password reset successful" + return res.render("member/Login",viewModel) + + +} catch (error) { + viewModel.error = error.message || "Something went wrong"; + return res.render("member/Reset",viewModel ) + +} +}); + +module.exports = app; + diff --git a/routes/member/google.js b/routes/member/google.js new file mode 100644 index 0000000..d8e3969 --- /dev/null +++ b/routes/member/google.js @@ -0,0 +1,72 @@ +const OAuthService = require('../../services/OAuthService'); +const JWTService = require('../../services/JwtService'); +const AuthService = require('../../services/AuthService'); +const ValidationService = require('../../services/ValidationService'); +const db = require('../../models'); +const app = require('express').Router(); +// prettier-ignore + + +app.get('/member/google/initialize', async function (req, res) { + const role_id = 2 +try { + + + const authenticationUrl = OAuthService.google.generateAuthURL({ + redirect_uri: process.env.DYNAMIC_CONFIG_GOOGLE_REDIRECT_URI, + client_id: process.env.DYNAMIC_CONFIG_GOOGLE_CLIENT_ID, + }); + + res.redirect(authenticationUrl) +} catch (error) { + res.status(500).json({ success: false, message: error.message }); +} +}); + +app.get('/member/google', async function (req, res) { +try { + const role_id = 2 + + const AuthViewModel = require('../../view_models/member_auth_view_model'); + var viewModel = new AuthViewModel(db.user, 'Google login'); + + const authToken = await OAuthService.google.generateAuthToken({ + redirect_uri: process.env.DYNAMIC_CONFIG_GOOGLE_REDIRECT_URI, + client_id: process.env.DYNAMIC_CONFIG_GOOGLE_CLIENT_ID, + client_secret: process.env.DYNAMIC_CONFIG_GOOGLE_CLIENT_SECRET, + auth_code: req.query.code, + }); + + const googleUser = await OAuthService.google.getUserInfo(authToken); + + const payload = await OAuthService.authenticate({ + provider: 'g', + id: googleUser.id, + email: googleUser.email, + first_name: googleUser.given_name, + last_name: googleUser.family_name, + image: googleUser.picture, + }); + + const session = req.session; + session.role = role_id; + session.user = payload.user; + + return session.save((error) => { + if (error) { + throw new Error(error); + } + return res.redirect('/member/dashboard'); + }); +} catch (error) { + + viewModel.error = error.message || "Something went wrong"; + return res.render('member/Login', viewModel); +} +}); + + + + + +module.exports = app; \ No newline at end of file diff --git a/routes/member/index.js b/routes/member/index.js new file mode 100644 index 0000000..0c659e9 --- /dev/null +++ b/routes/member/index.js @@ -0,0 +1,10 @@ +const Facebook = require("./facebook"); +const Forgot = require("./forgot"); +const Google = require("./google"); +const Login = require("./login"); +const Logout = require("./logout"); +const Profile = require("./profile"); +const Register = require("./register"); + +module.exports = [Facebook,Forgot,Google,Login,Logout,Profile,Register] + \ No newline at end of file diff --git a/routes/member/login.js b/routes/member/login.js new file mode 100644 index 0000000..23f08ea --- /dev/null +++ b/routes/member/login.js @@ -0,0 +1,94 @@ +'use strict'; + +const ValidationService = require('../../services/ValidationService') +const AuthService = require('../../services/AuthService'); +const JWTService = require('../../services/JwtService'); +const SessionService = require('../../services/SessionService'); +const db = require("../../models"); +const errors = require('../../core/errors'); +const app = require('express').Router(); +const role_id = 2 + +app.get('/member/login', +SessionService.preventAuthRoutes(role_id, 'member') +,async function (req, res, next) { + + + const AuthViewModel = require("../../view_models/member_auth_view_model") + + const viewModel =new AuthViewModel(db.user, "Login") + + return res.render("member/Login", viewModel) + + }); + +app.post('/member/login', + +ValidationService.validateInput({ + email:"required|email", + password:"required|minLength:6" +},{ + "email.required":"Email is required", + "email.email":"Invalid email", + "password.required":"Password is required.", + "password.minLength":"Password should be at least 6 characters long."}) + +,async function (req, res, next) { + const role_id = 2 + const {email, password} = req.body; + + const AuthViewModel = require("../../view_models/member_auth_view_model") + + const viewModel =new AuthViewModel(db.user,"Login") + + ValidationService.handleValidationErrorForViews( + req, + res, + viewModel, + 'member/Login', + 'login_fields', + { email }, + ); + +try { + const { credential, user } = await AuthService.login(email, password, role_id); + + + + + const session = req.session; + + + + + if (req.body.remember_me === 'on') { + const day = 60 * 60 * 1000 * 24; + req.session.cookie.expires = new Date(Date.now() + day * 31); + req.session.cookie.maxAge = day * 31; + } + + session.role = role_id + session.user = user + session.credential = credential + + + + return session.save((error) => { + if(error){ + throw new Error(error); + } + return res.redirect("/member/dashboard") + }) + + +} catch (error) { + viewModel.error = error.message || "Something went wrong"; + viewModel.login_fields.email = email; + return res.render("member/Login",viewModel ) + +} + + }); + +module.exports = app; + diff --git a/routes/member/logout.js b/routes/member/logout.js new file mode 100644 index 0000000..15930fb --- /dev/null +++ b/routes/member/logout.js @@ -0,0 +1,13 @@ +'use strict'; +const app = require('express').Router(); + +app.get('/member/logout', async function (req, res, next) { + req.session.destroy(function(err) { + req.session = {} + }) + + return res.redirect("/member/login") +}); + + +module.exports = app; diff --git a/routes/member/profile.js b/routes/member/profile.js new file mode 100644 index 0000000..877dd79 --- /dev/null +++ b/routes/member/profile.js @@ -0,0 +1,200 @@ +'use strict'; + +const ValidationService = require('../../services/ValidationService') +const AuthService = require('../../services/AuthService'); +const JWTService = require('../../services/JwtService'); +const SessionService = require('../../services/SessionService'); +const PasswordService = require('../../services/PasswordService'); +const db = require("../../models"); +const helpers = require("../../core/helpers"); +const { validateEmail } = require('../../core/utils'); +const app = require('express').Router(); + +const role_id= 2 + +app.get("/member/profile", SessionService.verifySessionMiddleware(role_id, "member"), + + + +async function ( + req, + res, + next +) { + const user = await db.user.getByPK(req.session.user); + const id = user.id; + + const AuthViewModel = require("../../view_models/member_auth_view_model") + + const viewModel = new AuthViewModel(db.user,"Profile") + + viewModel._base_url = '/member/profile' + + if(!user || !user.id){ + viewModel.error = "User Not Found" + return res.render("member/Profile", viewModel) + } + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + try{ + // TODO: make this responsive with no joins as well + const exists = await db.user.get_user_credential(id, db); + + if(!exists || +exists.status === 0){ + viewModel.error = "Profile Not Found"; + return res.render("member/Profile", viewModel); + } + + const values = exists; + Object.keys(viewModel.form_fields).forEach((field) => { + if (field === 'credential.email') { + viewModel.form_fields[field] = values["credential"]["email"]; + return; + } + if (field === 'credential.password') { + viewModel.form_fields[field] = values["credential"]["password"]; + return; + } + viewModel.form_fields[field] = values[field]; + }); + viewModel.credential = db.credential + + return res.render("member/Profile",viewModel) + } catch(error){ + viewModel.error = "Something went wrong" + return res.render("member/Profile", viewModel) + } + +}); + +app.post( + '/member/profile', + + + + SessionService.verifySessionMiddleware(role_id, 'member'), + + async function (req, res, next) { + let UserRef; + let CredentialRef; + + let User; + let Credential; + + const user = await db.user.getByPK(req.session.user); + + const AuthViewModel = require('../../view_models/member_auth_view_model'); + + const viewModel = new AuthViewModel(db.user,"Profile") + viewModel._base_url = '/member/profile' + + + if (!user || !user.id) { + viewModel.error = 'User Not Found'; + return res.render('member/Profile', viewModel); + } + + if (req.session.csrf === undefined) { + req.session.csrf = SessionService.randomString(100); + } + + const { first_name,last_name,credential_email,credential_password,status } = req.body; + + var credentialFields = { + 'email': credential_email,'password': credential_password + }; + + viewModel.form_fields = { + ...viewModel.form_fields, + first_name,last_name,'credential.email': credential_email,'credential.password': credential_password,status + }; + + + delete credentialFields.password; + delete viewModel.form_fields['credential.password']; + + if(credential_password && credential_password !== "" && credential_password !== null && credential_password !== undefined){ + credentialFields.password = credential_password; + } + + try { + if (req.validationError) { + viewModel.error = req.validationError; + return res.render('member/Profile', viewModel); + } + + CredentialRef = await db.credential.getByFields({ + user_id: user.id, + status: 1, + type: 0, + }); + + if (!CredentialRef) throw new Error('Email Address Not Found'); + + const credentialType = CredentialRef.type; + + UserRef = await db.user.getByFields({ + id: user.id, + status: 1, + }); + + if (!UserRef) throw new Error('Email Address Not Found'); + + if (credentialType == 0 && Object.entries(credentialFields).length > 0) { + if(credentialFields.email){ + if (!validateEmail(credentialFields.email)) { + viewModel.error = 'Invalid email'; + return res.render('member/Profile', viewModel); + } + + if (CredentialRef.email !== credentialFields.email) { + const userExists = await db.credential.getByField('email', credentialFields.email); + if (userExists) { + throw new Error('Email Address Already Exists'); + } + + } + } + if (credentialFields.password) { + credentialFields.password = await PasswordService.hash(credentialFields.password); + } + + Credential = await db.credential.edit( + credentialFields, + CredentialRef.id, + ); + + } + User = await db.user.edit( + { + first_name,last_name,status + }, + UserRef.id, + ); + + viewModel.success = 'Profile Updated Successfully'; + return res.render('member/Profile', viewModel); + } catch (error) { + console.error(error); + try { + if (Credential && CredentialRef) { + await db.credential.edit( + credentialFields, + CredentialRef.id, + ); + } + viewModel.error = error.message || "Something went wrong" + return res.render('member/Profile', viewModel); + } catch (error_2) {} + viewModel.error = error_2.message || "Something went wrong" + return res.render('member/Profile', viewModel); + } + }, +); + + + + +module.exports = app; diff --git a/routes/member/register.js b/routes/member/register.js new file mode 100644 index 0000000..ac3f662 --- /dev/null +++ b/routes/member/register.js @@ -0,0 +1,113 @@ +'use strict'; + +const ValidationService = require('../../services/ValidationService') +const AuthService = require('../../services/AuthService'); +const JWTService = require('../../services/JwtService'); +const SessionService = require('../../services/SessionService'); +const db = require("../../models"); +const app = require('express').Router(); + +const role_id = 2 + +app.get('/member/register', +SessionService.preventAuthRoutes(role_id, 'member') +, async function (req, res, next) { + + + const AuthViewModel = require("../../view_models/member_auth_view_model") + + const viewModel =new AuthViewModel(db.user, "Register") + + return res.render("member/Register", viewModel) + + }); + +app.post('/member/register', + +ValidationService.validateInput({ +email:"required|email", +first_name:"required", +last_name:"required", +password:"required|minLength:6", +confirm_password:"required|minLength:6" +},{ +"email.required":"Email is required", +"first_name.required":"First name is required", +"last_name.required":"Last name is required", +"email.email":"Invalid email", +"password.required":"Password is required.", +"confirm_password.required":"Password is required.", +"password.minLength":"Password should be at least 6 characters long.", +"confirm_password.minLength":"Password should be at least 6 characters long." +}) + +,async function (req, res, next) { + const role_id = 2 + const {email,first_name, last_name, password, confirm_password} = req.body; + + const AuthViewModel = require("../../view_models/member_auth_view_model") + + const viewModel =new AuthViewModel(db.user,"Register") + + + + ValidationService.handleValidationErrorForViews( + req, + res, + viewModel, + 'member/Register', + 'register_fields', + { email, first_name, last_name }, + ); + + let newUser = null + +try { + if(password!==confirm_password){ + viewModel.error = "Passwords do not match" + viewModel.register_fields.email = email + viewModel.register_fields.first_name = first_name + viewModel.register_fields.last_name = last_name + return res.render("member/Register",viewModel ) + } + + var { credential, user } = await AuthService.register( + email, + password, + role_id, + { + first_name, + last_name, + }, + ); + + if(user){ + const session = req.session; + session.role = role_id; + session.user = user; + session.credential = credential; + + return session.save((error) => { + if(error){ + throw new Error(error) + } + return res.redirect("/member/dashboard") + }) + } + + throw new Error(); + + +} catch (error) { + if(user){ + await db.user.destroy(user) + } + viewModel.error = error.message || "Something went wrong"; + viewModel.register_fields.email = email + viewModel.register_fields.first_name = first_name + viewModel.register_fields.last_name = last_name + return res.render("member/Register",viewModel )} + }); + +module.exports = app; + diff --git a/seed.js b/seed.js new file mode 100644 index 0000000..ee1f81f --- /dev/null +++ b/seed.js @@ -0,0 +1,1508 @@ +const db = require("./models"); +async function executeSeeds() { + await db.sequelize.sync({ force: true }); + + //load seed files and run the function to insert + await db.configuration.insert({ id: 1, image_id: 35 }); + await db.user.insert({ first_name: "Admin", last_name: "Admin", phone: "12345678", image: "/image/profile.png", role_id: 1, refer: "admin", status: 1 }); + await db.user.insert({ first_name: "Member", last_name: "Member", phone: "12345678", image: "/image/profile.png", role_id: 2, refer: "member", status: 1 }); + await db.setting.insert({ key: "site_name", type: 0, value: "manaknightdigital" }); + await db.setting.insert({ key: "site_logo", type: 0, value: "https://manaknightdigital.com/assets/img/logo.png" }); + await db.setting.insert({ key: "maintenance", type: 1, value: "0" }); + await db.setting.insert({ key: "version", type: 0, value: "1.0.0" }); + await db.setting.insert({ key: "copyright", type: 0, value: "Copyright © 2021 manaknightdigital. All rights reserved." }); + await db.setting.insert({ key: "license_key", type: 4, value: "4097fbd4f340955de76ca555c201b185cf9d6921d977301b05cdddeae4af54f924f0508cd0f7ca66" }); + await db.role.insert({ name: "admin" }); + await db.role.insert({ name: "member" }); + await db.credential.insert({ + email: "admin@manaknight.com", + password: "$2a$04$tQm/w6gJNKOoiZOn0WVISe1xG7BD1ulw72UNHXsXgLObtdKjlMhZK", + type: 0, + verify: 1, + role_id: 1, + user_id: 1, + status: 1, + }); + await db.credential.insert({ + email: "member@manaknight.com", + password: "$2a$04$A7JX0xG2Gwt06UKpxq/Yd.oJARP6.BpzkzjOhc67.2dkfqjJPJ0pe", + type: 0, + verify: 1, + role_id: 2, + user_id: 2, + status: 1, + }); + await db.email.insert({ + slug: "reset-password", + subject: "Reset your password", + tag: "email,reset_token,link", + html: 'Hi {{{email}}},
        You have requested to reset your password. Please click the link below to reset it.
        Link.
        Thanks,
        Admin', + }); + await db.email.insert({ + slug: "register", + subject: "Register", + tag: "email", + html: "Hi {{{email}}},
        Thanks for registering on our platform.
        Thanks,
        Admin", + }); + await db.email.insert({ + slug: "confirm-password", + subject: "Confirm your account", + tag: "email,confirm_token,link", + html: 'Hi {{{email}}},
        Please click the link below to confirm your account.
        LinkThanks,
        Admin', + }); + await db.email.insert({ slug: "verify", subject: "Account verification", tag: "code", html: "Your verification # is {{{code}}}" }); + await db.sms.insert({ slug: "verify", tag: "code", content: "Your verification # is {{{code}}}" }); + await db.image.insert({ id: 1, url: "/image/profile.png", caption: "", user_id: 1, width: 581, height: 581, mobile_width: 348, mobile_height: 348, type: 6 }); + await db.image.insert({ + id: 2, + url: "/frontend_images/Icons/SVG/Skin Sensitivity/Non Sensitive Skin.svg", + caption: "", + user_id: 1, + width: 183, + height: 183, + mobile_width: 183, + mobile_height: 183, + type: 6, + }); + await db.image.insert({ + id: 3, + url: "/frontend_images/Icons/SVG/Skin Sensitivity/Moderately Sensitive.svg", + caption: "", + user_id: 1, + width: 183, + height: 183, + mobile_width: 183, + mobile_height: 183, + type: 6, + }); + await db.image.insert({ + id: 4, + url: "/frontend_images/Icons/SVG/Skin Sensitivity/Extremely Sensitive.svg", + caption: "", + user_id: 1, + width: 183, + height: 183, + mobile_width: 183, + mobile_height: 183, + type: 6, + }); + await db.image.insert({ + id: 5, + url: "/frontend_images/Icons/SVG/Dry_Oily Skin/Dry Skin.svg", + caption: "", + user_id: 1, + width: 191, + height: 191, + mobile_width: 191, + mobile_height: 191, + type: 6, + }); + await db.image.insert({ + id: 6, + url: "/frontend_images/Icons/SVG/Dry_Oily Skin/Normal and Combination.svg", + caption: "", + user_id: 1, + width: 191, + height: 191, + mobile_width: 191, + mobile_height: 191, + type: 6, + }); + await db.image.insert({ + id: 7, + url: "/frontend_images/Icons/SVG/Dry_Oily Skin/Oily.svg", + caption: "", + user_id: 1, + width: 191, + height: 191, + mobile_width: 191, + mobile_height: 191, + type: 6, + }); + await db.image.insert({ + id: 8, + url: "/frontend_images/SkintoneGraphics/1.png", + caption: "", + user_id: 1, + width: 74, + height: 135, + mobile_width: 74, + mobile_height: 135, + type: 6, + }); + await db.image.insert({ + id: 9, + url: "/frontend_images/SkintoneGraphics/2.png", + caption: "", + user_id: 1, + width: 74, + height: 135, + mobile_width: 74, + mobile_height: 135, + type: 6, + }); + await db.image.insert({ + id: 10, + url: "/frontend_images/SkintoneGraphics/3.png", + caption: "", + user_id: 1, + width: 74, + height: 135, + mobile_width: 74, + mobile_height: 135, + type: 6, + }); + await db.image.insert({ + id: 11, + url: "/frontend_images/SkintoneGraphics/4.png", + caption: "", + user_id: 1, + width: 74, + height: 135, + mobile_width: 74, + mobile_height: 135, + type: 6, + }); + await db.image.insert({ + id: 12, + url: "/frontend_images/SkintoneGraphics/5.png", + caption: "", + user_id: 1, + width: 74, + height: 135, + mobile_width: 74, + mobile_height: 135, + type: 6, + }); + await db.image.insert({ + id: 13, + url: "/frontend_images/SkintoneGraphics/6.png", + caption: "", + user_id: 1, + width: 74, + height: 135, + mobile_width: 74, + mobile_height: 135, + type: 6, + }); + await db.image.insert({ + id: 14, + url: "/frontend_images/SkintoneGraphics/7.png", + caption: "", + user_id: 1, + width: 74, + height: 135, + mobile_width: 74, + mobile_height: 135, + type: 6, + }); + await db.image.insert({ + id: 15, + url: "/frontend_images/SkintoneGraphics/8.png", + caption: "", + user_id: 1, + width: 74, + height: 135, + mobile_width: 74, + mobile_height: 135, + type: 6, + }); + await db.image.insert({ + id: 16, + url: "/frontend_images/SkintoneGraphics/9.png", + caption: "", + user_id: 1, + width: 74, + height: 135, + mobile_width: 74, + mobile_height: 135, + type: 6, + }); + await db.image.insert({ + id: 17, + url: "/frontend_images/SkintoneGraphics/10.png", + caption: "", + user_id: 1, + width: 74, + height: 135, + mobile_width: 74, + mobile_height: 135, + type: 6, + }); + await db.image.insert({ + id: 18, + url: "/frontend_images/SkintoneGraphics/11.png", + caption: "", + user_id: 1, + width: 74, + height: 135, + mobile_width: 74, + mobile_height: 135, + type: 6, + }); + await db.image.insert({ + id: 19, + url: "/frontend_images/SkintoneGraphics/12.png", + caption: "", + user_id: 1, + width: 74, + height: 135, + mobile_width: 74, + mobile_height: 135, + type: 6, + }); + await db.image.insert({ + id: 20, + url: "/frontend_images/SkintoneGraphics/13.png", + caption: "", + user_id: 1, + width: 74, + height: 135, + mobile_width: 74, + mobile_height: 135, + type: 6, + }); + await db.image.insert({ + id: 21, + url: "/frontend_images/SkintoneGraphics/14.png", + caption: "", + user_id: 1, + width: 74, + height: 135, + mobile_width: 74, + mobile_height: 135, + type: 6, + }); + await db.image.insert({ + id: 22, + url: "/frontend_images/SkintoneGraphics/15.png", + caption: "", + user_id: 1, + width: 74, + height: 135, + mobile_width: 74, + mobile_height: 135, + type: 6, + }); + await db.image.insert({ + id: 23, + url: "/frontend_images/Icons/SVG/Blotchiness/No Blotchiness.svg", + caption: "", + user_id: 1, + width: 240, + height: 240, + mobile_width: 240, + mobile_height: 240, + type: 6, + }); + await db.image.insert({ + id: 24, + url: "/frontend_images/Icons/PNG/Blotchiness/Lot's of Blotchiness.png", + caption: "", + user_id: 1, + width: 240, + height: 240, + mobile_width: 240, + mobile_height: 240, + type: 6, + }); + await db.image.insert({ + id: 25, + url: "/frontend_images/Icons/SVG/Face Lines/No Wrinkles.svg", + caption: "", + user_id: 1, + width: 240, + height: 240, + mobile_width: 240, + mobile_height: 240, + type: 6, + }); + await db.image.insert({ + id: 26, + url: "/frontend_images/Icons/SVG/Face Lines/A Few Lines.svg", + caption: "", + user_id: 1, + width: 240, + height: 240, + mobile_width: 240, + mobile_height: 240, + type: 6, + }); + await db.image.insert({ + id: 27, + url: "/frontend_images/Icons/SVG/Face Lines/A Few Lines Observable at all times.svg", + caption: "", + user_id: 1, + width: 240, + height: 240, + mobile_width: 240, + mobile_height: 240, + type: 6, + }); + await db.image.insert({ + id: 28, + url: "/frontend_images/Icons/SVG/Face Lines/Some Lines.svg", + caption: "", + user_id: 1, + width: 240, + height: 240, + mobile_width: 240, + mobile_height: 240, + type: 6, + }); + await db.image.insert({ + id: 29, + url: "/frontend_images/Icons/SVG/Face Lines/Lines Plus Hints of Wrinkles.svg", + caption: "", + user_id: 1, + width: 240, + height: 240, + mobile_width: 240, + mobile_height: 240, + type: 6, + }); + await db.image.insert({ + id: 30, + url: "/frontend_images/Icons/SVG/Face Lines/A Few Wrinkles.svg", + caption: "", + user_id: 1, + width: 240, + height: 240, + mobile_width: 240, + mobile_height: 240, + type: 6, + }); + await db.image.insert({ + id: 31, + url: "/frontend_images/Icons/SVG/Face Lines/Lots of Wrinkles.svg", + caption: "", + user_id: 1, + width: 240, + height: 240, + mobile_width: 240, + mobile_height: 240, + type: 6, + }); + await db.image.insert({ + id: 32, + url: "/frontend_images/Icons/SVG/Water/1 Glass of Water.svg", + caption: "", + user_id: 1, + width: 140, + height: 190, + mobile_width: 140, + mobile_height: 190, + type: 6, + }); + await db.image.insert({ + id: 33, + url: "/frontend_images/Icons/SVG/Water/4 Glasses of Water.svg", + caption: "", + user_id: 1, + width: 140, + height: 190, + mobile_width: 140, + mobile_height: 190, + type: 6, + }); + await db.image.insert({ + id: 34, + url: "/frontend_images/Icons/SVG/Water/8 Glasses of Water.svg", + caption: "", + user_id: 1, + width: 140, + height: 190, + mobile_width: 140, + mobile_height: 190, + type: 6, + }); + await db.image.insert({ + id: 35, + url: "/frontend_images/MainImage/background.jpg", + user_id: 1, + type: 6, + }); + await db.rule.insert({ output_variable_name: "Age", actives: '["Camomile"]', operator: 3, compare_value: "30", action: 2 }); + await db.quiz.insert({ name: "The Basics", description: "Let’s start by getting to know you." }); + await db.quiz.insert({ name: "Your Skin", description: "Let’s learn about your skin and it’s uniqueness." }); + await db.quiz.insert({ name: "Your Environment", description: "Almost done, let’s talk environment & lifestyle." }); + + await db.output_variable.insert({ + name: "Bio Age", + priority: 0, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Age", + priority: 70, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Gender", + priority: 75, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Pregnancy", + priority: 100, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Hair", + priority: 75, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Sensitivity", + priority: 90, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Hydration", + priority: 100, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Breakouts", + priority: 100, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Color", + priority: 50, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Sun", + priority: 95, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Hyperpigmentation", + priority: 90, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Hypopigmentation", + priority: 90, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Redness", + priority: 85, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Lines", + priority: 100, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Firmness", + priority: 100, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Pores", + priority: 70, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Blackheads", + priority: 65, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Allergies", + priority: 100, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Pollution", + priority: 80, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Temperature", + priority: 0, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Stress", + priority: 40, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Diet", + priority: 30, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Sleep", + priority: 20, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Blue Light", + priority: 45, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.output_variable.insert({ + name: "Oxygenation", + priority: 40, + ranges_response: '[{"0-33":"Your skin is not that sensetive"},{"34-66":"Your skin is somewhat sensetive"},{"67-100":"Your skin is highly sensetive"}]', + }); + await db.question.insert({ + order: 1, + id: 1, + quiz_id: 1, + target: 4, + type: 1, + question: "What would you like to be called?", + save_response_into: "name", + placeholder: "name", + }); + await db.question.insert({ + order: 2, + id: 2, + quiz_id: 1, + target: 4, + type: 3, + note_type: 2, + note: "Your age plays an important role on which functional actives we may want to focus on for your skin assessment.", + output_variable_name: "Bio Age", + weight: 100, + extra_output_variable: '[{"name":"Age","weight":50}]', + question_arguments: '["name"]', + question: " When were you born <<>>?", + save_response_into: "age", + placeholder: "year", + }); + await db.question.insert({ + order: 3, + id: 3, + quiz_id: 1, + target: 4, + type: 4, + note_type: 1, + note: "Your hormones play an important role in your skin’s health and appearance.", + question: "What is your hormonal gender", + }); + await db.question.insert({ + order: 4, + id: 4, + quiz_id: 1, + depends_on: "3|female", + target: 1, + type: 4, + note_type: 2, + note: "Hormonal changes during pregnancy can lead to visible changes in skin appearance. It’s also very important to ensure that all actives are proven safe for this important period.", + question: "Are you pregnant or breastfeeding?", + output_variable_name: "Pregnancy", + weight: 100, + }); + await db.question.insert({ + order: 5, + id: 5, + quiz_id: 1, + depends_on: "3|male", + target: 2, + type: 4, + note_type: 2, + output_variable_name: "Hair", + weight: 100, + note: "Presence of hair on face can have an effect on the skin beneath.", + question: "What is your facial hair situation?", + }); + await db.question.insert({ + order: 1, + id: 6, + quiz_id: 2, + target: 4, + type: 6, + slider_range: "0-100", + note_type: 2, + output_variable_name: "Sensitivity", + weight: 100, + note: "We’ll be more careful of which actives we add to formula for those with more sensitive skin types. It’s all about balancing effectivity, complexity and leaving you feeling your best.", + question: "How Sensitive is your skin?", + }); + await db.question.insert({ + order: 2, + id: 7, + quiz_id: 2, + target: 4, + type: 6, + slider_range: "0-100", + output_variable_name: "Hydration", + weight: 70, + question: "How would you describe your skin on an average day?", + }); + await db.question.insert({ + order: 3, + id: 8, + quiz_id: 2, + target: 4, + type: 6, + slider_range: "0-100", + output_variable_name: "Breakouts", + weight: 100, + question: "How often do you have breakouts, such as an occasional pimple or frequent breakouts (such as chronic acne)?", + }); + await db.question.insert({ + order: 4, + id: 9, + quiz_id: 2, + target: 4, + type: 5, + note_type: 2, + image_width: 60, + image_height: 110, + output_variable_name: "Color", + weight: 100, + extra_output_variable: '[{"name":"Sun","weight":10},{"name":"Hyperpigmentation","weight":10}]', + note: "Different skin tones are associated with different levels of skin melanin, leading to differing reactions of skin to the effects of the sun.", + question: "What’s your skintone without a suntan?", + }); + await db.question.insert({ + order: 5, + id: 10, + quiz_id: 2, + target: 4, + type: 6, + slider_range: "0-100", + output_variable_name: "Sun", + weight: 20, + question: "How easily does your skin tan?", + }); + await db.question.insert({ + order: 6, + id: 11, + quiz_id: 2, + target: 4, + type: 6, + slider_range: "0-100", + note_type: 1, + output_variable_name: "Hyperpigmentation", + weight: 90, + extra_output_variable: '[{"name":"Sun","weight":10}]', + note: "This is the likelihood of skin discoloring associated with aging or after injury.", + question: "Is your skin prone to Hyperpigmentation?", + }); + await db.question.insert({ + order: 7, + id: 30, + quiz_id: 2, + question: "Is your skin prone to Hypopigmentation?", + note: "This is the likelihood of skin discoloring associated with aging or after injury.", + note_type: 1, + depends_on: "", + slider_range: "0-100", + output_variable_name: "Hypopigmentation", + weight: 100, + type: 6, + }); + await db.question.insert({ + order: 8, + id: 12, + quiz_id: 2, + target: 4, + type: 6, + slider_range: "0-100", + output_variable_name: "Sun", + weight: 60, + question: "How easily does your skin burn in the sun?", + }); + await db.question.insert({ + order: 9, + id: 13, + quiz_id: 2, + target: 4, + type: 6, + slider_range: "0-100", + output_variable_name: "Redness", + weight: 100, + question: "How often does your skin experience redness?", + }); + await db.question.insert({ + order: 10, + id: 14, + quiz_id: 2, + target: 4, + type: 1, + question: "Halfway There! Do you want to save your progress?", + placeholder: "email", + }); + await db.question.insert({ + order: 11, + id: 15, + quiz_id: 2, + target: 4, + type: 6, + slider_range: "0-100", + output_variable_name: "Lines", + weight: 100, + extra_output_variable: '[{"name":"Age","weight":30}]', + question: "Which best describes your face?", + }); + await db.question.insert({ + order: 12, + id: 16, + quiz_id: 2, + target: 4, + type: 6, + slider_range: "0-100", + output_variable_name: "Firmness", + weight: 100, + extra_output_variable: '[{"name":"Age","weight":20}]', + question: "How firm is your skin?", + }); + await db.question.insert({ + order: 13, + id: 17, + quiz_id: 2, + target: 4, + type: 6, + slider_range: "0-100", + output_variable_name: "Pores", + weight: 100, + question: "Do you have enlarged pores?", + }); + await db.question.insert({ + order: 14, + id: 18, + quiz_id: 2, + target: 4, + type: 6, + slider_range: "0-100", + output_variable_name: "Blackheads", + weight: 100, + question: "Do you have blackheads?", + }); + await db.question.insert({ + order: 15, + id: 19, + quiz_id: 2, + target: 4, + type: 4, + output_variable_name: "Allergies", + weight: 100, + question: "Do you have any known allergies?", + }); + await db.question.insert({ + order: 16, + id: 20, + quiz_id: 2, + depends_on: "19|yes", + target: 4, + type: 7, + question: "Do you know if you have allergies to any of the following?", + response: "We’ll make sure to leave those out", + }); + await db.question.insert({ + order: 1, + question: "Let’s adjust your cream to your geography. Enter your city below", + placeholder: "city", + id: 21, + quiz_id: 3, + target: 4, + type: 8, + }); + await db.question.insert({ + order: 2, + id: 22, + quiz_id: 3, + target: 4, + type: 6, + slider_range: "0-100", + output_variable_name: "Pollution", + weight: 33, + question: "How often do you smoke?", + }); + await db.question.insert({ + order: 3, + id: 23, + quiz_id: 3, + target: 4, + type: 6, + slider_range: "0-100", + output_variable_name: "Stress", + weight: 100, + question: "How would you describe your stress levels?", + }); + await db.question.insert({ + order: 4, + id: 24, + quiz_id: 3, + target: 4, + type: 4, + output_variable_name: "Diet", + weight: 100, + question: "Which of these closest resembles your diet?", + }); + await db.question.insert({ + order: 5, + id: 25, + quiz_id: 3, + target: 4, + type: 6, + slider_range: "4-8", + output_variable_name: "Sleep", + weight: 100, + question: "On average how many hours of sleep do you get a night?", + }); + await db.question.insert({ + order: 6, + id: 26, + quiz_id: 3, + target: 4, + type: 6, + slider_range: "0-6", + output_variable_name: "Blue Light", + weight: 100, + question: "How many hours a day do you sit in front of a screen, ex phone, computer, tv etc.?", + }); + await db.question.insert({ + order: 7, + id: 27, + quiz_id: 3, + target: 4, + type: 6, + slider_range: "0-100", + output_variable_name: "Hydration", + weight: 15, + question: "On average, how many glasses of water do you drink a day?", + }); + await db.question.insert({ + order: 8, + id: 28, + quiz_id: 3, + target: 4, + type: 6, + slider_range: "0-100", + output_variable_name: "Pollution", + weight: 33.33, + question: "How much makeup do you wear on a daily basis?", + }); + await db.question.insert({ + order: 9, + id: 29, + quiz_id: 3, + target: 4, + type: 6, + slider_range: "0-100", + output_variable_name: "Oxygenation", + weight: 100, + question: "On average, how many hours a week do you excercize?", + }); + + await db.answer.insert({ order: 1, question_id: 1, response_header: "<<>>", response_arguments: '["name"]' }); + await db.answer.insert({ + order: 1, + question_id: 2, + answer: "<25", + response_body: "We will focus on actives that will improving your skin health and appearance without adding anything unnecessary.", + }); + await db.answer.insert({ + order: 2, + question_id: 2, + answer: "25-40", + response_body: + "We will create a custom formula containing actives to ensure we maintain your optimal skin health and appearance. We will spoil you with some wonderful actives that will help delay visible signs of skin aging.", + }); + await db.answer.insert({ + order: 3, + question_id: 2, + answer: ">40", + response_body: "We have so many luxurious actives that will work to address any of the desires that come with time and knowledge.", + }); + await db.answer.insert({ + order: 1, + question_id: 3, + answer: "Female", + }); + await db.answer.insert({ + order: 2, + question_id: 3, + answer: "Male", + }); + await db.answer.insert({ + order: 3, + question_id: 3, + answer: "Non-binary", + }); + await db.answer.insert({ + order: 4, + question_id: 3, + answer: "Other", + }); + await db.answer.insert({ order: 1, question_id: 4, answer: "Yes", answer_value: 100 }); + await db.answer.insert({ order: 2, question_id: 4, answer: "No", answer_value: 0 }); + await db.answer.insert({ order: 1, question_id: 5, answer: "Beard", answer_value: 100 }); + await db.answer.insert({ order: 2, question_id: 5, answer: "Stubble", answer_value: 66 }); + await db.answer.insert({ order: 3, question_id: 5, answer: "Clean", answer_value: 33 }); + await db.answer.insert({ order: 4, question_id: 5, answer: "Shaven", answer_value: 0 }); + await db.answer.insert({ + order: 1, + question_id: 6, + answer: "It's not", + image_id: 2, + response_header: "Wonderful!", + response_body: + "We can now eliminate many active ingredients that are just suited for sensitive skin and focus on just the wonderful actives that will perform other wonderful functions! Don’t worry we won’t be adding anything that can or will lead to extra sensitivity.", + }); + await db.answer.insert({ + order: 2, + question_id: 6, + answer: "Moderately", + image_id: 3, + response_header: "Noted.", + response_body: + "We have many wonderful ingredients that are specifically proven to be soothing even for mildly sensitive skin. We will add these along with other functional actives that are non-sensitizing.", + }); + await db.answer.insert({ + order: 3, + question_id: 6, + answer: "Extremely", + image_id: 4, + response_header: "Noted.", + response_body: "We have many wonderful ingredients that are specifically proven to be soothing for sensitive skin. We will add these along with other functional actives that are non-sensitizing.", + }); + await db.answer.insert({ + order: 1, + question_id: 7, + answer: "Very Dry", + image_id: 5, + response_header: "Let’s hydrate!", + response_body: + "We will add some wonderful hydrating actives that will specifically address your dry skin needs (some of the later questions will help us determine exactly which of our hydrating actives are perfect for you based on their scientific mode of action)", + }); + await db.answer.insert({ + order: 2, + question_id: 7, + answer: "Normal / Combination", + image_id: 6, + response_header: "We know the feeling!", + response_body: "We have some wonderful ingredients that will maintain optimal skin hydration while controlling excess oil production.", + }); + await db.answer.insert({ + order: 3, + question_id: 7, + answer: "Very Oily", + image_id: 7, + response_header: "Ok! We’ll balance that out.", + response_body: "We will make sure to add actives that will help control excess skin oiliness, while still addressing all your other skin needs.", + }); + await db.answer.insert({ + order: 1, + question_id: 8, + answer: "Hardly", + response_header: "Great!", + response_body: "We will now just focus on those actives you need", + }); + await db.answer.insert({ + order: 2, + question_id: 8, + answer: "Sometimes", + response_header: "Great!", + response_body: "We'll make sure not to add any actives that may lead to breakouts in breakout-prone skin", + }); + await db.answer.insert({ + order: 3, + question_id: 8, + answer: "Always", + response_header: "Noted.", + response_body: + "We will add some of our amazing oil-control actives to alleviate some of the factors that can aggravate breakout prone skin. (Note: due to the personalized nature of our system we cannot make any claims to treat or prevent acne in accordance with FDA regulations.", + }); + await db.answer.insert({ order: 1, question_id: 9, answer: 15, image_id: 8, answer_value: 100 }); + await db.answer.insert({ order: 2, question_id: 9, answer: 14, image_id: 9, answer_value: 93.33333333 }); + await db.answer.insert({ order: 3, question_id: 9, answer: 13, image_id: 10, answer_value: 86.66666667 }); + await db.answer.insert({ order: 4, question_id: 9, answer: 12, image_id: 11, answer_value: 80 }); + await db.answer.insert({ order: 5, question_id: 9, answer: 11, image_id: 12, answer_value: 73.33333333 }); + await db.answer.insert({ order: 6, question_id: 9, answer: 10, image_id: 13, answer_value: 66.66666667 }); + await db.answer.insert({ order: 7, question_id: 9, answer: 9, image_id: 14, answer_value: 60 }); + await db.answer.insert({ order: 8, question_id: 9, answer: 8, image_id: 15, answer_value: 53.33333333 }); + await db.answer.insert({ order: 9, question_id: 9, answer: 7, image_id: 16, answer_value: 46.66666667 }); + await db.answer.insert({ order: 10, question_id: 9, answer: 6, image_id: 17, answer_value: 40 }); + await db.answer.insert({ order: 11, question_id: 9, answer: 5, image_id: 18, answer_value: 33.33333333 }); + await db.answer.insert({ order: 12, question_id: 9, answer: 4, image_id: 19, answer_value: 26.66666667 }); + await db.answer.insert({ order: 13, question_id: 9, answer: 3, image_id: 20, answer_value: 20 }); + await db.answer.insert({ order: 14, question_id: 9, answer: 2, image_id: 21, answer_value: 13.33333333 }); + await db.answer.insert({ order: 15, question_id: 9, answer: 1, image_id: 22, answer_value: 6.666666667 }); + await db.answer.insert({ + order: 1, + question_id: 10, + answer: "Never", + response_body: "Keep the sunscreen close! We’ll make sure to add some wonderful actives that will help you with your beautiful glow", + }); + await db.answer.insert({ + order: 2, + question_id: 10, + answer: "Sometimes", + response_body: "Don’t forget the sunscreen! We’ll make sure to add some wonderful actives that will help you with your beautiful glow", + }); + await db.answer.insert({ + order: 3, + question_id: 10, + answer: "Always", + response_body: "We’ll make sure to add some wonderful actives that will help you with your beautiful glow.", + }); + await db.answer.insert({ + order: 2, + question_id: 11, + answer: "Yes", + response_body: "We’ll add some of our wonderful actives that will minimize the appearance of any hyper or hypo-pigmentation.", + }); + await db.answer.insert({ + order: 1, + question_id: 11, + answer: "No", + response_body: "Great, we can eliminate the addition of unnecessary actives and only focus on those that you need.", + }); + await db.answer.insert({ + order: 3, + question_id: 12, + answer: "Instant Burn", + response_header: "We hear your pain!", + response_body: "Make sure to wear proper SPF and we’ll make sure we add actives that are not sun-sensitizing.", + }); + await db.answer.insert({ + order: 2, + question_id: 12, + answer: "Middle", + response_header: "Noted.", + response_body: "Make sure to wear proper SPF and we’ll make sure we add actives that will not make your skin extra sensitive to the sun during the day.", + }); + await db.answer.insert({ + order: 1, + question_id: 12, + answer: "Hardly ever", + response_header: "Lucky!", + response_body: "We can focus on all the great actives your skin needs without the sun’s distraction – though we still recommend using a daily SPF.", + }); + await db.answer.insert({ + order: 1, + question_id: 13, + answer: "Red? Huh? No red here", + image_id: 23, + response_header: "Great!", + response_body: "We’ll just focus on the actives that you need.", + }); + await db.answer.insert({ + order: 2, + question_id: 13, + answer: "Occaisonally red & blotchy.", + image_id: 24, + response_header: "Noted.", + response_body: "We have amazing actives specifically for redness – keep going till the end to find out what we have chosen specifically for your needs.", + }); + await db.answer.insert({ + order: 3, + question_id: 13, + answer: "I am constantly seeing red", + image_id: 24, + response_header: "Noted.", + response_body: "We have amazing actives specifically for redness – keep going till the end to find out what we have chosen specifically for your needs.", + }); + await db.answer.insert({ + order: 1, + question_id: 15, + answer: "No Wrinkles/Lines", + image_id: 25, + response_header: "Amazing <<>>,", + response_body: + "We have some amazing anti-wrinkle actives, most with more than ten letters, and you don’t need any of them. Save your money to splurge on things that will actually do something for you.", + response_arguments: '["name"]', + }); + await db.answer.insert({ + order: 2, + question_id: 15, + answer: "A Few Lines", + hide_answer: true, + image_id: 26, + response_body: "We have some wonderful actives that will minimize the appearance of lines. We’ll just focus on those that will give you the best bang for your buck.", + }); + await db.answer.insert({ + order: 3, + question_id: 15, + answer: "A Few Lines Observable at all times", + hide_answer: true, + image_id: 27, + response_body: "We have some wonderful actives that will minimize the appearance of lines. We’ll just focus on those that will give you the best bang for your buck.", + }); + await db.answer.insert({ + order: 4, + question_id: 15, + answer: "Some Lines", + image_id: 28, + response_body: "We have some wonderful actives that will minimize the appearance of lines. We’ll just focus on those that will give you the best bang for your buck.", + }); + await db.answer.insert({ + order: 5, + question_id: 15, + answer: "Lines Plus Hints of Wrinkles", + hide_answer: true, + image_id: 29, + response_body: "We have some wonderful actives that will minimize the appearance of lines. We’ll just focus on those that will give you the best bang for your buck.", + }); + await db.answer.insert({ + order: 6, + question_id: 15, + answer: "A Few Wrinkles", + hide_answer: true, + image_id: 30, + response_header: "We’re going to add some of our luxurious anti-wrinkle actives. Keep going till the end to see what we recommend.", + }); + await db.answer.insert({ + order: 7, + question_id: 15, + answer: "Lots of Wrinkles", + image_id: 31, + response_header: "We’re going to add some of our luxurious anti-wrinkle actives. Keep going till the end to see what we recommend.", + }); + + await db.answer.insert({ + order: 1, + question_id: 16, + answer: "Firm as a baby", + response_header: "Amazing!!", + response_body: "We’ll focus on the actives more appropriate to your skin and ensure we maintain your skin’s natural resilience.", + }); + await db.answer.insert({ + order: 2, + question_id: 16, + answer: "Middle", + response_body: "We’ll add some luxurious actives to your formulation that will help prevent and improve your skins firmness.", + }); + await db.answer.insert({ + order: 3, + question_id: 16, + answer: "Sagging", + response_header: "We got you!", + response_body: "We’ll add some of our wonderful actives that will improve your skin’s appearance of firmness.", + }); + await db.answer.insert({ + order: 1, + question_id: 17, + answer: "No - smooth as can be", + response_header: "Lucky you!", + response_body: "We can eliminate actives that will just be extra clutter for your wonderful skin.", + }); + await db.answer.insert({ + order: 2, + question_id: 17, + answer: "Some", + response_body: "We’ll keep this in mind (our algorithm’s mind) as we create your perfect formula.", + }); + await db.answer.insert({ + order: 3, + question_id: 17, + answer: "A lot", + response_body: "We’ll keep this in mind (our algorithm’s mind) as we create your perfect formula.", + }); + await db.answer.insert({ + order: 1, + question_id: 18, + answer: "No", + }); + await db.answer.insert({ + order: 2, + question_id: 18, + answer: "Some", + }); + await db.answer.insert({ + order: 3, + question_id: 18, + answer: "A lot", + }); + await db.answer.insert({ order: 1, question_id: 19, answer: "Yes", answer_value: 100 }); + await db.answer.insert({ order: 2, question_id: 19, answer: "No", response_header: "Lucky You!", answer_value: 0 }); + + await db.answer.insert({ order: 1, question_id: 20, answer: "Banana" }); + await db.answer.insert({ order: 2, question_id: 20, answer: "Olive" }); + await db.answer.insert({ order: 3, question_id: 20, answer: "Sunflowers" }); + await db.active.bulkCreate([ + { + id: 1, + name: "Acai", + variables_scores: + '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"70","Hydration":"70","Breakouts":"","Color":"","Sun":"90","Hyperpigmentation":"50","Hypopigmentation":"","Redness":"90","Lines":"90","Firmness":"90","Pores":"20","Blackheads":"10","Allergies":"","Pollution":"70","Temperature":"","Stress":"70","Diet":"","Sleep":"20","Blue Light":"","Oxygenation":""}', + }, + { + id: 2, + name: "Bakuchiol", + variables_scores: + '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"80","Hydration":"0","Breakouts":"100","Color":"","Sun":"100","Hyperpigmentation":"100","Hypopigmentation":"","Redness":"90","Lines":"100","Firmness":"100","Pores":"50","Blackheads":"80","Allergies":"","Pollution":"0","Temperature":"","Stress":"0","Diet":"","Sleep":"80","Blue Light":"","Oxygenation":"80"}', + }, + { + id: 3, + name: "Base", + variables_scores: null, + }, + { + id: 4, + name: "Base Refill", + variables_scores: null, + }, + { + id: 5, + name: "Chamomile", + variables_scores: + '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"90","Hydration":"90","Breakouts":"70","Color":"","Sun":"90","Hyperpigmentation":"70","Hypopigmentation":"","Redness":"100","Lines":"90","Firmness":"90","Pores":"40","Blackheads":"50","Allergies":"","Pollution":"80","Temperature":"","Stress":"10","Diet":"","Sleep":"40","Blue Light":"","Oxygenation":""}', + }, + { + id: 6, + name: "Chia", + variables_scores: + '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"90","Hydration":"70","Breakouts":"100","Color":"","Sun":"90","Hyperpigmentation":"70","Hypopigmentation":"","Redness":"20","Lines":"60","Firmness":"40","Pores":"80","Blackheads":"100","Allergies":"","Pollution":"50","Temperature":"","Stress":"10","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', + }, + { + id: 7, + name: "Coconut", + variables_scores: + '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"80","Hydration":"100","Breakouts":"30","Color":"","Sun":"90","Hyperpigmentation":"20","Hypopigmentation":"","Redness":"70","Lines":"40","Firmness":"40","Pores":"20","Blackheads":"0","Allergies":"","Pollution":"80","Temperature":"","Stress":"10","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', + }, + { + id: 8, + name: "Cogon Grass", + variables_scores: + '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"40","Hydration":"100","Breakouts":"20","Color":"","Sun":"90","Hyperpigmentation":"40","Hypopigmentation":"","Redness":"10","Lines":"80","Firmness":"80","Pores":"20","Blackheads":"10","Allergies":"","Pollution":"10","Temperature":"","Stress":"10","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', + }, + { + id: 9, + name: "Cucumber", + variables_scores: + '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"80","Hydration":"100","Breakouts":"60","Color":"","Sun":"90","Hyperpigmentation":"20","Hypopigmentation":"","Redness":"80","Lines":"60","Firmness":"60","Pores":"50","Blackheads":"20","Allergies":"","Pollution":"40","Temperature":"","Stress":"10","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', + }, + { + id: 10, + name: "Dragon's Blood", + variables_scores: + '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"80","Hydration":"80","Breakouts":"70","Color":"","Sun":"90","Hyperpigmentation":"50","Hypopigmentation":"","Redness":"80","Lines":"100","Firmness":"100","Pores":"20","Blackheads":"20","Allergies":"","Pollution":"80","Temperature":"","Stress":"80","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', + }, + { + id: 11, + name: "Ginseng", + variables_scores: + '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"80","Hydration":"10","Breakouts":"30","Color":"","Sun":"100","Hyperpigmentation":"50","Hypopigmentation":"","Redness":"70","Lines":"100","Firmness":"100","Pores":"10","Blackheads":"10","Allergies":"","Pollution":"90","Temperature":"","Stress":"10","Diet":"","Sleep":"20","Blue Light":"","Oxygenation":""}', + }, + { + id: 12, + name: "Gotu Kola", + variables_scores: + '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"90","Hydration":"80","Breakouts":"60","Color":"","Sun":"90","Hyperpigmentation":"60","Hypopigmentation":"","Redness":"90","Lines":"70","Firmness":"70","Pores":"60","Blackheads":"20","Allergies":"","Pollution":"70","Temperature":"","Stress":"10","Diet":"","Sleep":"50","Blue Light":"","Oxygenation":""}', + }, + { + id: 13, + name: "Licorice Root", + variables_scores: + '{"Bio Age":"","Age":"","Gender":"","Pregnancy":"","Hair":"","Sensitivity":"0","Hydration":"0","Breakouts":"10","Color":"","Sun":"40","Hyperpigmentation":"100","Hypopigmentation":"","Redness":"90","Lines":"60","Firmness":"20","Pores":"10","Blackheads":"10","Allergies":"","Pollution":"30","Temperature":"","Stress":"10","Diet":"","Sleep":"70","Blue Light":"","Oxygenation":""}', + }, + { + id: 14, + name: "Moringa", + variables_scores: null, + }, + { + id: 15, + name: "Moth Bean", + variables_scores: null, + }, + { + id: 16, + name: "Mushrooms", + variables_scores: null, + }, + { + id: 17, + name: "Oatmeal", + variables_scores: null, + }, + { + id: 18, + name: "Okra", + variables_scores: null, + }, + { + id: 19, + name: "Olive Squalane", + variables_scores: null, + }, + { + id: 20, + name: "Red Raddish", + variables_scores: null, + }, + { + id: 21, + name: "Rose Hip", + variables_scores: null, + }, + { + id: 22, + name: "Sake Extract", + variables_scores: null, + }, + { + id: 23, + name: "Sandalwood", + variables_scores: null, + }, + { + id: 24, + name: "Tonka Bean", + variables_scores: null, + }, + { + id: 25, + name: "White Willow Bark", + variables_scores: null, + }, + { + id: 26, + name: "Yeast Extract", + variables_scores: null, + }, + ]); + await db.answer.insert({ + order: 1, + question_id: 22, + answer: "Never", + response_header: "Great!", + response_body: "This means your skin is exposed to less pollution and better oxygenation!", + }); + await db.answer.insert({ + order: 2, + question_id: 22, + answer: "Sometimes", + response_body: "We’ll make sure to add extra actives to address the pollution your skin is exposed to.", + }); + await db.answer.insert({ + order: 3, + question_id: 22, + answer: "Multiple per day", + response_header: "Got it.", + response_body: "Your formula will include actives for anti-pollution and increased oxygenation to your skin.", + }); + await db.answer.insert({ + order: 1, + question_id: 23, + answer: "Cool as a cucumber", + response_header: "Lucky you!", + response_body: "We’ll rather focus on areas that are of greater concern to you.", + }); + await db.answer.insert({ + order: 2, + question_id: 23, + answer: "Sometimes", + response_body: + "Occasional stress can release cortisol and other factors that can negatively affect the skin. We’ll add some adaptogens and other actives that can help mitigate some of these effects.", + }); + await db.answer.insert({ + order: 3, + question_id: 23, + answer: "In a constant state of anxiety", + response_body: "Stress can release cortisol and other factors that can negatively affect the skin. We’ll add some adaptogens and other actives that can help mitigate some of these effects.", + }); + await db.answer.insert({ order: 1, question_id: 24, answer: "Vegan/Vegetarian", answer_value: 0 }); + await db.answer.insert({ order: 2, question_id: 24, answer: "Flexitarian, I sometime eat meat", answer_value: 25 }); + await db.answer.insert({ order: 3, question_id: 24, answer: "Pescatarian, I’ll have fish and seafood, but no meat", answer_value: 50 }); + await db.answer.insert({ order: 4, question_id: 24, answer: "I stay away from red meat", answer_value: 75 }); + await db.answer.insert({ order: 5, question_id: 24, answer: "I eat everything", answer_value: 100 }); + await db.answer.insert({ order: 1, question_id: 25, answer: "<4" }); + await db.answer.insert({ order: 2, question_id: 25, answer: "5-7" }); + await db.answer.insert({ order: 3, question_id: 25, answer: "8+" }); + await db.answer.insert({ + order: 1, + question_id: 26, + answer: "0-2", + response_header: "Good for you!", + response_body: + "Blue light emitted from screens can be harmful to your skin’s health and appearance. Your low exposure means we can rather focus on other areas to optimize your skin health and appearance.", + }); + await db.answer.insert({ + order: 2, + question_id: 26, + answer: "2-6", + response_body: + "Blue light emitted from screens can be harmful to your skin’s health and appearance. No worries though, we’ll add some actives, such as our innovative Rockrose extract that will help mitigate some of these effects.", + }); + await db.answer.insert({ + order: 3, + question_id: 26, + answer: "6+", + response_body: + "Blue light emitted from screens can affect your skin’s circadian rhythm as well as affect your skin’s health and appearance. We’ll add some actives, such as our innovative Rockrose extract that will help mitigate some of these effect", + }); + await db.answer.insert({ + order: 1, + question_id: 27, + answer: "0", + image_id: 32, + response_body: "We’ll add extra hydrating actives, but we recommend you drink more so your skin gets nourished from within as well.", + }); + await db.answer.insert({ + order: 2, + question_id: 27, + answer: "4", + image_id: 33, + response_body: "We’ll add extra hydrating actives, but we recommend you drink more so your skin gets nourished from within as well.", + }); + await db.answer.insert({ + order: 3, + question_id: 27, + answer: "8+", + image_id: 34, + response_header: "Great!", + response_body: "You don’t need extra actives to compensate from a lack of internal hydration.", + }); + await db.answer.insert({ order: 1, question_id: 28, answer: "None" }); + await db.answer.insert({ order: 2, question_id: 28, answer: "Full Coverage" }); + await db.answer.insert({ + order: 1, + question_id: 29, + answer: "Low", + response_body: "We’ll add extra actives to give your skin an extra boost on oxygenation and nutrient delivery.", + }); + await db.answer.insert({ + order: 2, + question_id: 29, + answer: "High", + response_header: "Great!", + response_body: + "By exercising you are providing extra oxygenation and nutrient delivery to your skin, so we don’t have to add extra actives to do what you are already doing an even better job at. ", + }); + await db.answer.insert({ + question_id: 30, + order: 1, + answer: "No", + hide_answer: 0, + response_header: "Great!", + response_body: "We can eliminate the addition of unnecessary actives and only focus on those that you need. ", + }); + await db.answer.insert({ + question_id: 30, + order: 1, + answer: "Yes", + hide_answer: 0, + response_body: "We'll add some of our wonderful actives that will minimize the appearance of hypopigmentation over time", + }); + await db.result_profile.insert({ + id: 1, + section_title: "Skin Sensitivity", + output_variable_list: "[6,7,13,11,10]", + }); + await db.result_profile.insert({ + id: 2, + section_title: "Skin Characteristics", + output_variable_list: "[14,15,17,16,8]", + }); + await db.result_profile.insert({ + id: 3, + section_title: "Environmental Factors", + output_variable_list: "[19,21,24,25]", + }); +} + +executeSeeds(); diff --git a/server.js b/server.js new file mode 100644 index 0000000..9bebe39 --- /dev/null +++ b/server.js @@ -0,0 +1,16 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2020*/ +/** + * Server + * @copyright 2020 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +const app = require('./app'); +app.set('port', process.env.NODE_PORT); +app.listen(app.get('port'), () => { + const port = app.get('port'); + console.log('Node Server Running at http://127.0.0.1:' + port); +}); diff --git a/services/.gitkeep b/services/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/services/AclService.js b/services/AclService.js new file mode 100644 index 0000000..e69de29 diff --git a/services/AuthService.js b/services/AuthService.js new file mode 100644 index 0000000..aa64a23 --- /dev/null +++ b/services/AuthService.js @@ -0,0 +1,289 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Auth Service + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const passwordService = require("./PasswordService"); +const mailService = require("./MailService"); +const generateCode = require("../utils/generateCode"); +const db = require("../models"); +const errors = require("../core/errors"); + +module.exports = { + /** + * Register new user with email and password + * @name authService.register + * @param {String} email user new email address + * @param {String} password user new password + * @returns {Promise.<{credential:String, user:String}>} payload to generate jwt access and refresh token + * @example + * const payload = await authService.register(req.body.email, req.body.password) + */ + register: async function (email, password, roleId, userDetails = {}) { + try { + const isEmailAddressExist = await db.credential.getByFields({ + email, + }); + + if (isEmailAddressExist) throw new Error(errors.EMAIL_ADDRESS_ALREADY_EXIST); + + const hashedPassword = await passwordService.hash(password); + + var user = await db.user.insert({ ...userDetails, role_id: roleId }, { returnAllFields: true }); + var credential = await db.credential.insert( + { + email: email, + password: hashedPassword, + user_id: user.id, + type: 0, + verify: 0, + status: 1, + }, + { returnAllFields: true } + ); + + return { credential: credential.id, user: user.id }; + } catch (error) { + if (credential) { + await db.credential.realDelete(credential.id); + } + if (user) { + await db.user.realDelete(user.id); + } + console.error(error); + throw error; + } + }, + /** + * Login user with email and password + * @name authService.login + * @param {String} email user email address + * @param {String} password user password + * @returns {Promise.<{credential:String, user:String}>} payload to generate jwt access and refresh token + * @example + * const payload = await authService.login(req.body.email, req.body.password) + */ + login: async function (email, password, roldId) { + try { + const isEmailAddressExist = await db.credential.findOne({ + where: { email, status: 1, type: 0 }, + include: [{ model: db.user, required: true, as: "user", where: { role_id: roldId } }], + }); + + if (!isEmailAddressExist) throw new Error(errors.EMAIL_ADDRESS_NOT_FOUND); + + const { password: hashedPassword, id, user_id } = isEmailAddressExist; + + const user = await db.user.getByPK(user_id); + + if (!user) { + throw new Error(errors.USER_NOT_FOUND); + } + + const isPasswordMatch = await passwordService.compareHash(password, hashedPassword); + + if (!isPasswordMatch) throw new Error(errors.INVALID_EMAIL_OR_PASSWORD); + + return { credential: id, user: user.id }; + } catch (error) { + console.error(error); + throw error; + } + }, + /** + * Send email and save to database + * @name authService.forgotPassword + * @param {String} email user email address + * @return {Promise.} + * @example + * await authService.forgotPassword(req.body.email) + */ + forgotPassword: async function (email) { + try { + const isEmailAddressExist = await db.credential.getByFields({ + email: email, + }); + + if (!isEmailAddressExist) throw new Error(errors.EMAIL_ADDRESS_NOT_FOUND); + + const { user_id } = isEmailAddressExist; + + const getUser = await db.user.getByPK(user_id); + + const verificationCode = generateCode(6); + + mailService.initialize({ + hostname: process.env.EMAIL_SMTP_SMTP_HOST, + port: process.env.EMAIL_SMTP_SMTP_PORT, + username: process.env.EMAIL_SMTP_SMTP_USER, + password: EMAIL_SMTP_SMTP_PASS, + from: process.env.MAIL_FROM, + to: email, + }); + + const mailTemplate = await mailService.template("reset-password"); + + const injectedMailTemplate = mailService.inject( + { + body: mailTemplate.body, + subject: mailTemplate.subject, + }, + { + username: `${getUser.first_name} ${getUser.last_name}`, + verification_code: verificationCode, + } + ); + + await mailService.send(injectedMailTemplate); + + await db.token.insert({ token: verificationCode, user_id }); + } catch (error) { + console.error(error); + throw error; + } + }, + /** + * Verify forgot password confirmation code + * @name authService.verifyForgotPassword + * @param {code} code confirmation code + * @returns {Promise.<{credential:String, user:String}>} payload to generate jwt access and refresh token + * @example + * const payload = await authService.verifyForgotPassword(req.body.code) + */ + verifyForgotPassword: async function (code) { + try { + const Token = await db.token.getByFields({ + token: code, + }); + + const Credential = await db.credential.getByFields({ + user_id: Token.user_id, + }); + + return { credential: Credential.id, user: Credential.user_id }; + } catch (error) { + console.error(error); + throw error; + } + }, + /** + * Reset password + * @name authService.resetPassword + * @param {String} password user new password + * @param {String} credential_id user credential id + * @example + * await authService.resetPassword(req.body.password, credential_id) + */ + resetPassword: async function (password, credential_id) { + try { + const hashedPassword = await passwordService.hash(password); + + await db.credential.edit( + { + password: hashedPassword, + }, + credential_id + ); + } catch (error) { + console.error(error); + throw error; + } + }, + /** + * Email confirmation + * @name authService.emailConfirmation + * @param {String} email user email address + * @example + * await authService.emailConfirmation(email) + */ + emailConfirmation: async function (email) { + try { + const isEmailAddressExist = await db.credential.getByFields({ + email: email, + }); + + if (!isEmailAddressExist) throw new Error(errors.EMAIL_ADDRESS_NOT_FOUND); + + const { user_id } = isEmailAddressExist; + + const user = await db.user.getByPK(user_id); + + const confirmationCode = generateCode(6); + + mailService.initialize({ + hostname: process.env.EMAIL_SMTP_SMTP_HOST, + port: process.env.EMAIL_SMTP_SMTP_PORT, + username: process.env.EMAIL_SMTP_SMTP_USER, + password: EMAIL_SMTP_SMTP_PASS, + from: process.env.MAIL_FROM, + to: email, + }); + + const mailTemplate = await mailService.template("email-confirmation"); + + const injectedMailTemplate = mailService.inject( + { + body: mailTemplate.body, + subject: mailTemplate.subject, + }, + { + username: `${user.first_name} ${user.last_name}`, + confirmation_code: confirmationCode, + } + ); + + await mailService.send(injectedMailTemplate); + + await db.token.insert({ token: confirmationCode, user_id, type: 6 }); + } catch (error) { + console.error(error); + throw error; + } + }, + /** + * Verify Email address + * @name authService.emailVerify + * @param {String} token email confirmation code + * @param {string} user_id user id + * @example + * await authService.emailVerify(email, user_id) + */ + emailVerify: async function (token, user_id) { + try { + const isTokenExist = await db.token.getByFields({ + user_id, + token, + type: 6, + }); + + if (!isTokenExist) throw new Error(errors.INVALID_EMAIL_CONFIRMATION_CODE); + + await db.token.realDelete(isTokenExist.id); + } catch (error) { + console.error(error); + throw error; + } + }, + /** + * check if user need to change password before logging in + * @name authService.forcePasswordChange + * @param {string} user_id user id + */ + forcePasswordChange: async function (user_id) { + try { + const { profile_id } = await db.user.getByPK(user_id); + const { force_password_change } = await db.profile.getByPK(profile_id); + + if (force_password_change) return true; + else return false; + } catch (error) { + console.error(error); + throw error; + } + }, +}; diff --git a/services/AuthServiceMerged.js b/services/AuthServiceMerged.js new file mode 100644 index 0000000..8cad31a --- /dev/null +++ b/services/AuthServiceMerged.js @@ -0,0 +1,277 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Auth Service + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const passwordService = require('./PasswordService'); +const mailService = require('./MailService'); +const generateCode = require('../utils/generateCode'); +const db = require('../models'); + +const errors = { + EMAIL_ADDRESS_NOT_FOUND: 'xyzEMAIL_ADDRESS_NOT_FOUND', + EMAIL_ADDRESS_ALREADY_EXIST: 'xyzEMAIL_ADDRESS_ALREADY_EXIST', + PASSWORD_NOT_MATCH: 'xyzPASSWORD_NOT_MATCH', + INVALID_EMAIL_CONFIRMATION_CODE: 'xyzINVALID_EMAIL_CONFIRMATION_CODE', + INVALID_EMAIL_OR_PASSWORD: 'xyzINVALID_EMAIL_OR_PASSWORD', +}; + +module.exports = { + /** + * Register new user with email and password + * @name authService.register + * @param {String} email user new email address + * @param {String} password user new password + * @returns {Promise.<{credential:String, user:String}>} payload to generate jwt access and refresh token + * @example + * const payload = await authService.register(req.body.email, req.body.password) + */ + register: async function (email, password, role_id, user_details = {}) { + try { + const isEmailAddressExist = await db.user.getByFields({ + email, + }); + + if (isEmailAddressExist) throw new Error(errors.EMAIL_ADDRESS_ALREADY_EXIST); + + const hashedPassword = await passwordService.hash(password); + + var user = await db.user.insert( + { + ...user_details, + email: email, + password: hashedPassword, + role_id, + type: 0, + verify: 1, + status: 1, + }, + { returnAllFields: true }, + ); + + return { user }; + } catch (error) { + if (user) { + await db.user.realDelete(user.id); + } + console.error(error); + throw error; + } + }, + /** + * Login user with email and password + * @name authService.login + * @param {String} email user email address + * @param {String} password user password + * @returns {Promise.<{credential:String, user:String}>} payload to generate jwt access and refresh token + * @example + * const payload = await authService.login(req.body.email, req.body.password) + */ + login: async function (email, password, role_id) { + try { + const user = await db.user.getByFields({ + email, + status: 1, + role_id, + type: 0, + }); + + if (!user) throw new Error(errors.EMAIL_ADDRESS_NOT_FOUND); + + const { password: hashedPassword } = user; + + const isPasswordMatch = await passwordService.compareHash(password, hashedPassword); + + if (!isPasswordMatch) throw new Error(errors.INVALID_EMAIL_OR_PASSWORD); + + return { user: user }; + } catch (error) { + console.error(error); + throw error; + } + }, + /** + * Send email and save to database + * @name authService.forgotPassword + * @param {String} email user email address + * @return {Promise.} + * @example + * await authService.forgotPassword(req.body.email) + */ + forgotPassword: async function (email) { + try { + const user = await db.user.getByFields({ + email: email, + }); + + if (!user) throw new Error(errors.EMAIL_ADDRESS_NOT_FOUND); + + const verificationCode = generateCode(6); + + mailService.initialize({ + hostname: process.env.EMAIL_SMTP_SMTP_HOST, + port: process.env.EMAIL_SMTP_SMTP_PORT, + username: process.env.EMAIL_SMTP_SMTP_USER, + password: EMAIL_SMTP_SMTP_PASS, + from: process.env.MAIL_FROM, + to: email, + }); + + const mailTemplate = await mailService.template('reset-password'); + + const injectedMailTemplate = mailService.inject( + { + body: mailTemplate.body, + subject: mailTemplate.subject, + }, + { + username: `${user.first_name} ${user.last_name}`, + verification_code: verificationCode, + }, + ); + + await mailService.send(injectedMailTemplate); + + await db.token.insert({ token: verificationCode, user_id: user.id }); + } catch (error) { + console.error(error); + throw error; + } + }, + /** + * Verify forgot password confirmation code + * @name authService.verifyForgotPassword + * @param {code} code confirmation code + * @returns {Promise.<{credential:String, user:String}>} payload to generate jwt access and refresh token + * @example + * const payload = await authService.verifyForgotPassword(req.body.code) + */ + verifyForgotPassword: async function (code) { + try { + const Token = await db.token.findByFields({ + token: code, + }); + const user = await db.user.getLast({ user_id: Token.user_id }); + return { user }; + } catch (error) { + console.error(error); + throw error; + } + }, + /** + * Reset password + * @name authService.resetPassword + * @param {String} password user new password + * @param {String} credential_id user credential id + * @example + * await authService.resetPassword(req.body.password, credential_id) + */ + resetPassword: async function (password, userId) { + try { + const hashedPassword = await passwordService.hash(password); + + await db.user.edit( + { + password: hashedPassword, + }, + userId, + ); + } catch (error) { + console.error(error); + throw error; + } + }, + /** + * Email confirmation + * @name authService.emailConfirmation + * @param {String} email user email address + * @example + * await authService.emailConfirmation(email) + */ + emailConfirmation: async function (email) { + try { + const user = await db.user.getByFields({ + email: email, + }); + + if (!user) throw new Error(errors.EMAIL_ADDRESS_NOT_FOUND); + + const confirmationCode = generateCode(6); + + mailService.initialize({ + hostname: process.env.EMAIL_SMTP_SMTP_HOST, + port: process.env.EMAIL_SMTP_SMTP_PORT, + username: process.env.EMAIL_SMTP_SMTP_USER, + password: EMAIL_SMTP_SMTP_PASS, + from: process.env.MAIL_FROM, + to: email, + }); + + const mailTemplate = await mailService.template('email-confirmation'); + + const injectedMailTemplate = mailService.inject( + { + body: mailTemplate.body, + subject: mailTemplate.subject, + }, + { + username: `${user.first_name} ${user.last_name}`, + confirmation_code: confirmationCode, + }, + ); + + await mailService.send(injectedMailTemplate); + + await db.token.insert({ token: confirmationCode, user_id: user.id, type: 6 }); + } catch (error) { + console.error(error); + throw error; + } + }, + /** + * Verify Email address + * @name authService.emailVerify + * @param {String} token email confirmation code + * @param {string} user_id user id + * @example + * await authService.emailVerify(email, user_id) + */ + emailVerify: async function (token, user_id) { + try { + const isTokenExist = await db.token.getByFields({ + user_id, + token, + type: 6, + }); + + if (!isTokenExist) throw new Error(errors.INVALID_EMAIL_CONFIRMATION_CODE); + + await db.token.realDelete(isTokenExist.id); + } catch (error) { + console.error(error); + throw error; + } + }, + /** + * check if user need to change password before logging in + * @name authService.forcePasswordChange + * @param {string} user_id user id + */ + forcePasswordChange: async function (user_id) { + try { + const { profile_id } = await db.user.getByPk(user_id); + const { force_password_change } = await db.profile.getByPk(profile_id); + + if (force_password_change) return true; + else return false; + } catch (error) { + console.error(error); + throw error; + } + }, +}; diff --git a/services/BarcodeService.js b/services/BarcodeService.js new file mode 100644 index 0000000..8f1e349 --- /dev/null +++ b/services/BarcodeService.js @@ -0,0 +1,24 @@ +const barcode = require('barcode'); + +module.exports = { + /** + * Generate barcode + * @param {string} string barcode text + * @param {{width?: number, height?: number}} param1 width and height for barcode image + * @returns {Promise.} + */ + generateBarcode: async function (string, { width = 400, height = 100 }) { + return new Promise((resolve, reject) => { + const code128 = barcode('Code128', { + data: string, + width, + height, + }); + + code128.getBase64(function (error, base64String) { + if (error) reject(error); + else resolve(base64String); + }); + }); + }, +}; diff --git a/services/CsvService.js b/services/CsvService.js new file mode 100644 index 0000000..2621e36 --- /dev/null +++ b/services/CsvService.js @@ -0,0 +1,84 @@ +const multer = require('multer'); +const converter = require('json-2-csv'); +const fs = require('fs'); +const path = require('path'); +const csv = require('fast-csv'); +const db = require('./../models'); +const upload_folder = path.resolve(__dirname, '../uploads'); + +module.exports = { + /** + * Import CSV file + * @param {request} req + * @param {response} res + */ + csv_preview: function (req, res) { + return new Promise((resolve, reject) => { + const upload = multer({ dest: path.resolve(upload_folder) }).single('file'); + upload(req, res, async function (error) { + if (error) { + reject(error); + } + let data = []; + fs.createReadStream(path.resolve(upload_folder, req.file.path)) + .pipe(csv.parse()) + .on('error', (error) => reject(error)) + .on('data', (row) => { + data.push(row); + }) + .on('end', (rowCount) => { + fs.unlinkSync(path.resolve(upload_folder, req.file.path)); + console.log(`Parsed ${rowCount} rows`); + resolve(data); + }); + }); + }); + }, + csv_import: async function (req, res) { + return new Promise((resolve, reject) => { + const table = req.params.model; + const upload = multer({ dest: path.resolve(upload_folder) }).single('file'); + let data = []; + upload(req, res, async function (error) { + if (error) { + throw new Error(error); + } + fs.createReadStream(path.resolve(upload_folder, req.file.path)) + .pipe(csv.parse({ headers: true })) + .on('error', (error) => reject(error)) + .on('data', (row) => { + data.push(row); + }) + .on('end', async (rowCount) => { + fs.unlinkSync(path.resolve(upload_folder, req.file.path)); + console.log(`Parsed ${rowCount} rows`); + await db[table].batchInsert(data).catch((error) => { + console.log(error); + reject(error); + }); + resolve(data); + }); + }); + }); + }, + /** + * Export CSV file + * @param {request} req + * @param {response} res + */ + csv_export: async function (req, res) { + try { + let fields = await db[req.table].getAll(req.where); + fields = JSON.stringify(fields); // do this needed? + + const csv = await converter.json2csvAsync(fields); + + res.header('Content-Type', 'text/csv'); + res.attachment(req.table + '.csv'); + + return res.send(csv); + } catch (error) { + console.log(error); + } + }, +}; diff --git a/services/EncryptDecryptService.js b/services/EncryptDecryptService.js new file mode 100644 index 0000000..beee8d3 --- /dev/null +++ b/services/EncryptDecryptService.js @@ -0,0 +1,15 @@ +const crypto = require('crypto'); + +module.exports = { + iv: crypto.randomBytes(16).toString('hex').slice(0, 16), + encrypt: function (message, secret) { + const encrypter = crypto.createCipheriv('aes-256-cbc', secret, this.iv); + let encryptMessage = encrypter.update(message, 'utf-8', 'hex'); + return (encryptMessage += encrypter.final('hex')); + }, + decrypt: function (encryptMessage, secret) { + const decrypter = crypto.createDecipheriv('aes-256-cbc', secret, this.iv); + let decryptedMessage = decrypter.update(encryptMessage, 'hex', 'utf8'); + return (decryptedMessage += decrypter.final('utf8')); + }, +}; diff --git a/services/FirebaseService.js b/services/FirebaseService.js new file mode 100644 index 0000000..dec7a64 --- /dev/null +++ b/services/FirebaseService.js @@ -0,0 +1,166 @@ +var firebase = require('firebase-admin'); +var serviceAccount = require('./serviceAccountKey.json'); + +/* +Examples: +Write: +firebaseService.write('notification', 1, { + a: 1, + b: 'd', + c:['a','w'], + d: [{a:1},{b:2}] +}) +Read Once: +firebaseService.read('notification', 1).then(function(notification){ + console.log(notification); + }); +Update: +firebaseService.update('notification', 1, {a:2}); +usersRef.update({ + "alanisawesome/nickname": "Alan The Machine", + "gracehop/nickname": "Amazing Grace" +}); +Read On Listeners: +ref.on("value", function(snapshot) { + console.log(snapshot.val()); +}, function (errorObject) { + console.log("The read failed: " + errorObject.code); +}); +Read Previous Listener: +ref.on("child_added", function(snapshot, prevChildKey) { + var newPost = snapshot.val(); + console.log("Author: " + newPost.author); + console.log("Title: " + newPost.title); + console.log("Previous Post ID: " + prevChildKey); +}); + +Child Changed Listener: +// Get the data on a post that has changed +ref.on("child_changed", function(snapshot) { + var changedPost = snapshot.val(); + console.log("The updated post title is " + changedPost.title); +}); + +Child Removed Listener: +// Get the data on a post that has been removed +ref.on("child_removed", function(snapshot) { + var deletedPost = snapshot.val(); + console.log("The blog post titled '" + deletedPost.title + "' has been deleted"); +}); +Order By Listener: +ref.orderByChild("height").on("child_added", function(snapshot) { + console.log(snapshot.key + " was " + snapshot.val().height + " meters tall"); +}); + +Order By key: +var ref = db.ref("dinosaurs"); +ref.orderByKey().on("child_added", function(snapshot) { + console.log(snapshot.key); +}); + +Limited: +var ref = db.ref("dinosaurs"); +ref.orderByChild("weight").limitToLast(2).on("child_added", function(snapshot) { + console.log(snapshot.key); +}); + +var ref = db.ref("dinosaurs"); + ref.orderByChild("height").startAt(3).on("child_added", function(snapshot) { + console.log(snapshot.key); + }); + +var ref = db.ref("dinosaurs"); +ref.orderByKey().endAt("pterodactyl").on("child_added", function(snapshot) { + console.log(snapshot.key); +}); + +var ref = db.ref("dinosaurs"); +ref.orderByKey().startAt("b").endAt("b\uf8ff").on("child_added", function(snapshot) { + console.log(snapshot.key); +}); +Equal To: +var ref = db.ref("dinosaurs"); +ref.orderByChild("height").equalTo(25).on("child_added", function(snapshot) { + console.log(snapshot.key); +}); + */ +function FirebaseService() { + this._transporter = firebase.initializeApp( + { + // credential: firebase.credential.cert('./serviceAccountKey.json'), + credential: firebase.credential.cert(serviceAccount), + databaseURL: 'https://konfer-243320.firebaseio.com', + }, + // , 'flashbid-prod' + ); + console.log('Prod Firebase'); + this._database = this._transporter.database(); + this._messaging = this._transporter.messaging(); + + this.write = function (table, id, payload) { + return this._database.ref(table + '/' + id).set(payload); + }; + + this.read = function (table, id) { + return this._database + .ref(table + '/' + id) + .once('value') + .then(function (snapshot) { + return snapshot.val(); + }); + }; + + this.update = function (table, id, payload) { + const ref = this._database.ref(table).child(id); + ref.update(payload); + }; + + this.updateSpecific = function (table, id, payload) { + return this._database.ref(table + '/' + id).update(payload); + }; + + this.pushToList = function (table, id, listField, payload) { + const ref = this._database.ref(table).child(id).child(listField).push(); + ref.set(payload); + }; + + this.sendPushNotification = function ( + id, + title, + subs, + description, + deviceId, + ) { + // This registration token comes from the client FCM SDKs. + + // See the "Defining the message payload" section above for details + // on how to define a message payload. + var payload = { + notification: { + title: title, + body: description, + }, + data: { + title: subs.text, + body: subs.desc, + action: subs.action, + id: id, + }, + }; + + // Set the message as high priority and have it expire after 24 hours. + var options = { + priority: 'high', + timeToLive: 60 * 60 * 24, + }; + + console.log('payload', payload); + console.log('device id', deviceId); + + // Send a message to the device corresponding to the provided + // registration token with the provided options. + return this._messaging.sendToDevice(deviceId, payload, options); + }; +} + +module.exports = FirebaseService; diff --git a/services/HtmlToPdf.js b/services/HtmlToPdf.js new file mode 100644 index 0000000..f40c154 --- /dev/null +++ b/services/HtmlToPdf.js @@ -0,0 +1,30 @@ +const html_to_pdf = require('html-pdf-node'); + +module.exports = { + html_to_pdf_with_content: async function (content, options) { + const file = { content }; + + return new Promise(function (resolve, reject) { + html_to_pdf + .generatePdf(file, options) + .then((pdfBuffer) => { + resolve(pdfBuffer); + }) + .catch((error) => reject(error)); + }); + }, + html_to_pdf_with_url: async function (url, options) { + const file = { url }; + + return new Promise(function (resolve, reject) { + html_to_pdf + .generatePdf(file, options) + .then((pdfBuffer) => { + resolve(pdfBuffer); + }) + .catch((error) => reject(error)); + }); + }, +}; + +// pdf to html https://www.npmjs.com/package/pdf2html diff --git a/services/JwtService.js b/services/JwtService.js new file mode 100644 index 0000000..10359d6 --- /dev/null +++ b/services/JwtService.js @@ -0,0 +1,108 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2020*/ +/** + * JWT Service + * @copyright 2020 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +var jwt = require('jsonwebtoken'); +var dotenv = require('dotenv'); +dotenv.config(); +dotenv.config({ path: './src/.env' }); + +module.exports = { + createAccessToken: function ( + payload, + expireIn = process.env.DYNAMIC_CONFIG_JWT_EXPIRE_AT, + ) { + const secret = process.env.DYNAMIC_CONFIG_JWT_KEY; + + return jwt.sign(payload, secret, { + expiresIn: Number(expireIn), + algorithm: 'HS256', + }); + }, + createRefreshToken: function (payload) { + return jwt.sign(payload, process.env.DYNAMIC_CONFIG_JWT_KEY, { + expiresIn: Number(process.env.DYNAMIC_CONFIG_JWT_REFRESH_EXPIRE_AT), + algorithm: 'HS256', + }); + }, + + verifyAccessToken: function (token) { + try { + return jwt.verify(token, process.env.DYNAMIC_CONFIG_JWT_KEY); + } catch (err) { + return false; + } + }, + verifyRefreshToken: function (token) { + try { + return jwt.verify(token, process.env.DYNAMIC_CONFIG_JWT_KEY); + } catch (err) { + return false; + } + }, + generateString: function (length) { + let d = new Date().getTime(); + const time = new Date().getTime(); + const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx-xxxx'.replace( + /[xy]/g, + function (c) { + let r = (d + Math.random() * 16) % 16 | 0; + d = Math.floor(d / 16); + return (c == 'x' ? r : (r & 0x7) | 0x8).toString(16); + }, + ); + + return (uuid.toUpperCase() + '-' + time.toString()).substring(0, length); + }, + generateUUID: function () { + let d = new Date().getTime(); + const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace( + /[xy]/g, + function (c) { + let r = (d + Math.random() * 16) % 16 | 0; + d = Math.floor(d / 16); + return (c == 'x' ? r : (r & 0x7) | 0x8).toString(16); + }, + ); + return uuid.toUpperCase(); + }, + getToken: function (req) { + if ( + req.headers.authorization && + req.headers.authorization.split(' ')[0] === 'Bearer' + ) { + return req.headers.authorization.split(' ')[1]; + } else if (req.query && req.query.token) { + return req.query.token; + } + + return null; + }, + verifyTokenMiddleware: function (role) { + const self = this; + return function (req, res, next) { + const token = self.getToken(req); + if (!token) { + return res.status(401).json({ + success: false, + code: 'UNAUTHORIZED', + }); + } else { + const result = self.verifyAccessToken(token); + if (!result) { + return res.status(401).json({ + success: false, + code: 'TOKEN_EXPIRED', + }); + } + req.user_id = result; + next(); + } + }; + }, +}; diff --git a/services/LoggingService.js b/services/LoggingService.js new file mode 100644 index 0000000..4711dd9 --- /dev/null +++ b/services/LoggingService.js @@ -0,0 +1,37 @@ +const winston = require("winston"); +winston.level = process.env.LOG_LEVEL; +const tsFormat = () => new Date().toLocaleString(); +const logger = winston.createLogger({ + level: "info", + format: winston.format.json(), + transports: [ + // + // - Write to all logs with level `info` and below to `combined.log` + // - Write all logs error (and below) to `error.log`. + // + new winston.transports.File({ + filename: "error.log", + level: "error", + timestamp: tsFormat, + }), + new winston.transports.File({ + filename: "combined.log", + timestamp: tsFormat, + }), + ], +}); + +// +// If we're not in production then log to the `console` with the format: +// `${info.level}: ${info.message} JSON.stringify({ ...rest }) ` +if (process.env.NODE_ENV != "production") { + logger.add( + new winston.transports.Console({ + format: winston.format.simple(), + timestamp: tsFormat, + colorize: true, + }) + ); +} + +module.exports = logger; diff --git a/services/MailService.js b/services/MailService.js new file mode 100644 index 0000000..fbffb2d --- /dev/null +++ b/services/MailService.js @@ -0,0 +1,99 @@ +const nodemailer = require('nodemailer'); + +const db = require('../models'); + +module.exports = { + /** @private */ + transport: null, + /** @private */ + from: null, + /** @private */ + to: null, + /** + * Nodemailer initializer + * @name mailService.initialize + * @param {{hostname: String, port: Number, username: String, password: String, from: String, to: String}} config Nodemailer configuration + * @returns {Void} + */ + initialize: function (config) { + this.transport = nodemailer.createTransport({ + host: config.hostname, + port: config.port, + auth: { + user: config.username, + pass: config.password, + }, + }); + + this.from = config.from; + this.to = config.to; + }, + /** + * Get email template from database + * @name mailService.template + * @param {String} slug email template slug + * @reject {Error} + * @returns {Promise.<{body: String, subject: String}>} email template + */ + template: function (slug) { + return new Promise(function (resolve, reject) { + db.email + .findOne({ where: { slug } }) + .then((response) => { + if (!response) { + return reject(`TEMPLATE_NOT_FOUND`); + } else resolve(response); + }) + .catch((error) => { + reject(error); + }); + }); + }, + /** + * Inject values into email template + * @name mailService.inject + * @param {{body: String, subject: String}} template email template + * @param {Object.} payload template values + * @returns {{from: String, to: String, subject: String, text: String}} Value injected email template + */ + inject: function (template, payload) { + let mailBody = template.body; + let mailSubject = template.subject; + + for (const key in payload) { + const value = payload[key]; + mailBody = mailBody.replace(new RegExp('{{{' + key + '}}}', 'g'), value); + } + + for (const key in payload) { + const value = payload[key]; + mailSubject = mailSubject.replace( + new RegExp('{{{' + key + '}}}', 'g'), + value, + ); + } + + return { + from: this.from, + to: this.to, + subject: mailSubject, + html: mailBody, + }; + }, + /** + * Send email + * @name mailService.send + * @param {nodemailer.SendMailOptions} template email template + * @reject {Error} send mail error + * @returns {Promise.} send mail info + */ + send: function (template) { + let self = this; + return new Promise(function (resolve, reject) { + self.transport + .sendMail(template) + .then((response) => resolve(response)) + .catch((error) => reject(error)); + }); + }, +}; diff --git a/services/MaintenanceService.js b/services/MaintenanceService.js new file mode 100644 index 0000000..e69de29 diff --git a/services/OAuthService.js b/services/OAuthService.js new file mode 100644 index 0000000..06d476f --- /dev/null +++ b/services/OAuthService.js @@ -0,0 +1,200 @@ +const querystring = require('querystring'); +const axios = require('axios').default; + +const db = require('../models'); + +module.exports = { + google: { + /** + * Generates authentication URL + * @name oAuth.google.generateAuthURL + * @param {{redirect_uri: String, client_id: String}} config + * @returns {String} authentication URL + */ + generateAuthURL(config) { + const rootUrl = 'https://accounts.google.com/o/oauth2/v2/auth'; + + const options = { + redirect_uri: config.redirect_uri, + client_id: config.client_id, + access_type: 'offline', + response_type: 'code', + prompt: 'consent', + scope: ['https://www.googleapis.com/auth/userinfo.profile', 'https://www.googleapis.com/auth/userinfo.email'].join(' '), + }; + + return `${rootUrl}?${querystring.stringify(options)}`; + }, + /** + * Generates authentication Token + * @name oAuth.google.generateAuthToken + * @param {{auth_code: String, client_id: String, client_secret: String, redirect_uri: String}} config + * @returns {Promise.<{{access_token: String, expires_in: String, refresh_token: String, scope: String, token_type: String id_token: String}}>} authentication token + */ + generateAuthToken(config) { + return new Promise(function (resolve, reject) { + const url = 'https://oauth2.googleapis.com/token'; + + const buildQuerystring = querystring.stringify({ + code: config.auth_code, + client_id: config.client_id, + client_secret: config.client_secret, + redirect_uri: config.redirect_uri, + grant_type: 'authorization_code', + }); + + axios.default + .post(url, buildQuerystring, { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + }) + .then((response) => resolve(response.data)) + .catch((error) => reject(error)); + }); + }, + /** + * Retrieve user information + * @name oAuth.google.getUserInfo + * @param {{access_token: String, expires_in: String, refresh_token: String, scope: String, id_token: String}} config + * @returns {Promise.<{id: string, email: string, verified_email: true, name: string, given_name: string, family_name: string, picture: string, locale: string}>} user information + */ + getUserInfo(config, isAPI = false) { + return new Promise(function (resolve, reject) { + axios + .get( + `https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=${config.access_token}`, + isAPI + ? {} + : { + headers: { + Authorization: `Bearer ${config.id_token}`, + }, + }, + ) + .then((response) => resolve(response.data)) + .catch((error) => reject(error)); + }); + }, + }, + facebook: { + /** + * Generates authentication URL + * @name oAuth.facebook.generateAuthURL + * @param {{redirect_uri: String, client_id: String}} config + * @returns {String} authentication URL + */ + generateAuthURL(config) { + const stringifiedParams = querystring.stringify({ + client_id: config.client_id, + redirect_uri: process.env.DYNAMIC_CONFIG_FACEBOOK_REDIRECT_URI, + scope: ['email', 'user_friends'].join(','), + response_type: 'code', + auth_type: 'rerequest', + display: 'popup', + }); + + return `https://www.facebook.com/v4.0/dialog/oauth?${stringifiedParams}`; + }, + /** + * Generates authentication Token + * @name oAuth.facebook.generateAuthToken + * @param {{auth_code: String, client_id: String, client_secret: String, redirect_uri: String}} config + * @returns {Promise.<{access_token: String, token_type: String, expires_in: String}>} authentication token + */ + async generateAuthToken(config) { + const url = 'https://graph.facebook.com/v4.0/oauth/access_token'; + + const { data } = await axios({ + url, + method: 'GET', + params: { + code: config.auth_code, + client_id: config.client_id, + client_secret: config.client_secret, + redirect_uri: config.redirect_uri, + }, + }); + + return data; + }, + /** + * Retrieve user information + * @name oAuth.facebook.getUserInfo + * @param {{access_token: String, token_type: String, expires_in: String}} config + * @returns {Promise.<{id: string, email: string, first_name: string, last_name: string, image: string}>} user information + */ + async getUserInfo(config) { + const { data } = await axios({ + url: 'https://graph.facebook.com/me', + method: 'GET', + params: { + fields: ['id', 'email', 'first_name', 'last_name'].join(','), + access_token: config.access_token, + }, + }); + + return data; + }, + }, + async authenticate(user) { + let User; + let Credential; + try { + const isEmailExist = await db.credential.getByField('email', user.email); + if (isEmailExist) { + // Check status and role + if (+isEmailExist.status === 0 || +user.role === +isEmailExist.role) { + throw new Error('EMAIL_ADDRESS_NOT_FOUND'); + } + // Check provider type type + const type = isEmailExist.type === user.provider; + if (!type) { + throw new Error('ACCOUNT_IS_REGISTERED_WITH_' + (user.provider === 'n' ? 'EMAIL_AND_PASSWORD' : user.provider === 'g' ? 'GOOGLE' : 'FACEBOOK')); + } + const userExists = await db.user.getByPK(isEmailExist.user_id); + + if (!userExists) { + throw new Error('EMAIL_ADDRESS_NOT_FOUND'); + } + + return { + credential: isEmailExist.id, + user: userExists, + }; + } + + User = await db.user.insert( + { + first_name: user.first_name, + last_name: user.last_name, + image: user.image, + }, + { returnAllFields: true }, + ); + + Credential = await db.credential.insert( + { + user_id: User.id, + email: user.email, + type: user.provider, + role_id: user.role_id, + status: 1, + }, + { returnAllFields: true }, + ); + + return { credential: Credential.id, user: User }; + } catch (error) { + if (User) { + User.destroy(); + } + + if (Credential) { + Credential.destroy(); + } + + throw new Error(error.message); + } + }, +}; diff --git a/services/PaginationService.js b/services/PaginationService.js new file mode 100644 index 0000000..36c8659 --- /dev/null +++ b/services/PaginationService.js @@ -0,0 +1,64 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2020*/ +/** + * Pagination Service + * @copyright 2020 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ +module.exports = function (page, numItems) { + this.page = page ? Number(page) : 1; + this.numItems = numItems ? Number(numItems) : 20; + this.data = []; + this.count = 0; + this.numPages = 0; + + this.getItems = function () { + return this.data; + }; + + this.getPage = function () { + return this.page; + }; + + this.getCount = function () { + return this.count; + }; + + this.setCount = function (count) { + this.count = count; + }; + + this.getNumPages = function () { + return this.numPages; + }; + + this.setItems = function (data) { + if (data.length == 1 && !data[0].id) { + this.count = 0; + this.numPages = 1; + this.data = [data[0]]; + return this; + } + this.data = data; + this.numPages = this.count > 1 ? Math.ceil(this.count / this.numItems) : 1; + + this.data = this.data.map(function (transaction) { + delete transaction.num; + return transaction.toJSON(); + }); + + return this; + }; + + this.getOffset = function () { + return (this.page - 1) * this.numItems; + }; + + this.getLimit = function () { + return this.numItems; + }; + + return this; +}; diff --git a/services/PasswordService.js b/services/PasswordService.js new file mode 100644 index 0000000..df4afeb --- /dev/null +++ b/services/PasswordService.js @@ -0,0 +1,22 @@ +const bcrypt = require('bcryptjs'); + +module.exports = { + /** + * Hash password + * @param {String} password password string to hash + * @returns {Promise.} hashed password + */ + hash: async function (password) { + const salt = await bcrypt.genSalt(10); + return await bcrypt.hash(password, salt); + }, + /** + * Compare hashed password with password string + * @param {String} password password string + * @param {String} hashedPassword hashed password + * @returns {Promise.} return true if hashed password match with password string else return false + */ + compareHash: async function (password, hashedPassword) { + return await bcrypt.compare(password, hashedPassword); + }, +}; diff --git a/services/PaymentService.js b/services/PaymentService.js new file mode 100644 index 0000000..480b592 --- /dev/null +++ b/services/PaymentService.js @@ -0,0 +1,680 @@ +require('dotenv').config(); //require .env for stripe configurations +const moment = require('moment'); +const stripe = require('./StripeApi'); //this is Payment Service +const paypal = require('./PaypalApi'); +const db = require('../models'); +const userModel = db.user; +const stripeSubscriptionsModel = db.stripe_subscriptions; +const stripeSubscriptionsLogModel = db.stripe_subscriptions_log; +const paymentPlansModel = db.payment_plans; +const stripeProductsModel = db.stripe_products; +const paymentServicesModel = db.payment_services; +const stripeCardsModel = db.stripe_cards; + +module.exports = new Service(); +function Service() { + this.userId = 0; + this.roleId = 0; + this.currency = process.env.STRIPE_CURRENCY; + this.prorate = process.env.STRIPE_PRORATE; + this.forceCancel = process.env.STRIPE_FORCE_CANCEL; + + this.setUserId = function (userId) { + this.userId = userId; + }; + this.setRoleId = function (roleId) { + this.roleId = roleId; + }; + this.setCurrency = function (currency) { + this.currency = currency; + }; + this.setProrationType = function (prorate) { + this.prorate = prorate; + }; + this.setCancelType = function (forceCancel) { + this.forceCancel = forceCancel; + }; + let convertToCents = function (amount) { + return amount * 100; + }; + let handleDBError = function (error) { + console.error(error); + throw new Error('Internal error: Database error'); + }; + let handleRequestError = function (error) { + console.error(error); + throw new Error('Internal error: Request error'); + }; + + this.subscribe = async function (subscriptionParams, plan) { + var subscription = await stripe.createSubscription(subscriptionParams); + //create model entry + let subscriptionModelEntry = { + stripe_id: subscription.id ?? '', + cancel_at_period_end: subscription.cancel_at_period_end ?? null, + current_period_start: moment(new Date(subscription.current_period_start * 1000)).format('YYYY-MM-DD') ?? null, + current_period_end: moment(new Date(subscription.current_period_end * 1000)).format('YYYY-MM-DD') ?? null, + user_id: this.userId ?? null, + role_id: this.roleId ?? null, + plan_id: plan?.id ?? null, + coupon_stripe_id: subscription.discount?.coupon?.id ?? '', + customer_stripe_id: subscription.customer ?? '', + collection_method: subscription.collection_method ?? '', + interval: stripeSubscriptionsModel.inverse_interval_mapping(subscription.plan?.interval) ?? 0, + interval_count: subscription.plan?.interval_count ?? '', + trial_period_days: subscription.plan?.trial_period_days ?? 0, + trial_end: subscription.trial_end ? moment(new Date(subscription.trial_end * 1000)).format('YYYY-MM-DD') : null, + trial_start: subscription.trial_start ? moment(new Date(subscription.subscriptiontrial_start * 1000)).format('YYYY-MM-DD') : null, + status: stripeSubscriptionsModel.inverse_status_mapping(subscription.status) ?? null, + }; + + let subscriptionCreatedId = await stripeSubscriptionsModel.insert(subscriptionModelEntry); + if (!subscriptionCreatedId) { + throw new Error('Subscription is not found.'); + } + + let subscriptionLogUpdated = await this.updateSubscriptionLog(subscriptionCreatedId, subscription.status, plan); + if (!subscriptionLogUpdated) { + throw new Error('Error while editing subscription log'); + } + return subscriptionCreatedId; + }; + this.updateSubscriptionLog = async function (subscriptionCreatedId, subscriptionCreatedStatus, plan) { + let subscriptionLog = await stripeSubscriptionsLogModel.getLast({ user_id: this.userId, role_id: this.roleId }); + + if (!subscriptionLog) { + let subscriptionLogModelEntry = { + user_id: this.userId, + role_id: this.roleId, + plan_id: plan?.id ?? null, + subscription_id: subscriptionCreatedId, + type: plan?.type ?? null, + status: subscriptionCreatedStatus == 'active' || subscriptionCreatedStatus == 'trialing' ? 1 : 0, + }; + if (!(await stripeSubscriptionsLogModel.insert(subscriptionLogModelEntry))) { + throw new Error('Subscription log add not successfull'); + } + } else { + let subscriptionLogModelEntry = { + plan_id: plan?.id ?? null, + subscription_id: subscriptionCreatedId, + type: plan?.type ?? null, + status: subscriptionCreatedStatus == 'active' || subscriptionCreatedStatus == 'trialing' ? 1 : 0, + }; + + if (!(await stripeSubscriptionsLogModel.edit(subscriptionLogModelEntry, subscriptionLog.id))) { + throw new Error('Subscription log edit not successfull'); + } + } + return true; + }; + this.createRegularSubscription = async function (user, plan, card, coupon) { + let subscriptionParams = { + customer: user.stripe_id, + items: [{ price: plan.stripe_id }], + trial_from_plan: true, + default_payment_method: card.stripe_card_id, + coupon: coupon?.stripe_id ?? null, + }; + return await this.subscribe(subscriptionParams, plan); + }; + this.createLifetimeSubscription = async function (user, plan, card, coupon) { + //create invoice, finalize and pay it. + let lifetimePlanStripeObject = await stripe.retrievePrice(plan.stripe_id); + let invoiceItemParams = { + customer: user.stripe_id, + price: plan.stripe_id, + discounts: [{ coupon: coupon?.stripe_id }], + }; + let invoiceItemCreated = await stripe.createInvoiceItem(invoiceItemParams); + + let invoiceParams = { + customer: user.stripe_id, + default_payment_method: card?.stripe_card_id ?? null, + }; + let invoiceCreated = await stripe.createInvoice(invoiceParams); + + let invoicePaid = await stripe.payInvoice(invoiceCreated.id); + + let subscriptionModelEntry = { + stripe_id: invoiceItemCreated.id ?? '', + cancel_at_period_end: null, + current_period_start: moment().format('YYYY-MM-DD') ?? null, + current_period_end: null, + user_id: this.userId ?? null, + role_id: this.roleId ?? null, + plan_id: plan?.id ?? null, + coupon_stripe_id: invoiceItemCreated.discounts.length > 0 ? coupon?.stripe_id : '', + customer_stripe_id: invoicePaid.customer ?? '', + collection_method: invoicePaid.collection_method ?? '', + interval: 4, + interval_count: null, + trial_period_days: 0, + trial_end: null, + trial_start: null, + status: 4, + }; + + let subscriptionCreatedId = await stripeSubscriptionsModel.insert(subscriptionModelEntry); + if (!subscriptionCreatedId) { + throw new Error('Subscription is not found.'); + } + + let subscriptionLogUpdated = await this.updateSubscriptionLog(subscriptionCreatedId, 'active', plan); + if (!subscriptionLogUpdated) { + throw new Error('Error while editing subscription log'); + } + + return subscriptionCreatedId; + }; + let calculateFullPeriod = function (interval, interval_count = 1) { + let totalNumberOfDays = paymentPlansModel.interval_days_mapping()[interval] * interval_count; + let cancelAtEpoch = moment().add(totalNumberOfDays, 'days').unix(); + return cancelAtEpoch; + }; + this.createTrialSubscription = async function (user, plan, card, coupon) { + let trialPlanFullPeriod = calculateFullPeriod(plan.interval, plan.interval_count); + let subscriptionParams = { + customer: user.stripe_id, + items: [{ price: plan.stripe_id }], + trial_from_plan: true, + default_payment_method: card.stripe_card_id, + coupon: coupon?.stripe_id ?? null, + cancel_at: trialPlanFullPeriod, + }; + return await this.subscribe(subscriptionParams, plan); + }; + this.cancelRegularSubscription = async function (subscription) { + if (this.forceCancel === 'true') { + var cancellationParams = { + subscriptionId: subscription.stripe_id, + params: { + invoice_now: true, + prorate: this.prorate, + }, + }; + let subscriptionCanceled = await stripe.cancelSubscription(cancellationParams); + + let newStatus = stripeSubscriptionsModel.inverse_status_mapping()[subscriptionCanceled.status]; + await stripeSubscriptionsModel.edit({ status: newStatus }, subscription.id); + } else { + let updateParams = { + subscriptionId: subscription.stripe_id, + params: { + cancel_at_period_end: true, + }, + }; + await stripe.updateSubscription(updateParams); + await stripeSubscriptionsModel.edit({ cancel_at_period_end: 1 }, subscription.id); + } + }; + this.cancelLifetimeSubscription = async function (subscription) { + //TODO check if we refund on this or not + //we could make a fixed refund amount + //right now we just cancel it locally and refund is never as it is a onetime product thing. + let subscriptionEdited = await stripeSubscriptionsModel.edit({ status: 5 }, parseInt(subscription.id)); + if (!subscriptionEdited) { + throw new Error("Couldn't edit subscription"); + } + let subscriptionLog = await stripeSubscriptionsLogModel.getByFields({ subscription_id: parseInt(subscription.id), status: 1 }); + if (!subscriptionLog) { + throw new Error("Couldn't find relative active subscription log"); + } + let subscriptionLogEdited = await stripeSubscriptionsLogModel.edit({ status: 0 }, subscriptionLog.id); + if (subscriptionLogEdited) { + return true; + } + throw new Error("Couldn't Edit subscription log"); + }; + this.createCustomerWithoutCard = async function (params) { + let createdCustomer = await stripe.createCustomer(params); + + let userModelEntry = { + stripe_id: createdCustomer.id, + }; + let modelEditedUser = await this.userModel.edit(userModelEntry, this.userId); + if (!modelEditedUser) { + throw new Error('Internal error: Error editing user stripe id'); + } + return modelEditedUser; + }; + this.createCustomer = async function (params) { + let createdCustomer = await stripe.createCustomer(params); + let userModelEntry = { + stripe_id: createdCustomer.id, + }; + let editedUserModel = await userModel.edit(userModelEntry, this.userId); + if (!editedUserModel) { + throw new Error('Error editing user stripe id'); + } + + let customerCardParams = { + customerId: createdCustomer.id, + cardId: createdCustomer.default_source, + }; + let card = await stripe.retrieveCard(customerCardParams); + + if (card) { + cardModelEntry = { + card_last: card.last4 ?? '', + card_brand: card.brand ?? '', + card_exp_month: card.exp_month ?? '', + exp_year: card.exp_year ?? '', + card_name: createdCustomer.metadata.card_name ?? '', + stripe_card_customer: card.customer, + stripe_card_id: card.id, + is_default: createdCustomer.metadata.is_default, + user_id: this.userId ?? null, + role_id: this.roleId ?? null, + }; + var modelCreatedCard = await stripeCardsModel.insert(cardModelEntry); + if (!modelCreatedCard) { + throw new Error('Internal error: Error adding card'); + } + } + return modelCreatedCard; + }; + + this.adminCreateProductPrice = async function (productStripeId, price, productLocalId) { + let priceArgs = { + unit_amount: convertToCents(price), + currency: this.currency, + product: productStripeId, + }; + let priceCreated = await stripe.createPrice(priceArgs); + + let productModelEditEntry = { + price, + price_stripe_id: priceCreated.id, + }; + let modelEditedProduct = await stripeProductsModel.edit(productModelEditEntry, productLocalId); + if (!modelEditedProduct) { + throw new Error('Internal Error: error setting price'); + } + return priceCreated; + }; + + this.adminCreateProduct = async function (stripeProductParam, paypalProductParam, localProductType) { + if (!stripeProductParam.name) { + throw new Error('Must provide a name for your product'); + } + await paypal.setAccessToken(); + let createdStripeProduct = await stripe.createProduct(stripeProductParam); + if (localProductType == 0) { + let productModelEntry = { + stripe_id: createdStripeProduct.id, + name: createdStripeProduct.name, + status: createdStripeProduct.active ? 1 : 0, + description: createdStripeProduct.description ?? '', + images: createdStripeProduct.images.join(';;;'), + shippable: createdStripeProduct.shippable ?? 0, + unit_label: createdStripeProduct.unit_label ?? '', + statement_descriptor: createdStripeProduct.statement_descriptor ?? '', + }; + + let modelCreatedStripeProduct = await stripeProductsModel.insert(productModelEntry); + + if (!modelCreatedStripeProduct) { + throw new Error('Internal error: error adding a product'); + } + return { + productStripeId: createdStripeProduct.id, + productLocalId: modelCreatedStripeProduct, + }; + } else if (localProductType == 1) { + let createdPaypalProduct = await paypal.createProduct(paypalProductParam); + + let paymentServiceModelEntry = { + name: createdStripeProduct.name, + stripe_id: createdStripeProduct.id, + paypal_id: createdPaypalProduct.data.id, + status: createdStripeProduct.active ? 1 : 0, + image: createdStripeProduct.images.length > 0 ? createdStripeProduct.images[0] : '', + url: createdStripeProduct.url ?? '', + category: createdStripeProduct.metadata.category, + description: createdStripeProduct.description ?? '', + }; + + let modelCreatedServiceId = await paymentServicesModel.insert(paymentServiceModelEntry); + + let service = paymentServicesModel.getByPK(modelCreatedServiceId); + + return { + serviceProductStripeId: service.stripe_id, + serviceProductPaypalId: service.paypal_id, + serviceProductLocalId: service.id, + }; + } + return false; + }; + + /** + * [adminCreateSubscriptionPlan allows an admin to create subscription plan through admin portal] + * @param {object} planParams [object that contain plan parameters] + * @param {integer} planType [integer that represent plan type in relative to stripe plans table] @see /models/stripe_plans.js type_mapping() + * @param {integer} localProductId [integer that represent product id in relative to stripe products table] + * @return {integer} [the id of the created plan in database] + */ + this.adminCreateSubscriptionPlan = async function (params, planType, localServiceId) { + if (!params.nickname) { + throw new Error('Must have a display name'); + } + if (!localServiceId) { + throw new Error('Must provide system product id'); + } + if (!planType) { + throw new Error('Must provide plan type'); + } + await paypal.setAccessToken(); + let service = await paymentServicesModel.getByPK(localServiceId); + + let stripeSubscriptionPlanParams = { + nickname: params.nickname, + currency: process.env.STRIPE_CURRENCY, + unit_amount: convertToCents(params.amount), + product: service.stripe_id, + recurring: { + interval: paymentPlansModel.interval_mapping()[params.interval], + interval_count: params.interval_count, + trial_period_days: params.trial_period_days, + }, + active: parseInt(params.status) === 1 ? true : false, + }; + let paypalSubscriptionPlanParams = { + product_id: service.paypal_id, + name: params.nickname, + billing_cycles: [ + { + frequency: { + interval_unit: paymentPlansModel.interval_mapping()[params.interval].toUpperCase(), + interval_count: params.interval_count, + }, + tenure_type: 'REGULAR', + sequence: 1, + total_cycles: 0, + pricing_scheme: { + fixed_price: { + value: params.amount, + currency_code: this.currency.toUpperCase(), + }, + }, + }, + ], + payment_preferences: { + auto_bill_outstanding: true, + setup_fee_failure_action: 'CANCEL', + payment_failure_threshold: 0, + }, + }; + if (params.trial_period_days > 0) { + paypalSubscriptionPlanParams.billing_cycles[0].sequence = 2; + paypalSubscriptionPlanParams.billing_cycles.unshift({ + frequency: { + interval_unit: 'DAY', + interval_count: parseInt(params.trial_period_days), + }, + tenure_type: 'TRIAL', + sequence: 1, + total_cycles: 1, + }); + } + + let stripePlanCreated = await stripe.createPrice(stripeSubscriptionPlanParams); + let paypalPlanCreated = await paypal.createSubscriptionPlan(paypalSubscriptionPlanParams); + + let planModelEntry = { + stripe_product_id: stripePlanCreated.product, + paypal_product_id: paypalPlanCreated.data.product_id, + stripe_id: stripePlanCreated.id, + paypal_id: paypalPlanCreated.data.id, + amount: stripePlanCreated.unit_amount / 100, + interval: paymentPlansModel.inverse_interval_mapping(stripePlanCreated.recurring.interval), + interval_count: stripePlanCreated.recurring.interval_count, + trial_period_days: stripePlanCreated.recurring.trial_period_days ?? 0, + nickname: stripePlanCreated.nickname, + service_id: localServiceId, + status: stripePlanCreated.active ? 1 : 0, + type: parseInt(planType), + }; + + let modelCreatedPlan = await paymentPlansModel.insert(planModelEntry); + + if (!modelCreatedPlan) { + throw new Error('Internal error: error creating plan'); + } + return modelCreatedPlan; + }; + + this._createStripeLifetimePlan = async function (params, service) { + //stripe doesn't have lifetime plans + //how it works is a price is created with no recurring parameter as a single time product + //which acts and dealt with internally within our system as a lifetime plan. + let stripeSubscriptionPlanParams = { + nickname: params.nickname, + currency: this.currency, + unit_amount: convertToCents(params.amount), + product: service.stripe_id, + active: parseInt(params.status) === 1 ? true : false, + }; + return await stripe.createPrice(stripeSubscriptionPlanParams); + }; + this._createPaypalLifetimePlan = async function (params, service) { + //paypal doesn't allow lifetime plan + //how it works is i create a blan with a trial with 999 years and setup fee for subscription as the main amount for the lifetime plan + //paypal needs to have a regular plan so after the 999 years there is a regular plan with 0.01 amount money + //this works for both lifetime paid and free plans. + await paypal.setAccessToken(); + + let paypalSubscriptionPlanParams = { + product_id: service.paypal_id, + name: params.nickname, + billing_cycles: [ + { + frequency: { + interval_unit: 'YEAR', + interval_count: 1, + }, + tenure_type: 'TRIAL', + sequence: 1, + total_cycles: 999, + }, + { + frequency: { + interval_unit: 'YEAR', + interval_count: 1, + }, + tenure_type: 'REGULAR', + sequence: 2, + total_cycles: 0, + pricing_scheme: { + fixed_price: { + value: '0.01', + currency_code: this.currency.toUpperCase(), + }, + }, + }, + ], + payment_preferences: { + auto_bill_outstanding: true, + setup_fee: { + value: params.amount, + currency_code: this.currency.toUpperCase(), + }, + setup_fee_failure_action: 'CANCEL', + payment_failure_threshold: 0, + }, + }; + return await paypal.createPlan(paypalSubscriptionPlanParams); + }; + this._destroyStripeLifetimePlan = async function (planStripeId) { + //stripe doesn't allow deleting a price. will be set to unactive instead + return await stripe.updatePrice({ priceId: planStripeId, params: { active: false } }); + }; + this._destroyPaypalLifetimePlan = async function (planPaypalId) { + //paypal doesn't allow deleting a price. will be set to unactive instead + return await paypal.deactivatePlan(planPaypalId); + }; + + this.adminCreateLifetimePlan = async function (params, planType, localServiceId) { + if (!params.nickname) { + throw new Error('Must have a display name'); + } + if (!localServiceId) { + throw new Error('Must provide system product id'); + } + if (!planType) { + throw new Error('Must provide plan type'); + } + if (parseInt(params.interval) !== 4) { + throw new Error('Interval must be "forever".'); + } + + let service = await paymentServicesModel.getByPK(localServiceId); + + let stripePlanCreated = await this._createStripeLifetimePlan(params, service); + let paypalPlanCreated = await this._createPaypalLifetimePlan(params, service); + + if (!stripePlanCreated && paypalPlanCreated) { + await this._destroyPaypalLifetimePlan(paypalPlanCreated.data.id); + throw new Error('Internal Error: Something happended while creating the plans.'); + } + if (!paypalPlanCreated && stripePlanCreated) { + await this._destroyStripeLifetimePlan(stripePlanCreated.id); + throw new Error('Internal Error: Something happended while creating the plans.'); + } + + let planModelEntry = { + stripe_product_id: stripePlanCreated?.product ?? '', + paypal_product_id: paypalPlanCreated?.data?.product_id ?? '', + stripe_id: stripePlanCreated?.id ?? '', + paypal_id: paypalPlanCreated?.data?.id ?? '', + amount: stripePlanCreated?.unit_amount ? stripePlanCreated.unit_amount / 100 : params.amount, + interval: 4, + interval_count: 1, + trial_period_days: 0, + nickname: stripePlanCreated?.nickname ?? paypalPlanCreated.data.name, + service_id: localServiceId, + status: stripePlanCreated?.active == true ? 1 : params.status, + type: parseInt(planType), + }; + + let modelCreatedPlan = await paymentPlansModel.insert(planModelEntry); + + if (!modelCreatedPlan) { + throw new Error('Internal error: error creating plan'); + } + return modelCreatedPlan; + }; + + this.adminCreateTrialPlan = async function (planParams, planType, localServiceId) { + if (Object.keys(planParams.recurring).length === 0 || planParams.recurring.constructor !== Object) { + throw new Error('Must have a recurring parameter (subscription interval)'); + } + if (!planParams.nickname) { + throw new Error('Must have a display name'); + } + if (!localServiceId) { + throw new Error('Must provide system product id'); + } + let priceCreated = await stripe.createPrice(planParams); + + let planModelEntry = { + stripe_product_id: priceCreated.product, + stripe_id: priceCreated.id, + amount: priceCreated.unit_amount / 100, + interval: paymentPlansModel.inverse_interval_mapping(priceCreated.recurring.interval), + interval_count: priceCreated.recurring.interval_count, + trial_period_days: priceCreated.recurring.trial_period_days ?? 0, + nickname: priceCreated.nickname, + service_id: localServiceId, + status: priceCreated.active ? 1 : 0, + type: parseInt(planType), + }; + let modelCreatedPlan = await paymentPlansModel.insert(planModelEntry); + if (!modelCreatedPlan) { + throw new Error('Internal error: error creating plan'); + } + return modelCreatedPlan; + }; + this.adminCancelSubscription = async function (subscriptionId) { + let subscriptionToCancel = await stripeSubscriptionsModel.getByPK(subscriptionId); + let subscriptionPlan = await paymentPlansModel.getByPK(subscriptionToCancel.plan_id); + if (!subscriptionToCancel || !subscriptionPlan) { + throw new Error('No subscription or plan of that id'); + } + // let subscirptionType = subscriptionPlan.type; + let subscirptionType = 3; + //if normal subscription + switch (subscirptionType) { + case 0: + case 3: + case 4: + let cancelSubscriptionParams = { + subscriptionId: subscriptionToCancel.stripe_id, + params: { + prorate: this.prorate, + invoice_now: true, + }, + }; + let subscriptionCanceled = await stripe.cancelSubscription(cancelSubscriptionParams); + let localCancellationParams = { + status: stripeSubscriptionsModel.inverse_status_mapping()[subscriptionCanceled.status], + }; + await stripeSubscriptionsModel.edit(localCancellationParams, subscriptionId); + return subscriptionCanceled; + default: + throw new Error('Something wrong'); + } + }; + this.userAddCard = async function (cardParams) { + let createdCard = await stripe.createCard(cardParams); + + if (createdCard) { + if (createdCard.metadata.is_default == '1') { + let customerUpdateParams = { + customerId: createdCard.customer, + params: { default_source: createdCard.id }, + }; + await stripe.updateCustomer(customerUpdateParams); + let defaultCards = await stripeCardsModel.getAll({ is_default: 1 }); + if (defaultCards.length > 0) { + defaultCards.forEach(async (card) => { + await stripeCardsModel.edit({ is_default: 0 }, card.id); + }); + } + } + cardModelEntry = { + card_last: createdCard.last4 ?? '', + card_brand: createdCard.brand ?? '', + card_exp_month: createdCard.exp_month ?? '', + exp_year: createdCard.exp_year ?? '', + card_name: createdCard.metadata.card_name ?? '', + stripe_card_customer: createdCard.customer, + stripe_card_id: createdCard.id, + is_default: createdCard.metadata.is_default, + user_id: this.userId ?? null, + role_id: this.roleId ?? null, + }; + var modelCreatedCard = await stripeCardsModel.insert(cardModelEntry); + if (!modelCreatedCard) { + throw new Error('Internal error: Error adding card'); + } + } + return modelCreatedCard; + }; + this.changePlan = async function (currentSubscription, newPlan, user, card, couponId = '') { + //if current subscriptions is canceled + if (!currentSubscription || currentSubscription.status == 5) { + let subscriptionParams = { + customer: user.stripe_id, + items: { plan: newPlan.id }, + coupon: couponId, + }; + return await this.subscribe(subscriptionParams, newPlan); + } + //user has subscription (upgrade/ downgrade) + if (currentSubscription && currentSubscription.status != 5) { + if (currentSubscription.plan_id == newPlan.id) throw new Error('Same Plan'); + } + }; +} diff --git a/services/PaypalApi.js b/services/PaypalApi.js new file mode 100644 index 0000000..5fdfed6 --- /dev/null +++ b/services/PaypalApi.js @@ -0,0 +1,300 @@ +require('dotenv').config(); + +const qs = require('qs'); //parse url form encoded params +const paypalBaseUrl = process.env.PAYPAL_BASE_URL; +const paypalSandboxBaseUrl = process.env.PAYPAL_SANDBOX_BASE_URL; + +if (process.env.MODE === 'development') { + var axios = require('axios').create({ + baseURL: paypalSandboxBaseUrl, + }); +} else if (process.env.MODE === 'production') { + var axios = require('axios').create({ + baseURL: paypalBaseUrl, + }); +} +let accessToken = ''; + +module.exports = new Service(); +function Service() { + // this.error = async function () { + // Error.call(this); + + // }; + this.setAccessToken = async function () { + accessToken = await this._getPaypalAccessToken().catch((error) => { + throw error; + }); + return accessToken; + }; + this._getPaypalAccessToken = async function () { + let data = await axios({ + method: 'post', + url: '/v1/oauth2/token', + auth: { + username: process.env.PAYPAL_CLIENT_ID, + password: process.env.PAYPAL_SECRET, + }, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + data: qs.stringify({ + grant_type: 'client_credentials', + }), + }).catch((error) => { + throw error; + }); + return data.data.access_token; + }; + this.createProduct = async function (params) { + let requiredFields = ['name', 'type']; + requiredFields.forEach((field) => { + if (!params[field]) { + throw new Error(`Must have "${field}" parameter`); + } + }); + params = this.filterParams(params); + let config = { + url: '/v1/catalogs/products', + data: params, + }; + try { + return await this.axiosPost(config); + } catch (error) { + console.dir(error.response, { depth: null }); + throw new Error(error.response?.data?.message ?? 'Internal Error: Error creating product'); + } + }; + this.getPlans = async function (paginationParams) { + let config = { + url: '/v1/billing/plans', + data: paginationParams, + }; + try { + return await this.axiosGet(config); + } catch (error) { + console.error(error.response); + throw new Error('Internal Error: Error getting plans'); + } + }; + this.getProducts = async function (paginationParams) { + let config = { + url: '/v1/catalogs/products', + data: paginationParams, + }; + try { + return await this.axiosGet(config); + } catch (error) { + console.error(error.response); + throw new Error('Internal Error: Error getting products'); + } + }; + this.getProductDetails = async function (productId) { + let config = { + url: `/v1/catalogs/products/${productId}`, + data: {}, + }; + try { + return await this.axiosGet(config); + } catch (error) { + console.error(error.response); + throw new Error('Internal Error: Error getting product details'); + } + }; + + this.getSubscriptions = async function (paginationParams) { + let createdProduct = await axios({ + method: 'get', + url: '/v1/billing/plans', + data: qs.stringify(paginationParams), + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${accessToken}`, + }, + }).catch((error) => { + throw error; + }); + return createdProduct.data; + }; + this.createSubscription = async function (params) { + let config = { + url: '/v1/billing/subscriptions', + data: params, + }; + return await this.axiosPost(config); + }; + this.createPlan = async function (params) { + let config = { + url: '/v1/billing/plans', + data: params, + }; + try { + return await this.axiosPost(config); + } catch (error) { + console.dir(error.response.data, { depth: null }); + throw new Error('Internal Error: Error creating paypal subscription plan'); + } + }; + this.deactivatePlan = async function (planId) { + let config = { + url: `/v1/billing/plans/${planId}/deactivate`, + data: {}, + }; + try { + return await this.axiosPost(config); + } catch (error) { + console.dir(error.response.data, { depth: null }); + throw new Error('Internal Error: Error deactivating paypal subscription plan'); + } + }; + this.getPlanDetails = async function (planId) { + let config = { + url: `/v1/billing/plans/${planId}`, + data: {}, + }; + try { + return await this.axiosGet(config); + } catch (error) { + console.dir(error.response.data, { depth: null }); + throw new Error('Internal Error: Error getting subscription details'); + } + }; + this.getSubscriptionDetails = async function (subscriptionId) { + let config = { + url: `/v1/billing/subscriptions/${subscriptionId}`, + data: {}, + }; + try { + return await this.axiosGet(config); + } catch (error) { + console.dir(error.response.data, { depth: null }); + throw new Error('Internal Error: Error getting subscription details'); + } + }; + this.updateProduct = async function (params, productId) { + let config = { + url: `/v1/catalogs/products/${productId}`, + data: params, + }; + try { + return await this.axiosPatch(config); + } catch (error) { + console.dir(error.response.data, { depth: null }); + throw new Error('Internal Error: Error updating product'); + } + }; + this.updatePlan = async function (params, planId) { + let config = { + url: `/v1/billing/plans/${planId}`, + data: params, + }; + try { + return await this.axiosPatch(config); + } catch (error) { + console.dir(error.response.data, { depth: null }); + throw new Error('Internal Error: Error updating plan'); + } + }; + this.updatePlanPricing = async function (params, planId) { + let config = { + url: `/v1/billing/plans/${planId}/update-pricing-schemes`, + data: params, + }; + try { + return await this.axiosPost(config); + } catch (error) { + console.dir(error.response.data, { depth: null }); + throw new Error('Internal Error: Error updating plan'); + } + }; + this.activatePlan = async function (planId) { + let config = { + url: `/v1/billing/plans/${planId}/activate`, + data: {}, + }; + try { + return await this.axiosPost(config); + } catch (error) { + console.dir(error.response.data, { depth: null }); + throw new Error('Internal Error: Error updating plan'); + } + }; + this.deactivatePlan = async function (planId) { + let config = { + url: `/v1/billing/plans/${planId}/deactivate`, + data: {}, + }; + try { + return await this.axiosPost(config); + } catch (error) { + console.dir(error.response.data, { depth: null }); + throw new Error('Internal Error: Error updating plan'); + } + }; + this.retrievePlan = async function (params, planId) { + let config = { + url: `/v1/billing/subscriptions/${planId}`, + data: params, + }; + return await this.axiosGet(config); + }; + this.axiosGet = async function (config) { + return await axios({ + method: 'get', + url: config.url, + data: qs.stringify(config.data ?? {}), + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${accessToken}`, + }, + }); + }; + + this.axiosPost = async function (config) { + return await axios({ + method: 'post', + url: config.url, + data: JSON.stringify(config.data), + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + Prefer: 'return=representation', + Authorization: `Bearer ${accessToken}`, + }, + }); + }; + + this.axiosPatch = async function (config) { + return await axios({ + method: 'patch', + url: config.url, + data: JSON.stringify(config.data), + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + Authorization: `Bearer ${accessToken}`, + }, + }); + }; + + /** + * [filterParams filters paramters from null, undefined, empty strings, empty arrays and empty objects as it can cause unwanted changes] + * @param {object} params [object that can contain one more object inside] + * @return {object} [object with only truth variables] + */ + this.filterParams = function (params) { + Object.keys(params).forEach((param) => { + if (this.empty(params[param]) || params[param].length === 0) { + console.log(`Parameter empty, null or undefined`); + delete params[param]; + } else if (params[param].constructor === Object && Object.entries(params[param]).length === 0) { + console.log(`Parameter object empty`); + delete params[param]; + } else if (params[param].constructor === Object && Object.entries(params[param]).length > 0) { + this.filterParams(params[param]); + } + }); + return params; + }; + this.empty = (value) => value === null || value === undefined; +} diff --git a/services/PaypalService.js b/services/PaypalService.js new file mode 100644 index 0000000..ffc6eaf --- /dev/null +++ b/services/PaypalService.js @@ -0,0 +1,705 @@ +require('dotenv').config(); //require .env for stripe configurations +// const moment = require('moment'); //this is Payment Service +const paypal = require('./PaypalApi'); +const db = require('../models'); +const { update } = require('lodash'); +const paypalPlansModel = db.paypal_plans; +const paypalServicesModel = db.paypal_services; +const paypalProductsModel = db.paypal_products; + +module.exports = new Service(); +function Service() { + this.userId = 0; + this.roleId = 0; + this.currency = process.env.PAYPAL_CURRENCY; + // this.prorate = process.env.STRIPE_PRORATE; + // this.forceCancel = process.env.STRIPE_FORCE_CANCEL; + + this.setUserId = function (userId) { + this.userId = userId; + }; + this.setRoleId = function (roleId) { + this.roleId = roleId; + }; + this.setCurrency = function (currency) { + this.currency = currency; + }; + // this.setProrationType = function (prorate) { + // this.prorate = prorate; + // }; + // this.setCancelType = function (forceCancel) { + // this.forceCancel = forceCancel; + // }; + + // this.subscribe = async function (subscriptionParams, plan) { + // var subscription = await stripe.createSubscription(subscriptionParams); + // //create model entry + // let subscriptionModelEntry = { + // stripe_id: subscription.id ?? '', + // cancel_at_period_end: subscription.cancel_at_period_end ?? null, + // current_period_start: moment(new Date(subscription.current_period_start * 1000)).format('YYYY-MM-DD') ?? null, + // current_period_end: moment(new Date(subscription.current_period_end * 1000)).format('YYYY-MM-DD') ?? null, + // user_id: this.userId ?? null, + // role_id: this.roleId ?? null, + // plan_id: plan?.id ?? null, + // coupon_stripe_id: subscription.discount?.coupon?.id ?? '', + // customer_stripe_id: subscription.customer ?? '', + // collection_method: subscription.collection_method ?? '', + // interval: stripeSubscriptionsModel.inverse_interval_mapping(subscription.plan?.interval) ?? 0, + // interval_count: subscription.plan?.interval_count ?? '', + // trial_period_days: subscription.plan?.trial_period_days ?? 0, + // trial_end: subscription.trial_end ? moment(new Date(subscription.trial_end * 1000)).format('YYYY-MM-DD') : null, + // trial_start: subscription.trial_start ? moment(new Date(subscription.subscriptiontrial_start * 1000)).format('YYYY-MM-DD') : null, + // status: stripeSubscriptionsModel.inverse_status_mapping(subscription.status) ?? null, + // }; + + // let subscriptionCreatedId = await stripeSubscriptionsModel.insert(subscriptionModelEntry); + // if (!subscriptionCreatedId) { + // throw new Error('Subscription is not found.'); + // } + + // let subscriptionLogUpdated = await this.updateSubscriptionLog(subscriptionCreatedId, subscription.status, plan); + // if (!subscriptionLogUpdated) { + // throw new Error('Error while editing subscription log'); + // } + // return subscriptionCreatedId; + // }; + // this.updateSubscriptionLog = async function (subscriptionCreatedId, subscriptionCreatedStatus, plan) { + // let subscriptionLog = await stripeSubscriptionsLogModel.getLast({ user_id: this.userId, role_id: this.roleId }); + + // if (!subscriptionLog) { + // let subscriptionLogModelEntry = { + // user_id: this.userId, + // role_id: this.roleId, + // plan_id: plan?.id ?? null, + // subscription_id: subscriptionCreatedId, + // type: plan?.type ?? null, + // status: subscriptionCreatedStatus == 'active' || subscriptionCreatedStatus == 'trialing' ? 1 : 0, + // }; + // if (!(await stripeSubscriptionsLogModel.insert(subscriptionLogModelEntry))) { + // throw new Error('Subscription log add not successfull'); + // } + // } else { + // let subscriptionLogModelEntry = { + // plan_id: plan?.id ?? null, + // subscription_id: subscriptionCreatedId, + // type: plan?.type ?? null, + // status: subscriptionCreatedStatus == 'active' || subscriptionCreatedStatus == 'trialing' ? 1 : 0, + // }; + + // if (!(await stripeSubscriptionsLogModel.edit(subscriptionLogModelEntry, subscriptionLog.id))) { + // throw new Error('Subscription log edit not successfull'); + // } + // } + // return true; + // }; + // this.createRegularSubscription = async function (user, plan, card, coupon) { + // let subscriptionParams = { + // customer: user.stripe_id, + // items: [{ price: plan.stripe_id }], + // trial_from_plan: true, + // default_payment_method: card.stripe_card_id, + // coupon: coupon?.stripe_id ?? null, + // }; + // return await this.subscribe(subscriptionParams, plan); + // }; + // this.createLifetimeSubscription = async function (user, plan, card, coupon) { + // //create invoice, finalize and pay it. + // let lifetimePlanStripeObject = await stripe.retrievePrice(plan.stripe_id); + // let invoiceItemParams = { + // customer: user.stripe_id, + // price: plan.stripe_id, + // discounts: [{ coupon: coupon?.stripe_id }], + // }; + // let invoiceItemCreated = await stripe.createInvoiceItem(invoiceItemParams); + + // let invoiceParams = { + // customer: user.stripe_id, + // default_payment_method: card?.stripe_card_id ?? null, + // }; + // let invoiceCreated = await stripe.createInvoice(invoiceParams); + + // let invoicePaid = await stripe.payInvoice(invoiceCreated.id); + + // let subscriptionModelEntry = { + // stripe_id: invoiceItemCreated.id ?? '', + // cancel_at_period_end: null, + // current_period_start: moment().format('YYYY-MM-DD') ?? null, + // current_period_end: null, + // user_id: this.userId ?? null, + // role_id: this.roleId ?? null, + // plan_id: plan?.id ?? null, + // coupon_stripe_id: invoiceItemCreated.discounts.length > 0 ? coupon?.stripe_id : '', + // customer_stripe_id: invoicePaid.customer ?? '', + // collection_method: invoicePaid.collection_method ?? '', + // interval: 4, + // interval_count: null, + // trial_period_days: 0, + // trial_end: null, + // trial_start: null, + // status: 4, + // }; + + // let subscriptionCreatedId = await stripeSubscriptionsModel.insert(subscriptionModelEntry); + // if (!subscriptionCreatedId) { + // throw new Error('Subscription is not found.'); + // } + + // let subscriptionLogUpdated = await this.updateSubscriptionLog(subscriptionCreatedId, 'active', plan); + // if (!subscriptionLogUpdated) { + // throw new Error('Error while editing subscription log'); + // } + + // return subscriptionCreatedId; + // }; + // let calculateFullPeriod = function (interval, interval_count = 1) { + // let totalNumberOfDays = paypalPlansModel.interval_days_mapping()[interval] * interval_count; + // let cancelAtEpoch = moment().add(totalNumberOfDays, 'days').unix(); + // return cancelAtEpoch; + // }; + // this.createTrialSubscription = async function (user, plan, card, coupon) { + // let trialPlanFullPeriod = calculateFullPeriod(plan.interval, plan.interval_count); + // let subscriptionParams = { + // customer: user.stripe_id, + // items: [{ price: plan.stripe_id }], + // trial_from_plan: true, + // default_payment_method: card.stripe_card_id, + // coupon: coupon?.stripe_id ?? null, + // cancel_at: trialPlanFullPeriod, + // }; + // return await this.subscribe(subscriptionParams, plan); + // }; + // this.cancelRegularSubscription = async function (subscription) { + // if (this.forceCancel === 'true') { + // var cancellationParams = { + // subscriptionId: subscription.stripe_id, + // params: { + // invoice_now: true, + // prorate: this.prorate, + // }, + // }; + // let subscriptionCanceled = await stripe.cancelSubscription(cancellationParams); + + // let newStatus = stripeSubscriptionsModel.inverse_status_mapping()[subscriptionCanceled.status]; + // await stripeSubscriptionsModel.edit({ status: newStatus }, subscription.id); + // } else { + // let updateParams = { + // subscriptionId: subscription.stripe_id, + // params: { + // cancel_at_period_end: true, + // }, + // }; + // await stripe.updateSubscription(updateParams); + // await stripeSubscriptionsModel.edit({ cancel_at_period_end: 1 }, subscription.id); + // } + // }; + // this.cancelLifetimeSubscription = async function (subscription) { + // //TODO check if we refund on this or not + // //we could make a fixed refund amount + // //right now we just cancel it locally and refund is never as it is a onetime product thing. + // let subscriptionEdited = await stripeSubscriptionsModel.edit({ status: 5 }, parseInt(subscription.id)); + // if (!subscriptionEdited) { + // throw new Error("Couldn't edit subscription"); + // } + // let subscriptionLog = await stripeSubscriptionsLogModel.getByFields({ subscription_id: parseInt(subscription.id), status: 1 }); + // if (!subscriptionLog) { + // throw new Error("Couldn't find relative active subscription log"); + // } + // let subscriptionLogEdited = await stripeSubscriptionsLogModel.edit({ status: 0 }, subscriptionLog.id); + // if (subscriptionLogEdited) { + // return true; + // } + // throw new Error("Couldn't Edit subscription log"); + // }; + + // this.adminCreateProductPrice = async function (productStripeId, price, productLocalId) { + // let priceArgs = { + // unit_amount: convertToCents(price), + // currency: this.currency, + // product: productStripeId, + // }; + // let priceCreated = await stripe.createPrice(priceArgs); + + // let productModelEditEntry = { + // price, + // price_stripe_id: priceCreated.id, + // }; + // let modelEditedProduct = await stripeProductsModel.edit(productModelEditEntry, productLocalId); + // if (!modelEditedProduct) { + // throw new Error('Internal Error: error setting price'); + // } + // return priceCreated; + // }; + + this._createPaypalProduct = async function (params) { + let productParams = { + name: params.name, + description: params.description, + type: params.type, + category: params.category, + image_url: params.image, + home_url: params.url, + }; + return await paypal.createProduct(productParams); + }; + this.adminUpdateProduct = async function (category, paypalId) { + await paypal.setAccessToken(); + let updateParams = [ + { + op: 'replace', + path: '/category', + value: category, + }, + ]; + await paypal.updateProduct(updateParams, paypalId); + return true; + }; + + this.adminCreateProduct = async function (params, type) { + if (!params.name) { + throw new Error('Must provide a name for your product'); + } + if (!params.type) { + throw new Error('Must provide a type for your product'); + } + + await paypal.setAccessToken(); + + let createdPaypalProduct = await this._createPaypalProduct(params); + + let paypalProductModelEntry = { + name: createdPaypalProduct.data.name, + paypal_id: createdPaypalProduct.data.id, + image: createdPaypalProduct.data.image_url ?? '', + type: createdPaypalProduct.data.type ?? '', + url: createdPaypalProduct.data.home_url ?? '', + category: createdPaypalProduct.data.category ?? '', + description: createdPaypalProduct.data.description ?? '', + status: params.status, + }; + + switch (params.type) { + case 'SERVICE': { + var modelCreatedProductId = await paypalServicesModel.insert(paypalProductModelEntry); + var product = await paypalServicesModel.getByPK(modelCreatedProductId); + break; + } + case 'PHYSICAL': + case 'DIGITAL': { + var modelCreatedProductId = await paypalProductsModel.insert(paypalProductModelEntry); + var product = await paypalProductsModel.getByPK(modelCreatedProductId); + break; + } + } + if (!modelCreatedProductId) { + throw new Error('Internal Error: Error adding product to our system'); + } + + return { + productPaypalId: product.paypal_id, + productLocalId: product.id, + }; + }; + + /** + * [adminCreateRegularPlan allows an admin to create subscription plan through admin portal] + * @param {object} planParams [object that contain plan parameters] + * @param {integer} planType [integer that represent plan type in relative to stripe plans table] @see /models/stripe_plans.js type_mapping() + * @param {integer} localProductId [integer that represent product id in relative to stripe products table] + * @return {integer} [the id of the created plan in database] + */ + this.adminCreateRegularPlan = async function (params) { + if (!params.name) { + throw new Error('Must have a display name'); + } + if (!params.type) { + throw new Error('Must provide plan type'); + } + if (!params.service_id) { + throw new Error('Must attach a service'); + } + await paypal.setAccessToken(); + let service = await paypalServicesModel.getByPK(params.service_id); + + let paypalSubscriptionPlanParams = { + product_id: service.paypal_id, + name: params.name, + billing_cycles: [ + { + frequency: { + interval_unit: paypalPlansModel.interval_unit_mapping()[params.interval_unit].toUpperCase(), + interval_count: params.interval_count, + }, + tenure_type: 'REGULAR', + sequence: 1, + total_cycles: 0, + pricing_scheme: { + fixed_price: { + value: params.pricing, + currency_code: this.currency.toUpperCase(), + }, + }, + }, + ], + payment_preferences: { + auto_bill_outstanding: true, + setup_fee_failure_action: 'CANCEL', + payment_failure_threshold: 0, + }, + }; + if (params.trial_period_days > 0) { + paypalSubscriptionPlanParams.billing_cycles[0].sequence = 2; + paypalSubscriptionPlanParams.billing_cycles.unshift({ + frequency: { + interval_unit: 'DAY', + interval_count: parseInt(params.trial_period_days), + }, + tenure_type: 'TRIAL', + sequence: 1, + total_cycles: 1, + }); + } + + let paypalPlanCreated = await paypal.createPlan(paypalSubscriptionPlanParams); + + let hasTrial = paypalPlanCreated.data.billing_cycles[1] ? true : false; + let trialPlanInfo = hasTrial ? paypalPlanCreated.data.billing_cycles[0] : null; + let regularPlanInfo = hasTrial ? paypalPlanCreated.data.billing_cycles[1] : paypalPlanCreated.data.billing_cycles[0]; + let price = regularPlanInfo.pricing_scheme.fixed_price.value; + let interval_unit = regularPlanInfo.frequency.interval_unit; + let interval_count = regularPlanInfo.frequency.interval_count; + + let planModelEntry = { + name: paypalPlanCreated.data.name, + type: params.type, + paypal_id: paypalPlanCreated.data.id, + description: paypalPlanCreated.data.description, + paypal_product_id: paypalPlanCreated.data.product_id, + pricing: price, + interval_unit: this.getMappingKey(paypalPlansModel.interval_unit_mapping, interval_unit.toLowerCase()), + interval_count: interval_count, + service_id: params.service_id, + trial_period_days: trialPlanInfo ? trialPlanInfo.frequency.interval_count : 0, + status: this.getMappingKey(paypalPlansModel.status_mapping, paypalPlanCreated.data.status), + }; + + let modelCreatedPlan = await paypalPlansModel.insert(planModelEntry); + + if (!modelCreatedPlan) { + throw new Error('Internal error: error creating plan'); + } + return modelCreatedPlan; + }; + + this.updateRegularPlan = async function (params, currentSettings) { + //if plan has a trial + await paypal.setAccessToken(); + let planPaypalId = currentSettings.paypal_id; + + if (currentSettings.status == 0 && params.status == 1) { + await paypal.activatePlan(planPaypalId); + } else if (currentSettings.status == 1 && params.status == 0) { + await this._destroyPaypalPlan(planPaypalId); + return { status: 0 }; + } else if (currentSettings.status == 0 && params.status == 0) { + throw new Error("Can't edit a plan if it is inactive"); + } + + let regularPlanIndex = currentSettings.trial_period_days ? 2 : 1; + + let updateParams = [ + { + op: 'replace', + path: '/name', + value: params.name, + }, + ]; + + await paypal.updatePlan(updateParams, planPaypalId); + + updateParams = { + pricing_schemes: [ + { + billing_cycle_sequence: regularPlanIndex, + pricing_scheme: { + fixed_price: { + value: params.pricing, + currency_code: this.currency.toUpperCase(), + }, + }, + }, + ], + }; + + await paypal.updatePlanPricing(updateParams, planPaypalId); + + return { name: params.name, pricing: params.pricing, status: params.status }; + }; + + this.adminCreateLifetimePlan = async function (params) { + //paypal doesn't allow lifetime plan + //how it works is i create a blan with a trial with 999 years and setup fee for subscription as the main amount for the lifetime plan + //paypal needs to have a regular plan so after the 999 years there is a regular plan with 0.01 amount money + //this works for both lifetime paid and free plans. + + if (!params.name) { + throw new Error('Must have a display name'); + } + if (!params.type) { + throw new Error('Must provide plan type'); + } + if (!params.service_id) { + throw new Error('Must attach a service'); + } + if (parseInt(params.interval_unit) !== 4) { + throw new Error('Interval must be "forever".'); + } + + let service = await paypalServicesModel.getByPK(params.service_id); + + await paypal.setAccessToken(); + + let planParams = { + product_id: service.paypal_id, + name: params.name, + billing_cycles: [ + { + frequency: { + interval_unit: 'YEAR', + interval_count: 1, + }, + tenure_type: 'TRIAL', + sequence: 1, + total_cycles: 999, + }, + { + frequency: { + interval_unit: 'YEAR', + interval_count: 1, + }, + tenure_type: 'REGULAR', + sequence: 2, + total_cycles: 0, + pricing_scheme: { + fixed_price: { + value: '0.01', + currency_code: this.currency.toUpperCase(), + }, + }, + }, + ], + payment_preferences: { + auto_bill_outstanding: true, + setup_fee: { + value: params.pricing, + currency_code: this.currency.toUpperCase(), + }, + setup_fee_failure_action: 'CANCEL', + payment_failure_threshold: 0, + }, + }; + let paypalPlanCreated = await paypal.createPlan(planParams); + + let price = paypalPlanCreated.data.payment_preferences.setup_fee.value; + + let planModelEntry = { + name: paypalPlanCreated.data.name, + type: params.type, + paypal_id: paypalPlanCreated.data.id, + description: paypalPlanCreated.data.description, + paypal_product_id: paypalPlanCreated.data.product_id, + pricing: price, + interval_unit: 4, + interval_count: null, + service_id: params.service_id, + trial_period_days: null, + status: this.getMappingKey(paypalPlansModel.status_mapping, paypalPlanCreated.data.status), + }; + + let modelCreatedPlan = await paypalPlansModel.insert(planModelEntry); + + if (!modelCreatedPlan) { + throw new Error('Internal error: error creating plan'); + } + return modelCreatedPlan; + }; + + this.adminCreateTrialPlan = async function (params) { + if (!params.name) { + throw new Error('Must have a display name'); + } + if (!params.type) { + throw new Error('Must provide plan type'); + } + if (!params.service_id) { + throw new Error('Must attach a service'); + } + if (parseInt(params.interval_unit) === 4) { + throw new Error('Interval can\'t be "forever".'); + } + let service = await paypalServicesModel.getByPK(params.service_id); + + await paypal.setAccessToken(); + + let planParams = { + product_id: service.paypal_id, + name: params.name, + billing_cycles: [ + // { + // frequency: { + // interval_unit: 'YEAR', + // interval_count: 1, + // }, + // tenure_type: 'TRIAL', + // sequence: 1, + // total_cycles: 999, + // }, + { + frequency: { + interval_unit: paypalPlansModel.interval_unit_mapping()[params.interval_unit].toUpperCase(), + interval_count: params.interval_count, + }, + tenure_type: 'REGULAR', + sequence: 1, + total_cycles: 1, + pricing_scheme: { + fixed_price: { + value: params.pricing, + currency_code: this.currency.toUpperCase(), + }, + }, + }, + ], + payment_preferences: { + auto_bill_outstanding: true, + // setup_fee: { + // value: params.pricing, + // currency_code: this.currency.toUpperCase(), + // }, + setup_fee_failure_action: 'CANCEL', + payment_failure_threshold: 0, + }, + }; + let paypalPlanCreated = await paypal.createPlan(planParams); + + let planInfo = paypalPlanCreated.data.billing_cycles[0]; + let price = planInfo.pricing_scheme.fixed_price.value; + let interval_unit = planInfo.frequency.interval_unit; + let interval_count = planInfo.frequency.interval_count; + + let planModelEntry = { + name: paypalPlanCreated.data.name, + type: params.type, + paypal_id: paypalPlanCreated.data.id, + description: paypalPlanCreated.data.description, + paypal_product_id: paypalPlanCreated.data.product_id, + pricing: price, + interval_unit: this.getMappingKey(paypalPlansModel.interval_unit_mapping, interval_unit.toLowerCase()), + interval_count: interval_count, + service_id: params.service_id, + trial_period_days: 0, + status: this.getMappingKey(paypalPlansModel.status_mapping, paypalPlanCreated.data.status), + }; + + let modelCreatedPlan = await paypalPlansModel.insert(planModelEntry); + + if (!modelCreatedPlan) { + throw new Error('Internal error: error creating plan'); + } + return modelCreatedPlan; + }; + + this._destroyStripeLifetimePlan = async function (planStripeId) { + //stripe doesn't allow deleting a price. will be set to unactive instead + return await stripe.updatePrice({ priceId: planStripeId, params: { active: false } }); + }; + this._destroyPaypalPlan = async function (planPaypalId) { + //paypal doesn't allow deleting a price. will be set to unactive instead + return await paypal.deactivatePlan(planPaypalId); + }; + + // this.adminCancelSubscription = async function (subscriptionId) { + // let subscriptionToCancel = await stripeSubscriptionsModel.getByPK(subscriptionId); + // let subscriptionPlan = await paypalPlansModel.getByPK(subscriptionToCancel.plan_id); + // if (!subscriptionToCancel || !subscriptionPlan) { + // throw new Error('No subscription or plan of that id'); + // } + // // let subscirptionType = subscriptionPlan.type; + // let subscirptionType = 3; + // //if normal subscription + // switch (subscirptionType) { + // case 0: + // case 3: + // case 4: + // let cancelSubscriptionParams = { + // subscriptionId: subscriptionToCancel.stripe_id, + // params: { + // prorate: this.prorate, + // invoice_now: true, + // }, + // }; + // let subscriptionCanceled = await stripe.cancelSubscription(cancelSubscriptionParams); + // let localCancellationParams = { + // status: stripeSubscriptionsModel.inverse_status_mapping()[subscriptionCanceled.status], + // }; + // await stripeSubscriptionsModel.edit(localCancellationParams, subscriptionId); + // return subscriptionCanceled; + // default: + // throw new Error('Something wrong'); + // } + // }; + // this.userAddCard = async function (cardParams) { + // let createdCard = await stripe.createCard(cardParams); + + // if (createdCard) { + // if (createdCard.metadata.is_default == '1') { + // let customerUpdateParams = { + // customerId: createdCard.customer, + // params: { default_source: createdCard.id }, + // }; + // await stripe.updateCustomer(customerUpdateParams); + // let defaultCards = await stripeCardsModel.getAll({ is_default: 1 }); + // if (defaultCards.length > 0) { + // defaultCards.forEach(async (card) => { + // await stripeCardsModel.edit({ is_default: 0 }, card.id); + // }); + // } + // } + // cardModelEntry = { + // card_last: createdCard.last4 ?? '', + // card_brand: createdCard.brand ?? '', + // card_exp_month: createdCard.exp_month ?? '', + // exp_year: createdCard.exp_year ?? '', + // card_name: createdCard.metadata.card_name ?? '', + // stripe_card_customer: createdCard.customer, + // stripe_card_id: createdCard.id, + // is_default: createdCard.metadata.is_default, + // user_id: this.userId ?? null, + // role_id: this.roleId ?? null, + // }; + // var modelCreatedCard = await stripeCardsModel.insert(cardModelEntry); + // if (!modelCreatedCard) { + // throw new Error('Internal error: Error adding card'); + // } + // } + // return modelCreatedCard; + // }; + // this.changePlan = async function (currentSubscription, newPlan, user, card, couponId = '') { + // //if current subscriptions is canceled + // if (!currentSubscription || currentSubscription.status == 5) { + // let subscriptionParams = { + // customer: user.stripe_id, + // items: { plan: newPlan.id }, + // coupon: couponId, + // }; + // return await this.subscribe(subscriptionParams, newPlan); + // } + // //user has subscription (upgrade/ downgrade) + // if (currentSubscription && currentSubscription.status != 5) { + // if (currentSubscription.plan_id == newPlan.id) throw new Error('Same Plan'); + // } + // }; + this.getMappingKey = function (mappingFunction, value) { + return Object.keys(mappingFunction()).find((key) => mappingFunction()[key] === value); + }; +} diff --git a/services/PermissionService.js b/services/PermissionService.js new file mode 100644 index 0000000..3f746bc --- /dev/null +++ b/services/PermissionService.js @@ -0,0 +1,17 @@ +module.exports = { + verifyPermission: function (role, roleName) { + return function (req, res, next) { + const permissions = req.session.permissions || []; + + const isAllowedPermission = permissions.find( + (permission) => `/${roleName}${permission}` === req.originalUrl, + ); + + if (isAllowedPermission) { + return next(); + } else { + return res.redirect(`/${roleName}/dashboard`); + } + }; + }, +}; diff --git a/services/PowerByService.js b/services/PowerByService.js new file mode 100644 index 0000000..fc8a832 --- /dev/null +++ b/services/PowerByService.js @@ -0,0 +1,4 @@ +module.exports = function (req, res, next) { + res.setHeader("X-Powered-By", "Manaknightdigital Inc."); + next(); +}; diff --git a/services/ProfileService.js b/services/ProfileService.js new file mode 100644 index 0000000..dc1a3c0 --- /dev/null +++ b/services/ProfileService.js @@ -0,0 +1,52 @@ +const db = require('../models'); + +module.exports = { + /** + * Get user profile from user and credential table + * @name profileService.get_profile + * @param {string} user_id user id + * @returns {Promise.<{email: string, password: string, first_name: string, last_name: string}>} profile fields + */ + async get_profile(user_id) { + try { + const { email, password } = await db.credential.getByField({ user_id }); + const { first_name, last_name } = await db.user.getByPK(user_id); + + return { + email, + password, + first_name, + last_name, + }; + } catch (error) { + throw new Error(error.message); + } + }, + /** + * Edit user profile update user and credential tables + * @param {string} user_id user id + * @param {{email: string, password: string, first_name: string, last_name: string}} profile user profile + * @returns {Promise.<{email: string, password: string, first_name: string, last_name: string}>} updated profile fields + */ + async edit_profile(user_id, profile) { + try { + await db.credential.editByField( + { email: profile.email, password: profile.password }, + { user_id }, + ); + await db.user.edit( + { first_name: profile.first_name, last_name: profile.last_name }, + user_id, + ); + + return { + email, + password, + first_name, + last_name, + }; + } catch (error) { + throw new Error(error.message); + } + }, +}; diff --git a/services/PushNotification.js b/services/PushNotification.js new file mode 100644 index 0000000..8867d5e --- /dev/null +++ b/services/PushNotification.js @@ -0,0 +1,90 @@ +const admin = require('firebase-admin'); + +class PushNotification { + /** + * Initialize firebase admin + * {@link https://firebase.google.com/docs/admin/setup#initialize-sdk Initialize the SDK}. + */ + constructor() { + this.admin = admin.initializeApp({ + credential: admin.credential.applicationDefault(), + }); + + this.messaging = this.admin.messaging(); + } + + /** + * Generate payload + * @param {{body: string, title: string, image_url: string}} payload + * @param {admin.messaging.MessagingPayload} override override default payload + */ + generatePayload(payload, override) { + return { + notification: { + body: payload.body, + title: payload.title, + }, + data: payload, + apns: { + payload: { + aps: { + 'mutable-content': 1, + }, + }, + fcm_options: { + image: payload.image_url, + }, + }, + android: { + notification: { + image: payload.image_url, + }, + }, + ...override, + }; + } + + /** + * Generate options + * @param {admin.messaging.MessagingOptions} override override default options + */ + generateOptions(override) { + return { + contentAvailable: true, + priority: 'high', + timeToLive: 60 * 60 * 24, + ...override, + }; + } + + /** + * Send push notification + * @param {string|string[]} deviceToken + * @param {admin.messaging.MessagingPayload} payload + * @param {admin.messaging.MessagingOptions} options + * @returns {Promise.} + * @example + * const pushNotification = new PushNotification(); + * const payload = pushNotification.generatePayload({}) // {} = custom configuration + * const options = pushNotification.generateOptions({}); // {} = custom configuration + * + * pushNotification + * .sendPushNotification('device_token', payload, options) + * .then((response) => { + * console.log('message send successfully'); + * }) + * .catch((error) => { + * console.log('error occurred'); + * }); + */ + sendPushNotification(deviceToken, payload, options) { + return new Promise((resolve, reject) => { + this.messaging + .sendToDevice(deviceToken, payload, options) + .then((response) => resolve(response)) + .catch((error) => reject(error)); + }); + } +} + +module.exports = PushNotification; diff --git a/services/QRCodeService.js b/services/QRCodeService.js new file mode 100644 index 0000000..01fcff6 --- /dev/null +++ b/services/QRCodeService.js @@ -0,0 +1,16 @@ +const QRCode = require('qrcode'); + +module.exports = { + /** + * Generate QRCode + * @param {string} text QRCode string + */ + generateQRCode: async function (text) { + return new Promise((resolve, reject) => { + QRCode.toDataURL(text, (error, url) => { + if (error) reject(error); + else resolve(url); + }); + }); + }, +}; diff --git a/services/S3Service.js b/services/S3Service.js new file mode 100644 index 0000000..316bdce --- /dev/null +++ b/services/S3Service.js @@ -0,0 +1,156 @@ +require('dotenv').config(); +const AWS = require('aws-sdk'); + +process.env.DYNAMIC_CONFIG_AWS_REGION = 'ap-south-1'; +process.env.DYNAMIC_CONFIG_AWS_KEY = 'AKIA5RTSM74BBOL52JEA'; +process.env.DYNAMIC_CONFIG_AWS_SECRET = + '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'; +process.env.DYNAMIC_CONFIG_AWS_BUCKET = 'sentry-test90426-dev'; + +class S3Service { + /** + * Initialize S3 service + * @param {bucket} bucket override default aws bucket name + */ + constructor(bucket) { + AWS.config.update({ + accessKeyId: process.env.DYNAMIC_CONFIG_AWS_KEY, + secretAccessKey: process.env.DYNAMIC_CONFIG_AWS_SECRET, + region: process.env.DYNAMIC_CONFIG_AWS_REGION, + signatureVersion: 'v4', + }); + + this.S3 = new AWS.S3(); + this.bucket = bucket || process.env.DYNAMIC_CONFIG_AWS_BUCKET; + } + + /** + * Upload an object to bucket + * {@link https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property s3.upload} + * @param {string} key object key + * @param {any} body object body + * @param {AWS.S3.PutObjectRequest} options upload object params + * @returns {Promise.} + * @throws {Error} + */ + upload(key, body, options) { + const params = { + Bucket: this.bucket, + Key: key, + Body: body, + ...options, + }; + + return new Promise((resolve, reject) => { + this.S3.upload(params, function (error, data) { + if (error) reject(error); + else resolve(data); + }); + }); + } + + /** + * Upload objects to bucket + * {@link https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property s3.upload} + * @param {[{key: string, body: any}]} objects objects key and body + * @param {AWS.S3.PutObjectRequest} options upload objects params + * @returns {Promise.<[AWS.S3.Types.ManagedUpload.SendData]>} + * @throws {Error} + */ + batchUpload(objects, options) { + const uploads = []; + + objects.forEach((object) => { + const singleUpload = this.upload(object.key, object.body, options); + uploads.push(singleUpload); + }); + + return Promise.all(uploads); + } + + /** + * Get object from bucket + * {@link https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property s3.getObject} + * @param {string} key object key + * @param {AWS.S3.GetObjectRequest} options get object params + * @returns {Promise.} + * @throws {AWS.S3.Error} + */ + get(key, options) { + const params = { + Bucket: this.bucket, + Key: key, + ...options, + }; + + return new Promise((resolve, reject) => { + this.S3.getObject(params, function (error, data) { + if (error) reject(error); + else resolve(data); + }); + }); + } + + /** + * Get objects from bucket + * {@link https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property s3.getObject} + * @param {[key: string]} keys object keys + * @param {AWS.S3.GetObjectRequest} options get objects params + * @returns {Promise.<[AWS.S3.Types.GetObjectOutput]>} + * @throws {AWS.S3.Error} + */ + batchGet(keys, options) { + const gets = []; + + keys.forEach((key) => { + const singleGet = this.get(key, options); + gets.push(singleGet); + }); + + return Promise.all(gets); + } + + /** + * Delete object from bucket + * {@link https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#deleteObject-property s3.getObject} + * @param {string} key object key + * @param {AWS.S3.DeleteObjectRequest} options delete object params + * @returns {Promise.} + * @throws {AWS.S3.Error} + */ + delete(key, options) { + const params = { + Bucket: this.bucket, + Key: key, + ...options, + }; + + return new Promise((resolve, reject) => { + this.S3.deleteObject(params, function (error, data) { + if (error) reject(error); + else resolve(data); + }); + }); + } + + /** + * Delete objects from bucket + * {@link https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#deleteObjects-property s3.getObjects} + * @param {[string]} key objects key + * @param {AWS.S3.DeleteObjectRequest} options delete objects params + * @returns {Promise.<[AWS.S3.Types.DeleteObjectOutput]>} + * @throws {AWS.S3.Error} + */ + batchDelete(keys, options) { + const deletes = []; + + keys.forEach((key) => { + const singleDelete = this.delete(key, options); + deletes.push(singleDelete); + }); + + return Promise.all(deletes); + } +} + +module.exports = S3Service; diff --git a/services/SessionService.js b/services/SessionService.js new file mode 100644 index 0000000..4d8c1f1 --- /dev/null +++ b/services/SessionService.js @@ -0,0 +1,61 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2020*/ +/** + * Session Service + * @copyright 2020 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +module.exports = { + verifySessionMiddleware: function (role, roleName = "") { + return function (req, res, next) { + const two_factor_authentication = req.session.two_factor_authentication; + + const currentRole = req.session.role ? req.session.role : 0; + if (currentRole === 0 || currentRole != role) { + return res.redirect(`${roleName ? "/" + roleName : ""}/login?redirect_to=${req.originalUrl}`); + } else if (two_factor_authentication) { + return res.redirect(`/${roleName}/verify-account`); + } else { + next(); + } + }; + }, + + preventAuthRoutes: function (role, roleName) { + return (req, res, next) => { + const sessionRole = req.session.role; + + if (sessionRole === role) { + return res.redirect("/" + roleName + "/dashboard"); + } else { + next(); + } + }; + }, + + prevent2FA: function (role, roleName) { + return (req, res, next) => { + const currentRole = req.session.role; + const twoFA = req.session.two_factor_authentication; + + if (currentRole !== role || !twoFA) { + return res.redirect("/" + roleName + "/login"); + } else { + next(); + } + }; + }, + + randomString: function (len) { + const charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~!@#$%^&*()_+{}|":?><,./;[]'; + let randomString = ""; + for (let i = 0; i < len; i++) { + let randomPoz = Math.floor(Math.random() * charSet.length); + randomString += charSet.substring(randomPoz, randomPoz + 1); + } + return randomString; + }, +}; diff --git a/services/SmsService.js b/services/SmsService.js new file mode 100644 index 0000000..e92610f --- /dev/null +++ b/services/SmsService.js @@ -0,0 +1,65 @@ +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2020*/ +/** + * SMS Service + * @copyright 2020 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + * + */ + +const db = require('../models'); + +const accountSid = process.env.TWILIO_SID; +const authToken = process.env.TWILIO_TOKEN; +const phoneNumber = process.env.TWILIO_PHONE_NUMBER; +const client = require('twilio')(accountSid, authToken); + +module.exports = { + from: phoneNumber, + + template: function (slug) { + return new Promise(function (resolve, reject) { + db.sms + .findOne({ where: { slug } }) + .then((response) => { + if (!response) { + return reject(`TEMPLATE_NOT_FOUND`); + } else resolve(response); + }) + .catch((error) => { + reject(error); + }); + }); + }, + + inject: function (template, payload) { + let body = template.content; + + for (const key in payload) { + const element = payload[key]; + body = body.replace(new RegExp('{{{' + key + '}}}', 'g'), element); + } + + return body; + }, + + /** + * Send SMS + * @param {string} to + * @param {string} body + */ + send: function (to, body) { + let self = this; + return new Promise(function (resolve, reject) { + client.messages + .create({ + body, + from: self.from, + to, + }) + .then((message) => resolve(message.sid)) + .catch((error) => reject(error)); + }); + }, +}; diff --git a/services/StripeApi.js b/services/StripeApi.js new file mode 100644 index 0000000..3a0fefb --- /dev/null +++ b/services/StripeApi.js @@ -0,0 +1,561 @@ +const Stripe = require('stripe'); +module.exports = new Service(); +function Service() { + this.apiSecretKey = process.env.STRIPE_SECRET_KEY; + this.apiPublishKey = process.env.STRIPE_PUBLISH_KEY; + this.stripe = Stripe(this.apiSecretKey); + + // Products Functions + this.createProduct = async function (params) { + args = this.filterParams(params); + let stripeType = 'product_create'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.retrieveProduct = async function (params) { + args = this.filterParams(params); + let stripeType = 'product_retrieve'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.listAllProducts = async function (params) { + args = this.filterParams(params); + let stripeType = 'product_list_all'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.updateProduct = async function (params) { + args = this.filterParams(params); + let stripeType = 'product_update'; + var result = await this.stripeType(stripeType, args); + return result; + }; + + // Cards Functions + this.createCard = async function (params) { + args = this.filterParams(params); + let stripeType = 'card_create'; + var result = await this.stripeType(stripeType, args); + return result; + }; + // Customers Functions + this.createCustomer = async function (params) { + args = this.filterParams(params); + let stripeType = 'customer_create'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.updateCustomer = async function (params) { + args = this.filterParams(params); + let stripeType = 'customer_update'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.retrieveCustomer = async function (params) { + args = this.filterParams(params); + let stripeType = 'customer_retrieve'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.listAllCustomers = async function (params) { + args = this.filterParams(params); + let stripeType = 'customer_list_all'; + var result = await this.stripeType(stripeType, args); + return result; + }; + // Card Functions + this.retrieveCard = async function (params) { + args = this.filterParams(params); + let stripeType = 'card_retrieve'; + var result = await this.stripeType(stripeType, args); + return result; + }; + + // Prices Functions + this.createPrice = async function (params) { + args = this.filterParams(params); + let stripeType = 'price_create'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.updatePrice = async function (params) { + args = this.filterParams(params); + let stripeType = 'price_update'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.retrievePrice = async function (params) { + args = this.filterParams(params); + let stripeType = 'price_retrieve'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.listAllPrices = async function (params) { + args = this.filterParams(params); + let stripeType = 'price_list_all'; + var result = await this.stripeType(stripeType, args); + return result; + }; + + // Charges Functions + this.createCharge = async function (params) { + args = this.filterParams(params); + let stripeType = 'charge_create'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.retrieveCharge = async function (params) { + // args = params; + args = this.filterParams(params); + let stripeType = 'charge_retrieve'; + var result = await this.stripeType(stripeType, args); + return result; + }; + + //Invoices Functions + this.createInvoice = async function (params) { + args = this.filterParams(params); + let stripeType = 'invoice_create'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.payInvoice = async function (params) { + args = this.filterParams(params); + let stripeType = 'invoice_pay'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.retrieveInvoice = async function (params) { + args = this.filterParams(params); + let stripeType = 'invoice_retrieve'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.createInvoiceItem = async function (params) { + args = this.filterParams(params); + let stripeType = 'invoice_item_create'; + var result = await this.stripeType(stripeType, args); + return result; + }; + + //subscriptions + this.createSubscription = async function (params) { + args = this.filterParams(params); + let stripeType = 'subscription_create'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.updateSubscription = async function (params) { + args = this.filterParams(params); + let stripeType = 'subscription_update'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.retrieveSubscription = async function (params) { + args = this.filterParams(params); + let stripeType = 'subscription_retrieve'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.cancelSubscription = async function (params) { + args = this.filterParams(params); + let stripeType = 'subscription_cancel'; + var result = await this.stripeType(stripeType, args); + return result; + }; + this.listAllSubscriptions = async function (params) { + args = this.filterParams(params); + let stripeType = 'subscription_list_all'; + var result = await this.stripeType(stripeType, args); + return result; + }; + + this.stripeType = async function (type, args) { + try { + switch (type) { + //Products + case 'product_create': + // @see https://stripe.com/docs/api/products/create?lang=node + var result = await this.stripe.products.create(args); + break; + case 'product_delete': + // @see https://stripe.com/docs/api/products/delete?lang=node + var result = await this.stripe.products.del(args); + break; + case 'product_retrieve': + // @see https://stripe.com/docs/api/products/retrieve?lang=node + var result = await this.stripe.products.retrieve(args); + break; + case 'product_update': + // @see https://stripe.com/docs/api/products/update?lang=node + var result = await this.stripe.products.update(args.productId, args.params); + break; + case 'product_list_all': + // @see https://stripe.com/docs/api/products/list?lang=node + var result = await this.stripe.products.list(args); + break; + + //Prices + case 'price_create': + // @see https://stripe.com/docs/api/prices/create?lang=node + var result = await this.stripe.prices.create(args); + break; + case 'price_retrieve': + // @see https://stripe.com/docs/api/prices/retrieve?lang=node + var result = await this.stripe.prices.retrieve(args); + break; + case 'price_update': + // @see https://stripe.com/docs/api/prices/update?lang=node + var result = await this.stripe.prices.update(args.priceId, args.params); + break; + case 'price_list_all': + // @see https://stripe.com/docs/api/prices/list?lang=node + var result = await this.stripe.prices.list(args); + break; + + //Charges + case 'charge_create': + // @see https://stripe.com/docs/api/charges/create?lang=node + var result = await this.stripe.charges.create(args); + break; + case 'charge_retrieve': + // @see https://stripe.com/docs/api/charges/retrieve?lang=node + var result = await this.stripe.charges.retrieve(args); + break; + case 'charge_update': + // @see https://stripe.com/docs/api/charges/update?lang=node + var result = await this.stripe.charges.update(args.chargeId, args.params); + break; + case 'charge_capture': + // @see https://stripe.com/docs/api/charges/capture?lang=node + var result = await this.stripe.charges.capture(args); + break; + case 'charge_list_all': + // @see https://stripe.com/docs/api/charges/list?lang=node + var result = await this.stripe.charges.list(args); + break; + + //Customer + case 'customer_create': + // @see https://stripe.com/docs/api/customers/create?lang=node + var result = await this.stripe.customers.create(args); + break; + case 'customer_retrieve': + // @see https://stripe.com/docs/api/customers/retrieve?lang=node + var result = await this.stripe.customers.retrieve(args); + break; + case 'customer_update': + // @see https://stripe.com/docs/api/customers/update?lang=node + var result = await this.stripe.customers.update(args.customerId, args.params); + break; + case 'customer_delete': + // @see https://stripe.com/docs/api/customers/capture?lang=node + var result = await this.stripe.customers.del(args); + break; + case 'customer_list_all': + // @see https://stripe.com/docs/api/customers/list?lang=node + var result = await this.stripe.customers.list(args); + break; + + //Refunds + case 'refund_create': + // @see https://stripe.com/docs/api/refunds/create?lang=node + var result = await this.stripe.refunds.create(args); + break; + case 'refund_retrieve': + // @see https://stripe.com/docs/api/refunds/retrieve?lang=node + var result = await this.stripe.refunds.retrieve(args); + break; + case 'refund_update': + // @see https://stripe.com/docs/api/refunds/update?lang=node + var result = await this.stripe.refunds.update(args.refundId, args.params); + break; + case 'refund_list_all': + // @see https://stripe.com/docs/api/refunds/list?lang=node + var result = await this.stripe.refunds.list(args); + break; + + //Cards (Sources) + case 'card_create': + // @see https://stripe.com/docs/api/cards/create?lang=node + var result = await this.stripe.customers.createSource(args.customerId, args.params); + break; + case 'card_retrieve': + // @see https://stripe.com/docs/api/cards/retrieve?lang=node + var result = await this.stripe.customers.retrieveSource(args.customerId, args.cardId); + break; + case 'card_update': + // @see https://stripe.com/docs/api/cards/update?lang=node + var result = await this.stripe.customers.updateSource(args.customerId, args.cardId, args.params); + break; + case 'card_delete': + // @see https://stripe.com/docs/api/cards/delete?lang=node + var result = await this.stripe.customers.deleteSource(args.customerId, args.cardId); + break; + case 'card_list_all': + // @see https://stripe.com/docs/api/cards/list?lang=node + var result = await this.stripe.customers.listSources(args.customerId, args.params); + break; + + //Payment Method + case 'paymentMethod_create': + // @see https://stripe.com/docs/api/payment_methods/create?lang=node + var result = await this.stripe.paymentMethods.create(args); + break; + case 'paymentMethod_retrieve': + // @see https://stripe.com/docs/api/payment_methods/retrieve?lang=node + var result = await this.stripe.paymentMethods.retrieve(args); + break; + case 'paymentMethod_update': + // @see https://stripe.com/docs/api/payment_methods/update?lang=node + var result = await this.stripe.paymentMethods.update(args.paymentMethodId, args.params); + break; + case 'paymentMethod_attach': + // @see https://stripe.com/docs/api/payment_methods/attach?lang=node + var result = await this.stripe.paymentMethods.attach(args.paymentMethodId, args.params); + break; + case 'paymentMethod_detach': + // @see https://stripe.com/docs/api/payment_methods/attach?lang=node + var result = await this.stripe.paymentMethods.attach(args); + break; + case 'paymentMethod_list_all': + // @see https://stripe.com/docs/api/payment_methods/list?lang=node + var result = await this.stripe.paymentMethods.list(args); + break; + + //Session + case 'session_create': + // @see https://stripe.com/docs/api/sessions/create?lang=node + var result = await this.stripe.checkout.sessions.create(args); + break; + case 'session_retrieve': + // @see https://stripe.com/docs/api/sessions/retrieve?lang=node + var result = await this.stripe.checkout.sessions.retrieve(args); + break; + case 'session_list_all_lineItems': + // @see https://stripe.com/docs/api/sessions/line_items?lang=node + var result = function () { + return new Promise((resolve, reject) => { + this.stripe.checkout.sessions.listLineItems(args.sessionId, args.params, function (err, lineItems) { + if (err) return reject(err); + return resolve(lineItems); + }); + }); + }; + result = await result(); + break; + case 'session_list_all': + // @see https://stripe.com/docs/api/session/list?lang=node + var result = await this.stripe.checkout.sessions.list(args); + break; + + //Coupon + case 'coupon_create': + // @see https://stripe.com/docs/api/coupons/create?lang=node + var result = await this.stripe.coupons.create(args); + break; + case 'coupon_retrieve': + // @see https://stripe.com/docs/api/coupons/retrieve?lang=node + var result = await this.stripe.coupons.retrieve(args); + break; + case 'coupon_update': + // @see https://stripe.com/docs/api/coupons/update?lang=node + var result = await this.stripe.coupons.update(args.couponId, args.params); + break; + case 'coupon_delete': + // @see https://stripe.com/docs/api/coupons/delete?lang=node + var result = await this.stripe.coupons.del(args); + break; + case 'coupon_list_all': + // @see https://stripe.com/docs/api/coupons/list?lang=node + var result = await this.stripe.coupons.list(args); + break; + + //Invoice items + case 'invoice_item_create': + // @see https://stripe.com/docs/api/invoiceitems/create?lang=node + var result = await this.stripe.invoiceItems.create(args); + break; + + //Invoice + case 'invoice_create': + // @see https://stripe.com/docs/api/invoices/create?lang=node + var result = await this.stripe.invoices.create(args); + break; + case 'invoice_retrieve': + // @see https://stripe.com/docs/api/invoices/retrieve?lang=node + var result = await this.stripe.invoices.retrieve(args); + break; + case 'invoice_update': + // @see https://stripe.com/docs/api/invoices/update?lang=node + var result = await this.stripe.invoices.update(args.invoiceId, args.params); + break; + case 'invoice_delete': + // @see https://stripe.com/docs/api/invoices/delete?lang=node + var result = await this.stripe.invoices.del(args); + break; + case 'invoice_finalize': + // @see https://stripe.com/docs/api/invoices/finalize?lang=node + var result = await this.stripe.invoices.finalizeInvoice(args); + break; + case 'invoice_pay': + // @see https://stripe.com/docs/api/invoices/pay?lang=node + var result = await this.stripe.invoices.pay(args); + break; + case 'invoice_void': + // @see https://stripe.com/docs/api/invoices/void?lang=node + var result = await this.stripe.invoices.voidInvoice(args); + break; + case 'invoice_list_all': + // @see https://stripe.com/docs/api/invoices/list?lang=node + var result = await this.stripe.invoices.list(args); + break; + + //Subscription + case 'subscription_create': + // @see https://stripe.com/docs/api/subscriptions/create?lang=node + var result = await this.stripe.subscriptions.create(args); + break; + case 'subscription_retrieve': + // @see https://stripe.com/docs/api/subscriptions/retrieve?lang=node + var result = await this.stripe.subscriptions.retrieve(args); + break; + case 'subscription_update': + // @see https://stripe.com/docs/api/subscriptions/update?lang=node + var result = await this.stripe.subscriptions.update(args.subscriptionId, args.params); + break; + case 'subscription_cancel': + // @see https://stripe.com/docs/api/subscriptions/cancel?lang=node + var result = await this.stripe.subscriptions.del(args.subscriptionId, args.params); + break; + case 'subscription_list_all': + // @see https://stripe.com/docs/api/subscriptions/list?lang=node + var result = await this.stripe.subscriptions.list(args); + break; + + //Subscription schedule + case 'subscription_schedule_create': + // @see https://stripe.com/docs/api/subscription_schedules/create?lang=node + var result = await this.stripe.subscriptionSchedules.create(args); + break; + case 'subscription_schedule_retrieve': + // @see https://stripe.com/docs/api/subscription_schedules/retrieve?lang=node + var result = await this.stripe.subscriptionSchedules.retrieve(args); + break; + case 'subscription_schedule_update': + // @see https://stripe.com/docs/api/subscription_schedules/update?lang=node + var result = await this.stripe.subscriptionSchedules.update(args.subScheduleId, args.params); + break; + case 'subscription_schedule_cancel': + // @see https://stripe.com/docs/api/subscription_schedules/cancel?lang=node + var result = await this.stripe.subscriptionSchedules.cancel(args); + break; + case 'subscription_schedule_release': + // @see https://stripe.com/docs/api/subscription_schedules/release?lang=node + var result = await this.stripe.subscriptionSchedules.release(args); + break; + case 'subscription_schedule_list_all': + // @see https://stripe.com/docs/api/subscription_schedules/list?lang=node + var result = await this.stripe.subscriptionSchedules.list(args); + break; + + //Transaction + case 'transaction_retrieve': + // @see https://stripe.com/docs/api/issuing/transactions/retrieve?lang=node + var result = await this.stripe.issuing.transactions.retrieve(args); + break; + case 'transaction_update': + // @see https://stripe.com/docs/api/issuing/transactions/update?lang=node + var result = await this.stripe.issuing.transactions.update(args.transactionId, args.params); + break; + case 'transaction_list_all': + // @see https://stripe.com/docs/api/issuing/transactions/list?lang=node + var result = await this.stripe.issuing.transactions.list(args); + break; + + //Order + case 'order_create': + // @see https://stripe.com/docs/api/orders/create?lang=node + var result = await this.stripe.orders.create(args); + break; + case 'order_retrieve': + // @see https://stripe.com/docs/api/orders/retrieve?lang=node + var result = await this.stripe.orders.retrieve(args); + break; + case 'order_update': + // @see https://stripe.com/docs/api/orders/update?lang=node + var result = await this.stripe.orders.update(args.orderId, args.params); + break; + case 'order_pay': + // @see https://stripe.com/docs/api/orders/pay?lang=node + var result = await this.stripe.orders.pay(args.orderId, args.params); + break; + case 'order_list_all': + // @see https://stripe.com/docs/api/orders/list?lang=node + var result = await this.stripe.orders.list(args); + break; + case 'order_return': + // @see https://stripe.com/docs/api/orders/return?lang=node + var result = function () { + return new Promise((resolve, reject) => { + this.stripe.orders.returnOrder(args.orderId, args.params, function (err, order) { + if (err) return reject(err); + return resolve(order); + }); + }); + }; + result = await result(); + break; + + //Webhooks + case 'webhook_create': + // @see https://stripe.com/docs/api/webhook_endpoints/create?lang=node + var result = await this.stripe.webhookEndpoints.create(args); + break; + case 'webhook_retrieve': + // @see https://stripe.com/docs/api/webhook_endpoints/retrieve?lang=node + var result = await this.stripe.webhookEndpoints.retrieve(args); + break; + case 'webhook_update': + // @see https://stripe.com/docs/api/webhook_endpoints/update?lang=node + var result = await this.stripe.webhookEndpoints.update(args.webhookId, args.params); + break; + case 'webhook_delete': + // @see https://stripe.com/docs/api/webhook_endpoints/delete?lang=node + var result = await this.stripe.webhookEndpoints.del(args); + break; + case 'webhook_list_all': + // @see https://stripe.com/docs/api/webhook_endpoints/list?lang=node + var result = await this.stripe.webhookEndpoints.list(args); + break; + } + return result; + } catch (error) { + // return { error: true, message: error.message, statusCode: error.statusCode, errorObject: error.raw }; + console.dir(error, { depth: null }); + throw new Error('Internal Error: error when doing stripe action'); + } + }; + + /** + * [filterParams filters paramters from null, undefined, empty strings, empty arrays and empty objects as it can cause unwanted changes] + * @param {object} params [object that can contain one more object inside] + * @return {object} [object with only truth variables] + */ + this.filterParams = function (params) { + Object.keys(params).forEach((param) => { + if (this.empty(params[param]) || (Array.isArray(params[param]) && !params[param].length)) { + console.log(`Parameter empty, null or undefined`); + delete params[param]; + } else if (params[param].constructor === Object && Object.entries(params[param]).length === 0) { + console.log(`Parameter object empty`); + delete params[param]; + } else if (params[param].constructor === Object && Object.entries(params[param]).length > 0) { + this.filterParams(params[param]); + } + }); + return params; + }; + // this.empty = (value) => value === null || value === undefined || value === ''; + this.empty = (value) => value === null || value === undefined; +} diff --git a/services/StripeService.js b/services/StripeService.js new file mode 100644 index 0000000..a48e374 --- /dev/null +++ b/services/StripeService.js @@ -0,0 +1,1009 @@ +require('dotenv').config(); //require .env for stripe configurations +const moment = require('moment'); +const stripe = require('./StripeApi'); +const db = require('../models'); +const helpers = require('../core/helpers'); +const userModel = db.user; +const stripeSubscriptionModel = db.stripe_subscription; +const stripeSubscriptionLogModel = db.stripe_subscription_log; +const stripePlanModel = db.stripe_plan; +const stripeProductModel = db.stripe_product; +const stripePaymentModel = db.stripe_payment; +const stripeServiceModel = db.stripe_service; +const stripeCardModel = db.stripe_card; +const stripeInvoiceModel = db.stripe_invoice; +const stripeRefundModel = db.stripe_refund; +const stripeCouponModel = db.stripe_coupon; +const stripeCheckoutSessionModel = db.stripe_checkout_session; + +module.exports = new Service(); +function Service() { + this.userID = null; + this.roleID = null; + this.currency = process.env.STRIPE_CURRENCY; + this.prorate = process.env.STRIPE_PRORATE; + this.forceCancel = process.env.STRIPE_FORCE_CANCEL; + + this.setUserId = function (userID) { + this.userID = userID; + }; + this.setRoleId = function (roleID) { + this.roleID = roleID; + }; + this.setCurrency = function (currency) { + this.currency = currency; + }; + this.setProrationType = function (prorate) { + this.prorate = prorate; + }; + this.setCancelType = function (forceCancel) { + this.forceCancel = forceCancel; + }; + + this.subscribe = async function (subscriptionParams, plan) { + var subscription = await stripe.createSubscription(subscriptionParams); + //create model entry + + let subscriptionModelEntry = { + stripe_id: subscription.id ?? '', + cancel_at_period_end: subscription.cancel_at_period_end ?? null, + current_period_start: moment(new Date(subscription.current_period_start * 1000)).format('YYYY-MM-DD') ?? null, + current_period_end: moment(new Date(subscription.current_period_end * 1000)).format('YYYY-MM-DD') ?? null, + user_id: this.userID ?? null, + role_id: this.roleID ?? null, + plan_id: plan.id ?? null, + plan_stripe_id: subscription.plan.id ?? null, + coupon_stripe_id: subscription.discount?.coupon?.id ?? '', + customer_stripe_id: subscription.customer ?? '', + collection_method: subscription.collection_method ?? '', + interval: helpers.getMappingKey(stripeSubscriptionModel.interval_mapping, subscription.plan?.interval) ?? null, + interval_count: subscription.plan.interval_count ?? '', + trial_period_days: subscription.plan.trial_period_days ?? 0, + trial_end: subscription.trial_end ? moment(new Date(subscription.trial_end * 1000)).format('YYYY-MM-DD') : null, + trial_start: subscription.trial_start ? moment(new Date(subscription.subscriptiontrial_start * 1000)).format('YYYY-MM-DD') : null, + status: helpers.getMappingKey(stripeSubscriptionModel.status_mapping, subscription.status) ?? null, + }; + + let subscriptionCreatedId = await stripeSubscriptionModel.insert(subscriptionModelEntry); + if (!subscriptionCreatedId) { + throw new Error('Subscription is not found.'); + } + + let subscriptionLogUpdated = await this.updateSubscriptionLogByUser(subscriptionCreatedId, subscription.status, plan); + if (!subscriptionLogUpdated) { + throw new Error('Error while editing subscription log'); + } + return { localSubscriptionID: subscriptionCreatedId, subscription }; + }; + this.updateSubscriptionLogByUser = async function (subscriptionCreatedId, subscriptionCreatedStatus, plan) { + let subscriptionLog = await stripeSubscriptionLogModel.getLast({ user_id: this.userID, role_id: this.roleID }); + + if (!subscriptionLog) { + let subscriptionLogModelEntry = { + user_id: this.userID, + role_id: this.roleID, + plan_id: plan?.id ?? null, + subscription_id: subscriptionCreatedId, + type: plan?.type ?? null, + status: subscriptionCreatedStatus == 'active' || subscriptionCreatedStatus == 'trialing' ? 1 : 0, + }; + if (!(await stripeSubscriptionLogModel.insert(subscriptionLogModelEntry))) { + throw new Error('Subscription log add not successfull'); + } + } else { + let subscriptionLogModelEntry = { + plan_id: plan?.id ?? null, + subscription_id: subscriptionCreatedId, + type: plan?.type ?? null, + status: subscriptionCreatedStatus == 'active' || subscriptionCreatedStatus == 'trialing' ? 1 : 0, + }; + let editedLog = await stripeSubscriptionLogModel.edit(subscriptionLogModelEntry, subscriptionLog.id); + if (!editedLog) { + throw new Error('Subscription log edit not successfull'); + } + } + return true; + }; + this.updateSubscriptionLogBySubscription = async function (subscription) { + let localSubscription = await stripeSubscriptionModel.getLast({ stripe_id: subscription.id }); + if (!localSubscription) { + throw new Error("Subscription Doesn't exist"); + } + + let subscriptionLog = await stripeSubscriptionLogModel.getLast({ subscription_id: localSubscription.id }); + if (!subscriptionLog) { + throw new Error("Subscription log Doesn't exist"); + } + + let plan = await stripePlanModel.getByFields({ stripe_id: subscription.plan.id }); + if (!plan) { + throw new Error("Plan Doesn't exist"); + } + let subscriptionLogModelEntry = { + plan_id: plan.id ?? null, + subscription_id: localSubscription.id, + type: plan.type ?? null, + status: subscription.status == 'active' || subscription.status == 'trialing' ? 1 : 0, + }; + + let editedLog = await stripeSubscriptionLogModel.edit(subscriptionLogModelEntry, subscriptionLog.id); + if (!editedLog) { + throw new Error('Error editing subscription log'); + } + return true; + }; + this.saveSubscriptionInvoice = async function (invoice) {}; + this.createRegularSubscription = async function (user, plan, card, coupon) { + let subscriptionParams = { + customer: user.stripe_id, + items: [{ price: plan.stripe_id }], + trial_from_plan: true, + default_payment_method: card?.stripe_card_id ?? null, + coupon: coupon?.stripe_id ?? null, + proration_behavior: this.prorate == 'true' ? 'create_prorations' : 'none', + }; + let { subscription } = await this.subscribe(subscriptionParams, plan); + + let retrieveParams = { + invoiceId: subscription.latest_invoice, + params: { expand: ['payment_intent'] }, + }; + let invoice = await stripe.retrieveInvoice(retrieveParams); + let paymentIntent = invoice.payment_intent; + + let localInvoice = await stripeInvoiceModel.getByFields({ stripe_id: invoice.id }); + if (!localInvoice) { + let invoiceModelEntry = { + stripe_id: invoice.id, + user_id: this.userID, + role_id: this.roleID, + billing_reason: invoice.billing_reason, + subscription_stripe_id: invoice.subscription, + customer_stripe_id: invoice.customer, + charge_stripe_id: invoice.charge, + collection_method: invoice.collection_method, + currency: invoice.currency, + invoice_url: invoice.hosted_invoice_url, + invoice_pdf_url: invoice.invoice_pdf, + payment_intent: invoice.payment_intent?.id ?? null, + amount_due: helpers.convertFromCents(invoice.amount_due), + amount_paid: helpers.convertFromCents(invoice.amount_paid), + amount_total: helpers.convertFromCents(invoice.total), + line_items: JSON.stringify(invoice.lines), + payment_attempted: invoice.attempted == true ? 1 : 0, + status: helpers.getMappingKey(stripeInvoiceModel.status_mapping, invoice.status), + refunded: 0, + }; + let createdInvoiceID = await stripeInvoiceModel.insert(invoiceModelEntry); + if (!createdInvoiceID) { + throw new Error('Internal Error: error creating invoice'); + } + } + + if (subscription.status == 'incomplete' && invoice.status == 'open') { + if (paymentIntent.status == 'requires_action') { + let authLink = paymentIntent.next_action.use_stripe_sdk.stripe_js; + throw { type: 'CardRequiresAction', message: 'Card requires confirmation', link: authLink }; + } + } + + return subscription; + }; + this.createLifetimeSubscription = async function (user, plan, card, coupon) { + //create invoice, finalize and pay it. + let lifetimePlanStripeObject = await stripe.retrievePrice({ priceId: plan.stripe_id, params: {} }); + let invoiceItemParams = { + customer: user.stripe_id, + price: plan.stripe_id, + discounts: [{ coupon: coupon?.stripe_id }], + }; + let invoiceItemCreated = await stripe.createInvoiceItem(invoiceItemParams); + + let invoiceParams = { + customer: user.stripe_id, + default_payment_method: card?.stripe_card_id ?? null, + }; + let invoiceCreated = await stripe.createInvoice(invoiceParams); + + let invoicePaid = await stripe.payInvoice(invoiceCreated.id); + + let subscriptionModelEntry = { + stripe_id: invoiceItemCreated.id ?? '', + cancel_at_period_end: null, + current_period_start: moment().format('YYYY-MM-DD') ?? null, + current_period_end: null, + user_id: this.userID ?? null, + role_id: this.roleID ?? null, + plan_id: plan?.id ?? null, + coupon_stripe_id: invoiceItemCreated.discounts.length > 0 ? coupon?.stripe_id : '', + customer_stripe_id: invoicePaid.customer ?? '', + collection_method: invoicePaid.collection_method ?? '', + interval: 4, + interval_count: null, + trial_period_days: 0, + trial_end: null, + trial_start: null, + status: 4, + }; + + let subscriptionCreatedId = await stripeSubscriptionModel.insert(subscriptionModelEntry); + if (!subscriptionCreatedId) { + throw new Error('Subscription is not found.'); + } + + let subscriptionLogUpdated = await this.updateSubscriptionLogByUser(subscriptionCreatedId, 'active', plan); + if (!subscriptionLogUpdated) { + throw new Error('Error while editing subscription log'); + } + + return subscriptionCreatedId; + }; + let calculateFullPeriod = function (interval, interval_count = 1) { + let totalNumberOfDays = stripePlanModel.interval_days_mapping()[interval] * interval_count; + let cancelAtEpoch = moment().add(totalNumberOfDays, 'days').unix(); + return cancelAtEpoch; + }; + this.createTrialSubscription = async function (user, plan, card, coupon) { + let trialPlanFullPeriod = calculateFullPeriod(plan.interval, plan.interval_count); + let subscriptionParams = { + customer: user.stripe_id, + items: [{ price: plan.stripe_id }], + trial_from_plan: true, + default_payment_method: card?.stripe_card_id ?? null, + coupon: coupon?.stripe_id ?? null, + cancel_at: trialPlanFullPeriod, + proration_behavior: this.prorate == 'true' ? 'create_prorations' : 'none', + }; + // return await this.subscribe(subscriptionParams, plan); + let { subscription } = await this.subscribe(subscriptionParams, plan); + + let retrieveParams = { + invoiceId: subscription.latest_invoice, + params: { expand: ['payment_intent'] }, + }; + let invoice = await stripe.retrieveInvoice(retrieveParams); + let paymentIntent = invoice.payment_intent; + + let localInvoice = await stripeInvoiceModel.getByFields({ stripe_id: invoice.id }); + if (!localInvoice) { + let invoiceModelEntry = { + stripe_id: invoice.id, + user_id: this.userID, + role_id: this.roleID, + billing_reason: invoice.billing_reason, + subscription_stripe_id: invoice.subscription, + customer_stripe_id: invoice.customer, + charge_stripe_id: invoice.charge, + collection_method: invoice.collection_method, + currency: invoice.currency, + invoice_url: invoice.hosted_invoice_url, + invoice_pdf_url: invoice.invoice_pdf, + payment_intent: invoice.payment_intent?.id ?? null, + amount_due: helpers.convertFromCents(invoice.amount_due), + amount_paid: helpers.convertFromCents(invoice.amount_paid), + amount_total: helpers.convertFromCents(invoice.total), + line_items: JSON.stringify(invoice.lines), + payment_attempted: invoice.attempted == true ? 1 : 0, + status: helpers.getMappingKey(stripeInvoiceModel.status_mapping, invoice.status), + refunded: 0, + }; + let createdInvoiceID = await stripeInvoiceModel.insert(invoiceModelEntry); + if (!createdInvoiceID) { + throw new Error('Internal Error: error creating invoice'); + } + } + + if (subscription.status == 'incomplete' && invoice.status == 'open') { + if (paymentIntent.status == 'requires_action') { + let authLink = paymentIntent.next_action.use_stripe_sdk.stripe_js; + throw { type: 'CardRequiresAction', message: 'Card requires confirmation', link: authLink }; + } + } + return subscription; + }; + this.updateSubscription = async function (activeSubscription, user, fromPlan, newPlan, card, coupon) { + let subscriptionStripeId = activeSubscription.stripe_id; + + let fromRegularToRegular = fromPlan.type == 0 && newPlan.type == 0 ? true : false; + let fromTrialToRegular = (fromPlan.type == 3 || fromPlan.type == 4) && newPlan.type == 0 ? true : false; + let fromRegularToTrial = fromPlan.type == 0 && (newPlan.type == 3 || newPlan.type == 4) ? true : false; + let fromAnyToLifetime = newPlan.type == 1 || newPlan.type == 2 ? true : false; + let fromLifetimeToAny = fromPlan.type == 1 || fromPlan.type == 2 ? true : false; + + if (fromRegularToTrial || fromTrialToRegular || fromRegularToRegular) { + let subscription = await stripe.retrieveSubscription({ subscriptionId: subscriptionStripeId, params: {} }); + let updateParams = { + default_payment_method: card?.stripe_card_id, + cancel_at: '', + items: [ + { + id: subscription.items.data[0].id, + price: newPlan.stripe_id, + }, + ], + coupon: coupon?.stripe_id ?? null, + proration_behavior: 'create_prorations', + payment_behavior: 'error_if_incomplete', + // trial_from_plan: true, + }; + if (fromRegularToTrial) { + let trialPlanFullPeriod = calculateFullPeriod(newPlan.interval, newPlan.interval_count); + updateParams.cancel_at = trialPlanFullPeriod; + } + let newSubscription = await stripe.updateSubscription({ subscriptionId: subscriptionStripeId, params: updateParams }); + + let newSubscriptionModelEntry = { + cancel_at_period_end: newSubscription.cancel_at_period_end ?? null, + current_period_start: moment(new Date(newSubscription.current_period_start * 1000)).format('YYYY-MM-DD') ?? null, + current_period_end: moment(new Date(newSubscription.current_period_end * 1000)).format('YYYY-MM-DD') ?? null, + plan_id: newPlan?.id ?? null, + coupon_stripe_id: newSubscription.discount?.coupon?.id ?? '', + interval: helpers.getMappingKey(stripeSubscriptionModel.interval_mapping, newSubscription.plan?.interval) ?? 0, + interval_count: newSubscription.plan?.interval_count ?? '', + trial_period_days: newSubscription.plan?.trial_period_days ?? 0, + trial_end: newSubscription.trial_end ? moment(new Date(newSubscription.trial_end * 1000)).format('YYYY-MM-DD') : null, + trial_start: newSubscription.trial_start ? moment(new Date(newSubscription.subscriptiontrial_start * 1000)).format('YYYY-MM-DD') : null, + status: helpers.getMappingKey(stripeSubscriptionModel.status_mapping, newSubscription.status) ?? null, + }; + + let subscriptionCreatedId = await stripeSubscriptionModel.edit(newSubscriptionModelEntry, activeSubscription.id); + if (!subscriptionCreatedId) { + throw new Error('Subscription is not found.'); + } + + let subscriptionLogUpdated = await this.updateSubscriptionLogByUser(activeSubscription.id, newSubscription.status, newPlan); + if (!subscriptionLogUpdated) { + throw new Error('Error while editing subscription log'); + } + return subscriptionCreatedId; + } else if (fromAnyToLifetime) { + await this.cancelRegularSubscription(activeSubscription); + await this.createLifetimeSubscription(user, newPlan, card, coupon); + } else if (fromLifetimeToAny) { + await this.cancelLifetimeSubscription(activeSubscription); + if (newPlan.type == 0) { + await this.createRegularSubscription(user, newPlan, card, coupon); + } else if (newPlan.type == 1 || newPlan.type == 2) { + await this.createLifetimeSubscription(user, newPlan, card, coupon); + } else if (newPlan.type == 3 || newPlan.type == 4) { + await this.createTrialSubscription(user, newPlan, card, coupon); + } + } + }; + + this.cancelRegularSubscription = async function (subscription) { + var cancellationParams = { + subscriptionId: subscription.stripe_id, + params: { + invoice_now: true, + prorate: this.prorate == 'true' ? true : false, + }, + }; + let subscriptionCanceled = await stripe.cancelSubscription(cancellationParams); + + let newStatus = helpers.getMappingKey(stripeSubscriptionModel.status_mapping, subscriptionCanceled.status); + await stripeSubscriptionModel.edit({ status: newStatus }, subscription.id); + + let subscriptionLog = await stripeSubscriptionLogModel.getByFields({ subscription_id: parseInt(subscription.id), status: 1 }); + if (!subscriptionLog) { + throw new Error("Internal Error: Couldn't find relative active subscription log"); + } + let subscriptionLogEdited = await stripeSubscriptionLogModel.edit({ status: 0 }, subscriptionLog.id); + if (!subscriptionLogEdited) { + throw new Error("Internal Error: Couldn't Edit subscription log"); + } + }; + this.suspendRegularSubscription = async function (subscription) { + let updateParams = { + subscriptionId: subscription.stripe_id, + params: { + cancel_at_period_end: true, + }, + }; + await stripe.updateSubscription(updateParams); + if (!(await stripeSubscriptionModel.edit({ cancel_at_period_end: 1 }, subscription.id))) { + throw new Error('Internal Error: Error suspending subscription'); + } + }; + this.suspendLifetimeSubscription = async function (subscription) { + if (!(await stripeSubscriptionModel.edit({ cancel_at_period_end: 1 }, subscription.id))) { + throw new Error('Internal Error: Error suspending subscription'); + } + }; + + this.cancelLifetimeSubscription = async function (subscription) { + //TODO check if we refund on this or not + //we could make a fixed refund amount + //right now we just cancel it locally and refund is never as it is a onetime product thing. + let subscriptionEdited = await stripeSubscriptionModel.edit({ status: 5 }, parseInt(subscription.id)); + if (!subscriptionEdited) { + throw new Error("Couldn't edit subscription"); + } + let subscriptionLog = await stripeSubscriptionLogModel.getByFields({ subscription_id: parseInt(subscription.id), status: 1 }); + if (!subscriptionLog) { + throw new Error("Couldn't find relative active subscription log"); + } + let subscriptionLogEdited = await stripeSubscriptionLogModel.edit({ status: 0 }, subscriptionLog.id); + if (!subscriptionLogEdited) { + throw new Error("Couldn't Edit subscription log"); + } + return true; + }; + this.createCustomerWithoutCard = async function (params) { + let createdCustomer = await stripe.createCustomer(params); + + let userModelEntry = { + stripe_id: createdCustomer.id, + }; + + let modelEditedUser = await userModel.edit(userModelEntry, this.userID); + if (!modelEditedUser) { + throw new Error('Internal error: Error editing user stripe id'); + } + return modelEditedUser; + }; + this.createCustomer = async function (params) { + let createdCustomer = await stripe.createCustomer(params); + let userModelEntry = { + stripe_id: createdCustomer.id, + }; + let editedUserModel = await userModel.edit(userModelEntry, this.userID); + if (!editedUserModel) { + throw new Error('Error editing user stripe id'); + } + + let customerCardParams = { + customerId: createdCustomer.id, + cardId: createdCustomer.default_source, + }; + let card = await stripe.retrieveCard(customerCardParams); + + if (card) { + cardModelEntry = { + card_last: card.last4 ?? '', + card_brand: card.brand ?? '', + card_exp_month: card.exp_month ?? '', + exp_year: card.exp_year ?? '', + card_name: createdCustomer.metadata.card_name ?? '', + stripe_card_customer: card.customer, + stripe_card_id: card.id, + is_default: createdCustomer.metadata.is_default, + user_id: this.userID ?? null, + role_id: this.roleID ?? null, + }; + var modelCreatedCard = await stripeCardModel.insert(cardModelEntry); + if (!modelCreatedCard) { + throw new Error('Internal error: Error adding card'); + } + } + return modelCreatedCard; + }; + + this.adminCreateProductPrice = async function (productStripeId, productLocalId, price) { + let priceArgs = { + unit_amount: helpers.convertToCents(price), + currency: this.currency, + product: productStripeId, + }; + let priceCreated = await stripe.createPrice(priceArgs); + + let productModelEditEntry = { + price, + price_stripe_id: priceCreated.id, + }; + let modelEditedProduct = await stripeProductModel.edit(productModelEditEntry, productLocalId); + if (!modelEditedProduct) { + throw new Error('Internal Error: error setting price'); + } + return priceCreated; + }; + + this._createStripeService = async function (params) { + let serviceParams = { + name: params.name, + description: params.description, + url: params.url, + images: params.image ? [params.image] : [], + active: parseInt(params.status) === 1 ? true : false, + }; + + return await stripe.createProduct(serviceParams); + }; + this._createStripeProduct = async function (params) { + let productParams = { + name: params.name, + active: parseInt(params.status) === 1 ? true : false, + images: params.images ? [params.images] : [], + description: params.description, + shippable: parseInt(params.shippable) === 1 ? true : false, + unit_label: params.unit_label, + statement_descriptor: params.statement_descriptor, + }; + + return await stripe.createProduct(productParams); + }; + + /** + * [adminCreateProduct allows an admin to create a physical, digital goods or services] + * @param {object} params [object that contain needed parameters to create a said product or service] + * @param {strine} type [string that represents the type of the product] + * @return {object} [product or service stripe id as well as product or service local id and if a product it also returns the price object stripe id] + */ + this.adminCreateProduct = async function (params, type) { + if (!params.name) { + throw new Error('Must provide a name for your product'); + } + if (!type) { + throw new Error('Must provide a type for your product'); + } + if (type === 'PRODUCT') { + var createdStripeProduct = await this._createStripeProduct(params); + let productModelEntry = { + stripe_id: createdStripeProduct.id, + name: createdStripeProduct.name, + status: createdStripeProduct.active === true ? 1 : 0, + description: createdStripeProduct.description ?? '', + images: createdStripeProduct.images?.length > 0 ? createdStripeProduct.images[0] : '', + shippable: createdStripeProduct.shippable ?? 0, + unit_label: createdStripeProduct.unit_label ?? '', + statement_descriptor: createdStripeProduct.statement_descriptor ?? '', + }; + + let modelCreatedServiceId = await stripeProductModel.insert(productModelEntry); + let product = await stripeProductModel.getByPK(modelCreatedServiceId); + + return { + productStripeId: product.stripe_id, + productLocalId: product.id, + }; + } else if (type === 'SERVICE') { + var createdStripeService = await this._createStripeService(params); + + let serviceModelEntry = { + name: createdStripeService.name, + stripe_id: createdStripeService.id, + status: createdStripeService.active === true ? 1 : 0, + image: createdStripeService.images.length > 0 ? createdStripeService.images[0] : '', + url: createdStripeService.url ?? '', + description: createdStripeService.description ?? '', + }; + let modelCreatedServiceId = await stripeServiceModel.insert(serviceModelEntry); + let service = await stripeServiceModel.getByPK(modelCreatedServiceId); + + return { + serviceStripeId: service.stripe_id, + serviceLocalId: service.id, + }; + } + + throw new Error('Missing plan type parameter.'); + }; + this.reactivateRegularSubscription = async function (subscription) { + let updateParams = { + subscriptionId: subscription.stripe_id, + params: { + cancel_at_period_end: false, + }, + }; + await stripe.updateSubscription(updateParams); + if (!(await stripeSubscriptionModel.edit({ cancel_at_period_end: 0 }, subscription.id))) { + throw new Error('Internal Error: Error reactivating subscription'); + } + }; + this.reactivateLifetimeSubscription = async function (subscription) { + if (!(await stripeSubscriptionModel.edit({ cancel_at_period_end: 0 }, subscription.id))) { + throw new Error('Internal Error: Error reactivating subscription'); + } + }; + /** + * [adminUpdateService allows an admin to update certain field of a service] + * @param {object} params [object that contain parameters to be edited] + * @param {integer} serviceId [integer that represents service local primary key (id) in database] + * @return {object} [return updated service object] + */ + this.adminUpdateService = async function (params, serviceId) { + let service = await stripeServiceModel.getByPK(serviceId); + + await stripe.updateProduct({ productId: service.stripe_id, params }); + let updateParams = { + name: params.name, + status: params.active ? 1 : 0, + }; + let updatedService = await stripeServiceModel.edit(updateParams, serviceId); + if (!updatedService) { + throw new Error('Internal Error: Error editing service'); + } + return updatedService; + }; + /** + * [adminUpdateProduct allows an admin to update certain field of a product] + * @param {object} params [object that contain parameters to be edited] + * @param {integer} productId [integer that represents product local primary key (id) in database] + * @return {object} [return updated product object] + */ + this.adminUpdateProduct = async function (params, productId) { + let product = await stripeProductModel.getByPK(productId); + + await stripe.updateProduct({ productId: product.stripe_id, params }); + let updateParams = { + name: params.name, + status: params.active ? 1 : 0, + }; + let updatedProduct = await stripeProductModel.edit(updateParams, productId); + if (!updatedProduct) { + throw new Error('Internal Error: Error editing product'); + } + return updatedProduct; + }; + /** + * [adminCreateRegularPlan allows an admin to create subscription plan through admin portal] + * @param {object} params [object that contain plan parameters] + * @param {integer} planType [integer that represent plan type in relative to stripe plans table] @see /models/stripe_plans.js type_mapping() + * @param {integer} localProductId [integer that represent product id in relative to stripe products table] + * @return {integer} [the id of the created plan in database] + */ + this.adminCreateRegularPlan = async function (params, planType, localServiceId) { + if (!params.interval) { + throw new Error('Must have a recurring parameter with interval value set'); + } + if (!params.nickname) { + throw new Error('Must have a display name'); + } + if (!localServiceId) { + throw new Error('Must provide system product id'); + } + if (planType === null || undefined) { + throw new Error('Must provide plan type'); + } + + let service = await stripeServiceModel.getByPK(localServiceId); + + let stripePlanCreated = await this._createStripeRegularPlan(params, service); + + let planModelEntry = { + nickname: stripePlanCreated.nickname, + stripe_id: stripePlanCreated.id, + stripe_product_id: stripePlanCreated.product, + amount: stripePlanCreated.unit_amount / 100, + interval: helpers.getMappingKey(stripePlanModel.interval_mapping, stripePlanCreated.recurring.interval), + interval_count: stripePlanCreated.recurring.interval_count, + trial_period_days: stripePlanCreated.recurring.trial_period_days ?? 0, + service_id: localServiceId, + status: stripePlanCreated.active === true ? 1 : 0, + type: parseInt(planType), + }; + + let modelCreatedPlan = await stripePlanModel.insert(planModelEntry); + + if (!modelCreatedPlan) { + throw new Error('Internal error: error creating plan'); + } + return modelCreatedPlan; + }; + + this._createStripeRegularPlan = async function (params, service) { + let stripeSubscriptionPlanParams = { + nickname: params.nickname, + currency: this.currency, + unit_amount: helpers.convertToCents(params.amount), + product: service.stripe_id, + recurring: { + interval: stripePlanModel.interval_mapping()[params.interval], + interval_count: params.interval_count, + trial_period_days: params.trial_period_days, + }, + active: parseInt(params.status) === 1 ? true : false, + }; + return await stripe.createPrice(stripeSubscriptionPlanParams); + }; + this._createStripeLifetimePlan = async function (params, service) { + //stripe doesn't have lifetime plans + //how it works is a price is created with no recurring parameter as a single time product + //which acts and dealt with internally within our system as a lifetime plan. + let stripeSubscriptionPlanParams = { + nickname: params.nickname, + currency: this.currency, + unit_amount: helpers.convertToCents(params.amount), + product: service.stripe_id, + active: parseInt(params.status) === 1 ? true : false, + }; + return await stripe.createPrice(stripeSubscriptionPlanParams); + }; + this._createStripeTrialOnlyPlan = async function (params, service) { + let trialOnlyPlanParams = { + nickname: params.nickname, + currency: this.currency, + unit_amount: helpers.convertToCents(params.amount), + recurring: { + interval: stripePlanModel.interval_mapping()[params.interval], + interval_count: params.interval_count, + }, + product: service.stripe_id, + active: parseInt(params.status) === 1 ? true : false, + }; + return await stripe.createPrice(trialOnlyPlanParams); + }; + this._deactivateStripeLifetimePlan = async function (planStripeId) { + //stripe doesn't allow deleting a price. will be set to unactive instead + return await stripe.updatePrice({ priceId: planStripeId, params: { active: false } }); + }; + + this.adminCreateLifetimePlan = async function (params, planType, localServiceId) { + if (!params.nickname) { + throw new Error('Must have a display name'); + } + if (!localServiceId) { + throw new Error('Must provide system product id'); + } + if (planType === null || undefined) { + throw new Error('Must provide plan type'); + } + if (parseInt(params.interval) !== 4) { + throw new Error('Interval must be "forever".'); + } + + let service = await stripeServiceModel.getByPK(localServiceId); + let stripePlanCreated = await this._createStripeLifetimePlan(params, service); + + let planModelEntry = { + stripe_product_id: stripePlanCreated.product ?? '', + stripe_id: stripePlanCreated.id ?? '', + amount: stripePlanCreated.unit_amount / 100, + interval: 4, + interval_count: null, + trial_period_days: null, + nickname: stripePlanCreated.nickname ?? '', + service_id: localServiceId, + status: stripePlanCreated.active === true ? 1 : 0, + type: parseInt(planType), + }; + + let modelCreatedPlan = await stripePlanModel.insert(planModelEntry); + if (!modelCreatedPlan) { + throw new Error('Internal error: error creating plan'); + } + + return modelCreatedPlan; + }; + + this.adminCreateTrialPlan = async function (params, planType, localServiceId) { + if (!params.interval) { + throw new Error('Must have a recurring parameter with interval value set'); + } + if (!params.nickname) { + throw new Error('Must have a display name'); + } + if (!localServiceId) { + throw new Error('Must provide system product id'); + } + if (planType === null || undefined) { + throw new Error('Must provide plan type'); + } + + let service = await stripeServiceModel.getByPK(localServiceId); + let priceCreated = await this._createStripeTrialOnlyPlan(params, service); + + let planModelEntry = { + stripe_product_id: priceCreated.product, + stripe_id: priceCreated.id, + amount: priceCreated.unit_amount / 100, + interval: helpers.getMappingKey(stripePlanModel.interval_mapping, priceCreated.recurring.interval), + interval_count: priceCreated.recurring.interval_count, + trial_period_days: priceCreated.recurring.trial_period_days ?? 0, + nickname: priceCreated.nickname, + service_id: localServiceId, + status: priceCreated.active ? 1 : 0, + type: parseInt(planType), + }; + let modelCreatedPlan = await stripePlanModel.insert(planModelEntry); + if (!modelCreatedPlan) { + throw new Error('Internal error: error creating plan'); + } + return modelCreatedPlan; + }; + + this.adminEditPlan = async function (params, price) { + await stripe.updatePrice({ priceId: price.stripe_id, params }); + let updateParams = { + nickname: params.nickname, + status: params.active ? 1 : 0, + }; + let updatedPrice = await stripePlanModel.edit(updateParams, price.id); + if (!updatedPrice) { + throw new Error('Internal error: error editing plan'); + } + return true; + }; + this.adminCancelSubscription = async function (subscriptionId) { + let subscriptionToCancel = await stripeSubscriptionModel.getByPK(subscriptionId); + let subscriptionLog = await stripeSubscriptionLogModel.getByFields({ subscription_id: subscriptionId }); + let subscriptionPlan = await stripePlanModel.getByPK(subscriptionToCancel.plan_id); + if (!subscriptionToCancel || !subscriptionPlan) { + throw new Error('No subscription or plan of that id'); + } + let subscirptionType = subscriptionPlan.type; + + switch (subscirptionType) { + case 0: + case 3: + case 4: + let cancelSubscriptionParams = { + subscriptionId: subscriptionToCancel.stripe_id, + params: { + prorate: this.prorate == 'true' ? true : false, + invoice_now: true, + }, + }; + let subscriptionCanceled = await stripe.cancelSubscription(cancelSubscriptionParams); + let localCancellationParams = { + status: helpers.getMappingKey(stripeSubscriptionModel.status_mapping, subscriptionCanceled.status), + }; + await stripeSubscriptionModel.edit(localCancellationParams, subscriptionId); + await stripeSubscriptionLogModel.edit({ status: 0 }, subscriptionLog.id); + return subscriptionCanceled; + case 1: + case 2: + await stripeSubscriptionModel.edit({ status: 5 }, subscriptionId); + await stripeSubscriptionLogModel.edit({ status: 0 }, subscriptionLog.id); + default: + throw new Error('Something wrong'); + } + return true; + }; + this.userAddCard = async function (cardParams) { + let createdCard = await stripe.createCard(cardParams); + + if (createdCard) { + if (createdCard.metadata.is_default == '1') { + let customerUpdateParams = { + customerId: createdCard.customer, + params: { default_source: createdCard.id }, + }; + await stripe.updateCustomer(customerUpdateParams); + let defaultCards = await stripeCardModel.getAll({ is_default: 1 }); + if (defaultCards.length > 0) { + defaultCards.forEach(async (card) => { + await stripeCardModel.edit({ is_default: 0 }, card.id); + }); + } + } + cardModelEntry = { + card_last: createdCard.last4 ?? '', + card_brand: createdCard.brand ?? '', + card_exp_month: createdCard.exp_month ?? '', + exp_year: createdCard.exp_year ?? '', + card_name: createdCard.metadata.card_name ?? '', + stripe_card_customer: createdCard.customer, + stripe_card_id: createdCard.id, + is_default: createdCard.metadata.is_default, + user_id: this.userID ?? null, + role_id: this.roleID ?? null, + }; + var modelCreatedCard = await stripeCardModel.insert(cardModelEntry); + if (!modelCreatedCard) { + throw new Error('Internal error: Error adding card'); + } + } + return modelCreatedCard; + }; + this.adminCreateCoupon = async function (params) { + helpers.checkFor({ name: params.name, duration: params.duration, usage_limit: params.usage_limit, amount: params.amount, amount_type: params.amount_type }); + + let couponStripeParams = { + name: params.name, + duration: stripeCouponModel.duration_mapping()[params.duration].toLowerCase(), + max_redemptions: params.usage_limit, + metadata: { + slug: params.slug, + }, + }; + switch (params.amount_type) { + case '0': { + if (params.amount > 100) { + throw new Error("Percentage can't be over 100"); + } + couponStripeParams['percent_off'] = params.amount; + break; + } + case '1': { + couponStripeParams['amount_off'] = helpers.convertToCents(params.amount); + couponStripeParams['currency'] = this.currency; + break; + } + } + const coupon = await stripe.createCoupon(couponStripeParams); + + let couponModelEntry = { + stripe_id: coupon.id, + name: coupon.name, + slug: coupon.metadata.slug, + duration: helpers.getMappingKey(stripeCouponModel.duration_mapping, coupon.duration), + usage_limit: coupon.max_redemptions, + amount: coupon.percent_off ?? helpers.convertFromCents(coupon.amount_off), + amount_type: coupon.percent_off ? 0 : 1, + current_usage_limit: coupon.max_redemptions, + status: helpers.getMappingKey(stripeCouponModel.status_mapping, 'active'), + }; + let localCoupon = await stripeCouponModel.insert(couponModelEntry); + if (!localCoupon) { + throw new Error('Internal error: Error adding coupon'); + } + return localCoupon; + }; + this.createSession = async function (params) { + let productID = params.product_id; + + let user = await userModel.getByPK(this.userID); + let price = await stripeProductModel.getByPK(productID); + params = { + success_url: `${process.env.BASE_URL}/member/checkout/item/completed`, + cancel_url: `${process.env.BASE_URL}/member/checkout/item/cancelled`, + payment_method_types: ['card'], + mode: 'payment', + line_items: [{ price: price.price_stripe_id, quantity: 1 }], + customer: user.stripe_id, + payment_intent_data: { + setup_future_usage: 'on_session', + }, + }; + let session = await stripe.createSession(params); + + let sessionModelEntry = { + object: session.object, + stripe_id: session.id, + amount_total: helpers.convertFromCents(session.amount_total), + payment_intent: session.payment_intent, + payment_method_types: JSON.stringify(session.payment_method_types), + currency: session.currency, + user_id: this.userID, + role_id: this.roleID, + status: helpers.getMappingKey(stripeCheckoutSessionModel.status_mapping, session.payment_status), + }; + + let createdLocalSession = await stripeCheckoutSessionModel.insert(sessionModelEntry); + if (!createdLocalSession) { + throw new Error('Internal error: Error creating session'); + } + return session; + }; + this.refundInvoice = async function (invoiceID) { + let localInvoice = await stripeInvoiceModel.getByPK(invoiceID); + + let localPayment = await stripePaymentModel.getByFields({ stripe_id: localInvoice.charge_stripe_id }); + + let params = { + charge: localInvoice.charge_stripe_id, + amount: helpers.convertToCents(localInvoice.amount_paid), + }; + let refunded = await stripe.createRefund(params); + let refundModelEntry = { + stripe_id: refunded.id, + stripe_invoice_id: localInvoice.stripe_id, + charge_stripe_id: refunded.charge, + payment_intent: refunded.payment_intent, + amount: helpers.convertFromCents(refunded.amount), + balance_transaction: refunded.balance_transaction, + reason: refunded.reason ?? '', + status: helpers.getMappingKey(stripeRefundModel.status_mapping, refunded.status), + receipt_number: refunded.receipt_number, + }; + let createdRefund = await stripeRefundModel.insert(refundModelEntry); + if (!createdRefund) { + throw new Error('Internal error: Error creating refund'); + } + + let yesIndex = helpers.getMappingKey(stripeInvoiceModel.refunded_mapping, 'Yes'); + + let editedInvoice = await stripeInvoiceModel.edit({ refunded: yesIndex }, localInvoice.id); + if (!editedInvoice) { + throw new Error('Internal error: Error editing invoice'); + } + + let editedPayment = await stripePaymentModel.edit({ refunded: yesIndex }, localPayment.id); + if (!editedPayment) { + throw new Error('Internal error: Error editing payment'); + } + + return; + }; +} diff --git a/services/UploadService.js b/services/UploadService.js new file mode 100644 index 0000000..df1ad34 --- /dev/null +++ b/services/UploadService.js @@ -0,0 +1,62 @@ +const path = require('path'); +const aws = require('aws-sdk'); +const multer = require('multer'); +const multerS3 = require('multer-s3'); +const { createDirectoriesRecursiveV2 } = require('./../core/helpers'); + +module.exports = { + upload: function (location) { + if (process.env.NODE_ENV === 'production') { + return this.s3_upload(location); + } else { + return this.local_upload(''); + } + }, + s3_upload: function (location) { + try { + aws.config.update({ + accessKeyId: process.env.DYNAMIC_CONFIG_AWS_KEY, + secretAccessKey: process.env.DYNAMIC_CONFIG_AWS_SECRET, + region: process.env.DYNAMIC_CONFIG_AWS_REGION, + }); + + const s3 = new aws.S3(); + + const upload = multer({ + storage: multerS3({ + s3: s3, + bucket: process.env.DYNAMIC_CONFIG_AWS_BUCKET, + acl: 'public-read', + contentType: multerS3.AUTO_CONTENT_TYPE, + key: function (req, file, cb) { + cb(null, location + file.originalname); + }, + }), + }); + + return upload; + } catch (error) { + console.log('s3_upload => ', error); + } + }, + local_upload: function () { + try { + const storage = multer.diskStorage({ + destination: function (req, file, cb) { + createDirectoriesRecursiveV2(path.join(__dirname, '..', 'public', 'uploads')); + cb(null, path.join(__dirname, '..', 'public', 'uploads')); + }, + filename: function (req, file, cb) { + const fileName = file.filename ?? file.originalname; + cb(null, Date.now() + '-' + fileName); + }, + }); + + const upload = multer({ storage: storage }); + + return upload; + } catch (error) { + console.log('local_upload => ', error); + } + }, +}; diff --git a/services/ValidationService.js b/services/ValidationService.js new file mode 100644 index 0000000..bf60bc8 --- /dev/null +++ b/services/ValidationService.js @@ -0,0 +1,85 @@ +const { Validator, addCustomMessages } = require('node-input-validator'); + +// {fieldName:message} eg:{email:"Invalid Email", password:"Password too short"} +const formatValidationError = (error) => { + const formatted = Object.entries(error) + .map(([key, value]) => ({ + field: key, + message: value.message, + })) + .reduce((accumulator, currentValue) => { + if (!accumulator[currentValue]) { + accumulator[currentValue.field] = currentValue.message; + } + return accumulator; + }, {}); + return formatted; +}; + +module.exports = { + /** + * Input Validator middleware for controller + * @param {object} validationObject object defining body fields and its validation types eg:{email:required|email} + * @param {object} _extendMessages object defining message to throw on validation error eg: {"email.required":"Email is required","email.email":"Invalid email"} + * + */ + validateInput: (validationObject = {}, _extendMessages = {}) => async ( + req, + res, + next, + ) => { + const validation = new Validator(req.body, validationObject); + addCustomMessages(_extendMessages); + + try { + const isValid = await validation.check(); + if (!isValid) { + req.validationError = formatValidationError(validation.errors); + } + return next(); + } catch (error) { + req.validationError = error.message; + return next(); + } + }, + + handleValidationErrorForViews: ( + req, + res, + viewModel, + viewPath = '/', + fieldsStoreKey, + defaultValue = {}, + ) => { + const validationError = req.validationError; + + if (validationError) { + // Remembers fields if validation error occurs + Object.entries(defaultValue).forEach(([key, value]) => { + viewModel[fieldsStoreKey][key] = value; + }); + + if (typeof validationError === 'string') { + viewModel.error = validationError; + } else { + viewModel.validationError = req.validationError; + } + return res.render(viewPath, viewModel); + } + }, + + handleValidationErrorForAPI: (req, res, next) => { + const validationError = req.validationError; + + if (validationError) { + let error; + if (typeof validationError === 'string') { + error = validationError; + } else { + error = req.validationError; + } + return res.json({ success: false, error }); + } + next(); + }, +}; diff --git a/services/paypal/paypalProductsCategories.json b/services/paypal/paypalProductsCategories.json new file mode 100644 index 0000000..01fb43b --- /dev/null +++ b/services/paypal/paypalProductsCategories.json @@ -0,0 +1,449 @@ +{ + "categories": { + "ACADEMIC_SOFTWARE": "Academic Software", + "ACCESSORIES": "Accessories", + "ACCOUNTING": "Accounting", + "ADULT": "Adult", + "ADVERTISING": "Advertising", + "AFFILIATED_AUTO_RENTAL": "Affiliated Auto Rental", + "AGENCIES": "Agencies", + "AGGREGATORS": "Aggregators", + "AGRICULTURAL_COOPERATIVE_FOR_MAIL_ORDER": "Agricultural Cooperative for Mail Order", + "AIR_CARRIERS_AIRLINES": "Air Carriers, Airlines", + "AIRLINES": "Airlines", + "AIRPORTS_FLYING_FIELDS": "Airports, Flying Fields", + "ALCOHOLIC_BEVERAGES": "Alcoholic Beverages", + "AMUSEMENT_PARKS_CARNIVALS": "Amusement Parks/Carnivals", + "ANIMATION": "Animation", + "ANTIQUES": "Antiques", + "APPLIANCES": "Appliances", + "AQUARIAMS_SEAQUARIUMS_DOLPHINARIUMS": "Aquariams Seaquariums Dolphinariums", + "ARCHITECTURAL_ENGINEERING_AND_SURVEYING_SERVICES": "Architectural,Engineering,And Surveying Services", + "ART_AND_CRAFT_SUPPLIES": "Art & Craft Supplies", + "ART_DEALERS_AND_GALLERIES": "Art dealers and galleries", + "ARTIFACTS_GRAVE_RELATED_AND_NATIVE_AMERICAN_CRAFTS": "Artifacts, Grave related, and Native American Crafts", + "ARTS_AND_CRAFTS": "Arts and crafts", + "ARTS_CRAFTS_AND_COLLECTIBLES": "Arts, crafts, and collectibles", + "AUDIO_BOOKS": "Audio books", + "AUTO_ASSOCIATIONS_CLUBS": "Auto Associations/Clubs", + "AUTO_DEALER_USED_ONLY": "Auto dealer - used only", + "AUTO_RENTALS": "Auto Rentals", + "AUTO_SERVICE": "Auto service", + "AUTOMATED_FUEL_DISPENSERS": "Automated Fuel Dispensers", + "AUTOMOBILE_ASSOCIATIONS": "Automobile Associations", + "AUTOMOTIVE": "Automotive", + "AUTOMOTIVE_REPAIR_SHOPS_NON_DEALER": "Automotive Repair Shops - Non-Dealer", + "AUTOMOTIVE_TOP_AND_BODY_SHOPS": "Automotive Top And Body Shops", + "AVIATION": "Aviation", + "BABIES_CLOTHING_AND_SUPPLIES": "Babies Clothing & Supplies", + "BABY": "Baby", + "BANDS_ORCHESTRAS_ENTERTAINERS": "Bands,Orchestras,Entertainers", + "BARBIES": "Barbies", + "BATH_AND_BODY": "Bath and body", + "BATTERIES": "Batteries", + "BEAN_BABIES": "Bean Babies", + "BEAUTY": "Beauty", + "BEAUTY_AND_FRAGRANCES": "Beauty and fragrances", + "BED_AND_BATH": "Bed & Bath", + "BICYCLE_SHOPS_SALES_AND_SERVICE": "Bicycle Shops-Sales And Service", + "BICYCLES_AND_ACCESSORIES": "Bicycles & Accessories", + "BILLIARD_POOL_ESTABLISHMENTS": "Billiard/Pool Establishments", + "BOAT_DEALERS": "Boat Dealers", + "BOAT_RENTALS_AND_LEASING": "Boat Rentals And Leasing", + "BOATING_SAILING_AND_ACCESSORIES": "Boating, sailing and accessories", + "BOOKS": "Books", + "BOOKS_AND_MAGAZINES": "Books and magazines", + "BOOKS_MANUSCRIPTS": "Books, Manuscripts", + "BOOKS_PERIODICALS_AND_NEWSPAPERS": "Books, Periodicals And Newspapers", + "BOWLING_ALLEYS": "Bowling Alleys", + "BULLETIN_BOARD": "Bulletin board", + "BUS_LINE": "Bus line", + "BUS_LINES_CHARTERS_TOUR_BUSES": "Bus Lines,Charters,Tour Buses", + "BUSINESS": "Business", + "BUSINESS_AND_SECRETARIAL_SCHOOLS": "Business and secretarial schools", + "BUYING_AND_SHOPPING_SERVICES_AND_CLUBS": "Buying And Shopping Services And Clubs", + "CABLE_SATELLITE_AND_OTHER_PAY_TELEVISION_AND_RADIO_SERVICES": "Cable,Satellite,And Other Pay Television And Radio Services", + "CABLE_SATELLITE_AND_OTHER_PAY_TV_AND_RADIO": "Cable, satellite, and other pay TV and radio", + "CAMERA_AND_PHOTOGRAPHIC_SUPPLIES": "Camera and photographic supplies", + "CAMERAS": "Cameras", + "CAMERAS_AND_PHOTOGRAPHY": "Cameras & Photography", + "CAMPER_RECREATIONAL_AND_UTILITY_TRAILER_DEALERS": "Camper,Recreational And Utility Trailer Dealers", + "CAMPING_AND_OUTDOORS": "Camping and outdoors", + "CAMPING_AND_SURVIVAL": "Camping & Survival", + "CAR_AND_TRUCK_DEALERS": "Car And Truck Dealers", + "CAR_AND_TRUCK_DEALERS_USED_ONLY": "Car And Truck Dealers - Used Only", + "CAR_AUDIO_AND_ELECTRONICS": "Car Audio & Electronics", + "CAR_RENTAL_AGENCY": "Car rental agency", + "CATALOG_MERCHANT": "Catalog Merchant", + "CATALOG_RETAIL_MERCHANT": "Catalog/Retail Merchant", + "CATERING_SERVICES": "Catering services", + "CHARITY": "Charity", + "CHECK_CASHIER": "Check Cashier", + "CHILD_CARE_SERVICES": "Child Care Services", + "CHILDREN_BOOKS": "Children Books", + "CHIROPODISTS_PODIATRISTS": "Chiropodists/Podiatrists", + "CHIROPRACTORS": "Chiropractors", + "CIGAR_STORES_AND_STANDS": "Cigar Stores And Stands", + "CIVIC_SOCIAL_FRATERNAL_ASSOCIATIONS": "Civic, Social, Fraternal Associations", + "CIVIL_SOCIAL_FRAT_ASSOCIATIONS": "Civil/Social/Frat Associations", + "CLOTHING": "Clothing", + "CLOTHING_ACCESSORIES_AND_SHOES": "Clothing, accessories, and shoes", + "CLOTHING_RENTAL": "Clothing Rental", + "COFFEE_AND_TEA": "Coffee and tea", + "COIN_OPERATED_BANKS_AND_CASINOS": "Coin Operated Banks & Casinos", + "COLLECTIBLES": "Collectibles", + "COLLECTION_AGENCY": "Collection agency", + "COLLEGES_AND_UNIVERSITIES": "Colleges and universities", + "COMMERCIAL_EQUIPMENT": "Commercial Equipment", + "COMMERCIAL_FOOTWEAR": "Commercial Footwear", + "COMMERCIAL_PHOTOGRAPHY": "Commercial photography", + "COMMERCIAL_PHOTOGRAPHY_ART_AND_GRAPHICS": "Commercial photography, art, and graphics", + "COMMERCIAL_SPORTS_PROFESSIONA": "Commercial Sports/Professiona", + "COMMODITIES_AND_FUTURES_EXCHANGE": "Commodities and futures exchange", + "COMPUTER_AND_DATA_PROCESSING_SERVICES": "Computer and data processing services", + "COMPUTER_HARDWARE_AND_SOFTWARE": "Computer Hardware & Software", + "COMPUTER_MAINTENANCE_REPAIR_AND_SERVICES_NOT_ELSEWHERE_CLAS": "Computer Maintenance, Repair And Services Not Elsewhere Clas", + "CONSTRUCTION": "Construction", + "CONSTRUCTION_MATERIALS_NOT_ELSEWHERE_CLASSIFIED": "Construction Materials Not Elsewhere Classified", + "CONSULTING_SERVICES": "Consulting services", + "CONSUMER_CREDIT_REPORTING_AGENCIES": "Consumer Credit Reporting Agencies", + "CONVALESCENT_HOMES": "Convalescent Homes", + "COSMETIC_STORES": "Cosmetic Stores", + "COUNSELING_SERVICES_DEBT_MARRIAGE_PERSONAL": "Counseling Services--Debt,Marriage,Personal", + "COUNTERFEIT_CURRENCY_AND_STAMPS": "Counterfeit Currency and Stamps", + "COUNTERFEIT_ITEMS": "Counterfeit Items", + "COUNTRY_CLUBS": "Country Clubs", + "COURIER_SERVICES": "Courier services", + "COURIER_SERVICES_AIR_AND_GROUND_AND_FREIGHT_FORWARDERS": "Courier Services-Air And Ground,And Freight Forwarders", + "COURT_COSTS_ALIMNY_CHILD_SUPT": "Court Costs/Alimny/Child Supt", + "COURT_COSTS_INCLUDING_ALIMONY_AND_CHILD_SUPPORT_COURTS_OF_LAW": "Court Costs, Including Alimony and Child Support - Courts of Law", + "CREDIT_CARDS": "Credit Cards", + "CREDIT_UNION": "Credit union", + "CULTURE_AND_RELIGION": "Culture & Religion", + "DAIRY_PRODUCTS_STORES": "Dairy Products Stores", + "DANCE_HALLS_STUDIOS_AND_SCHOOLS": "Dance Halls,Studios,And Schools", + "DECORATIVE": "Decorative", + "DENTAL": "Dental", + "DENTISTS_AND_ORTHODONTISTS": "Dentists And Orthodontists", + "DEPARTMENT_STORES": "Department Stores", + "DESKTOP_PCS": "Desktop PCs", + "DEVICES": "Devices", + "DIECAST_TOYS_VEHICLES": "Diecast, Toys Vehicles", + "DIGITAL_GAMES": "Digital games", + "DIGITAL_MEDIA_BOOKS_MOVIES_MUSIC": "Digital media,books,movies,music", + "DIRECT_MARKETING": "Direct Marketing", + "DIRECT_MARKETING_CATALOG_MERCHANT": "Direct Marketing - Catalog Merchant", + "DIRECT_MARKETING_INBOUND_TELE": "Direct Marketing - Inbound Tele", + "DIRECT_MARKETING_OUTBOUND_TELE": "Direct Marketing - Outbound Tele", + "DIRECT_MARKETING_SUBSCRIPTION": "Direct Marketing - Subscription", + "DISCOUNT_STORES": "Discount Stores", + "DOOR_TO_DOOR_SALES": "Door-To-Door Sales", + "DRAPERY_WINDOW_COVERING_AND_UPHOLSTERY": "Drapery, window covering, and upholstery", + "DRINKING_PLACES": "Drinking Places", + "DRUGSTORE": "Drugstore", + "DURABLE_GOODS": "Durable goods", + "ECOMMERCE_DEVELOPMENT": "eCommerce Development", + "ECOMMERCE_SERVICES": "eCommerce Services", + "EDUCATIONAL_AND_TEXTBOOKS": "Educational and textbooks", + "ELECTRIC_RAZOR_STORES": "Electric Razor Stores", + "ELECTRICAL_AND_SMALL_APPLIANCE_REPAIR": "Electrical and small appliance repair", + "ELECTRICAL_CONTRACTORS": "Electrical Contractors", + "ELECTRICAL_PARTS_AND_EQUIPMENT": "Electrical Parts and Equipment", + "ELECTRONIC_CASH": "Electronic Cash", + "ELEMENTARY_AND_SECONDARY_SCHOOLS": "Elementary and secondary schools", + "EMPLOYMENT": "Employment", + "ENTERTAINERS": "Entertainers", + "ENTERTAINMENT_AND_MEDIA": "Entertainment and media", + "EQUIP_TOOL_FURNITURE_AND_APPLIANCE_RENTAL_AND_LEASING": "Equip, Tool, Furniture, And Appliance Rental And Leasing", + "ESCROW": "Escrow", + "EVENT_AND_WEDDING_PLANNING": "Event & Wedding Planning", + "EXERCISE_AND_FITNESS": "Exercise and fitness", + "EXERCISE_EQUIPMENT": "Exercise Equipment", + "EXTERMINATING_AND_DISINFECTING_SERVICES": "Exterminating and disinfecting services", + "FABRICS_AND_SEWING": "Fabrics & Sewing", + "FAMILY_CLOTHING_STORES": "Family Clothing Stores", + "FASHION_JEWELRY": "Fashion jewelry", + "FAST_FOOD_RESTAURANTS": "Fast Food Restaurants", + "FICTION_AND_NONFICTION": "Fiction and nonfiction", + "FINANCE_COMPANY": "Finance company", + "FINANCIAL_AND_INVESTMENT_ADVICE": "Financial and investment advice", + "FINANCIAL_INSTITUTIONS_MERCHANDISE_AND_SERVICES": "Financial Institutions - Merchandise And Services", + "FIREARM_ACCESSORIES": "Firearm accessories", + "FIREARMS_WEAPONS_AND_KNIVES": "Firearms, Weapons and Knives", + "FIREPLACE_AND_FIREPLACE_SCREENS": "Fireplace, and fireplace screens", + "FIREWORKS": "Fireworks", + "FISHING": "Fishing", + "FLORISTS": "Florists", + "FLOWERS": "Flowers", + "FOOD_DRINK_AND_NUTRITION": "Food, Drink & Nutrition", + "FOOD_PRODUCTS": "Food Products", + "FOOD_RETAIL_AND_SERVICE": "Food retail and service", + "FRAGRANCES_AND_PERFUMES": "Fragrances and perfumes", + "FREEZER_AND_LOCKER_MEAT_PROVISIONERS": "Freezer and Locker Meat Provisioners", + "FUEL_DEALERS_FUEL_OIL_WOOD_AND_COAL": "Fuel Dealers-Fuel Oil, Wood & Coal", + "FUEL_DEALERS_NON_AUTOMOTIVE": "Fuel Dealers - Non Automotive", + "FUNERAL_SERVICES_AND_CREMATORIES": "Funeral Services & Crematories", + "FURNISHING_AND_DECORATING": "Furnishing & Decorating", + "FURNITURE": "Furniture", + "FURRIERS_AND_FUR_SHOPS": "Furriers and Fur Shops", + "GADGETS_AND_OTHER_ELECTRONICS": "Gadgets & other electronics", + "GAMBLING": "Gambling", + "GAME_SOFTWARE": "Game Software", + "GAMES": "Games", + "GARDEN_SUPPLIES": "Garden supplies", + "GENERAL": "General", + "GENERAL_CONTRACTORS": "General contractors", + "GENERAL_GOVERNMENT": "General - Government", + "GENERAL_SOFTWARE": "General - Software", + "GENERAL_TELECOM": "General - Telecom", + "GIFTS_AND_FLOWERS": "Gifts and flowers", + "GLASS_PAINT_AND_WALLPAPER_STORES": "Glass,Paint,And Wallpaper Stores", + "GLASSWARE_CRYSTAL_STORES": "Glassware, Crystal Stores", + "GOVERNMENT": "Government", + "GOVERNMENT_IDS_AND_LICENSES": "Government IDs and Licenses", + "GOVERNMENT_LICENSED_ON_LINE_CASINOS_ON_LINE_GAMBLING": "Government Licensed On-Line Casinos - On-Line Gambling", + "GOVERNMENT_OWNED_LOTTERIES": "Government-Owned Lotteries", + "GOVERNMENT_SERVICES": "Government services", + "GRAPHIC_AND_COMMERCIAL_DESIGN": "Graphic & Commercial Design", + "GREETING_CARDS": "Greeting Cards", + "GROCERY_STORES_AND_SUPERMARKETS": "Grocery Stores & Supermarkets", + "HARDWARE_AND_TOOLS": "Hardware & Tools", + "HARDWARE_EQUIPMENT_AND_SUPPLIES": "Hardware, Equipment, and Supplies", + "HAZARDOUS_RESTRICTED_AND_PERISHABLE_ITEMS": "Hazardous, Restricted and Perishable Items", + "HEALTH_AND_BEAUTY_SPAS": "Health and beauty spas", + "HEALTH_AND_NUTRITION": "Health & Nutrition", + "HEALTH_AND_PERSONAL_CARE": "Health and personal care", + "HEARING_AIDS_SALES_AND_SUPPLIES": "Hearing Aids Sales and Supplies", + "HEATING_PLUMBING_AC": "Heating, Plumbing, AC", + "HIGH_RISK_MERCHANT": "High Risk Merchant", + "HIRING_SERVICES": "Hiring services", + "HOBBIES_TOYS_AND_GAMES": "Hobbies, Toys & Games", + "HOME_AND_GARDEN": "Home and garden", + "HOME_AUDIO": "Home Audio", + "HOME_DECOR": "Home decor", + "HOME_ELECTRONICS": "Home Electronics", + "HOSPITALS": "Hospitals", + "HOTELS_MOTELS_INNS_RESORTS": "Hotels/Motels/Inns/Resorts", + "HOUSEWARES": "Housewares", + "HUMAN_PARTS_AND_REMAINS": "Human Parts and Remains", + "HUMOROUS_GIFTS_AND_NOVELTIES": "Humorous Gifts & Novelties", + "HUNTING": "Hunting", + "IDS_LICENSES_AND_PASSPORTS": "IDs, licenses, and passports", + "ILLEGAL_DRUGS_AND_PARAPHERNALIA": "Illegal Drugs & Paraphernalia", + "INDUSTRIAL": "Industrial", + "INDUSTRIAL_AND_MANUFACTURING_SUPPLIES": "Industrial and manufacturing supplies", + "INSURANCE_AUTO_AND_HOME": "Insurance - auto and home", + "INSURANCE_DIRECT": "Insurance - Direct", + "INSURANCE_LIFE_AND_ANNUITY": "Insurance - life and annuity", + "INSURANCE_SALES_UNDERWRITING": "Insurance Sales/Underwriting", + "INSURANCE_UNDERWRITING_PREMIUMS": "Insurance Underwriting, Premiums", + "INTERNET_AND_NETWORK_SERVICES": "Internet & Network Services", + "INTRA_COMPANY_PURCHASES": "Intra-Company Purchases", + "LABORATORIES_DENTAL_MEDICAL": "Laboratories-Dental/Medical", + "LANDSCAPING": "Landscaping", + "LANDSCAPING_AND_HORTICULTURAL_SERVICES": "Landscaping And Horticultural Services", + "LAUNDRY_CLEANING_SERVICES": "Laundry, Cleaning Services", + "LEGAL": "Legal", + "LEGAL_SERVICES_AND_ATTORNEYS": "Legal services and attorneys", + "LOCAL_DELIVERY_SERVICE": "Local delivery service", + "LOCKSMITH": "Locksmith", + "LODGING_AND_ACCOMMODATIONS": "Lodging and accommodations", + "LOTTERY_AND_CONTESTS": "Lottery and contests", + "LUGGAGE_AND_LEATHER_GOODS": "Luggage and leather goods", + "LUMBER_AND_BUILDING_MATERIALS": "Lumber & Building Materials", + "MAGAZINES": "Magazines", + "MAINTENANCE_AND_REPAIR_SERVICES": "Maintenance and repair services", + "MAKEUP_AND_COSMETICS": "Makeup and cosmetics", + "MANUAL_CASH_DISBURSEMENTS": "Manual Cash Disbursements", + "MASSAGE_PARLORS": "Massage Parlors", + "MEDICAL": "Medical", + "MEDICAL_AND_PHARMACEUTICAL": "Medical & Pharmaceutical", + "MEDICAL_CARE": "Medical care", + "MEDICAL_EQUIPMENT_AND_SUPPLIES": "Medical equipment and supplies", + "MEDICAL_SERVICES": "Medical Services", + "MEETING_PLANNERS": "Meeting Planners", + "MEMBERSHIP_CLUBS_AND_ORGANIZATIONS": "Membership clubs and organizations", + "MEMBERSHIP_COUNTRY_CLUBS_GOLF": "Membership/Country Clubs/Golf", + "MEMORABILIA": "Memorabilia", + "MEN_AND_BOY_CLOTHING_AND_ACCESSORY_STORES": "Men's And Boy's Clothing And Accessory Stores", + "MEN_CLOTHING": "Men's Clothing", + "MERCHANDISE": "Merchandise", + "METAPHYSICAL": "Metaphysical", + "MILITARIA": "Militaria", + "MILITARY_AND_CIVIL_SERVICE_UNIFORMS": "Military and civil service uniforms", + "MISC_AUTOMOTIVE_AIRCRAFT_AND_FARM_EQUIPMENT_DEALERS": "Misc,Automotive,Aircraft,And Farm Equipment Dealers", + "MISC_GENERAL_MERCHANDISE": "Misc General Merchandise", + "MISCELLANEOUS_GENERAL_SERVICES": "Miscellaneous General Services", + "MISCELLANEOUS_REPAIR_SHOPS_AND_RELATED_SERVICES": "Miscellaneous Repair Shops And Related Services", + "MODEL_KITS": "Model Kits", + "MONEY_TRANSFER_MEMBER_FINANCIAL_INSTITUTION": "Money Transfer - Member Financial Institution", + "MONEY_TRANSFER_MERCHANT": "Money Transfer--Merchant", + "MOTION_PICTURE_THEATERS": "Motion Picture Theaters", + "MOTOR_FREIGHT_CARRIERS_AND_TRUCKING": "Motor Freight Carriers & Trucking", + "MOTOR_HOME_AND_RECREATIONAL_VEHICLE_RENTAL": "Motor Home And Recreational Vehicle Rental", + "MOTOR_HOMES_DEALERS": "Motor Homes Dealers", + "MOTOR_VEHICLE_SUPPLIES_AND_NEW_PARTS": "Motor Vehicle Supplies and New Parts", + "MOTORCYCLE_DEALERS": "Motorcycle Dealers", + "MOTORCYCLES": "Motorcycles", + "MOVIE": "Movie", + "MOVIE_TICKETS": "Movie tickets", + "MOVING_AND_STORAGE": "Moving and storage", + "MULTI_LEVEL_MARKETING": "Multi-level marketing", + "MUSIC_CDS_CASSETTES_AND_ALBUMS": "Music - CDs, cassettes and albums", + "MUSIC_STORE_INSTRUMENTS_AND_SHEET_MUSIC": "Music store - instruments and sheet music", + "NETWORKING": "Networking", + "NEW_AGE": "New Age", + "NEW_PARTS_AND_SUPPLIES_MOTOR_VEHICLE": "New parts and supplies - motor vehicle", + "NEWS_DEALERS_AND_NEWSTANDS": "News Dealers and Newstands", + "NON_DURABLE_GOODS": "Non-durable goods", + "NON_FICTION": "Non-Fiction", + "NON_PROFIT_POLITICAL_AND_RELIGION": "Non-Profit, Political & Religion", + "NONPROFIT": "Nonprofit", + "NOVELTIES": "Novelties", + "OEM_SOFTWARE": "Oem Software", + "OFFICE_SUPPLIES_AND_EQUIPMENT": "Office Supplies and Equipment", + "ONLINE_DATING": "Online Dating", + "ONLINE_GAMING": "Online gaming", + "ONLINE_GAMING_CURRENCY": "Online gaming currency", + "ONLINE_SERVICES": "online services", + "OOUTBOUND_TELEMARKETING_MERCH": "Ooutbound Telemarketing Merch", + "OPHTHALMOLOGISTS_OPTOMETRIST": "Ophthalmologists/Optometrist", + "OPTICIANS_AND_DISPENSING": "Opticians And Dispensing", + "ORTHOPEDIC_GOODS_PROSTHETICS": "Orthopedic Goods/Prosthetics", + "OSTEOPATHS": "Osteopaths", + "OTHER": "Other", + "PACKAGE_TOUR_OPERATORS": "Package Tour Operators", + "PAINTBALL": "Paintball", + "PAINTS_VARNISHES_AND_SUPPLIES": "Paints, Varnishes, and Supplies", + "PARKING_LOTS_AND_GARAGES": "Parking Lots & Garages", + "PARTS_AND_ACCESSORIES": "Parts and accessories", + "PAWN_SHOPS": "Pawn Shops", + "PAYCHECK_LENDER_OR_CASH_ADVANCE": "Paycheck lender or cash advance", + "PERIPHERALS": "Peripherals", + "PERSONALIZED_GIFTS": "Personalized Gifts", + "PET_SHOPS_PET_FOOD_AND_SUPPLIES": "Pet shops, pet food, and supplies", + "PETROLEUM_AND_PETROLEUM_PRODUCTS": "Petroleum and Petroleum Products", + "PETS_AND_ANIMALS": "Pets and animals", + "PHOTOFINISHING_LABORATORIES_PHOTO_DEVELOPING": "Photofinishing Laboratories,Photo Developing", + "PHOTOGRAPHIC_STUDIOS_PORTRAITS": "Photographic studios - portraits", + "PHOTOGRAPHY": "Photography", + "PHYSICAL_GOOD": "Physical Good", + "PICTURE_VIDEO_PRODUCTION": "Picture/Video Production", + "PIECE_GOODS_NOTIONS_AND_OTHER_DRY_GOODS": "Piece Goods Notions and Other Dry Goods", + "PLANTS_AND_SEEDS": "Plants and Seeds", + "PLUMBING_AND_HEATING_EQUIPMENTS_AND_SUPPLIES": "Plumbing & Heating Equipments & Supplies", + "POLICE_RELATED_ITEMS": "Police-Related Items", + "POLITICAL_ORGANIZATIONS": "Politcal Organizations", + "POSTAL_SERVICES_GOVERNMENT_ONLY": "Postal Services - Government Only", + "POSTERS": "Posters", + "PREPAID_AND_STORED_VALUE_CARDS": "Prepaid and stored value cards", + "PRESCRIPTION_DRUGS": "Prescription Drugs", + "PROMOTIONAL_ITEMS": "Promotional Items", + "PUBLIC_WAREHOUSING_AND_STORAGE": "Public Warehousing and Storage", + "PUBLISHING_AND_PRINTING": "Publishing and printing", + "PUBLISHING_SERVICES": "Publishing Services", + "RADAR_DECTORS": "Radar Dectors", + "RADIO_TELEVISION_AND_STEREO_REPAIR": "Radio, television, and stereo repair", + "REAL_ESTATE": "Real Estate", + "REAL_ESTATE_AGENT": "Real estate agent", + "REAL_ESTATE_AGENTS_AND_MANAGERS_RENTALS": "Real Estate Agents And Managers - Rentals", + "RELIGION_AND_SPIRITUALITY_FOR_PROFIT": "Religion and spirituality for profit", + "RELIGIOUS": "Religious", + "RELIGIOUS_ORGANIZATIONS": "Religious Organizations", + "REMITTANCE": "Remittance", + "RENTAL_PROPERTY_MANAGEMENT": "Rental property management", + "RESIDENTIAL": "Residential", + "RETAIL": "Retail", + "RETAIL_FINE_JEWELRY_AND_WATCHES": "Retail - fine jewelry and watches", + "REUPHOLSTERY_AND_FURNITURE_REPAIR": "Reupholstery and furniture repair", + "RINGS": "Rings", + "ROOFING_SIDING_SHEET_METAL": "Roofing/Siding, Sheet Metal", + "RUGS_AND_CARPETS": "Rugs & Carpets", + "SCHOOLS_AND_COLLEGES": "Schools and Colleges", + "SCIENCE_FICTION": "Science Fiction", + "SCRAPBOOKING": "Scrapbooking", + "SCULPTURES": "Sculptures", + "SECURITIES_BROKERS_AND_DEALERS": "Securities - Brokers And Dealers", + "SECURITY_AND_SURVEILLANCE": "Security and surveillance", + "SECURITY_AND_SURVEILLANCE_EQUIPMENT": "Security and surveillance equipment", + "SECURITY_BROKERS_AND_DEALERS": "Security brokers and dealers", + "SEMINARS": "Seminars", + "SERVICE_STATIONS": "Service Stations", + "SERVICES": "Services", + "SEWING_NEEDLEWORK_FABRIC_AND_PIECE_GOODS_STORES": "Sewing,Needlework,Fabric And Piece Goods Stores", + "SHIPPING_AND_PACKING": "Shipping & Packaging", + "SHOE_REPAIR_HAT_CLEANING": "Shoe Repair/Hat Cleaning", + "SHOE_STORES": "Shoe Stores", + "SHOES": "Shoes", + "SNOWMOBILE_DEALERS": "Snowmobile Dealers", + "SOFTWARE": "Software", + "SPECIALTY_AND_MISC_FOOD_STORES": "Specialty and misc food stores", + "SPECIALTY_CLEANING_POLISHING_AND_SANITATION_PREPARATIONS": "Specialty Cleaning, Polishing And Sanitation Preparations", + "SPECIALTY_OR_RARE_PETS": "Specialty or rare pets", + "SPORT_GAMES_AND_TOYS": "Sport games and toys", + "SPORTING_AND_RECREATIONAL_CAMPS": "Sporting And Recreational Camps", + "SPORTING_GOODS": "Sporting Goods", + "SPORTS_AND_OUTDOORS": "Sports and outdoors", + "SPORTS_AND_RECREATION": "Sports & Recreation", + "STAMP_AND_COIN": "Stamp and coin", + "STATIONARY_PRINTING_AND_WRITING_PAPER": "Stationary, printing, and writing paper", + "STENOGRAPHIC_AND_SECRETARIAL_SUPPORT_SERVICES": "Stenographic and secretarial support services", + "STOCKS_BONDS_SECURITIES_AND_RELATED_CERTIFICATES": "Stocks, Bonds, Securities and Related Certificates", + "STORED_VALUE_CARDS": "Stored Value Cards", + "SUPPLIES": "Supplies", + "SUPPLIES_AND_TOYS": "Supplies & Toys", + "SURVEILLANCE_EQUIPMENT": "Surveillance Equipment", + "SWIMMING_POOLS_AND_SPAS": "Swimming Pools & Spas", + "SWIMMING_POOLS_SALES_SUPPLIES_SERVICES": "Swimming Pools-Sales,Supplies,Services", + "TAILORS_AND_ALTERATIONS": "Tailors and alterations", + "TAX_PAYMENTS": "Tax Payments", + "TAX_PAYMENTS_GOVERNMENT_AGENCIES": "Tax Payments - Government Agencies", + "TAXICABS_AND_LIMOUSINES": "Taxicabs and limousines", + "TELECOMMUNICATION_SERVICES": "Telecommunication Services", + "TELEPHONE_CARDS": "Telephone Cards", + "TELEPHONE_EQUIPMENT": "Telephone Equipment", + "TELEPHONE_SERVICES": "Telephone Services", + "THEATER": "Theater", + "TIRE_RETREADING_AND_REPAIR": "Tire Retreading and Repair", + "TOLL_OR_BRIDGE_FEES": "Toll or Bridge Fees", + "TOOLS_AND_EQUIPMENT": "Tools and equipment", + "TOURIST_ATTRACTIONS_AND_EXHIBITS": "Tourist Attractions And Exhibits", + "TOWING_SERVICE": "Towing service", + "TOYS_AND_GAMES": "Toys and games", + "TRADE_AND_VOCATIONAL_SCHOOLS": "Trade And Vocational Schools", + "TRADEMARK_INFRINGEMENT": "Trademark Infringement", + "TRAILER_PARKS_AND_CAMPGROUNDS": "Trailer Parks And Campgrounds", + "TRAINING_SERVICES": "Training services", + "TRANSPORTATION_SERVICES": "Transportation Services", + "TRAVEL": "Travel", + "TRUCK_AND_UTILITY_TRAILER_RENTALS": "Truck And Utility Trailer Rentals", + "TRUCK_STOP": "Truck Stop", + "TYPESETTING_PLATE_MAKING_AND_RELATED_SERVICES": "Typesetting, Plate Making, and Related Services", + "USED_MERCHANDISE_AND_SECONDHAND_STORES": "Used Merchandise And Secondhand Stores", + "USED_PARTS_MOTOR_VEHICLE": "Used parts - motor vehicle", + "UTILITIES": "Utilities", + "UTILITIES_ELECTRIC_GAS_WATER_SANITARY": "Utilities - Electric,Gas,Water,Sanitary", + "VARIETY_STORES": "Variety Stores", + "VEHICLE_SALES": "Vehicle sales", + "VEHICLE_SERVICE_AND_ACCESSORIES": "Vehicle service and accessories", + "VIDEO_EQUIPMENT": "Video Equipment", + "VIDEO_GAME_ARCADES_ESTABLISH": "Video Game Arcades/Establish", + "VIDEO_GAMES_AND_SYSTEMS": "Video Games & Systems", + "VIDEO_TAPE_RENTAL_STORES": "Video Tape Rental Stores", + "VINTAGE_AND_COLLECTIBLE_VEHICLES": "Vintage and Collectible Vehicles", + "VINTAGE_AND_COLLECTIBLES": "Vintage and collectibles", + "VITAMINS_AND_SUPPLEMENTS": "Vitamins & Supplements", + "VOCATIONAL_AND_TRADE_SCHOOLS": "Vocational and trade schools", + "WATCH_CLOCK_AND_JEWELRY_REPAIR": "Watch, clock, and jewelry repair", + "WEB_HOSTING_AND_DESIGN": "Web hosting and design", + "WELDING_REPAIR": "Welding Repair", + "WHOLESALE_CLUBS": "Wholesale Clubs", + "WHOLESALE_FLORIST_SUPPLIERS": "Wholesale Florist Suppliers", + "WHOLESALE_PRESCRIPTION_DRUGS": "Wholesale Prescription Drugs", + "WILDLIFE_PRODUCTS": "Wildlife Products", + "WIRE_TRANSFER": "Wire Transfer", + "WIRE_TRANSFER_AND_MONEY_ORDER": "Wire transfer and money order", + "WOMEN_ACCESSORY_SPECIALITY": "Women's Accessory/Speciality", + "WOMEN_CLOTHING": "Women's clothing" + } +} diff --git a/termination_screen.png b/termination_screen.png new file mode 100644 index 0000000..e9f72d6 Binary files /dev/null and b/termination_screen.png differ diff --git a/types/schema copy.graphql.sample b/types/schema copy.graphql.sample new file mode 100644 index 0000000..3c04777 --- /dev/null +++ b/types/schema copy.graphql.sample @@ -0,0 +1,24 @@ +type Author { + id: ID! + firstName: String! + lastName: String! + posts: [Post!]! +} +type Post { + id: ID! + title: String + content: String! + authorId: ID! + author: Author! +} +type Query { + posts: [Post!]! + post(id: ID!): Post + author(id: ID!): Author + authors: [Author!]! +} +type Mutation { + createPost(title: String, content:String!, authorId: ID!): Post! + updatePost(id: ID!, title: String, content:String!): [Int!]! + deletePost(id: ID!): Int! +} \ No newline at end of file diff --git a/types/schema.graphql b/types/schema.graphql new file mode 100644 index 0000000..15a789b --- /dev/null +++ b/types/schema.graphql @@ -0,0 +1,451 @@ +scalar Date + + + type User { + id: ID! + role_id: Int + profile_id: Int + organization_id: Int + first_name: String + last_name: String + phone: String + image: String + refer: String + stripe_uid: String + paypal_uid: String + expire_at: Date + status: Int + created_at: Date + updated_at: Date + + + profile: Profile + organization: Organization + } + + + type ActivityLog { + id: ID! + name: String + action: String + data: String + created_at: Date + updated_at: Date + + + + } + + + type ReferLog { + id: ID! + user_id: Int + referrer_user_id: Int + type: Int + created_at: Date + updated_at: Date + + + user: User + } + + + type Credential { + id: ID! + oauth: String + email: String + password: String + user_id: Int + type: Int + verify: Int + status: Int + two_factor_authentication: Int + force_password_change: String + created_at: Date + updated_at: Date + + + user: User + } + + + type Image { + id: ID! + url: String + caption: String + user_id: Int + width: Int + height: Int + mobile_width: Int + mobile_height: Int + upload_type: Int + created_at: Date + updated_at: Date + + + user: User + } + + + type Rule { + id: ID! + output_variable_name: String + actives: String + operator: Int + compare_value: Float + min: Float + max: Float + action: Int + created_at: Date + updated_at: Date + + + + } + + + type Quiz { + id: ID! + name: String + description: String + created_at: Date + updated_at: Date + + + + } + + + type Active { + id: ID! + name: String + created_at: Date + updated_at: Date + + + + } + + + type OutputVariable { + id: ID! + name: String + active_list: String + ranges_response: String + created_at: Date + updated_at: Date + + + + } + + + type Question { + id: ID! + quiz_id: Int + question: String + question_arguments: String + note: String + note_type: Int + target: Int + response: String + save_response_into: String + depends_on: String + slider_range: String + output_variable_name: String + weight: Float + extra_output_variable: String + type: Int + created_at: Date + updated_at: Date + + + quiz: Quiz + } + + + type Answer { + id: ID! + question_id: Int + answer: String + answer_value: Float + explaination: String + image_id: String + response_header: String + response_body: String + response_arguments: String + black_list_actives: String + created_at: Date + updated_at: Date + + + question: Question + } + + # ------------------------ PAGINATION ------------------------ + + # USER + type UserEdge { + cursor: String + node: User + } + + type Users { + edges: [UserEdge] + pageInfo: PageInfo + } + + + # ACTIVITY_LOG + type ActivityLogEdge { + cursor: String + node: ActivityLog + } + + type ActivityLogs { + edges: [ActivityLogEdge] + pageInfo: PageInfo + } + + + # REFER_LOG + type ReferLogEdge { + cursor: String + node: ReferLog + } + + type ReferLogs { + edges: [ReferLogEdge] + pageInfo: PageInfo + } + + + # CREDENTIAL + type CredentialEdge { + cursor: String + node: Credential + } + + type Credentials { + edges: [CredentialEdge] + pageInfo: PageInfo + } + + + # IMAGE + type ImageEdge { + cursor: String + node: Image + } + + type Images { + edges: [ImageEdge] + pageInfo: PageInfo + } + + + # RULE + type RuleEdge { + cursor: String + node: Rule + } + + type Rules { + edges: [RuleEdge] + pageInfo: PageInfo + } + + + # QUIZ + type QuizEdge { + cursor: String + node: Quiz + } + + type Quizs { + edges: [QuizEdge] + pageInfo: PageInfo + } + + + # ACTIVE + type ActiveEdge { + cursor: String + node: Active + } + + type Actives { + edges: [ActiveEdge] + pageInfo: PageInfo + } + + + # OUTPUT_VARIABLE + type OutputVariableEdge { + cursor: String + node: OutputVariable + } + + type OutputVariables { + edges: [OutputVariableEdge] + pageInfo: PageInfo + } + + + # QUESTION + type QuestionEdge { + cursor: String + node: Question + } + + type Questions { + edges: [QuestionEdge] + pageInfo: PageInfo + } + + + # ANSWER + type AnswerEdge { + cursor: String + node: Answer + } + + type Answers { + edges: [AnswerEdge] + pageInfo: PageInfo + } + + + type PageInfo { + endCursor: String + hasNextPage: Boolean + } + + + + # ------------------------ QUERY ------------------------ + type Query { + + # USER + User(id: ID!): User + Users(first: Int, after: ID): Users + + + + # ACTIVITY_LOG + ActivityLog(id: ID!): ActivityLog + ActivityLogs(first: Int, after: ID): ActivityLogs + + + + # REFER_LOG + ReferLog(id: ID!): ReferLog + ReferLogs(first: Int, after: ID): ReferLogs + + + + # CREDENTIAL + Credential(id: ID!): Credential + Credentials(first: Int, after: ID): Credentials + + + + # IMAGE + Image(id: ID!): Image + Images(first: Int, after: ID): Images + + + + # RULE + Rule(id: ID!): Rule + Rules(first: Int, after: ID): Rules + + + + # QUIZ + Quiz(id: ID!): Quiz + Quizs(first: Int, after: ID): Quizs + + + + # ACTIVE + Active(id: ID!): Active + Actives(first: Int, after: ID): Actives + + + + # OUTPUT_VARIABLE + OutputVariable(id: ID!): OutputVariable + OutputVariables(first: Int, after: ID): OutputVariables + + + + # QUESTION + Question(id: ID!): Question + Questions(first: Int, after: ID): Questions + + + + # ANSWER + Answer(id: ID!): Answer + Answers(first: Int, after: ID): Answers + + } + + # ------------------------ MUTATION ------------------------ + type Mutation { + # USER +createUser(role_id:Int,profile_id:Int,organization_id:Int,first_name:String!,last_name:String!,phone:String,image:String,refer:String,stripe_uid:String,paypal_uid:String,expire_at:Date,status:Int!): User! +updateUser(id: ID! ,role_id:Int,profile_id:Int,organization_id:Int,first_name:String,last_name:String,phone:String,image:String,refer:String,stripe_uid:String,paypal_uid:String,expire_at:Date,status:Int): [Int!]! +deleteUser(id: ID!): Int! + +# ACTIVITY_LOG +createActivityLog(name:String): ActivityLog! +updateActivityLog(id: ID! ,name:String): [Int!]! +deleteActivityLog(id: ID!): Int! + +# REFER_LOG +createReferLog(user_id:Int!,type:Int!): ReferLog! +updateReferLog(id: ID! ): [Int!]! +deleteReferLog(id: ID!): Int! + +# CREDENTIAL +createCredential(email:String!,password:String!): Credential! +updateCredential(id: ID! ,email:String!,password:String): [Int!]! +deleteCredential(id: ID!): Int! + +# IMAGE +createImage(url:String!,caption:String): Image! +updateImage(id: ID! ,url:String!,caption:String): [Int!]! +deleteImage(id: ID!): Int! + +# RULE +createRule: Rule! +updateRule(id: ID! ): [Int!]! +deleteRule(id: ID!): Int! + +# QUIZ +createQuiz: Quiz! +updateQuiz(id: ID! ): [Int!]! +deleteQuiz(id: ID!): Int! + +# ACTIVE +createActive: Active! +updateActive(id: ID! ): [Int!]! +deleteActive(id: ID!): Int! + +# OUTPUT_VARIABLE +createOutputVariable: OutputVariable! +updateOutputVariable(id: ID! ): [Int!]! +deleteOutputVariable(id: ID!): Int! + +# QUESTION +createQuestion: Question! +updateQuestion(id: ID! ): [Int!]! +deleteQuestion(id: ID!): Int! + +# ANSWER +createAnswer: Answer! +updateAnswer(id: ID! ): [Int!]! +deleteAnswer(id: ID!): Int! + } diff --git a/utils/generateCode.js b/utils/generateCode.js new file mode 100644 index 0000000..95c524e --- /dev/null +++ b/utils/generateCode.js @@ -0,0 +1,16 @@ +/** + * Generate random code with given length + * @param {Number} length code length + * @returns {String} Generated code + * @example + * generateCode(6) + */ +module.exports = function generateCode(length) { + var result = ''; + var characters = '0123456789'; + var charactersLength = characters.length; + for (var i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; +}; diff --git a/view_models/actives_admin_add_view_model.js b/view_models/actives_admin_add_view_model.js new file mode 100644 index 0000000..17ef505 --- /dev/null +++ b/view_models/actives_admin_add_view_model.js @@ -0,0 +1,36 @@ +"use strict"; + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Actives Add View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +const db = require("../models"); +let AuthService = require("../services/AuthService"); + +module.exports = function (entity, pageName = "", success, error, base_url = "") { + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this._base_url = base_url; + + this.get_page_name = () => pageName; + + this.endpoint = "/admin/actives"; + + this.heading = "Add active"; + + this.action = "/admin/actives-add"; + + this.form_fields = { name: "", handle: "", description: "" }; + + return this; +}; diff --git a/view_models/actives_admin_delete_view_model.js b/view_models/actives_admin_delete_view_model.js new file mode 100644 index 0000000..7cde075 --- /dev/null +++ b/view_models/actives_admin_delete_view_model.js @@ -0,0 +1,40 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Actives Delete View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +const db = require('../models'); + +module.exports = function (entity, success, error) { + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + return this; +}; diff --git a/view_models/actives_admin_detail_view_model.js b/view_models/actives_admin_detail_view_model.js new file mode 100644 index 0000000..ad62352 --- /dev/null +++ b/view_models/actives_admin_detail_view_model.js @@ -0,0 +1,30 @@ +"use strict"; + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Actives V View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName = "", success, error, base_url = "") { + this.entity = entity; + + this.success = success || null; + this.error = error || null; + + this._base_url = base_url; + + this.endpoint = "/admin/actives"; + + this.get_page_name = () => pageName; + + this.heading = "Active details"; + + this.detail_fields = { id: "", name: "", description: "" }; + + return this; +}; diff --git a/view_models/actives_admin_edit_view_model.js b/view_models/actives_admin_edit_view_model.js new file mode 100644 index 0000000..be4f4cc --- /dev/null +++ b/view_models/actives_admin_edit_view_model.js @@ -0,0 +1,51 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Actives Edit View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ +const db = require("../models"); + +module.exports = function (entity, pageName = "", success, error, base_url = "") { + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this._base_url = base_url; + + this.endpoint = "/admin/actives"; + + this.get_page_name = () => pageName; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + this.heading = "Edit active"; + + this.action = "/admin/actives-edit"; + + this.form_fields = { name: "", id: "", handle: "", description: "" }; + + return this; +}; diff --git a/view_models/actives_admin_list_paginate_view_model.js b/view_models/actives_admin_list_paginate_view_model.js new file mode 100644 index 0000000..9605b7d --- /dev/null +++ b/view_models/actives_admin_list_paginate_view_model.js @@ -0,0 +1,555 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Actives Paginate List View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName, success, error, baseUrl) { + this.success = success ? success : ""; + this.error = error ? error : ""; + this._list = []; + this._column = ["ID", "Name", "Description", "Action"]; + this._readable_column = ["ID", "Name", "Description"]; + this._entity = entity; + this._heading = "Actives"; + this._base_url = baseUrl.endsWith("/") ? baseUrl.substring(0, -1) : baseUrl; + this._query = {}; + this._total_rows = 0; + this._format_layout = ""; + this._per_page = 10; + this._page; + this._num_links = 5; + this._field_column = ["id", "name", "description"]; + this._readable_field_column = ["id", "name", "description"]; + this._links = ""; + this._sort_base_url = ""; + this._order_by = ""; + this._sort = ""; + this._link_types = { start: "start", prev: "prev", next: "next" }; + this._attributes = ' class="page-link"'; + this.reuse_query_string = true; + this.page_query_string = true; + this.full_tag_open = ""; + this.full_tag_close = ""; + this.attributes = ""; + this.first_link = ""; + this.last_link = ""; + this.first_tag_open = ""; + this.query_string_segment = "per_page"; + this.first_tag_close = ""; + this.prev_link = ""; + this.prev_tag_open = ""; + this.prev_tag_close = ""; + this.next_link = ""; + this.next_tag_open = ""; + this.next_tag_close = ""; + this.last_tag_open = ""; + this.last_tag_close = ""; + this.cur_tag_open = ""; + this.cur_tag_close = ""; + this.num_tag_open = ""; + this.num_tag_close = ""; + this.suffix = ""; + this.prefix = ""; + this.cur_page = 0; + + this.get_page_name = () => pageName; + + this.get_heading = function () { + return pageName; + }; + + this.get_column = function () { + return this._column; + }; + + this.get_readable_column = function () { + return this._readable_column; + }; + + this.set_list = function (list) { + this._list = list; + }; + + this.set_query = function (query = {}) { + Object.keys(query).forEach((key) => { + if (this._field_column.includes(key)) { + console.log(this._query); + this._query[key] = query[key]; + } + }); + }; + + this.get_list = function () { + return this._list; + }; + + /** + * get_links function + * + * @return mixed + */ + this.get_links = function () { + this._links = this.createLinks(); + return this._links; + }; + + /** + * set_total_rows function + * + * @param integer total_rows + * @return void + */ + this.set_total_rows = function (total_rows) { + this._total_rows = total_rows; + }; + + /** + * set_per_page function + * + * @param integer per_page + * @return void + */ + this.set_per_page = function (per_page) { + this._per_page = per_page; + }; + /** + * format_layout function + * + * @param integer _format_layout + * @return void + */ + this.set_format_layout = function (_format_layout) { + this._format_layout = _format_layout; + }; + + /** + * set_order_by function + * + * @param string order_by + * @return void + */ + this.set_order_by = function (order_by) { + this._order_by = order_by; + }; + + /** + * set_sort function + * + * @param string sort + * @return void + */ + this.set_sort = function (sort) { + this._sort = sort; + }; + + /** + * set_sort_base_url function + * + * @param string sort_base_url + * @return void + */ + this.set_sort_base_url = function (sort_base_url) { + this._sort_base_url = sort_base_url; + }; + + /** + * get_total_rows function + * + * @return integer + */ + this.get_total_rows = function () { + return this._total_rows; + }; + + /** + * get_format_layout function + * + * @return integer + */ + this.get_format_layout = function () { + return this._format_layout; + }; + + /** + * get_per_page function + * + * @return integer + */ + this.get_per_page = function () { + return this._per_page; + }; + + /** + * get_page function + * + * @return integer + */ + this.get_page = function () { + return this._page; + }; + + /** + * num_links function + * + * @return integer + */ + this.get_num_links = function () { + return this._num_links; + }; + + /** + * set_order_by function + * + */ + this.get_order_by = function () { + return this._order_by; + }; + + /** + * get_field_column function + * + */ + this.get_field_column = function () { + return this._field_column; + }; + + this.get_readable_field_column = function () { + return this._readable_field_column; + }; + + /** + * set_sort function + * + */ + this.get_sort = function () { + return this._sort; + }; + + this.get_query = function () { + return this._query; + }; + + /** + * set_sort_base_url function + * + */ + this.get_sort_base_url = function () { + return this._sort_base_url; + }; + + /** + * set_page function + * + * @param integer page + * @return void + */ + this.set_page = function (page) { + this._page = page; + }; + + /** + * num_pages function + * + * @return integer + */ + this.get_num_page = function () { + let num = Math.ceil(this._total_rows / this._per_page); + return num > 0 ? parseInt(num) : 1; + }; + + this.image_or_file = function (file) { + const images = [".jpg", ".png", ".gif", ".jpeg", ".bmp"]; + let is_image = false; + const exist = images.filter(function (value) { + return value.indexOf(file) > -1; + }); + + if (exist.length > 0) { + return `
        `; + } + + return `${file}`; + }; + + this.timeago = function (date) { + const newDate = new Date(date); + const today = new Date(); + const currentTime = today.getTime(); + const timestamp = newDate.getTime(); + + const strTime = array("second", "minute", "hour", "day", "month", "year"); + const duration = array(60, 60, 24, 30, 12, 10); + + if (currentTime >= timestamp) { + diff = currentTime - timestamp; + + for (let i = 0; diff >= duration[i] && i < duration.length - 1; i++) { + diff = diff / duration[i]; + } + + diff = Math.round(diff, 0); + return diff + " " + strTime[i] + "(s) ago "; + } + }; + + this.time_default_mapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0" + i : i; + let min = j < 10 ? "0" + j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + this.convertToString = function (input) { + if (input) { + if (typeof input === "string") { + return input; + } + + return String(input); + } + return ""; + }; + + // convert string to words + this.toWords = function (input) { + input = this.convertToString(input); + + var regex = /[A-Z\xC0-\xD6\xD8-\xDE]?[a-z\xDF-\xF6\xF8-\xFF]+|[A-Z\xC0-\xD6\xD8-\xDE]+(?![a-z\xDF-\xF6\xF8-\xFF])|\d+/g; + + return input.match(regex); + }; + + // convert the input array to camel case + this.toCamelCase = function (inputArray) { + let result = ""; + + for (let i = 0, len = inputArray.length; i < len; i++) { + let currentStr = inputArray[i]; + + let tempStr = currentStr.toLowerCase(); + + if (i != 0) { + // convert first letter to upper case (the word is in lowercase) + tempStr = tempStr.substr(0, 1).toUpperCase() + tempStr.substr(1); + } + + result += tempStr; + } + + return result; + }; + + this.toCamelCaseString = function (input) { + let words = this.toWords(input); + + return this.toCamelCase(words); + }; + + this.ucFirst = function (string) { + if (typeof string === "string") { + return string.charAt(0).toUpperCase() + string.slice(1); + } + return ""; + }; + + this.number_format = function (field, n) { + return field.toFixed(n); + }; + + this.date = function (d) { + return ("0" + (d.getMonth() + 1)).slice(-2) + " " + ("0" + d.getDate()).slice(-2) + " " + d.getFullYear(); + }; + + this.datetime = function (d) { + return ("0" + (d.getMonth() + 1)).slice(-2) + " " + ("0" + d.getDate()).slice(-2) + " " + d.getFullYear() + " " + ("0" + d.getHours()).slice(-2) + ":" + ("0" + d.getMinutes()).slice(-2); + }; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + // 2018-06-12T19:30 + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + this.createLinks = function () { + let totalItems = this._total_rows; + let currentPage = this._page; + let pageSize = this._per_page; + let maxPages = 10; + // calculate total pages + let totalPages = Math.ceil(totalItems / pageSize); + + // ensure current page isn't out of range + if (currentPage < 0) { + currentPage = 0; + } else if (currentPage > totalPages) { + currentPage = +totalPages; + } + + let startPage = 0; + let endPage = 0; + + if (totalPages <= maxPages) { + // total pages less than max so show all pages + startPage = 1; + endPage = totalPages; + } else { + // total pages more than max so calculate start and end pages + let maxPagesBeforeCurrentPage = Math.floor(maxPages / 2); + let maxPagesAfterCurrentPage = Math.ceil(maxPages / 2) - 1; + if (currentPage <= maxPagesBeforeCurrentPage) { + // current page near the start + startPage = 1; + endPage = maxPages; + } else if (currentPage + maxPagesAfterCurrentPage >= totalPages) { + // current page near the end + startPage = totalPages - maxPages + 1; + endPage = totalPages; + } else { + // current page somewhere in the middle + startPage = currentPage - maxPagesBeforeCurrentPage; + endPage = currentPage + maxPagesAfterCurrentPage; + } + } + + // calculate start and end item indexes + let startIndex = (currentPage - 1) * pageSize; + let endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1); + + // create an array of pages to ng-repeat in the pager control + let pages = Array.from(Array(endPage + 1 - startPage).keys()).map((i) => startPage + i); + + // return object with all pager properties required by the view + const payload = { + totalItems: totalItems, + currentPage: currentPage, + pageSize: pageSize, + totalPages: totalPages, + startPage: startPage, + endPage: endPage, + startIndex: startIndex, + endIndex: endIndex, + pages: pages, + }; + + let html = '
          '; + for (let i = 0; i < payload.pages.length && payload.pages.length > 1; i++) { + const element = +payload.pages[i]; + if (element - 1 == payload.currentPage) { + html += `
        • ${element}(current)
        • `; + } else { + html += `
        • ${element}
        • `; + } + } + html += "
        "; + return html; + }; + + this.get_id = function () { + return this._id; + }; + + this.set_id = function (id) { + this._id = id; + }; + + this._id = null; + + this.get_name = function () { + return this._name; + }; + + this.set_name = function (name) { + this._name = name; + }; + + this._name = null; + + this.to_json = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["name"] = value["name"]; + clean_list_entry["description"] = value["description"]; + clean_list.push(clean_list_entry); + } + + return { + page: this.get_page(), + num_page: this.get_num_page(), + num_item: this.get_total_rows(), + item: clean_list, + }; + }; + + this.to_csv = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["name"] = value["name"]; + clean_list_entry["description"] = value["description"]; + clean_list.push(clean_list_entry); + } + + const columns = this.get_field_column(); + + const column_fields = this.get_readable_field_column(); + + const fields = column_fields.filter(function (v, index) { + if (v.length === 0) { + columns.splice(index, 1); + } + return v.length > 0; + }); + + let csv = columns.join(",") + "\n"; + for (let i = 0; i < clean_list.length; i++) { + let row = clean_list[i]; + let row_csv = []; + for (const key in row) { + let column = row[key]; + if (fields.includes(key)) { + row_csv.push('"' + column + '"'); + } + } + csv = csv + row_csv.join(",") + "\n"; + } + return csv; + }; + + return this; +}; diff --git a/view_models/admin_auth_view_model.js b/view_models/admin_auth_view_model.js new file mode 100644 index 0000000..26f39fc --- /dev/null +++ b/view_models/admin_auth_view_model.js @@ -0,0 +1,224 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Admin Authentication View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +const { nanoid, customAlphabet } = require('nanoid'); +const { Op } = require('sequelize'); +const bcrypt = require('bcryptjs'); + +const db = require('../models'); +const MailService = require('../services/MailService'); +// const SmsService = require('../services/SmsService'); + +module.exports = function (entity, pageName = '', success, error) { + this.entity = entity; + + this.success = success || null; + this.error = error || null; + + this.email = ''; + this.resetToken = ''; + + this.get_page_name = () => pageName; + + this.login_fields = { email: '', password: '' }; + this.register_fields = { + email: '', + first_name: '', + last_name: '', + password: '', + confirm_password: '', + }; + this.forgot_fields = { email: '' }; + this.reset_fields = { password: '', confirm_password: '' }; + this.account_verification_fields = { verificationCode: '' }; + this.form_fields = { 'first_name': '','last_name': '','credential.email': '','credential.password': '','status': '' } + + this.google_auth_url = '/admin/google/initialize'; + this.facebook_auth_url = '/admin/facebook/initialize'; + + + this.account_exists = function (email, otherFields={}) { + return db.credential.getByFields({ email, status: 1, ...otherFields }); + }; + + this.get_associated_user = function (id) { + return this.entity.getByPK(id); + }; + + this.compare_password = function (password, hashedPassword) { + return bcrypt.compare(password, hashedPassword); + }; + + this.generate_hash = function (password) { + return bcrypt.hash(password, bcrypt.genSaltSync(10)); + }; + + this.create_credential = function ({ ...args }) { + return db.credential.insert({ + ...args, + }); + }; + this.create_user = function ({ ...args }) { + return this.entity.insert({ + ...args, + }); + }; + + this.destroy_credential = function (id) { + return db.credential.realDelete(id); + }; + this.destroy_user = function (id) { + return db.user.realDelete(id); + }; + + this.createResetPasswordEmailTemplateForViews = function (slug) { + return db.email.insert({ + slug: slug, + subject: 'Forgot Password', + "tag": "email,reset_token,link", + html: `Hi {{{email}}},
        You have requested to reset your password. Please click the link below to reset it.
        Link.
        Thanks,
        Admin`, + }, { + returnAllFields:true + }); + }; + + this.initializeMailService = function (email) { + MailService.initialize({ + hostname: process.env.EMAIL_SMTP_SMTP_HOST, + port: process.env.EMAIL_SMTP_SMTP_PORT, + username: process.env.EMAIL_SMTP_SMTP_USER, + password: process.env.EMAIL_SMTP_SMTP_PASS, + from: process.env.MAIL_FROM, + to: email, + }); + }; + + this.getForgotPasswordMailTemplate = async function (slug) { + try { + const template = await MailService.template(slug); + return template; + } catch (error) { + if (error === 'TEMPLATE_NOT_FOUND') { + const template = await this.createResetPasswordEmailTemplateForViews( + slug, + ); + if (template) { + return template; + } + } + return null; + } + }; + + this.injectMailTemplate = function (template, payload) { + return MailService.inject(template, payload); + }; + + this.sendMail = function (template) { + return MailService.send(template); + }; + + this.generateRandomToken = function (size = 32) { + return nanoid(size); + }; + + this.saveTokenToDB = function ( + token, + user_id, + issue_at = new Date(), + expire_at = Date.now() + 36000000, + ) { + return db.token.insert({ token, user_id, issue_at, expire_at }); + }; + + this.validateToken = async function (token) { + try { + const isValid = await db.token.findOne({ + where: { + token, + expire_at: { [Op.gt]: new Date() }, + }, + }); + return isValid; + } catch (error) { + return false; + } + }; + + this.getUserCredential = function (user_id) { + return db.credential.findOne({ where: { user_id } }); + }; + + this.updatePassword = function (hashedPassword, credential_id) { + return db.credential.edit( + { + password: hashedPassword, + }, + credential_id, + ); + }; + + this.create2FATemplate = function () { + return db.sms.insert({ + slug: 'verify', + tag: 'code', + content: 'Your verification code is {{{code}}}', + }); + }; + + this.sendSMS = async function (to, userID, slug = 'verify') { + const code = customAlphabet('0123456789', 8)(); + + try { + const template = await SmsService.template(slug); + const finalTemplate = SmsService.inject(template, { code }); + await this.saveTokenToDB(code, userID); + return SmsService.send(to, finalTemplate); + } catch (error) { + if (error === 'TEMPLATE_NOT_FOUND') { + const template = await this.create2FATemplate(); + if (template) { + const finalTemplate = SmsService.inject(template, { code }); + await this.saveTokenToDB(code, userID); + return SmsService.send(to, finalTemplate); + } + throw new Error(error); + } + throw new Error(error); + } + }; + + this.status_mapping = function () { + return db.user.status_mapping(); + }; + this.role_id_mapping = function () { + return db.user.role_id_mapping(); + }; + + this.type_mapping = function () { + return db.user.type_mapping(); + }; + + this.verify_mapping = function () { + return db.user.verify_mapping(); + }; + + this.two_factor_authentication_mapping = function () { + return db.user.two_factor_authentication_mapping(); + }; + + this.force_password_change_mapping = function () { + return db.user.force_password_change_mapping(); + }; + + + return this; +}; diff --git a/view_models/answers_admin_add_view_model.js b/view_models/answers_admin_add_view_model.js new file mode 100644 index 0000000..a89a3aa --- /dev/null +++ b/view_models/answers_admin_add_view_model.js @@ -0,0 +1,47 @@ +"use strict"; + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Answers Add View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +const db = require("../models"); +let AuthService = require("../services/AuthService"); + +module.exports = function (entity, pageName = "", success, error, base_url = "") { + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this._base_url = base_url; + + this.get_page_name = () => pageName; + + this.endpoint = "/admin/answers"; + + this.heading = "Add answer"; + + this.action = "/admin/answers-add"; + + this.form_fields = { + question_id: "", + answer: "", + order: "", + answer_value: "", + explaination: "", + image_id: "", + response_header: "", + response_body: "", + response_arguments: "", + black_list_actives: "", + }; + + return this; +}; diff --git a/view_models/answers_admin_delete_view_model.js b/view_models/answers_admin_delete_view_model.js new file mode 100644 index 0000000..5c59a40 --- /dev/null +++ b/view_models/answers_admin_delete_view_model.js @@ -0,0 +1,40 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Answers Delete View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +const db = require('../models'); + +module.exports = function (entity, success, error) { + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + return this; +}; diff --git a/view_models/answers_admin_detail_view_model.js b/view_models/answers_admin_detail_view_model.js new file mode 100644 index 0000000..f4cd8d5 --- /dev/null +++ b/view_models/answers_admin_detail_view_model.js @@ -0,0 +1,33 @@ +'use strict' + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Answers V View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName='', success, error, base_url = "" ) { + + this.entity = entity + + this.success = success || null + this.error = error || null + + this._base_url = base_url + + this.endpoint = "/admin/answers" + + this.get_page_name = () => pageName + + this.heading = "Answer details" + + + this.detail_fields = {"id":"","question_id":"","question.question":"","answer":"","answer_value":"","explaination":"","image_id":"","response_header":"","response_body":"","response_arguments":"","black_list_actives":""} + + + return this; +} diff --git a/view_models/answers_admin_edit_view_model.js b/view_models/answers_admin_edit_view_model.js new file mode 100644 index 0000000..79f362f --- /dev/null +++ b/view_models/answers_admin_edit_view_model.js @@ -0,0 +1,63 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Answers Edit View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ +const db = require("../models"); + +module.exports = function (entity, pageName = "", success, error, base_url = "") { + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this._base_url = base_url; + + this.endpoint = "/admin/answers"; + + this.get_page_name = () => pageName; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + this.heading = "Edit answer"; + + this.action = "/admin/answers-edit"; + + this.form_fields = { + question_id: "", + answer: "", + answer_value: "", + order: "", + explaination: "", + image_id: "", + response_header: "", + response_body: "", + response_arguments: "", + black_list_actives: "", + id: "", + }; + + return this; +}; diff --git a/view_models/answers_admin_list_paginate_view_model.js b/view_models/answers_admin_list_paginate_view_model.js new file mode 100644 index 0000000..6410866 --- /dev/null +++ b/view_models/answers_admin_list_paginate_view_model.js @@ -0,0 +1,559 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Answers Paginate List View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName, success, error, baseUrl) { + this.success = success ? success : ""; + this.error = error ? error : ""; + this._list = []; + this._column = ["Quiz", "Question", "Answer", "Order", "Image", "BL Actives", "Action"]; + this._readable_column = ["Quiz", "Question", "Answer", "Order", "Image", "BL Actives"]; + this._entity = entity; + this._heading = "Answers"; + this._base_url = baseUrl.endsWith("/") ? baseUrl.substring(0, -1) : baseUrl; + this._query = {}; + this._total_rows = 0; + this._format_layout = ""; + this._per_page = 10; + this._page; + this._num_links = 5; + this._field_column = ["question.quiz_id", "question.id", "answer", "order", "", "black_list_actives"]; + this._readable_field_column = ["quiz", "question", "answer", "order", "", "black_list_actives"]; + this._links = ""; + this._sort_base_url = ""; + this._order_by = ""; + this._sort = ""; + this._link_types = { start: "start", prev: "prev", next: "next" }; + this._attributes = ' class="page-link"'; + this.reuse_query_string = true; + this.page_query_string = true; + this.full_tag_open = ""; + this.full_tag_close = ""; + this.attributes = ""; + this.first_link = ""; + this.last_link = ""; + this.first_tag_open = ""; + this.query_string_segment = "per_page"; + this.first_tag_close = ""; + this.prev_link = ""; + this.prev_tag_open = ""; + this.prev_tag_close = ""; + this.next_link = ""; + this.next_tag_open = ""; + this.next_tag_close = ""; + this.last_tag_open = ""; + this.last_tag_close = ""; + this.cur_tag_open = ""; + this.cur_tag_close = ""; + this.num_tag_open = ""; + this.num_tag_close = ""; + this.suffix = ""; + this.prefix = ""; + this.cur_page = 0; + + this.get_page_name = () => pageName; + + this.get_heading = function () { + return pageName; + }; + + this.get_column = function () { + return this._column; + }; + + this.get_readable_column = function () { + return this._readable_column; + }; + + this.set_list = function (list) { + this._list = list; + }; + + this.set_query = function (query = {}) { + Object.keys(query).forEach((key) => { + if (this._field_column.includes(key)) { + console.log(this._query); + this._query[key] = query[key]; + } + }); + }; + + this.get_list = function () { + return this._list; + }; + + /** + * get_links function + * + * @return mixed + */ + this.get_links = function () { + this._links = this.createLinks(); + return this._links; + }; + + /** + * set_total_rows function + * + * @param integer total_rows + * @return void + */ + this.set_total_rows = function (total_rows) { + this._total_rows = total_rows; + }; + + /** + * set_per_page function + * + * @param integer per_page + * @return void + */ + this.set_per_page = function (per_page) { + this._per_page = per_page; + }; + /** + * format_layout function + * + * @param integer _format_layout + * @return void + */ + this.set_format_layout = function (_format_layout) { + this._format_layout = _format_layout; + }; + + /** + * set_order_by function + * + * @param string order_by + * @return void + */ + this.set_order_by = function (order_by) { + this._order_by = order_by; + }; + + /** + * set_sort function + * + * @param string sort + * @return void + */ + this.set_sort = function (sort) { + this._sort = sort; + }; + + /** + * set_sort_base_url function + * + * @param string sort_base_url + * @return void + */ + this.set_sort_base_url = function (sort_base_url) { + this._sort_base_url = sort_base_url; + }; + + /** + * get_total_rows function + * + * @return integer + */ + this.get_total_rows = function () { + return this._total_rows; + }; + + /** + * get_format_layout function + * + * @return integer + */ + this.get_format_layout = function () { + return this._format_layout; + }; + + /** + * get_per_page function + * + * @return integer + */ + this.get_per_page = function () { + return this._per_page; + }; + + /** + * get_page function + * + * @return integer + */ + this.get_page = function () { + return this._page; + }; + + /** + * num_links function + * + * @return integer + */ + this.get_num_links = function () { + return this._num_links; + }; + + /** + * set_order_by function + * + */ + this.get_order_by = function () { + return this._order_by; + }; + + /** + * get_field_column function + * + */ + this.get_field_column = function () { + return this._field_column; + }; + + this.get_readable_field_column = function () { + return this._readable_field_column; + }; + + /** + * set_sort function + * + */ + this.get_sort = function () { + return this._sort; + }; + + this.get_query = function () { + return this._query; + }; + + /** + * set_sort_base_url function + * + */ + this.get_sort_base_url = function () { + return this._sort_base_url; + }; + + /** + * set_page function + * + * @param integer page + * @return void + */ + this.set_page = function (page) { + this._page = page; + }; + + /** + * num_pages function + * + * @return integer + */ + this.get_num_page = function () { + let num = Math.ceil(this._total_rows / this._per_page); + return num > 0 ? parseInt(num) : 1; + }; + + this.image_or_file = function (file) { + const images = [".jpg", ".png", ".gif", ".jpeg", ".bmp"]; + let is_image = false; + const exist = images.filter(function (value) { + return value.indexOf(file) > -1; + }); + + if (exist.length > 0) { + return `
        `; + } + + return `${file}`; + }; + + this.timeago = function (date) { + const newDate = new Date(date); + const today = new Date(); + const currentTime = today.getTime(); + const timestamp = newDate.getTime(); + + const strTime = array("second", "minute", "hour", "day", "month", "year"); + const duration = array(60, 60, 24, 30, 12, 10); + + if (currentTime >= timestamp) { + diff = currentTime - timestamp; + + for (let i = 0; diff >= duration[i] && i < duration.length - 1; i++) { + diff = diff / duration[i]; + } + + diff = Math.round(diff, 0); + return diff + " " + strTime[i] + "(s) ago "; + } + }; + + this.time_default_mapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0" + i : i; + let min = j < 10 ? "0" + j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + this.convertToString = function (input) { + if (input) { + if (typeof input === "string") { + return input; + } + + return String(input); + } + return ""; + }; + + // convert string to words + this.toWords = function (input) { + input = this.convertToString(input); + + var regex = /[A-Z\xC0-\xD6\xD8-\xDE]?[a-z\xDF-\xF6\xF8-\xFF]+|[A-Z\xC0-\xD6\xD8-\xDE]+(?![a-z\xDF-\xF6\xF8-\xFF])|\d+/g; + + return input.match(regex); + }; + + // convert the input array to camel case + this.toCamelCase = function (inputArray) { + let result = ""; + + for (let i = 0, len = inputArray.length; i < len; i++) { + let currentStr = inputArray[i]; + + let tempStr = currentStr.toLowerCase(); + + if (i != 0) { + // convert first letter to upper case (the word is in lowercase) + tempStr = tempStr.substr(0, 1).toUpperCase() + tempStr.substr(1); + } + + result += tempStr; + } + + return result; + }; + + this.toCamelCaseString = function (input) { + let words = this.toWords(input); + + return this.toCamelCase(words); + }; + + this.ucFirst = function (string) { + if (typeof string === "string") { + return string.charAt(0).toUpperCase() + string.slice(1); + } + return ""; + }; + + this.number_format = function (field, n) { + return field.toFixed(n); + }; + + this.date = function (d) { + return ("0" + (d.getMonth() + 1)).slice(-2) + " " + ("0" + d.getDate()).slice(-2) + " " + d.getFullYear(); + }; + + this.datetime = function (d) { + return ("0" + (d.getMonth() + 1)).slice(-2) + " " + ("0" + d.getDate()).slice(-2) + " " + d.getFullYear() + " " + ("0" + d.getHours()).slice(-2) + ":" + ("0" + d.getMinutes()).slice(-2); + }; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + // 2018-06-12T19:30 + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + this.createLinks = function () { + let totalItems = this._total_rows; + let currentPage = this._page; + let pageSize = this._per_page; + let maxPages = 10; + // calculate total pages + let totalPages = Math.ceil(totalItems / pageSize); + + // ensure current page isn't out of range + if (currentPage < 0) { + currentPage = 0; + } else if (currentPage > totalPages) { + currentPage = +totalPages; + } + + let startPage = 0; + let endPage = 0; + + if (totalPages <= maxPages) { + // total pages less than max so show all pages + startPage = 1; + endPage = totalPages; + } else { + // total pages more than max so calculate start and end pages + let maxPagesBeforeCurrentPage = Math.floor(maxPages / 2); + let maxPagesAfterCurrentPage = Math.ceil(maxPages / 2) - 1; + if (currentPage <= maxPagesBeforeCurrentPage) { + // current page near the start + startPage = 1; + endPage = maxPages; + } else if (currentPage + maxPagesAfterCurrentPage >= totalPages) { + // current page near the end + startPage = totalPages - maxPages + 1; + endPage = totalPages; + } else { + // current page somewhere in the middle + startPage = currentPage - maxPagesBeforeCurrentPage; + endPage = currentPage + maxPagesAfterCurrentPage; + } + } + + // calculate start and end item indexes + let startIndex = (currentPage - 1) * pageSize; + let endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1); + + // create an array of pages to ng-repeat in the pager control + let pages = Array.from(Array(endPage + 1 - startPage).keys()).map((i) => startPage + i); + + // return object with all pager properties required by the view + const payload = { + totalItems: totalItems, + currentPage: currentPage, + pageSize: pageSize, + totalPages: totalPages, + startPage: startPage, + endPage: endPage, + startIndex: startIndex, + endIndex: endIndex, + pages: pages, + }; + + let html = '
          '; + for (let i = 0; i < payload.pages.length && payload.pages.length > 1; i++) { + const element = +payload.pages[i]; + if (element - 1 == payload.currentPage) { + html += `
        • ${element}(current)
        • `; + } else { + html += `
        • ${element}
        • `; + } + } + html += "
        "; + return html; + }; + + this.get_id = function () { + return this._id; + }; + + this.set_id = function (id) { + this._id = id; + }; + + this._id = null; + + this.get_question_id = function () { + return this._question_id; + }; + + this.set_question_id = function (question_id) { + this._question_id = question_id; + }; + + this._question_id = null; + + this.to_json = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["answer"] = value["answer"]; + clean_list_entry["question"] = value["question"]["question"]; + clean_list_entry["image_id"] = value["image_id"]; + clean_list_entry["black_list_actives"] = value["black_list_actives"]; + clean_list.push(clean_list_entry); + } + + return { + page: this.get_page(), + num_page: this.get_num_page(), + num_item: this.get_total_rows(), + item: clean_list, + }; + }; + + this.to_csv = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["answer"] = value["answer"]; + clean_list_entry["question"] = value["question"]["question"]; + clean_list_entry["image_id"] = value["image_id"]; + clean_list_entry["black_list_actives"] = value["black_list_actives"]; + clean_list.push(clean_list_entry); + } + + const columns = this.get_field_column(); + + const column_fields = this.get_readable_field_column(); + + const fields = column_fields.filter(function (v, index) { + if (v.length === 0) { + columns.splice(index, 1); + } + return v.length > 0; + }); + + let csv = columns.join(",") + "\n"; + for (let i = 0; i < clean_list.length; i++) { + let row = clean_list[i]; + let row_csv = []; + for (const key in row) { + let column = row[key]; + if (fields.includes(key)) { + row_csv.push('"' + column + '"'); + } + } + csv = csv + row_csv.join(",") + "\n"; + } + return csv; + }; + + return this; +}; diff --git a/view_models/file_upload_local.js b/view_models/file_upload_local.js new file mode 100644 index 0000000..8171f6c --- /dev/null +++ b/view_models/file_upload_local.js @@ -0,0 +1,44 @@ +'use strict' + + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * file_upload_local Image View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + + +module.exports = function (entity, pageName='', success, error ) { + + this.entity = entity + + this.success = success || null + this.error = error || null + + this.endpoint = "{{{route}}}" + + this.get_page_name = () => pageName + + + this.create_resource = function(data) { + return this.entity.insert(data) + } + + this.upload_resource = function (req, res) { + const filename = nanoid(); + + const upload = uploader.local_upload('/uploads', 'file').single('file') + + upload(req, res, function (error) { + if (error) throw new Error(error); + }); + + return filename; + }; + + return this +} diff --git a/view_models/image_upload_local.js b/view_models/image_upload_local.js new file mode 100644 index 0000000..ffb205c --- /dev/null +++ b/view_models/image_upload_local.js @@ -0,0 +1,44 @@ +'use strict' + + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * image_upload_local Image View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + + +module.exports = function (entity, pageName='', success, error ) { + + this.entity = entity + + this.success = success || null + this.error = error || null + + this.endpoint = "{{{route}}}" + + this.get_page_name = () => pageName + + + this.create_resource = function(data) { + return this.entity.insert(data) + } + + this.upload_resource = function (req, res) { + const filename = nanoid(); + + const upload = uploader.local_upload('/uploads', 'image').single('image') + + upload(req, res, function (error) { + if (error) throw new Error(error); + }); + + return filename; + }; + + return this +} diff --git a/view_models/member_auth_view_model.js b/view_models/member_auth_view_model.js new file mode 100644 index 0000000..62361bd --- /dev/null +++ b/view_models/member_auth_view_model.js @@ -0,0 +1,224 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Admin Authentication View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +const { nanoid, customAlphabet } = require('nanoid'); +const { Op } = require('sequelize'); +const bcrypt = require('bcryptjs'); + +const db = require('../models'); +const MailService = require('../services/MailService'); +// const SmsService = require('../services/SmsService'); + +module.exports = function (entity, pageName = '', success, error) { + this.entity = entity; + + this.success = success || null; + this.error = error || null; + + this.email = ''; + this.resetToken = ''; + + this.get_page_name = () => pageName; + + this.login_fields = { email: '', password: '' }; + this.register_fields = { + email: '', + first_name: '', + last_name: '', + password: '', + confirm_password: '', + }; + this.forgot_fields = { email: '' }; + this.reset_fields = { password: '', confirm_password: '' }; + this.account_verification_fields = { verificationCode: '' }; + this.form_fields = { 'first_name': '','last_name': '','credential.email': '','credential.password': '','status': '' } + + this.google_auth_url = '/member/google/initialize'; + this.facebook_auth_url = '/member/facebook/initialize'; + + + this.account_exists = function (email, otherFields={}) { + return db.credential.getByFields({ email, status: 1, ...otherFields }); + }; + + this.get_associated_user = function (id) { + return this.entity.getByPK(id); + }; + + this.compare_password = function (password, hashedPassword) { + return bcrypt.compare(password, hashedPassword); + }; + + this.generate_hash = function (password) { + return bcrypt.hash(password, bcrypt.genSaltSync(10)); + }; + + this.create_credential = function ({ ...args }) { + return db.credential.insert({ + ...args, + }); + }; + this.create_user = function ({ ...args }) { + return this.entity.insert({ + ...args, + }); + }; + + this.destroy_credential = function (id) { + return db.credential.realDelete(id); + }; + this.destroy_user = function (id) { + return db.user.realDelete(id); + }; + + this.createResetPasswordEmailTemplateForViews = function (slug) { + return db.email.insert({ + slug: slug, + subject: 'Forgot Password', + "tag": "email,reset_token,link", + html: `Hi {{{email}}},
        You have requested to reset your password. Please click the link below to reset it.
        Link.
        Thanks,
        Admin`, + }, { + returnAllFields:true + }); + }; + + this.initializeMailService = function (email) { + MailService.initialize({ + hostname: process.env.EMAIL_SMTP_SMTP_HOST, + port: process.env.EMAIL_SMTP_SMTP_PORT, + username: process.env.EMAIL_SMTP_SMTP_USER, + password: process.env.EMAIL_SMTP_SMTP_PASS, + from: process.env.MAIL_FROM, + to: email, + }); + }; + + this.getForgotPasswordMailTemplate = async function (slug) { + try { + const template = await MailService.template(slug); + return template; + } catch (error) { + if (error === 'TEMPLATE_NOT_FOUND') { + const template = await this.createResetPasswordEmailTemplateForViews( + slug, + ); + if (template) { + return template; + } + } + return null; + } + }; + + this.injectMailTemplate = function (template, payload) { + return MailService.inject(template, payload); + }; + + this.sendMail = function (template) { + return MailService.send(template); + }; + + this.generateRandomToken = function (size = 32) { + return nanoid(size); + }; + + this.saveTokenToDB = function ( + token, + user_id, + issue_at = new Date(), + expire_at = Date.now() + 36000000, + ) { + return db.token.insert({ token, user_id, issue_at, expire_at }); + }; + + this.validateToken = async function (token) { + try { + const isValid = await db.token.findOne({ + where: { + token, + expire_at: { [Op.gt]: new Date() }, + }, + }); + return isValid; + } catch (error) { + return false; + } + }; + + this.getUserCredential = function (user_id) { + return db.credential.findOne({ where: { user_id } }); + }; + + this.updatePassword = function (hashedPassword, credential_id) { + return db.credential.edit( + { + password: hashedPassword, + }, + credential_id, + ); + }; + + this.create2FATemplate = function () { + return db.sms.insert({ + slug: 'verify', + tag: 'code', + content: 'Your verification code is {{{code}}}', + }); + }; + + this.sendSMS = async function (to, userID, slug = 'verify') { + const code = customAlphabet('0123456789', 8)(); + + try { + const template = await SmsService.template(slug); + const finalTemplate = SmsService.inject(template, { code }); + await this.saveTokenToDB(code, userID); + return SmsService.send(to, finalTemplate); + } catch (error) { + if (error === 'TEMPLATE_NOT_FOUND') { + const template = await this.create2FATemplate(); + if (template) { + const finalTemplate = SmsService.inject(template, { code }); + await this.saveTokenToDB(code, userID); + return SmsService.send(to, finalTemplate); + } + throw new Error(error); + } + throw new Error(error); + } + }; + + this.status_mapping = function () { + return db.user.status_mapping(); + }; + this.role_id_mapping = function () { + return db.user.role_id_mapping(); + }; + + this.type_mapping = function () { + return db.user.type_mapping(); + }; + + this.verify_mapping = function () { + return db.user.verify_mapping(); + }; + + this.two_factor_authentication_mapping = function () { + return db.user.two_factor_authentication_mapping(); + }; + + this.force_password_change_mapping = function () { + return db.user.force_password_change_mapping(); + }; + + + return this; +}; diff --git a/view_models/orders_admin_list_paginate_view_model.js b/view_models/orders_admin_list_paginate_view_model.js new file mode 100644 index 0000000..654f427 --- /dev/null +++ b/view_models/orders_admin_list_paginate_view_model.js @@ -0,0 +1,589 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Orders Paginate List View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName, success, error, baseUrl) { + this.success = success ? success : ""; + this.error = error ? error : ""; + this._list = []; + this._column = ["ID", "Order shopify id", "Customer", "Financial status", "Fulfillment status", "Created at", "Printables"]; + this._readable_column = ["ID", "Order shopify id", "Customer", "Financial status", "Fulfillment status", "Created at"]; + this._entity = entity; + this._heading = "Orders"; + this._base_url = baseUrl.endsWith("/") ? baseUrl.substring(0, -1) : baseUrl; + this._query = {}; + this._total_rows = 0; + this._format_layout = ""; + this._per_page = 10; + this._page; + this._num_links = 5; + this._field_column = ["id", "shopify_id", "customer", "financial_status", "fulfillment_status", "created_at", ""]; + this._readable_field_column = ["id", "shopify_id", "customer", "financial_status", "fulfillment_status", "created_at"]; + this._links = ""; + this._sort_base_url = ""; + this._order_by = ""; + this._sort = ""; + this._link_types = { start: "start", prev: "prev", next: "next" }; + this._attributes = ' class="page-link"'; + this.reuse_query_string = true; + this.page_query_string = true; + this.full_tag_open = ""; + this.full_tag_close = ""; + this.attributes = ""; + this.first_link = ""; + this.last_link = ""; + this.first_tag_open = ""; + this.query_string_segment = "per_page"; + this.first_tag_close = ""; + this.prev_link = ""; + this.prev_tag_open = ""; + this.prev_tag_close = ""; + this.next_link = ""; + this.next_tag_open = ""; + this.next_tag_close = ""; + this.last_tag_open = ""; + this.last_tag_close = ""; + this.cur_tag_open = ""; + this.cur_tag_close = ""; + this.num_tag_open = ""; + this.num_tag_close = ""; + this.suffix = ""; + this.prefix = ""; + this.cur_page = 0; + + this.get_page_name = () => pageName; + + this.get_heading = function () { + return pageName; + }; + + this.get_column = function () { + return this._column; + }; + + this.get_readable_column = function () { + return this._readable_column; + }; + + this.set_list = function (list) { + this._list = list; + }; + + this.set_query = function (query = {}) { + Object.keys(query).forEach((key) => { + if (this._field_column.includes(key)) { + console.log(this._query); + this._query[key] = query[key]; + } + }); + }; + + this.get_list = function () { + return this._list; + }; + + /** + * get_links function + * + * @return mixed + */ + this.get_links = function () { + this._links = this.createLinks(); + return this._links; + }; + + /** + * set_total_rows function + * + * @param integer total_rows + * @return void + */ + this.set_total_rows = function (total_rows) { + this._total_rows = total_rows; + }; + + /** + * set_per_page function + * + * @param integer per_page + * @return void + */ + this.set_per_page = function (per_page) { + this._per_page = per_page; + }; + /** + * format_layout function + * + * @param integer _format_layout + * @return void + */ + this.set_format_layout = function (_format_layout) { + this._format_layout = _format_layout; + }; + + /** + * set_order_by function + * + * @param string order_by + * @return void + */ + this.set_order_by = function (order_by) { + this._order_by = order_by; + }; + + /** + * set_sort function + * + * @param string sort + * @return void + */ + this.set_sort = function (sort) { + this._sort = sort; + }; + + /** + * set_sort_base_url function + * + * @param string sort_base_url + * @return void + */ + this.set_sort_base_url = function (sort_base_url) { + this._sort_base_url = sort_base_url; + }; + + /** + * get_total_rows function + * + * @return integer + */ + this.get_total_rows = function () { + return this._total_rows; + }; + + /** + * get_format_layout function + * + * @return integer + */ + this.get_format_layout = function () { + return this._format_layout; + }; + + /** + * get_per_page function + * + * @return integer + */ + this.get_per_page = function () { + return this._per_page; + }; + + /** + * get_page function + * + * @return integer + */ + this.get_page = function () { + return this._page; + }; + + /** + * num_links function + * + * @return integer + */ + this.get_num_links = function () { + return this._num_links; + }; + + /** + * set_order_by function + * + */ + this.get_order_by = function () { + return this._order_by; + }; + + /** + * get_field_column function + * + */ + this.get_field_column = function () { + return this._field_column; + }; + + this.get_readable_field_column = function () { + return this._readable_field_column; + }; + + /** + * set_sort function + * + */ + this.get_sort = function () { + return this._sort; + }; + + this.get_query = function () { + return this._query; + }; + + /** + * set_sort_base_url function + * + */ + this.get_sort_base_url = function () { + return this._sort_base_url; + }; + + /** + * set_page function + * + * @param integer page + * @return void + */ + this.set_page = function (page) { + this._page = page; + }; + + /** + * num_pages function + * + * @return integer + */ + this.get_num_page = function () { + let num = Math.ceil(this._total_rows / this._per_page); + return num > 0 ? parseInt(num) : 1; + }; + + this.image_or_file = function (file) { + const images = [".jpg", ".png", ".gif", ".jpeg", ".bmp"]; + let is_image = false; + const exist = images.filter(function (value) { + return value.indexOf(file) > -1; + }); + + if (exist.length > 0) { + return `
        `; + } + + return `${file}`; + }; + + this.timeago = function (date) { + const newDate = new Date(date); + const today = new Date(); + const currentTime = today.getTime(); + const timestamp = newDate.getTime(); + + const strTime = array("second", "minute", "hour", "day", "month", "year"); + const duration = array(60, 60, 24, 30, 12, 10); + + if (currentTime >= timestamp) { + diff = currentTime - timestamp; + + for (let i = 0; diff >= duration[i] && i < duration.length - 1; i++) { + diff = diff / duration[i]; + } + + diff = Math.round(diff, 0); + return diff + " " + strTime[i] + "(s) ago "; + } + }; + + this.time_default_mapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0" + i : i; + let min = j < 10 ? "0" + j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + this.convertToString = function (input) { + if (input) { + if (typeof input === "string") { + return input; + } + + return String(input); + } + return ""; + }; + + // convert string to words + this.toWords = function (input) { + input = this.convertToString(input); + + var regex = /[A-Z\xC0-\xD6\xD8-\xDE]?[a-z\xDF-\xF6\xF8-\xFF]+|[A-Z\xC0-\xD6\xD8-\xDE]+(?![a-z\xDF-\xF6\xF8-\xFF])|\d+/g; + + return input.match(regex); + }; + + // convert the input array to camel case + this.toCamelCase = function (inputArray) { + let result = ""; + + for (let i = 0, len = inputArray.length; i < len; i++) { + let currentStr = inputArray[i]; + + let tempStr = currentStr.toLowerCase(); + + if (i != 0) { + // convert first letter to upper case (the word is in lowercase) + tempStr = tempStr.substr(0, 1).toUpperCase() + tempStr.substr(1); + } + + result += tempStr; + } + + return result; + }; + + this.toCamelCaseString = function (input) { + let words = this.toWords(input); + + return this.toCamelCase(words); + }; + + this.ucFirst = function (string) { + if (typeof string === "string") { + return string.charAt(0).toUpperCase() + string.slice(1); + } + return ""; + }; + + this.number_format = function (field, n) { + return field.toFixed(n); + }; + + this.date = function (d) { + return ("0" + (d.getMonth() + 1)).slice(-2) + " " + ("0" + d.getDate()).slice(-2) + " " + d.getFullYear(); + }; + + this.datetime = function (d) { + return ("0" + (d.getMonth() + 1)).slice(-2) + " " + ("0" + d.getDate()).slice(-2) + " " + d.getFullYear() + " " + ("0" + d.getHours()).slice(-2) + ":" + ("0" + d.getMinutes()).slice(-2); + }; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + // 2018-06-12T19:30 + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + this.createLinks = function () { + let totalItems = this._total_rows; + let currentPage = this._page; + let pageSize = this._per_page; + let maxPages = 10; + // calculate total pages + let totalPages = Math.ceil(totalItems / pageSize); + + // ensure current page isn't out of range + if (currentPage < 0) { + currentPage = 0; + } else if (currentPage > totalPages) { + currentPage = +totalPages; + } + + let startPage = 0; + let endPage = 0; + + if (totalPages <= maxPages) { + // total pages less than max so show all pages + startPage = 1; + endPage = totalPages; + } else { + // total pages more than max so calculate start and end pages + let maxPagesBeforeCurrentPage = Math.floor(maxPages / 2); + let maxPagesAfterCurrentPage = Math.ceil(maxPages / 2) - 1; + if (currentPage <= maxPagesBeforeCurrentPage) { + // current page near the start + startPage = 1; + endPage = maxPages; + } else if (currentPage + maxPagesAfterCurrentPage >= totalPages) { + // current page near the end + startPage = totalPages - maxPages + 1; + endPage = totalPages; + } else { + // current page somewhere in the middle + startPage = currentPage - maxPagesBeforeCurrentPage; + endPage = currentPage + maxPagesAfterCurrentPage; + } + } + + // calculate start and end item indexes + let startIndex = (currentPage - 1) * pageSize; + let endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1); + + // create an array of pages to ng-repeat in the pager control + let pages = Array.from(Array(endPage + 1 - startPage).keys()).map((i) => startPage + i); + + // return object with all pager properties required by the view + const payload = { + totalItems: totalItems, + currentPage: currentPage, + pageSize: pageSize, + totalPages: totalPages, + startPage: startPage, + endPage: endPage, + startIndex: startIndex, + endIndex: endIndex, + pages: pages, + }; + + let html = '
          '; + for (let i = 0; i < payload.pages.length && payload.pages.length > 1; i++) { + const element = +payload.pages[i]; + if (element - 1 == payload.currentPage) { + html += `
        • ${element}(current)
        • `; + } else { + html += `
        • ${element}
        • `; + } + } + html += "
        "; + return html; + }; + + this.get_id = function () { + return this._id; + }; + + this.set_id = function (id) { + this._id = id; + }; + + this._id = null; + + this.get_customer_shopify_id = function () { + return this._customer_shopify_id; + }; + + this.set_customer_shopify_id = function (customer_shopify_id) { + this._customer_shopify_id = customer_shopify_id; + }; + + this._customer_shopify_id = null; + + this.get_shopify_id = function () { + return this._shopify_id; + }; + + this.set_shopify_id = function (shopify_id) { + this._shopify_id = shopify_id; + }; + + this._shopify_id = null; + + this.get_financial_status = function () { + return this._financial_status; + }; + + this.set_financial_status = function (financial_status) { + this._financial_status = financial_status; + }; + + this._financial_status = null; + + this.get_fulfillment_status = function () { + return this._fulfillment_status; + }; + + this.set_fulfillment_status = function (fulfillment_status) { + this._fulfillment_status = fulfillment_status; + }; + + this._fulfillment_status = null; + + this.to_json = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["shopify_id"] = value["shopify_id"]; + clean_list_entry["customer"] = value["customer"]; + clean_list_entry["financial_status"] = value["financial_status"]; + clean_list_entry["fulfillment_status"] = value["fulfillment_status"]; + clean_list.push(clean_list_entry); + } + + return { + page: this.get_page(), + num_page: this.get_num_page(), + num_item: this.get_total_rows(), + item: clean_list, + }; + }; + + this.to_csv = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["shopify_id"] = value["shopify_id"]; + clean_list_entry["customer"] = value["customer"]; + clean_list_entry["financial_status"] = value["financial_status"]; + clean_list_entry["fulfillment_status"] = value["fulfillment_status"]; + clean_list.push(clean_list_entry); + } + + const columns = this.get_field_column(); + + const column_fields = this.get_readable_field_column(); + + const fields = column_fields.filter(function (v, index) { + if (v.length === 0) { + columns.splice(index, 1); + } + return v.length > 0; + }); + + let csv = columns.join(",") + "\n"; + for (let i = 0; i < clean_list.length; i++) { + let row = clean_list[i]; + let row_csv = []; + for (const key in row) { + let column = row[key]; + if (fields.includes(key)) { + row_csv.push('"' + column + '"'); + } + } + csv = csv + row_csv.join(",") + "\n"; + } + return csv; + }; + + return this; +}; diff --git a/view_models/output_variables_admin_add_view_model.js b/view_models/output_variables_admin_add_view_model.js new file mode 100644 index 0000000..dc1184a --- /dev/null +++ b/view_models/output_variables_admin_add_view_model.js @@ -0,0 +1,46 @@ +'use strict' + + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Output_variables Add View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + + const db = require('../models') + let AuthService = require('../services/AuthService'); + + +module.exports = function (entity, pageName='', success, error, base_url = "" ) { + + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this._base_url = base_url; + + + + this.get_page_name = () => pageName; + + this.endpoint = "/admin/output-variables" + + + this.heading = "Add output variable" + + this.action = "/admin/output-variables-add" + + + + this.form_fields = {"name":"","active_list":"","ranges_response":""} + + + + return this; +} diff --git a/view_models/output_variables_admin_delete_view_model.js b/view_models/output_variables_admin_delete_view_model.js new file mode 100644 index 0000000..b630a57 --- /dev/null +++ b/view_models/output_variables_admin_delete_view_model.js @@ -0,0 +1,40 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Output_variables Delete View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +const db = require('../models'); + +module.exports = function (entity, success, error) { + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + return this; +}; diff --git a/view_models/output_variables_admin_detail_view_model.js b/view_models/output_variables_admin_detail_view_model.js new file mode 100644 index 0000000..bd0825a --- /dev/null +++ b/view_models/output_variables_admin_detail_view_model.js @@ -0,0 +1,33 @@ +'use strict' + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Output_variables V View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName='', success, error, base_url = "" ) { + + this.entity = entity + + this.success = success || null + this.error = error || null + + this._base_url = base_url + + this.endpoint = "/admin/output-variables" + + this.get_page_name = () => pageName + + this.heading = "Output variable details" + + + this.detail_fields = {"id":"","name":"","active_list":"","ranges_response":""} + + + return this; +} diff --git a/view_models/output_variables_admin_edit_view_model.js b/view_models/output_variables_admin_edit_view_model.js new file mode 100644 index 0000000..8207b38 --- /dev/null +++ b/view_models/output_variables_admin_edit_view_model.js @@ -0,0 +1,58 @@ +'use strict' +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Output_variables Edit View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + const db = require('../models'); + +module.exports = function (entity, pageName='', success, error, base_url = "") { + + this._entity = entity + this.session = null + + this.success = success || null + this.error = error || null + + this._base_url = base_url + + this.endpoint = "/admin/output-variables" + + this.get_page_name = () => pageName + + this.format_date_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + return `${year}-${month}-${day}` + } + + this.format_date_local_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + const hrs = d.getHours() < 10 ? `0${d.getHours() }` : d.getHours() ; + const mins = d.getMinutes() < 10 ? `0${d.getMinutes() }` : d.getMinutes() ; + return `${year}-${month}-${day}T${hrs}:${mins}` + } + + this.heading = "Edit output variable" + + this.action = "/admin/output-variables-edit" + + + + + this.form_fields = {"name":"","active_list":"","ranges_response":"","id":""} + + + + + return this; +} diff --git a/view_models/output_variables_admin_list_paginate_view_model.js b/view_models/output_variables_admin_list_paginate_view_model.js new file mode 100644 index 0000000..3f3b3a1 --- /dev/null +++ b/view_models/output_variables_admin_list_paginate_view_model.js @@ -0,0 +1,557 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Output_variables Paginate List View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName, success, error, baseUrl) { + this.success = success ? success : ""; + this.error = error ? error : ""; + this._list = []; + this._column = ["ID", "Name", "Priority", "Actives list", "Ranges responses", "Action"]; + this._readable_column = ["ID", "Name", "Priority", "Actives list", "Ranges responses"]; + this._entity = entity; + this._heading = "Output variables"; + this._base_url = baseUrl.endsWith("/") ? baseUrl.substring(0, -1) : baseUrl; + this._query = {}; + this._total_rows = 0; + this._format_layout = ""; + this._per_page = 10; + this._page; + this._num_links = 5; + this._field_column = ["id", "name", "priority", "active_list", "ranges_response"]; + this._readable_field_column = ["id", "name", "priority", "active_list", "ranges_response"]; + this._links = ""; + this._sort_base_url = ""; + this._order_by = ""; + this._sort = ""; + this._link_types = { start: "start", prev: "prev", next: "next" }; + this._attributes = ' class="page-link"'; + this.reuse_query_string = true; + this.page_query_string = true; + this.full_tag_open = ""; + this.full_tag_close = ""; + this.attributes = ""; + this.first_link = ""; + this.last_link = ""; + this.first_tag_open = ""; + this.query_string_segment = "per_page"; + this.first_tag_close = ""; + this.prev_link = ""; + this.prev_tag_open = ""; + this.prev_tag_close = ""; + this.next_link = ""; + this.next_tag_open = ""; + this.next_tag_close = ""; + this.last_tag_open = ""; + this.last_tag_close = ""; + this.cur_tag_open = ""; + this.cur_tag_close = ""; + this.num_tag_open = ""; + this.num_tag_close = ""; + this.suffix = ""; + this.prefix = ""; + this.cur_page = 0; + + this.get_page_name = () => pageName; + + this.get_heading = function () { + return pageName; + }; + + this.get_column = function () { + return this._column; + }; + + this.get_readable_column = function () { + return this._readable_column; + }; + + this.set_list = function (list) { + this._list = list; + }; + + this.set_query = function (query = {}) { + Object.keys(query).forEach((key) => { + if (this._field_column.includes(key)) { + console.log(this._query); + this._query[key] = query[key]; + } + }); + }; + + this.get_list = function () { + return this._list; + }; + + /** + * get_links function + * + * @return mixed + */ + this.get_links = function () { + this._links = this.createLinks(); + return this._links; + }; + + /** + * set_total_rows function + * + * @param integer total_rows + * @return void + */ + this.set_total_rows = function (total_rows) { + this._total_rows = total_rows; + }; + + /** + * set_per_page function + * + * @param integer per_page + * @return void + */ + this.set_per_page = function (per_page) { + this._per_page = per_page; + }; + /** + * format_layout function + * + * @param integer _format_layout + * @return void + */ + this.set_format_layout = function (_format_layout) { + this._format_layout = _format_layout; + }; + + /** + * set_order_by function + * + * @param string order_by + * @return void + */ + this.set_order_by = function (order_by) { + this._order_by = order_by; + }; + + /** + * set_sort function + * + * @param string sort + * @return void + */ + this.set_sort = function (sort) { + this._sort = sort; + }; + + /** + * set_sort_base_url function + * + * @param string sort_base_url + * @return void + */ + this.set_sort_base_url = function (sort_base_url) { + this._sort_base_url = sort_base_url; + }; + + /** + * get_total_rows function + * + * @return integer + */ + this.get_total_rows = function () { + return this._total_rows; + }; + + /** + * get_format_layout function + * + * @return integer + */ + this.get_format_layout = function () { + return this._format_layout; + }; + + /** + * get_per_page function + * + * @return integer + */ + this.get_per_page = function () { + return this._per_page; + }; + + /** + * get_page function + * + * @return integer + */ + this.get_page = function () { + return this._page; + }; + + /** + * num_links function + * + * @return integer + */ + this.get_num_links = function () { + return this._num_links; + }; + + /** + * set_order_by function + * + */ + this.get_order_by = function () { + return this._order_by; + }; + + /** + * get_field_column function + * + */ + this.get_field_column = function () { + return this._field_column; + }; + + this.get_readable_field_column = function () { + return this._readable_field_column; + }; + + /** + * set_sort function + * + */ + this.get_sort = function () { + return this._sort; + }; + + this.get_query = function () { + return this._query; + }; + + /** + * set_sort_base_url function + * + */ + this.get_sort_base_url = function () { + return this._sort_base_url; + }; + + /** + * set_page function + * + * @param integer page + * @return void + */ + this.set_page = function (page) { + this._page = page; + }; + + /** + * num_pages function + * + * @return integer + */ + this.get_num_page = function () { + let num = Math.ceil(this._total_rows / this._per_page); + return num > 0 ? parseInt(num) : 1; + }; + + this.image_or_file = function (file) { + const images = [".jpg", ".png", ".gif", ".jpeg", ".bmp"]; + let is_image = false; + const exist = images.filter(function (value) { + return value.indexOf(file) > -1; + }); + + if (exist.length > 0) { + return `
        `; + } + + return `${file}`; + }; + + this.timeago = function (date) { + const newDate = new Date(date); + const today = new Date(); + const currentTime = today.getTime(); + const timestamp = newDate.getTime(); + + const strTime = array("second", "minute", "hour", "day", "month", "year"); + const duration = array(60, 60, 24, 30, 12, 10); + + if (currentTime >= timestamp) { + diff = currentTime - timestamp; + + for (let i = 0; diff >= duration[i] && i < duration.length - 1; i++) { + diff = diff / duration[i]; + } + + diff = Math.round(diff, 0); + return diff + " " + strTime[i] + "(s) ago "; + } + }; + + this.time_default_mapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0" + i : i; + let min = j < 10 ? "0" + j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + this.convertToString = function (input) { + if (input) { + if (typeof input === "string") { + return input; + } + + return String(input); + } + return ""; + }; + + // convert string to words + this.toWords = function (input) { + input = this.convertToString(input); + + var regex = /[A-Z\xC0-\xD6\xD8-\xDE]?[a-z\xDF-\xF6\xF8-\xFF]+|[A-Z\xC0-\xD6\xD8-\xDE]+(?![a-z\xDF-\xF6\xF8-\xFF])|\d+/g; + + return input.match(regex); + }; + + // convert the input array to camel case + this.toCamelCase = function (inputArray) { + let result = ""; + + for (let i = 0, len = inputArray.length; i < len; i++) { + let currentStr = inputArray[i]; + + let tempStr = currentStr.toLowerCase(); + + if (i != 0) { + // convert first letter to upper case (the word is in lowercase) + tempStr = tempStr.substr(0, 1).toUpperCase() + tempStr.substr(1); + } + + result += tempStr; + } + + return result; + }; + + this.toCamelCaseString = function (input) { + let words = this.toWords(input); + + return this.toCamelCase(words); + }; + + this.ucFirst = function (string) { + if (typeof string === "string") { + return string.charAt(0).toUpperCase() + string.slice(1); + } + return ""; + }; + + this.number_format = function (field, n) { + return field.toFixed(n); + }; + + this.date = function (d) { + return ("0" + (d.getMonth() + 1)).slice(-2) + " " + ("0" + d.getDate()).slice(-2) + " " + d.getFullYear(); + }; + + this.datetime = function (d) { + return ("0" + (d.getMonth() + 1)).slice(-2) + " " + ("0" + d.getDate()).slice(-2) + " " + d.getFullYear() + " " + ("0" + d.getHours()).slice(-2) + ":" + ("0" + d.getMinutes()).slice(-2); + }; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + // 2018-06-12T19:30 + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + this.createLinks = function () { + let totalItems = this._total_rows; + let currentPage = this._page; + let pageSize = this._per_page; + let maxPages = 10; + // calculate total pages + let totalPages = Math.ceil(totalItems / pageSize); + + // ensure current page isn't out of range + if (currentPage < 0) { + currentPage = 0; + } else if (currentPage > totalPages) { + currentPage = +totalPages; + } + + let startPage = 0; + let endPage = 0; + + if (totalPages <= maxPages) { + // total pages less than max so show all pages + startPage = 1; + endPage = totalPages; + } else { + // total pages more than max so calculate start and end pages + let maxPagesBeforeCurrentPage = Math.floor(maxPages / 2); + let maxPagesAfterCurrentPage = Math.ceil(maxPages / 2) - 1; + if (currentPage <= maxPagesBeforeCurrentPage) { + // current page near the start + startPage = 1; + endPage = maxPages; + } else if (currentPage + maxPagesAfterCurrentPage >= totalPages) { + // current page near the end + startPage = totalPages - maxPages + 1; + endPage = totalPages; + } else { + // current page somewhere in the middle + startPage = currentPage - maxPagesBeforeCurrentPage; + endPage = currentPage + maxPagesAfterCurrentPage; + } + } + + // calculate start and end item indexes + let startIndex = (currentPage - 1) * pageSize; + let endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1); + + // create an array of pages to ng-repeat in the pager control + let pages = Array.from(Array(endPage + 1 - startPage).keys()).map((i) => startPage + i); + + // return object with all pager properties required by the view + const payload = { + totalItems: totalItems, + currentPage: currentPage, + pageSize: pageSize, + totalPages: totalPages, + startPage: startPage, + endPage: endPage, + startIndex: startIndex, + endIndex: endIndex, + pages: pages, + }; + + let html = '
          '; + for (let i = 0; i < payload.pages.length && payload.pages.length > 1; i++) { + const element = +payload.pages[i]; + if (element - 1 == payload.currentPage) { + html += `
        • ${element}(current)
        • `; + } else { + html += `
        • ${element}
        • `; + } + } + html += "
        "; + return html; + }; + + this.get_id = function () { + return this._id; + }; + + this.set_id = function (id) { + this._id = id; + }; + + this._id = null; + + this.get_name = function () { + return this._name; + }; + + this.set_name = function (name) { + this._name = name; + }; + + this._name = null; + + this.to_json = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["name"] = value["name"]; + clean_list_entry["active_list"] = value["active_list"]; + clean_list_entry["ranges_response"] = value["ranges_response"]; + clean_list.push(clean_list_entry); + } + + return { + page: this.get_page(), + num_page: this.get_num_page(), + num_item: this.get_total_rows(), + item: clean_list, + }; + }; + + this.to_csv = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["name"] = value["name"]; + clean_list_entry["active_list"] = value["active_list"]; + clean_list_entry["ranges_response"] = value["ranges_response"]; + clean_list.push(clean_list_entry); + } + + const columns = this.get_field_column(); + + const column_fields = this.get_readable_field_column(); + + const fields = column_fields.filter(function (v, index) { + if (v.length === 0) { + columns.splice(index, 1); + } + return v.length > 0; + }); + + let csv = columns.join(",") + "\n"; + for (let i = 0; i < clean_list.length; i++) { + let row = clean_list[i]; + let row_csv = []; + for (const key in row) { + let column = row[key]; + if (fields.includes(key)) { + row_csv.push('"' + column + '"'); + } + } + csv = csv + row_csv.join(",") + "\n"; + } + return csv; + }; + + return this; +}; diff --git a/view_models/questions_admin_add_view_model.js b/view_models/questions_admin_add_view_model.js new file mode 100644 index 0000000..d744de7 --- /dev/null +++ b/view_models/questions_admin_add_view_model.js @@ -0,0 +1,66 @@ +"use strict"; + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Questions Add View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +const db = require("../models"); +let AuthService = require("../services/AuthService"); + +module.exports = function (entity, pageName = "", success, error, base_url = "") { + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this._base_url = base_url; + + this.get_page_name = () => pageName; + + this.endpoint = "/admin/questions"; + + this.heading = "Add question"; + + this.action = "/admin/questions-add"; + + this.form_fields = { + quiz_id: "", + question: "", + question_arguments: "", + order: "", + image_width: "", + image_height: "", + note: "", + note_type: "", + target: "", + response: "", + save_response_into: "", + depends_on: "", + slider_range: "", + output_variable_name: "", + weight: "", + extra_output_variable: "", + type: "", + }; + + this.type_mapping = function () { + return this._entity.type_mapping(); + }; + + this.target_mapping = function () { + return this._entity.target_mapping(); + }; + + this.note_type_mapping = function () { + return this._entity.note_type_mapping(); + }; + + return this; +}; diff --git a/view_models/questions_admin_delete_view_model.js b/view_models/questions_admin_delete_view_model.js new file mode 100644 index 0000000..b56174a --- /dev/null +++ b/view_models/questions_admin_delete_view_model.js @@ -0,0 +1,40 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Questions Delete View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +const db = require('../models'); + +module.exports = function (entity, success, error) { + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + return this; +}; diff --git a/view_models/questions_admin_detail_view_model.js b/view_models/questions_admin_detail_view_model.js new file mode 100644 index 0000000..9cfc27e --- /dev/null +++ b/view_models/questions_admin_detail_view_model.js @@ -0,0 +1,47 @@ +"use strict"; + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Questions V View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName = "", success, error, base_url = "") { + this.entity = entity; + + this.success = success || null; + this.error = error || null; + + this._base_url = base_url; + + this.endpoint = "/admin/questions"; + + this.get_page_name = () => pageName; + + this.heading = "Question details"; + + this.detail_fields = { + id: "", + "quiz.name": "", + question: "", + question_arguments: "", + order: "", + note: "", + note_type: "", + target: "", + response: "", + save_response_into: "", + depends_on: "", + slider_range: "", + output_variable_name: "", + weight: "", + extra_output_variable: "", + type: "", + }; + + return this; +}; diff --git a/view_models/questions_admin_edit_view_model.js b/view_models/questions_admin_edit_view_model.js new file mode 100644 index 0000000..906c598 --- /dev/null +++ b/view_models/questions_admin_edit_view_model.js @@ -0,0 +1,82 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Questions Edit View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ +const db = require("../models"); + +module.exports = function (entity, pageName = "", success, error, base_url = "") { + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this._base_url = base_url; + + this.endpoint = "/admin/questions"; + + this.get_page_name = () => pageName; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + this.heading = "Edit question"; + + this.action = "/admin/questions-edit"; + + this.form_fields = { + quiz_id: "", + question: "", + order: "", + question_arguments: "", + note: "", + image_width: "", + image_height: "", + note_type: "", + target: "", + response: "", + save_response_into: "", + depends_on: "", + slider_range: "", + output_variable_name: "", + weight: "", + extra_output_variable: "", + type: "", + id: "", + }; + + this.type_mapping = function () { + return this._entity.type_mapping(); + }; + + this.target_mapping = function () { + return this._entity.target_mapping(); + }; + + this.note_type_mapping = function () { + return this._entity.note_type_mapping(); + }; + + return this; +}; diff --git a/view_models/questions_admin_list_paginate_view_model.js b/view_models/questions_admin_list_paginate_view_model.js new file mode 100644 index 0000000..6660f13 --- /dev/null +++ b/view_models/questions_admin_list_paginate_view_model.js @@ -0,0 +1,583 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Questions Paginate List View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName, success, error, baseUrl) { + this.success = success ? success : ""; + this.error = error ? error : ""; + this._list = []; + this._column = ["Quiz", "Question", "Order", "Type", "Output variable", "Action"]; + this._readable_column = ["Quiz", "Question", "Order", "Type", "Output variable"]; + this._entity = entity; + this._heading = "Questions"; + this._base_url = baseUrl.endsWith("/") ? baseUrl.substring(0, -1) : baseUrl; + this._query = {}; + this._total_rows = 0; + this._format_layout = ""; + this._per_page = 10; + this._page; + this._num_links = 5; + this._field_column = ["quiz.id", "order", "id", "type", "", ""]; + this._readable_field_column = ["quiz", "order", "id", "type"]; + this._links = ""; + this._sort_base_url = ""; + this._order_by = ""; + this._sort = ""; + this._link_types = { start: "start", prev: "prev", next: "next" }; + this._attributes = ' class="page-link"'; + this.reuse_query_string = true; + this.page_query_string = true; + this.full_tag_open = ""; + this.full_tag_close = ""; + this.attributes = ""; + this.first_link = ""; + this.last_link = ""; + this.first_tag_open = ""; + this.query_string_segment = "per_page"; + this.first_tag_close = ""; + this.prev_link = ""; + this.prev_tag_open = ""; + this.prev_tag_close = ""; + this.next_link = ""; + this.next_tag_open = ""; + this.next_tag_close = ""; + this.last_tag_open = ""; + this.last_tag_close = ""; + this.cur_tag_open = ""; + this.cur_tag_close = ""; + this.num_tag_open = ""; + this.num_tag_close = ""; + this.suffix = ""; + this.prefix = ""; + this.cur_page = 0; + + this.get_page_name = () => pageName; + + this.get_heading = function () { + return pageName; + }; + + this.get_column = function () { + return this._column; + }; + + this.get_readable_column = function () { + return this._readable_column; + }; + + this.set_list = function (list) { + this._list = list; + }; + + this.set_query = function (query = {}) { + Object.keys(query).forEach((key) => { + if (this._field_column.includes(key)) { + console.log(this._query); + this._query[key] = query[key]; + } + }); + }; + + this.get_list = function () { + return this._list; + }; + + /** + * get_links function + * + * @return mixed + */ + this.get_links = function () { + this._links = this.createLinks(); + return this._links; + }; + + /** + * set_total_rows function + * + * @param integer total_rows + * @return void + */ + this.set_total_rows = function (total_rows) { + this._total_rows = total_rows; + }; + + /** + * set_per_page function + * + * @param integer per_page + * @return void + */ + this.set_per_page = function (per_page) { + this._per_page = per_page; + }; + /** + * format_layout function + * + * @param integer _format_layout + * @return void + */ + this.set_format_layout = function (_format_layout) { + this._format_layout = _format_layout; + }; + + /** + * set_order_by function + * + * @param string order_by + * @return void + */ + this.set_order_by = function (order_by) { + this._order_by = order_by; + }; + + /** + * set_sort function + * + * @param string sort + * @return void + */ + this.set_sort = function (sort) { + this._sort = sort; + }; + + /** + * set_sort_base_url function + * + * @param string sort_base_url + * @return void + */ + this.set_sort_base_url = function (sort_base_url) { + this._sort_base_url = sort_base_url; + }; + + /** + * get_total_rows function + * + * @return integer + */ + this.get_total_rows = function () { + return this._total_rows; + }; + + /** + * get_format_layout function + * + * @return integer + */ + this.get_format_layout = function () { + return this._format_layout; + }; + + /** + * get_per_page function + * + * @return integer + */ + this.get_per_page = function () { + return this._per_page; + }; + + /** + * get_page function + * + * @return integer + */ + this.get_page = function () { + return this._page; + }; + + /** + * num_links function + * + * @return integer + */ + this.get_num_links = function () { + return this._num_links; + }; + + /** + * set_order_by function + * + */ + this.get_order_by = function () { + return this._order_by; + }; + + /** + * get_field_column function + * + */ + this.get_field_column = function () { + return this._field_column; + }; + + this.get_readable_field_column = function () { + return this._readable_field_column; + }; + + /** + * set_sort function + * + */ + this.get_sort = function () { + return this._sort; + }; + + this.get_query = function () { + return this._query; + }; + + /** + * set_sort_base_url function + * + */ + this.get_sort_base_url = function () { + return this._sort_base_url; + }; + + /** + * set_page function + * + * @param integer page + * @return void + */ + this.set_page = function (page) { + this._page = page; + }; + + /** + * num_pages function + * + * @return integer + */ + this.get_num_page = function () { + let num = Math.ceil(this._total_rows / this._per_page); + return num > 0 ? parseInt(num) : 1; + }; + + this.image_or_file = function (file) { + const images = [".jpg", ".png", ".gif", ".jpeg", ".bmp"]; + let is_image = false; + const exist = images.filter(function (value) { + return value.indexOf(file) > -1; + }); + + if (exist.length > 0) { + return `
        `; + } + + return `${file}`; + }; + + this.timeago = function (date) { + const newDate = new Date(date); + const today = new Date(); + const currentTime = today.getTime(); + const timestamp = newDate.getTime(); + + const strTime = array("second", "minute", "hour", "day", "month", "year"); + const duration = array(60, 60, 24, 30, 12, 10); + + if (currentTime >= timestamp) { + diff = currentTime - timestamp; + + for (let i = 0; diff >= duration[i] && i < duration.length - 1; i++) { + diff = diff / duration[i]; + } + + diff = Math.round(diff, 0); + return diff + " " + strTime[i] + "(s) ago "; + } + }; + + this.time_default_mapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0" + i : i; + let min = j < 10 ? "0" + j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + this.convertToString = function (input) { + if (input) { + if (typeof input === "string") { + return input; + } + + return String(input); + } + return ""; + }; + + // convert string to words + this.toWords = function (input) { + input = this.convertToString(input); + + var regex = /[A-Z\xC0-\xD6\xD8-\xDE]?[a-z\xDF-\xF6\xF8-\xFF]+|[A-Z\xC0-\xD6\xD8-\xDE]+(?![a-z\xDF-\xF6\xF8-\xFF])|\d+/g; + + return input.match(regex); + }; + + // convert the input array to camel case + this.toCamelCase = function (inputArray) { + let result = ""; + + for (let i = 0, len = inputArray.length; i < len; i++) { + let currentStr = inputArray[i]; + + let tempStr = currentStr.toLowerCase(); + + if (i != 0) { + // convert first letter to upper case (the word is in lowercase) + tempStr = tempStr.substr(0, 1).toUpperCase() + tempStr.substr(1); + } + + result += tempStr; + } + + return result; + }; + + this.toCamelCaseString = function (input) { + let words = this.toWords(input); + + return this.toCamelCase(words); + }; + + this.ucFirst = function (string) { + if (typeof string === "string") { + return string.charAt(0).toUpperCase() + string.slice(1); + } + return ""; + }; + + this.number_format = function (field, n) { + return field.toFixed(n); + }; + + this.date = function (d) { + return ("0" + (d.getMonth() + 1)).slice(-2) + " " + ("0" + d.getDate()).slice(-2) + " " + d.getFullYear(); + }; + + this.datetime = function (d) { + return ("0" + (d.getMonth() + 1)).slice(-2) + " " + ("0" + d.getDate()).slice(-2) + " " + d.getFullYear() + " " + ("0" + d.getHours()).slice(-2) + ":" + ("0" + d.getMinutes()).slice(-2); + }; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + // 2018-06-12T19:30 + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + this.createLinks = function () { + let totalItems = this._total_rows; + let currentPage = this._page; + let pageSize = this._per_page; + let maxPages = 10; + // calculate total pages + let totalPages = Math.ceil(totalItems / pageSize); + + // ensure current page isn't out of range + if (currentPage < 0) { + currentPage = 0; + } else if (currentPage > totalPages) { + currentPage = +totalPages; + } + + let startPage = 0; + let endPage = 0; + + if (totalPages <= maxPages) { + // total pages less than max so show all pages + startPage = 1; + endPage = totalPages; + } else { + // total pages more than max so calculate start and end pages + let maxPagesBeforeCurrentPage = Math.floor(maxPages / 2); + let maxPagesAfterCurrentPage = Math.ceil(maxPages / 2) - 1; + if (currentPage <= maxPagesBeforeCurrentPage) { + // current page near the start + startPage = 1; + endPage = maxPages; + } else if (currentPage + maxPagesAfterCurrentPage >= totalPages) { + // current page near the end + startPage = totalPages - maxPages + 1; + endPage = totalPages; + } else { + // current page somewhere in the middle + startPage = currentPage - maxPagesBeforeCurrentPage; + endPage = currentPage + maxPagesAfterCurrentPage; + } + } + + // calculate start and end item indexes + let startIndex = (currentPage - 1) * pageSize; + let endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1); + + // create an array of pages to ng-repeat in the pager control + let pages = Array.from(Array(endPage + 1 - startPage).keys()).map((i) => startPage + i); + + // return object with all pager properties required by the view + const payload = { + totalItems: totalItems, + currentPage: currentPage, + pageSize: pageSize, + totalPages: totalPages, + startPage: startPage, + endPage: endPage, + startIndex: startIndex, + endIndex: endIndex, + pages: pages, + }; + + let html = '
          '; + for (let i = 0; i < payload.pages.length && payload.pages.length > 1; i++) { + const element = +payload.pages[i]; + if (element - 1 == payload.currentPage) { + html += `
        • ${element}(current)
        • `; + } else { + html += `
        • ${element}
        • `; + } + } + html += "
        "; + return html; + }; + + this.get_id = function () { + return this._id; + }; + + this.set_id = function (id) { + this._id = id; + }; + + this._id = null; + + this.get_quiz_id = function () { + return this._quiz_id; + }; + + this.set_quiz_id = function (quiz_id) { + this._quiz_id = quiz_id; + }; + + this._quiz_id = null; + + this.get_type = function () { + return this._type; + }; + + this.set_type = function (type) { + this._type = type; + }; + + this._type = null; + + this.type_mapping = function () { + return this._entity.type_mapping(); + }; + + this.target_mapping = function () { + return this._entity.target_mapping(); + }; + + this.note_type_mapping = function () { + return this._entity.note_type_mapping(); + }; + + this.to_json = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + list[key].type = this.type_mapping()[value.type]; + list[key].target = this.target_mapping()[value.target]; + list[key].note_type = this.note_type_mapping()[value.note_type]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["question"] = value["question"]; + clean_list_entry["type"] = value["type"]; + clean_list.push(clean_list_entry); + } + + return { + page: this.get_page(), + num_page: this.get_num_page(), + num_item: this.get_total_rows(), + item: clean_list, + }; + }; + + this.to_csv = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + list[key].type = this.type_mapping()[value.type]; + list[key].target = this.target_mapping()[value.target]; + list[key].note_type = this.note_type_mapping()[value.note_type]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["question"] = value["question"]; + clean_list_entry["type"] = value["type"]; + clean_list.push(clean_list_entry); + } + + const columns = this.get_field_column(); + + const column_fields = this.get_readable_field_column(); + + const fields = column_fields.filter(function (v, index) { + if (v.length === 0) { + columns.splice(index, 1); + } + return v.length > 0; + }); + + let csv = columns.join(",") + "\n"; + for (let i = 0; i < clean_list.length; i++) { + let row = clean_list[i]; + let row_csv = []; + for (const key in row) { + let column = row[key]; + if (fields.includes(key)) { + row_csv.push('"' + column + '"'); + } + } + csv = csv + row_csv.join(",") + "\n"; + } + return csv; + }; + + return this; +}; diff --git a/view_models/quizzes_admin_add_view_model.js b/view_models/quizzes_admin_add_view_model.js new file mode 100644 index 0000000..53a9241 --- /dev/null +++ b/view_models/quizzes_admin_add_view_model.js @@ -0,0 +1,46 @@ +'use strict' + + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Quizzes Add View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + + const db = require('../models') + let AuthService = require('../services/AuthService'); + + +module.exports = function (entity, pageName='', success, error, base_url = "" ) { + + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this._base_url = base_url; + + + + this.get_page_name = () => pageName; + + this.endpoint = "/admin/quizzes" + + + this.heading = "Add quiz" + + this.action = "/admin/quizzes-add" + + + + this.form_fields = {"name":"","description":""} + + + + return this; +} diff --git a/view_models/quizzes_admin_delete_view_model.js b/view_models/quizzes_admin_delete_view_model.js new file mode 100644 index 0000000..314a401 --- /dev/null +++ b/view_models/quizzes_admin_delete_view_model.js @@ -0,0 +1,40 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Quizzes Delete View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +const db = require('../models'); + +module.exports = function (entity, success, error) { + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + return this; +}; diff --git a/view_models/quizzes_admin_detail_view_model.js b/view_models/quizzes_admin_detail_view_model.js new file mode 100644 index 0000000..f4e6af6 --- /dev/null +++ b/view_models/quizzes_admin_detail_view_model.js @@ -0,0 +1,33 @@ +'use strict' + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Quizzes V View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName='', success, error, base_url = "" ) { + + this.entity = entity + + this.success = success || null + this.error = error || null + + this._base_url = base_url + + this.endpoint = "/admin/quizzes" + + this.get_page_name = () => pageName + + this.heading = "Quiz details" + + + this.detail_fields = {"id":"","name":"","description":""} + + + return this; +} diff --git a/view_models/quizzes_admin_edit_view_model.js b/view_models/quizzes_admin_edit_view_model.js new file mode 100644 index 0000000..922fa59 --- /dev/null +++ b/view_models/quizzes_admin_edit_view_model.js @@ -0,0 +1,58 @@ +'use strict' +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Quizzes Edit View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + const db = require('../models'); + +module.exports = function (entity, pageName='', success, error, base_url = "") { + + this._entity = entity + this.session = null + + this.success = success || null + this.error = error || null + + this._base_url = base_url + + this.endpoint = "/admin/quizzes" + + this.get_page_name = () => pageName + + this.format_date_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + return `${year}-${month}-${day}` + } + + this.format_date_local_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + const hrs = d.getHours() < 10 ? `0${d.getHours() }` : d.getHours() ; + const mins = d.getMinutes() < 10 ? `0${d.getMinutes() }` : d.getMinutes() ; + return `${year}-${month}-${day}T${hrs}:${mins}` + } + + this.heading = "Edit quiz" + + this.action = "/admin/quizzes-edit" + + + + + this.form_fields = {"name":"","description":"","id":""} + + + + + return this; +} diff --git a/view_models/quizzes_admin_list_paginate_view_model.js b/view_models/quizzes_admin_list_paginate_view_model.js new file mode 100644 index 0000000..c09fd24 --- /dev/null +++ b/view_models/quizzes_admin_list_paginate_view_model.js @@ -0,0 +1,583 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Quizzes Paginate List View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName, success, error, baseUrl) { + this.success = success ? success : ""; + this.error = error ? error : ""; + this._list = []; + this._column = ['ID','Name','Description','Action']; + this._readable_column = ["ID","Name","Description"]; + this._entity = entity; + this._heading = 'Quizzes'; + this._base_url = baseUrl.endsWith('/') ? baseUrl.substring(0, -1) : baseUrl; + this._query = {}; + this._total_rows = 0; + this._format_layout = ''; + this._per_page = 10; + this._page; + this._num_links = 5; + this._field_column = ['id','name','description']; + this._readable_field_column = ["id","name","description"] + this._links = ''; + this._sort_base_url = ''; + this._order_by = ''; + this._sort = ''; + this._link_types = {'start': 'start', 'prev': 'prev', 'next': 'next'}; + this._attributes = ' class="page-link"'; + this.reuse_query_string = true; + this.page_query_string = true; + this.full_tag_open = ''; + this.full_tag_close = ''; + this.attributes = ''; + this.first_link = ''; + this.last_link = ''; + this.first_tag_open = ''; + this.query_string_segment = 'per_page'; + this.first_tag_close = ''; + this.prev_link = ''; + this.prev_tag_open = ''; + this.prev_tag_close = ''; + this.next_link = ''; + this.next_tag_open = ''; + this.next_tag_close = ''; + this.last_tag_open = ''; + this.last_tag_close = ''; + this.cur_tag_open = ''; + this.cur_tag_close = ''; + this.num_tag_open = ''; + this.num_tag_close = ''; + this.suffix = ''; + this.prefix = ''; + this.cur_page = 0; + + + this.get_page_name = () => pageName + + + this.get_heading = function () { + return pageName; + }; + + this.get_column = function () { + return this._column; + }; + + this.get_readable_column = function () { + return this._readable_column; + }; + + this.set_list = function (list) { + this._list = list; + }; + + this.set_query = function (query = {}) { + Object.keys(query).forEach((key) => { + if (this._field_column.includes(key)) { + console.log(this._query); + this._query[key] = query[key]; + } + }); + }; + + + this.get_list = function () { + return this._list; + }; + + /** + * get_links function + * + * @return mixed + */ + this.get_links = function () { + this._links = this.createLinks(); + return this._links; + }; + + /** + * set_total_rows function + * + * @param integer total_rows + * @return void + */ + this.set_total_rows = function (total_rows) { + this._total_rows = total_rows; + }; + + /** + * set_per_page function + * + * @param integer per_page + * @return void + */ + this.set_per_page = function (per_page) { + this._per_page = per_page; + }; + /** + * format_layout function + * + * @param integer _format_layout + * @return void + */ + this.set_format_layout = function (_format_layout) { + this._format_layout = _format_layout; + }; + + /** + * set_order_by function + * + * @param string order_by + * @return void + */ + this.set_order_by = function (order_by) { + this._order_by = order_by; + }; + + /** + * set_sort function + * + * @param string sort + * @return void + */ + this.set_sort = function (sort) { + this._sort = sort; + }; + + /** + * set_sort_base_url function + * + * @param string sort_base_url + * @return void + */ + this.set_sort_base_url = function (sort_base_url) { + this._sort_base_url = sort_base_url; + }; + + /** + * get_total_rows function + * + * @return integer + */ + this.get_total_rows = function () { + return this._total_rows; + }; + + /** + * get_format_layout function + * + * @return integer + */ + this.get_format_layout = function () { + return this._format_layout; + }; + + /** + * get_per_page function + * + * @return integer + */ + this.get_per_page = function () { + return this._per_page; + }; + + /** + * get_page function + * + * @return integer + */ + this.get_page = function () { + return this._page; + }; + + /** + * num_links function + * + * @return integer + */ + this.get_num_links = function () { + return this._num_links; + }; + + /** + * set_order_by function + * + */ + this.get_order_by = function () { + return this._order_by; + }; + + /** + * get_field_column function + * + */ + this.get_field_column = function () { + return this._field_column; + }; + + this.get_readable_field_column = function () { + return this._readable_field_column; + }; + + /** + * set_sort function + * + */ + this.get_sort = function () { + return this._sort; + }; + + + this.get_query = function () { + return this._query; + }; + + + /** + * set_sort_base_url function + * + */ + this.get_sort_base_url = function () { + return this._sort_base_url; + }; + + /** + * set_page function + * + * @param integer page + * @return void + */ + this.set_page = function (page) { + this._page = page; + }; + + /** + * num_pages function + * + * @return integer + */ + this.get_num_page = function () { + let num = Math.ceil(this._total_rows / this._per_page); + return num > 0 ? parseInt(num) : 1; + }; + + this.image_or_file = function (file) { + const images = [".jpg", ".png", ".gif", ".jpeg", ".bmp"]; + let is_image = false; + const exist = images.filter(function (value) { + return value.indexOf(file) > -1; + }); + + if (exist.length > 0) { + return `
        `; + } + + return `${file}`; + }; + + this.timeago = function (date) { + const newDate = new Date(date); + const today = new Date(); + const currentTime = today.getTime(); + const timestamp = newDate.getTime(); + + const strTime = array("second", "minute", "hour", "day", "month", "year"); + const duration = array(60, 60, 24, 30, 12, 10); + + if (currentTime >= timestamp) { + diff = currentTime - timestamp; + + for (let i = 0; diff >= duration[i] && i < duration.length - 1; i++) { + diff = diff / duration[i]; + } + + diff = Math.round(diff, 0); + return diff + " " + strTime[i] + "(s) ago "; + } + }; + + this.time_default_mapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0" + i : i; + let min = j < 10 ? "0" + j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + this.convertToString = function (input) { + if (input) { + if (typeof input === "string") { + return input; + } + + return String(input); + } + return ""; + }; + + // convert string to words + this.toWords = function (input) { + input = this.convertToString(input); + + var regex = /[A-Z\xC0-\xD6\xD8-\xDE]?[a-z\xDF-\xF6\xF8-\xFF]+|[A-Z\xC0-\xD6\xD8-\xDE]+(?![a-z\xDF-\xF6\xF8-\xFF])|\d+/g; + + return input.match(regex); + }; + + // convert the input array to camel case + this.toCamelCase = function (inputArray) { + let result = ""; + + for (let i = 0, len = inputArray.length; i < len; i++) { + let currentStr = inputArray[i]; + + let tempStr = currentStr.toLowerCase(); + + if (i != 0) { + // convert first letter to upper case (the word is in lowercase) + tempStr = tempStr.substr(0, 1).toUpperCase() + tempStr.substr(1); + } + + result += tempStr; + } + + return result; + }; + + this.toCamelCaseString = function (input) { + let words = this.toWords(input); + + return this.toCamelCase(words); + }; + + this.ucFirst = function (string) { + if (typeof string === 'string') { + return string.charAt(0).toUpperCase() + string.slice(1); + } + return ''; + }; + + + this.number_format = function (field, n) { + return field.toFixed(n); + }; + + this.date = function (d) { + return ( + ("0" + (d.getMonth() + 1)).slice(-2) + + " " + + ("0" + d.getDate()).slice(-2) + + " " + + d.getFullYear() + ); + }; + + this.datetime = function (d) { + return ( + ("0" + (d.getMonth() + 1)).slice(-2) + + " " + + ("0" + d.getDate()).slice(-2) + + " " + + d.getFullYear() + + " " + + ("0" + d.getHours()).slice(-2) + + ":" + + ("0" + d.getMinutes()).slice(-2) + ); + }; + + this.format_date_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + return `${year}-${month}-${day}` + } + // 2018-06-12T19:30 + this.format_date_local_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + const hrs = d.getHours() < 10 ? `0${d.getHours() }` : d.getHours() ; + const mins = d.getMinutes() < 10 ? `0${d.getMinutes() }` : d.getMinutes() ; + return `${year}-${month}-${day}T${hrs}:${mins}` + } + + this.createLinks = function () { + let totalItems = this._total_rows; + let currentPage = this._page; + let pageSize = this._per_page; + let maxPages = 10; + // calculate total pages + let totalPages = Math.ceil(totalItems / pageSize); + + // ensure current page isn't out of range + if (currentPage < 0) { + currentPage = 0; + } else if (currentPage > totalPages) { + currentPage = +totalPages; + } + + let startPage = 0; + let endPage = 0; + + if (totalPages <= maxPages) { + // total pages less than max so show all pages + startPage = 1; + endPage = totalPages; + } else { + // total pages more than max so calculate start and end pages + let maxPagesBeforeCurrentPage = Math.floor(maxPages / 2); + let maxPagesAfterCurrentPage = Math.ceil(maxPages / 2) - 1; + if (currentPage <= maxPagesBeforeCurrentPage) { + // current page near the start + startPage = 1; + endPage = maxPages; + } else if (currentPage + maxPagesAfterCurrentPage >= totalPages) { + // current page near the end + startPage = totalPages - maxPages + 1; + endPage = totalPages; + } else { + // current page somewhere in the middle + startPage = currentPage - maxPagesBeforeCurrentPage; + endPage = currentPage + maxPagesAfterCurrentPage; + } + } + + // calculate start and end item indexes + let startIndex = (currentPage - 1) * pageSize; + let endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1); + + // create an array of pages to ng-repeat in the pager control + let pages = Array.from(Array(endPage + 1 - startPage).keys()).map( + (i) => startPage + i + ); + + + // return object with all pager properties required by the view + const payload = { + totalItems: totalItems, + currentPage: currentPage, + pageSize: pageSize, + totalPages: totalPages, + startPage: startPage, + endPage: endPage, + startIndex: startIndex, + endIndex: endIndex, + pages: pages, + }; + + + let html = '
          '; + for (let i = 0; i < payload.pages.length && payload.pages.length > 1; i++) { + const element = +payload.pages[i]; + if (element - 1 == payload.currentPage) { + html += `
        • ${element}(current)
        • `; + } else { + html += `
        • ${element}
        • `; + } + } + html += "
        "; + return html; + }; + + + this.get_id = function () { + return this._id; + } + + this.set_id = function (id) { + this._id = id; + } + + this._id = null; + + this.get_name = function () { + return this._name; + } + + this.set_name = function (name) { + this._name = name; + } + + this._name = null; + + + + this.to_json = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["name"] = value["name"]; + clean_list_entry["description"] = value["description"]; + clean_list.push(clean_list_entry); + } + + return { + "page" : this.get_page(), + "num_page" : this.get_num_page(), + "num_item" : this.get_total_rows(), + "item" : clean_list + }; + }; + + this.to_csv = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["name"] = value["name"]; + clean_list_entry["description"] = value["description"]; + clean_list.push(clean_list_entry); + } + + const columns = this.get_field_column(); + + const column_fields = this.get_readable_field_column(); + + const fields = column_fields.filter(function(v, index){ +if (v.length === 0) {columns.splice(index, 1); +} +return v.length > 0;}); + + let csv = columns.join(",") + "\n"; + for (let i = 0; i < clean_list.length; i++) { + let row = clean_list[i]; + let row_csv = []; + for (const key in row) { + let column = row[key]; + if (fields.includes(key)) { + row_csv.push('"' + column + '"'); + } + } + csv = csv + row_csv.join(',') + "\n"; + } + return csv; +} + + + return this; +}; \ No newline at end of file diff --git a/view_models/result_profile_admin_add_view_model.js b/view_models/result_profile_admin_add_view_model.js new file mode 100644 index 0000000..123c6f4 --- /dev/null +++ b/view_models/result_profile_admin_add_view_model.js @@ -0,0 +1,46 @@ +'use strict' + + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Result_profile Add View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + + const db = require('../models') + let AuthService = require('../services/AuthService'); + + +module.exports = function (entity, pageName='', success, error, base_url = "" ) { + + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this._base_url = base_url; + + + + this.get_page_name = () => pageName; + + this.endpoint = "/admin/profile-sections" + + + this.heading = "Add result profile" + + this.action = "/admin/profile-sections-add" + + + + this.form_fields = {"section_title":"","output_variable_list":""} + + + + return this; +} diff --git a/view_models/result_profile_admin_delete_view_model.js b/view_models/result_profile_admin_delete_view_model.js new file mode 100644 index 0000000..e15acdd --- /dev/null +++ b/view_models/result_profile_admin_delete_view_model.js @@ -0,0 +1,40 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Result_profile Delete View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +const db = require('../models'); + +module.exports = function (entity, success, error) { + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + return this; +}; diff --git a/view_models/result_profile_admin_detail_view_model.js b/view_models/result_profile_admin_detail_view_model.js new file mode 100644 index 0000000..006b847 --- /dev/null +++ b/view_models/result_profile_admin_detail_view_model.js @@ -0,0 +1,33 @@ +'use strict' + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Result_profile V View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName='', success, error, base_url = "" ) { + + this.entity = entity + + this.success = success || null + this.error = error || null + + this._base_url = base_url + + this.endpoint = "/admin/profile-sections" + + this.get_page_name = () => pageName + + this.heading = "Result profile details" + + + this.detail_fields = {"id":"","section_title":"","output_variable_list":""} + + + return this; +} diff --git a/view_models/result_profile_admin_edit_view_model.js b/view_models/result_profile_admin_edit_view_model.js new file mode 100644 index 0000000..2bc1dd8 --- /dev/null +++ b/view_models/result_profile_admin_edit_view_model.js @@ -0,0 +1,58 @@ +'use strict' +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Result_profile Edit View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + const db = require('../models'); + +module.exports = function (entity, pageName='', success, error, base_url = "") { + + this._entity = entity + this.session = null + + this.success = success || null + this.error = error || null + + this._base_url = base_url + + this.endpoint = "/admin/profile-sections" + + this.get_page_name = () => pageName + + this.format_date_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + return `${year}-${month}-${day}` + } + + this.format_date_local_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + const hrs = d.getHours() < 10 ? `0${d.getHours() }` : d.getHours() ; + const mins = d.getMinutes() < 10 ? `0${d.getMinutes() }` : d.getMinutes() ; + return `${year}-${month}-${day}T${hrs}:${mins}` + } + + this.heading = "Edit result profile" + + this.action = "/admin/profile-sections-edit" + + + + + this.form_fields = {"section_title":"","output_variable_list":"","id":""} + + + + + return this; +} diff --git a/view_models/result_profile_admin_list_paginate_view_model.js b/view_models/result_profile_admin_list_paginate_view_model.js new file mode 100644 index 0000000..f2db434 --- /dev/null +++ b/view_models/result_profile_admin_list_paginate_view_model.js @@ -0,0 +1,583 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Result_profile Paginate List View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName, success, error, baseUrl) { + this.success = success ? success : ""; + this.error = error ? error : ""; + this._list = []; + this._column = ['ID','Section title','Variables List','Action']; + this._readable_column = ["ID","Section title","Variables List"]; + this._entity = entity; + this._heading = 'Result profile'; + this._base_url = baseUrl.endsWith('/') ? baseUrl.substring(0, -1) : baseUrl; + this._query = {}; + this._total_rows = 0; + this._format_layout = ''; + this._per_page = 10; + this._page; + this._num_links = 5; + this._field_column = ['id','section_title','output_variable_list']; + this._readable_field_column = ["id","section_title","output_variable_list"] + this._links = ''; + this._sort_base_url = ''; + this._order_by = ''; + this._sort = ''; + this._link_types = {'start': 'start', 'prev': 'prev', 'next': 'next'}; + this._attributes = ' class="page-link"'; + this.reuse_query_string = true; + this.page_query_string = true; + this.full_tag_open = ''; + this.full_tag_close = ''; + this.attributes = ''; + this.first_link = ''; + this.last_link = ''; + this.first_tag_open = ''; + this.query_string_segment = 'per_page'; + this.first_tag_close = ''; + this.prev_link = ''; + this.prev_tag_open = ''; + this.prev_tag_close = ''; + this.next_link = ''; + this.next_tag_open = ''; + this.next_tag_close = ''; + this.last_tag_open = ''; + this.last_tag_close = ''; + this.cur_tag_open = ''; + this.cur_tag_close = ''; + this.num_tag_open = ''; + this.num_tag_close = ''; + this.suffix = ''; + this.prefix = ''; + this.cur_page = 0; + + + this.get_page_name = () => pageName + + + this.get_heading = function () { + return pageName; + }; + + this.get_column = function () { + return this._column; + }; + + this.get_readable_column = function () { + return this._readable_column; + }; + + this.set_list = function (list) { + this._list = list; + }; + + this.set_query = function (query = {}) { + Object.keys(query).forEach((key) => { + if (this._field_column.includes(key)) { + console.log(this._query); + this._query[key] = query[key]; + } + }); + }; + + + this.get_list = function () { + return this._list; + }; + + /** + * get_links function + * + * @return mixed + */ + this.get_links = function () { + this._links = this.createLinks(); + return this._links; + }; + + /** + * set_total_rows function + * + * @param integer total_rows + * @return void + */ + this.set_total_rows = function (total_rows) { + this._total_rows = total_rows; + }; + + /** + * set_per_page function + * + * @param integer per_page + * @return void + */ + this.set_per_page = function (per_page) { + this._per_page = per_page; + }; + /** + * format_layout function + * + * @param integer _format_layout + * @return void + */ + this.set_format_layout = function (_format_layout) { + this._format_layout = _format_layout; + }; + + /** + * set_order_by function + * + * @param string order_by + * @return void + */ + this.set_order_by = function (order_by) { + this._order_by = order_by; + }; + + /** + * set_sort function + * + * @param string sort + * @return void + */ + this.set_sort = function (sort) { + this._sort = sort; + }; + + /** + * set_sort_base_url function + * + * @param string sort_base_url + * @return void + */ + this.set_sort_base_url = function (sort_base_url) { + this._sort_base_url = sort_base_url; + }; + + /** + * get_total_rows function + * + * @return integer + */ + this.get_total_rows = function () { + return this._total_rows; + }; + + /** + * get_format_layout function + * + * @return integer + */ + this.get_format_layout = function () { + return this._format_layout; + }; + + /** + * get_per_page function + * + * @return integer + */ + this.get_per_page = function () { + return this._per_page; + }; + + /** + * get_page function + * + * @return integer + */ + this.get_page = function () { + return this._page; + }; + + /** + * num_links function + * + * @return integer + */ + this.get_num_links = function () { + return this._num_links; + }; + + /** + * set_order_by function + * + */ + this.get_order_by = function () { + return this._order_by; + }; + + /** + * get_field_column function + * + */ + this.get_field_column = function () { + return this._field_column; + }; + + this.get_readable_field_column = function () { + return this._readable_field_column; + }; + + /** + * set_sort function + * + */ + this.get_sort = function () { + return this._sort; + }; + + + this.get_query = function () { + return this._query; + }; + + + /** + * set_sort_base_url function + * + */ + this.get_sort_base_url = function () { + return this._sort_base_url; + }; + + /** + * set_page function + * + * @param integer page + * @return void + */ + this.set_page = function (page) { + this._page = page; + }; + + /** + * num_pages function + * + * @return integer + */ + this.get_num_page = function () { + let num = Math.ceil(this._total_rows / this._per_page); + return num > 0 ? parseInt(num) : 1; + }; + + this.image_or_file = function (file) { + const images = [".jpg", ".png", ".gif", ".jpeg", ".bmp"]; + let is_image = false; + const exist = images.filter(function (value) { + return value.indexOf(file) > -1; + }); + + if (exist.length > 0) { + return `
        `; + } + + return `${file}`; + }; + + this.timeago = function (date) { + const newDate = new Date(date); + const today = new Date(); + const currentTime = today.getTime(); + const timestamp = newDate.getTime(); + + const strTime = array("second", "minute", "hour", "day", "month", "year"); + const duration = array(60, 60, 24, 30, 12, 10); + + if (currentTime >= timestamp) { + diff = currentTime - timestamp; + + for (let i = 0; diff >= duration[i] && i < duration.length - 1; i++) { + diff = diff / duration[i]; + } + + diff = Math.round(diff, 0); + return diff + " " + strTime[i] + "(s) ago "; + } + }; + + this.time_default_mapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0" + i : i; + let min = j < 10 ? "0" + j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + this.convertToString = function (input) { + if (input) { + if (typeof input === "string") { + return input; + } + + return String(input); + } + return ""; + }; + + // convert string to words + this.toWords = function (input) { + input = this.convertToString(input); + + var regex = /[A-Z\xC0-\xD6\xD8-\xDE]?[a-z\xDF-\xF6\xF8-\xFF]+|[A-Z\xC0-\xD6\xD8-\xDE]+(?![a-z\xDF-\xF6\xF8-\xFF])|\d+/g; + + return input.match(regex); + }; + + // convert the input array to camel case + this.toCamelCase = function (inputArray) { + let result = ""; + + for (let i = 0, len = inputArray.length; i < len; i++) { + let currentStr = inputArray[i]; + + let tempStr = currentStr.toLowerCase(); + + if (i != 0) { + // convert first letter to upper case (the word is in lowercase) + tempStr = tempStr.substr(0, 1).toUpperCase() + tempStr.substr(1); + } + + result += tempStr; + } + + return result; + }; + + this.toCamelCaseString = function (input) { + let words = this.toWords(input); + + return this.toCamelCase(words); + }; + + this.ucFirst = function (string) { + if (typeof string === 'string') { + return string.charAt(0).toUpperCase() + string.slice(1); + } + return ''; + }; + + + this.number_format = function (field, n) { + return field.toFixed(n); + }; + + this.date = function (d) { + return ( + ("0" + (d.getMonth() + 1)).slice(-2) + + " " + + ("0" + d.getDate()).slice(-2) + + " " + + d.getFullYear() + ); + }; + + this.datetime = function (d) { + return ( + ("0" + (d.getMonth() + 1)).slice(-2) + + " " + + ("0" + d.getDate()).slice(-2) + + " " + + d.getFullYear() + + " " + + ("0" + d.getHours()).slice(-2) + + ":" + + ("0" + d.getMinutes()).slice(-2) + ); + }; + + this.format_date_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + return `${year}-${month}-${day}` + } + // 2018-06-12T19:30 + this.format_date_local_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + const hrs = d.getHours() < 10 ? `0${d.getHours() }` : d.getHours() ; + const mins = d.getMinutes() < 10 ? `0${d.getMinutes() }` : d.getMinutes() ; + return `${year}-${month}-${day}T${hrs}:${mins}` + } + + this.createLinks = function () { + let totalItems = this._total_rows; + let currentPage = this._page; + let pageSize = this._per_page; + let maxPages = 10; + // calculate total pages + let totalPages = Math.ceil(totalItems / pageSize); + + // ensure current page isn't out of range + if (currentPage < 0) { + currentPage = 0; + } else if (currentPage > totalPages) { + currentPage = +totalPages; + } + + let startPage = 0; + let endPage = 0; + + if (totalPages <= maxPages) { + // total pages less than max so show all pages + startPage = 1; + endPage = totalPages; + } else { + // total pages more than max so calculate start and end pages + let maxPagesBeforeCurrentPage = Math.floor(maxPages / 2); + let maxPagesAfterCurrentPage = Math.ceil(maxPages / 2) - 1; + if (currentPage <= maxPagesBeforeCurrentPage) { + // current page near the start + startPage = 1; + endPage = maxPages; + } else if (currentPage + maxPagesAfterCurrentPage >= totalPages) { + // current page near the end + startPage = totalPages - maxPages + 1; + endPage = totalPages; + } else { + // current page somewhere in the middle + startPage = currentPage - maxPagesBeforeCurrentPage; + endPage = currentPage + maxPagesAfterCurrentPage; + } + } + + // calculate start and end item indexes + let startIndex = (currentPage - 1) * pageSize; + let endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1); + + // create an array of pages to ng-repeat in the pager control + let pages = Array.from(Array(endPage + 1 - startPage).keys()).map( + (i) => startPage + i + ); + + + // return object with all pager properties required by the view + const payload = { + totalItems: totalItems, + currentPage: currentPage, + pageSize: pageSize, + totalPages: totalPages, + startPage: startPage, + endPage: endPage, + startIndex: startIndex, + endIndex: endIndex, + pages: pages, + }; + + + let html = '
          '; + for (let i = 0; i < payload.pages.length && payload.pages.length > 1; i++) { + const element = +payload.pages[i]; + if (element - 1 == payload.currentPage) { + html += `
        • ${element}(current)
        • `; + } else { + html += `
        • ${element}
        • `; + } + } + html += "
        "; + return html; + }; + + + this.get_id = function () { + return this._id; + } + + this.set_id = function (id) { + this._id = id; + } + + this._id = null; + + this.get_section_title = function () { + return this._section_title; + } + + this.set_section_title = function (section_title) { + this._section_title = section_title; + } + + this._section_title = null; + + + + this.to_json = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["section_title"] = value["section_title"]; + clean_list_entry["output_variable_list"] = value["output_variable_list"]; + clean_list.push(clean_list_entry); + } + + return { + "page" : this.get_page(), + "num_page" : this.get_num_page(), + "num_item" : this.get_total_rows(), + "item" : clean_list + }; + }; + + this.to_csv = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["section_title"] = value["section_title"]; + clean_list_entry["output_variable_list"] = value["output_variable_list"]; + clean_list.push(clean_list_entry); + } + + const columns = this.get_field_column(); + + const column_fields = this.get_readable_field_column(); + + const fields = column_fields.filter(function(v, index){ +if (v.length === 0) {columns.splice(index, 1); +} +return v.length > 0;}); + + let csv = columns.join(",") + "\n"; + for (let i = 0; i < clean_list.length; i++) { + let row = clean_list[i]; + let row_csv = []; + for (const key in row) { + let column = row[key]; + if (fields.includes(key)) { + row_csv.push('"' + column + '"'); + } + } + csv = csv + row_csv.join(',') + "\n"; + } + return csv; +} + + + return this; +}; \ No newline at end of file diff --git a/view_models/rules_admin_add_view_model.js b/view_models/rules_admin_add_view_model.js new file mode 100644 index 0000000..7a2b5d1 --- /dev/null +++ b/view_models/rules_admin_add_view_model.js @@ -0,0 +1,56 @@ +'use strict' + + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Rules Add View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + + const db = require('../models') + let AuthService = require('../services/AuthService'); + + +module.exports = function (entity, pageName='', success, error, base_url = "" ) { + + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this._base_url = base_url; + + + + this.get_page_name = () => pageName; + + this.endpoint = "/admin/rules" + + + this.heading = "Add rule" + + this.action = "/admin/rules-add" + + + + this.form_fields = {"output_variable_name":"","actives":"","operator":"","compare_value":"","min":"","max":"","action":""} + + + this.operator_mapping = function () { + return this._entity.operator_mapping(); + + } + + this.action_mapping = function () { + return this._entity.action_mapping(); + + } + + + return this; +} diff --git a/view_models/rules_admin_delete_view_model.js b/view_models/rules_admin_delete_view_model.js new file mode 100644 index 0000000..5baf5a2 --- /dev/null +++ b/view_models/rules_admin_delete_view_model.js @@ -0,0 +1,40 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Rules Delete View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +const db = require('../models'); + +module.exports = function (entity, success, error) { + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + return this; +}; diff --git a/view_models/rules_admin_detail_view_model.js b/view_models/rules_admin_detail_view_model.js new file mode 100644 index 0000000..5d2bee9 --- /dev/null +++ b/view_models/rules_admin_detail_view_model.js @@ -0,0 +1,33 @@ +'use strict' + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Rules V View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName='', success, error, base_url = "" ) { + + this.entity = entity + + this.success = success || null + this.error = error || null + + this._base_url = base_url + + this.endpoint = "/admin/rules" + + this.get_page_name = () => pageName + + this.heading = "Rule details" + + + this.detail_fields = {"id":"","output_variable_name":"","actives":"","operator":"","compare_value":"","min":"","max":"","action":""} + + + return this; +} diff --git a/view_models/rules_admin_edit_view_model.js b/view_models/rules_admin_edit_view_model.js new file mode 100644 index 0000000..6954dd7 --- /dev/null +++ b/view_models/rules_admin_edit_view_model.js @@ -0,0 +1,68 @@ +'use strict' +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Rules Edit View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + const db = require('../models'); + +module.exports = function (entity, pageName='', success, error, base_url = "") { + + this._entity = entity + this.session = null + + this.success = success || null + this.error = error || null + + this._base_url = base_url + + this.endpoint = "/admin/rules" + + this.get_page_name = () => pageName + + this.format_date_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + return `${year}-${month}-${day}` + } + + this.format_date_local_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + const hrs = d.getHours() < 10 ? `0${d.getHours() }` : d.getHours() ; + const mins = d.getMinutes() < 10 ? `0${d.getMinutes() }` : d.getMinutes() ; + return `${year}-${month}-${day}T${hrs}:${mins}` + } + + this.heading = "Edit rule" + + this.action = "/admin/rules-edit" + + + + + this.form_fields = {"output_variable_name":"","actives":"","operator":"","compare_value":"","min":"","max":"","action":"","id":""} + + + this.operator_mapping = function () { + return this._entity.operator_mapping(); + + } + + this.action_mapping = function () { + return this._entity.action_mapping(); + + } + + + + return this; +} diff --git a/view_models/rules_admin_list_paginate_view_model.js b/view_models/rules_admin_list_paginate_view_model.js new file mode 100644 index 0000000..f690d93 --- /dev/null +++ b/view_models/rules_admin_list_paginate_view_model.js @@ -0,0 +1,593 @@ +"use strict"; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Rules Paginate List View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName, success, error, baseUrl) { + this.success = success ? success : ""; + this.error = error ? error : ""; + this._list = []; + this._column = ["ID", "Output variable", "Actives", "Condition operator", "Compare value", "Operation", "Action"]; + this._readable_column = ["ID", "Output variable", "Actives", "Condition operator", "Compare value", "Operation"]; + this._entity = entity; + this._heading = "Rules"; + this._base_url = baseUrl.endsWith("/") ? baseUrl.substring(0, -1) : baseUrl; + this._query = {}; + this._total_rows = 0; + this._format_layout = ""; + this._per_page = 10; + this._page; + this._num_links = 5; + this._field_column = ["id", "output_variable_name", "actives", "operator", "compare_value", "action"]; + this._readable_field_column = ["id", "output_variable_name", "actives", "operator", "compare_value", "action"]; + this._links = ""; + this._sort_base_url = ""; + this._order_by = ""; + this._sort = ""; + this._link_types = { start: "start", prev: "prev", next: "next" }; + this._attributes = ' class="page-link"'; + this.reuse_query_string = true; + this.page_query_string = true; + this.full_tag_open = ""; + this.full_tag_close = ""; + this.attributes = ""; + this.first_link = ""; + this.last_link = ""; + this.first_tag_open = ""; + this.query_string_segment = "per_page"; + this.first_tag_close = ""; + this.prev_link = ""; + this.prev_tag_open = ""; + this.prev_tag_close = ""; + this.next_link = ""; + this.next_tag_open = ""; + this.next_tag_close = ""; + this.last_tag_open = ""; + this.last_tag_close = ""; + this.cur_tag_open = ""; + this.cur_tag_close = ""; + this.num_tag_open = ""; + this.num_tag_close = ""; + this.suffix = ""; + this.prefix = ""; + this.cur_page = 0; + + this.get_page_name = () => pageName; + + this.get_heading = function () { + return pageName; + }; + + this.get_column = function () { + return this._column; + }; + + this.get_readable_column = function () { + return this._readable_column; + }; + + this.set_list = function (list) { + this._list = list; + }; + + this.set_query = function (query = {}) { + Object.keys(query).forEach((key) => { + if (this._field_column.includes(key)) { + console.log(this._query); + this._query[key] = query[key]; + } + }); + }; + + this.get_list = function () { + return this._list; + }; + + /** + * get_links function + * + * @return mixed + */ + this.get_links = function () { + this._links = this.createLinks(); + return this._links; + }; + + /** + * set_total_rows function + * + * @param integer total_rows + * @return void + */ + this.set_total_rows = function (total_rows) { + this._total_rows = total_rows; + }; + + /** + * set_per_page function + * + * @param integer per_page + * @return void + */ + this.set_per_page = function (per_page) { + this._per_page = per_page; + }; + /** + * format_layout function + * + * @param integer _format_layout + * @return void + */ + this.set_format_layout = function (_format_layout) { + this._format_layout = _format_layout; + }; + + /** + * set_order_by function + * + * @param string order_by + * @return void + */ + this.set_order_by = function (order_by) { + this._order_by = order_by; + }; + + /** + * set_sort function + * + * @param string sort + * @return void + */ + this.set_sort = function (sort) { + this._sort = sort; + }; + + /** + * set_sort_base_url function + * + * @param string sort_base_url + * @return void + */ + this.set_sort_base_url = function (sort_base_url) { + this._sort_base_url = sort_base_url; + }; + + /** + * get_total_rows function + * + * @return integer + */ + this.get_total_rows = function () { + return this._total_rows; + }; + + /** + * get_format_layout function + * + * @return integer + */ + this.get_format_layout = function () { + return this._format_layout; + }; + + /** + * get_per_page function + * + * @return integer + */ + this.get_per_page = function () { + return this._per_page; + }; + + /** + * get_page function + * + * @return integer + */ + this.get_page = function () { + return this._page; + }; + + /** + * num_links function + * + * @return integer + */ + this.get_num_links = function () { + return this._num_links; + }; + + /** + * set_order_by function + * + */ + this.get_order_by = function () { + return this._order_by; + }; + + /** + * get_field_column function + * + */ + this.get_field_column = function () { + return this._field_column; + }; + + this.get_readable_field_column = function () { + return this._readable_field_column; + }; + + /** + * set_sort function + * + */ + this.get_sort = function () { + return this._sort; + }; + + this.get_query = function () { + return this._query; + }; + + /** + * set_sort_base_url function + * + */ + this.get_sort_base_url = function () { + return this._sort_base_url; + }; + + /** + * set_page function + * + * @param integer page + * @return void + */ + this.set_page = function (page) { + this._page = page; + }; + + /** + * num_pages function + * + * @return integer + */ + this.get_num_page = function () { + let num = Math.ceil(this._total_rows / this._per_page); + return num > 0 ? parseInt(num) : 1; + }; + + this.image_or_file = function (file) { + const images = [".jpg", ".png", ".gif", ".jpeg", ".bmp"]; + let is_image = false; + const exist = images.filter(function (value) { + return value.indexOf(file) > -1; + }); + + if (exist.length > 0) { + return `
        `; + } + + return `${file}`; + }; + + this.timeago = function (date) { + const newDate = new Date(date); + const today = new Date(); + const currentTime = today.getTime(); + const timestamp = newDate.getTime(); + + const strTime = array("second", "minute", "hour", "day", "month", "year"); + const duration = array(60, 60, 24, 30, 12, 10); + + if (currentTime >= timestamp) { + diff = currentTime - timestamp; + + for (let i = 0; diff >= duration[i] && i < duration.length - 1; i++) { + diff = diff / duration[i]; + } + + diff = Math.round(diff, 0); + return diff + " " + strTime[i] + "(s) ago "; + } + }; + + this.time_default_mapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0" + i : i; + let min = j < 10 ? "0" + j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + this.convertToString = function (input) { + if (input) { + if (typeof input === "string") { + return input; + } + + return String(input); + } + return ""; + }; + + // convert string to words + this.toWords = function (input) { + input = this.convertToString(input); + + var regex = /[A-Z\xC0-\xD6\xD8-\xDE]?[a-z\xDF-\xF6\xF8-\xFF]+|[A-Z\xC0-\xD6\xD8-\xDE]+(?![a-z\xDF-\xF6\xF8-\xFF])|\d+/g; + + return input.match(regex); + }; + + // convert the input array to camel case + this.toCamelCase = function (inputArray) { + let result = ""; + + for (let i = 0, len = inputArray.length; i < len; i++) { + let currentStr = inputArray[i]; + + let tempStr = currentStr.toLowerCase(); + + if (i != 0) { + // convert first letter to upper case (the word is in lowercase) + tempStr = tempStr.substr(0, 1).toUpperCase() + tempStr.substr(1); + } + + result += tempStr; + } + + return result; + }; + + this.toCamelCaseString = function (input) { + let words = this.toWords(input); + + return this.toCamelCase(words); + }; + + this.ucFirst = function (string) { + if (typeof string === "string") { + return string.charAt(0).toUpperCase() + string.slice(1); + } + return ""; + }; + + this.number_format = function (field, n) { + return field.toFixed(n); + }; + + this.date = function (d) { + return ("0" + (d.getMonth() + 1)).slice(-2) + " " + ("0" + d.getDate()).slice(-2) + " " + d.getFullYear(); + }; + + this.datetime = function (d) { + return ("0" + (d.getMonth() + 1)).slice(-2) + " " + ("0" + d.getDate()).slice(-2) + " " + d.getFullYear() + " " + ("0" + d.getHours()).slice(-2) + ":" + ("0" + d.getMinutes()).slice(-2); + }; + + this.format_date_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + return `${year}-${month}-${day}`; + }; + // 2018-06-12T19:30 + this.format_date_local_input = function (date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1}` : d.getMonth() + 1; + const day = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate(); + const hrs = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours(); + const mins = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes(); + return `${year}-${month}-${day}T${hrs}:${mins}`; + }; + + this.createLinks = function () { + let totalItems = this._total_rows; + let currentPage = this._page; + let pageSize = this._per_page; + let maxPages = 10; + // calculate total pages + let totalPages = Math.ceil(totalItems / pageSize); + + // ensure current page isn't out of range + if (currentPage < 0) { + currentPage = 0; + } else if (currentPage > totalPages) { + currentPage = +totalPages; + } + + let startPage = 0; + let endPage = 0; + + if (totalPages <= maxPages) { + // total pages less than max so show all pages + startPage = 1; + endPage = totalPages; + } else { + // total pages more than max so calculate start and end pages + let maxPagesBeforeCurrentPage = Math.floor(maxPages / 2); + let maxPagesAfterCurrentPage = Math.ceil(maxPages / 2) - 1; + if (currentPage <= maxPagesBeforeCurrentPage) { + // current page near the start + startPage = 1; + endPage = maxPages; + } else if (currentPage + maxPagesAfterCurrentPage >= totalPages) { + // current page near the end + startPage = totalPages - maxPages + 1; + endPage = totalPages; + } else { + // current page somewhere in the middle + startPage = currentPage - maxPagesBeforeCurrentPage; + endPage = currentPage + maxPagesAfterCurrentPage; + } + } + + // calculate start and end item indexes + let startIndex = (currentPage - 1) * pageSize; + let endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1); + + // create an array of pages to ng-repeat in the pager control + let pages = Array.from(Array(endPage + 1 - startPage).keys()).map((i) => startPage + i); + + // return object with all pager properties required by the view + const payload = { + totalItems: totalItems, + currentPage: currentPage, + pageSize: pageSize, + totalPages: totalPages, + startPage: startPage, + endPage: endPage, + startIndex: startIndex, + endIndex: endIndex, + pages: pages, + }; + + let html = '
          '; + for (let i = 0; i < payload.pages.length && payload.pages.length > 1; i++) { + const element = +payload.pages[i]; + if (element - 1 == payload.currentPage) { + html += `
        • ${element}(current)
        • `; + } else { + html += `
        • ${element}
        • `; + } + } + html += "
        "; + return html; + }; + + this.get_id = function () { + return this._id; + }; + + this.set_id = function (id) { + this._id = id; + }; + + this._id = null; + + this.get_operator = function () { + return this._operator; + }; + + this.set_operator = function (operator) { + this._operator = operator; + }; + + this._operator = null; + + this.get_action = function () { + return this._action; + }; + + this.set_action = function (action) { + this._action = action; + }; + + this._action = null; + + this.get_output_variable_name = function () { + return this._output_variable_name; + }; + + this.set_output_variable_name = function (output_variable_name) { + this._output_variable_name = output_variable_name; + }; + + this._output_variable_name = null; + + this.operator_mapping = function () { + return this._entity.operator_mapping(); + }; + + this.action_mapping = function () { + return this._entity.action_mapping(); + }; + + this.to_json = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + list[key].operator = this.operator_mapping()[value.operator]; + list[key].action = this.action_mapping()[value.action]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["output_variable_name"] = value["output_variable_name"]; + clean_list_entry["actives"] = value["actives"]; + clean_list_entry["operator"] = value["operator"]; + clean_list_entry["compare_value"] = value["compare_value"]; + clean_list_entry["action"] = value["action"]; + clean_list.push(clean_list_entry); + } + + return { + page: this.get_page(), + num_page: this.get_num_page(), + num_item: this.get_total_rows(), + item: clean_list, + }; + }; + + this.to_csv = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + list[key].operator = this.operator_mapping()[value.operator]; + list[key].action = this.action_mapping()[value.action]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["output_variable_name"] = value["output_variable_name"]; + clean_list_entry["actives"] = value["actives"]; + clean_list_entry["operator"] = value["operator"]; + clean_list_entry["compare_value"] = value["compare_value"]; + clean_list_entry["action"] = value["action"]; + clean_list.push(clean_list_entry); + } + + const columns = this.get_field_column(); + + const column_fields = this.get_readable_field_column(); + + const fields = column_fields.filter(function (v, index) { + if (v.length === 0) { + columns.splice(index, 1); + } + return v.length > 0; + }); + + let csv = columns.join(",") + "\n"; + for (let i = 0; i < clean_list.length; i++) { + let row = clean_list[i]; + let row_csv = []; + for (const key in row) { + let column = row[key]; + if (fields.includes(key)) { + row_csv.push('"' + column + '"'); + } + } + csv = csv + row_csv.join(",") + "\n"; + } + return csv; + }; + + return this; +}; diff --git a/view_models/users_admin_add_view_model.js b/view_models/users_admin_add_view_model.js new file mode 100644 index 0000000..538493a --- /dev/null +++ b/view_models/users_admin_add_view_model.js @@ -0,0 +1,51 @@ +'use strict' + + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Users Add View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + + const db = require('../models') + let AuthService = require('../services/AuthService'); + + +module.exports = function (entity, pageName='', success, error, base_url = "" ) { + + this._entity = entity; + this.session = null; + + this.success = success || null; + this.error = error || null; + + this._base_url = base_url; + + + + this.get_page_name = () => pageName; + + this.endpoint = "/admin/users" + + + this.heading = "Add user" + + this.action = "/admin/users-add" + + + + this.form_fields = {"email":"","password":"","first_name":"","last_name":"","image":"","role_id":"","phone":"","status":""} + + + this.status_mapping = function () { + return this._entity.status_mapping(); + + } + + + return this; +} diff --git a/view_models/users_admin_detail_view_model.js b/view_models/users_admin_detail_view_model.js new file mode 100644 index 0000000..d847b6c --- /dev/null +++ b/view_models/users_admin_detail_view_model.js @@ -0,0 +1,33 @@ +'use strict' + +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Users V View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName='', success, error, base_url = "" ) { + + this.entity = entity + + this.success = success || null + this.error = error || null + + this._base_url = base_url + + this.endpoint = "/admin/users" + + this.get_page_name = () => pageName + + this.heading = "User details" + + + this.detail_fields = {"id":"","credential.email":"","first_name":"","last_name":"","role_id":"","status":""} + + + return this; +} diff --git a/view_models/users_admin_edit_view_model.js b/view_models/users_admin_edit_view_model.js new file mode 100644 index 0000000..458b614 --- /dev/null +++ b/view_models/users_admin_edit_view_model.js @@ -0,0 +1,63 @@ +'use strict' +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Users Edit View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + const db = require('../models'); + +module.exports = function (entity, pageName='', success, error, base_url = "") { + + this._entity = entity + this.session = null + + this.success = success || null + this.error = error || null + + this._base_url = base_url + + this.endpoint = "/admin/users" + + this.get_page_name = () => pageName + + this.format_date_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + return `${year}-${month}-${day}` + } + + this.format_date_local_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + const hrs = d.getHours() < 10 ? `0${d.getHours() }` : d.getHours() ; + const mins = d.getMinutes() < 10 ? `0${d.getMinutes() }` : d.getMinutes() ; + return `${year}-${month}-${day}T${hrs}:${mins}` + } + + this.heading = "Edit user" + + this.action = "/admin/users-edit" + + + + + this.form_fields = {"credential.email":"","credential.password":"","first_name":"","last_name":"","role_id":"","image":"","phone":"","status":"","id":""} + + + this.status_mapping = function () { + return this._entity.status_mapping(); + + } + + + + return this; +} diff --git a/view_models/users_admin_list_paginate_view_model.js b/view_models/users_admin_list_paginate_view_model.js new file mode 100644 index 0000000..fc8bb28 --- /dev/null +++ b/view_models/users_admin_list_paginate_view_model.js @@ -0,0 +1,612 @@ +'use strict'; +/*Powered By: Manaknightdigital Inc. https://manaknightdigital.com/ Year: 2021*/ +/** + * Users Paginate List View Model + * + * @copyright 2021 Manaknightdigital Inc. + * @link https://manaknightdigital.com + * @license Proprietary Software licensing + * @author Ryan Wong + */ + +module.exports = function (entity, pageName, success, error, baseUrl) { + this.success = success ? success : ""; + this.error = error ? error : ""; + this._list = []; + this._column = ['ID','Image','Email','Name','Status','Action']; + this._readable_column = ["ID","Email","Status"]; + this._entity = entity; + this._heading = 'Users'; + this._base_url = baseUrl.endsWith('/') ? baseUrl.substring(0, -1) : baseUrl; + this._query = {}; + this._total_rows = 0; + this._format_layout = ''; + this._per_page = 10; + this._page; + this._num_links = 5; + this._field_column = ['id','image','credential.email','','status']; + this._readable_field_column = ["id","email","status"] + this._links = ''; + this._sort_base_url = ''; + this._order_by = ''; + this._sort = ''; + this._link_types = {'start': 'start', 'prev': 'prev', 'next': 'next'}; + this._attributes = ' class="page-link"'; + this.reuse_query_string = true; + this.page_query_string = true; + this.full_tag_open = ''; + this.full_tag_close = ''; + this.attributes = ''; + this.first_link = ''; + this.last_link = ''; + this.first_tag_open = ''; + this.query_string_segment = 'per_page'; + this.first_tag_close = ''; + this.prev_link = ''; + this.prev_tag_open = ''; + this.prev_tag_close = ''; + this.next_link = ''; + this.next_tag_open = ''; + this.next_tag_close = ''; + this.last_tag_open = ''; + this.last_tag_close = ''; + this.cur_tag_open = ''; + this.cur_tag_close = ''; + this.num_tag_open = ''; + this.num_tag_close = ''; + this.suffix = ''; + this.prefix = ''; + this.cur_page = 0; + + + this.get_page_name = () => pageName + + + this.get_heading = function () { + return pageName; + }; + + this.get_column = function () { + return this._column; + }; + + this.get_readable_column = function () { + return this._readable_column; + }; + + this.set_list = function (list) { + this._list = list; + }; + + this.set_query = function (query = {}) { + Object.keys(query).forEach((key) => { + if (this._field_column.includes(key)) { + console.log(this._query); + this._query[key] = query[key]; + } + }); + }; + + + this.get_list = function () { + return this._list; + }; + + /** + * get_links function + * + * @return mixed + */ + this.get_links = function () { + this._links = this.createLinks(); + return this._links; + }; + + /** + * set_total_rows function + * + * @param integer total_rows + * @return void + */ + this.set_total_rows = function (total_rows) { + this._total_rows = total_rows; + }; + + /** + * set_per_page function + * + * @param integer per_page + * @return void + */ + this.set_per_page = function (per_page) { + this._per_page = per_page; + }; + /** + * format_layout function + * + * @param integer _format_layout + * @return void + */ + this.set_format_layout = function (_format_layout) { + this._format_layout = _format_layout; + }; + + /** + * set_order_by function + * + * @param string order_by + * @return void + */ + this.set_order_by = function (order_by) { + this._order_by = order_by; + }; + + /** + * set_sort function + * + * @param string sort + * @return void + */ + this.set_sort = function (sort) { + this._sort = sort; + }; + + /** + * set_sort_base_url function + * + * @param string sort_base_url + * @return void + */ + this.set_sort_base_url = function (sort_base_url) { + this._sort_base_url = sort_base_url; + }; + + /** + * get_total_rows function + * + * @return integer + */ + this.get_total_rows = function () { + return this._total_rows; + }; + + /** + * get_format_layout function + * + * @return integer + */ + this.get_format_layout = function () { + return this._format_layout; + }; + + /** + * get_per_page function + * + * @return integer + */ + this.get_per_page = function () { + return this._per_page; + }; + + /** + * get_page function + * + * @return integer + */ + this.get_page = function () { + return this._page; + }; + + /** + * num_links function + * + * @return integer + */ + this.get_num_links = function () { + return this._num_links; + }; + + /** + * set_order_by function + * + */ + this.get_order_by = function () { + return this._order_by; + }; + + /** + * get_field_column function + * + */ + this.get_field_column = function () { + return this._field_column; + }; + + this.get_readable_field_column = function () { + return this._readable_field_column; + }; + + /** + * set_sort function + * + */ + this.get_sort = function () { + return this._sort; + }; + + + this.get_query = function () { + return this._query; + }; + + + /** + * set_sort_base_url function + * + */ + this.get_sort_base_url = function () { + return this._sort_base_url; + }; + + /** + * set_page function + * + * @param integer page + * @return void + */ + this.set_page = function (page) { + this._page = page; + }; + + /** + * num_pages function + * + * @return integer + */ + this.get_num_page = function () { + let num = Math.ceil(this._total_rows / this._per_page); + return num > 0 ? parseInt(num) : 1; + }; + + this.image_or_file = function (file) { + const images = [".jpg", ".png", ".gif", ".jpeg", ".bmp"]; + let is_image = false; + const exist = images.filter(function (value) { + return value.indexOf(file) > -1; + }); + + if (exist.length > 0) { + return `
        `; + } + + return `${file}`; + }; + + this.timeago = function (date) { + const newDate = new Date(date); + const today = new Date(); + const currentTime = today.getTime(); + const timestamp = newDate.getTime(); + + const strTime = array("second", "minute", "hour", "day", "month", "year"); + const duration = array(60, 60, 24, 30, 12, 10); + + if (currentTime >= timestamp) { + diff = currentTime - timestamp; + + for (let i = 0; diff >= duration[i] && i < duration.length - 1; i++) { + diff = diff / duration[i]; + } + + diff = Math.round(diff, 0); + return diff + " " + strTime[i] + "(s) ago "; + } + }; + + this.time_default_mapping = function () { + let results = []; + for (let i = 0; i < 24; i++) { + for (let j = 0; j < 60; j++) { + let hour = i < 10 ? "0" + i : i; + let min = j < 10 ? "0" + j : j; + results[i * 60 + j] = `${hour}:${min}`; + } + } + return results; + }; + + this.convertToString = function (input) { + if (input) { + if (typeof input === "string") { + return input; + } + + return String(input); + } + return ""; + }; + + // convert string to words + this.toWords = function (input) { + input = this.convertToString(input); + + var regex = /[A-Z\xC0-\xD6\xD8-\xDE]?[a-z\xDF-\xF6\xF8-\xFF]+|[A-Z\xC0-\xD6\xD8-\xDE]+(?![a-z\xDF-\xF6\xF8-\xFF])|\d+/g; + + return input.match(regex); + }; + + // convert the input array to camel case + this.toCamelCase = function (inputArray) { + let result = ""; + + for (let i = 0, len = inputArray.length; i < len; i++) { + let currentStr = inputArray[i]; + + let tempStr = currentStr.toLowerCase(); + + if (i != 0) { + // convert first letter to upper case (the word is in lowercase) + tempStr = tempStr.substr(0, 1).toUpperCase() + tempStr.substr(1); + } + + result += tempStr; + } + + return result; + }; + + this.toCamelCaseString = function (input) { + let words = this.toWords(input); + + return this.toCamelCase(words); + }; + + this.ucFirst = function (string) { + if (typeof string === 'string') { + return string.charAt(0).toUpperCase() + string.slice(1); + } + return ''; + }; + + + this.number_format = function (field, n) { + return field.toFixed(n); + }; + + this.date = function (d) { + return ( + ("0" + (d.getMonth() + 1)).slice(-2) + + " " + + ("0" + d.getDate()).slice(-2) + + " " + + d.getFullYear() + ); + }; + + this.datetime = function (d) { + return ( + ("0" + (d.getMonth() + 1)).slice(-2) + + " " + + ("0" + d.getDate()).slice(-2) + + " " + + d.getFullYear() + + " " + + ("0" + d.getHours()).slice(-2) + + ":" + + ("0" + d.getMinutes()).slice(-2) + ); + }; + + this.format_date_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + return `${year}-${month}-${day}` + } + // 2018-06-12T19:30 + this.format_date_local_input = function(date){ + const d = new Date(date) + const year = d.getFullYear(); + const month = d.getMonth() + 1 < 10 ? `0${d.getMonth() + 1 }` : d.getMonth() + 1 ; + const day = d.getDate() < 10 ? `0${d.getDate() }` : d.getDate() ; + const hrs = d.getHours() < 10 ? `0${d.getHours() }` : d.getHours() ; + const mins = d.getMinutes() < 10 ? `0${d.getMinutes() }` : d.getMinutes() ; + return `${year}-${month}-${day}T${hrs}:${mins}` + } + + this.createLinks = function () { + let totalItems = this._total_rows; + let currentPage = this._page; + let pageSize = this._per_page; + let maxPages = 10; + // calculate total pages + let totalPages = Math.ceil(totalItems / pageSize); + + // ensure current page isn't out of range + if (currentPage < 0) { + currentPage = 0; + } else if (currentPage > totalPages) { + currentPage = +totalPages; + } + + let startPage = 0; + let endPage = 0; + + if (totalPages <= maxPages) { + // total pages less than max so show all pages + startPage = 1; + endPage = totalPages; + } else { + // total pages more than max so calculate start and end pages + let maxPagesBeforeCurrentPage = Math.floor(maxPages / 2); + let maxPagesAfterCurrentPage = Math.ceil(maxPages / 2) - 1; + if (currentPage <= maxPagesBeforeCurrentPage) { + // current page near the start + startPage = 1; + endPage = maxPages; + } else if (currentPage + maxPagesAfterCurrentPage >= totalPages) { + // current page near the end + startPage = totalPages - maxPages + 1; + endPage = totalPages; + } else { + // current page somewhere in the middle + startPage = currentPage - maxPagesBeforeCurrentPage; + endPage = currentPage + maxPagesAfterCurrentPage; + } + } + + // calculate start and end item indexes + let startIndex = (currentPage - 1) * pageSize; + let endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1); + + // create an array of pages to ng-repeat in the pager control + let pages = Array.from(Array(endPage + 1 - startPage).keys()).map( + (i) => startPage + i + ); + + + // return object with all pager properties required by the view + const payload = { + totalItems: totalItems, + currentPage: currentPage, + pageSize: pageSize, + totalPages: totalPages, + startPage: startPage, + endPage: endPage, + startIndex: startIndex, + endIndex: endIndex, + pages: pages, + }; + + + let html = '
          '; + for (let i = 0; i < payload.pages.length && payload.pages.length > 1; i++) { + const element = +payload.pages[i]; + if (element - 1 == payload.currentPage) { + html += `
        • ${element}(current)
        • `; + } else { + html += `
        • ${element}
        • `; + } + } + html += "
        "; + return html; + }; + + + this.get_id = function () { + return this._id; + } + + this.set_id = function (id) { + this._id = id; + } + + this._id = null; + + this.get_credential_email = function () { + return this._credential_email; + } + + this.set_credential_email = function (credential_email) { + this._credential_email = credential_email; + } + + this._credential_email = null; + + this.get_first_name = function () { + return this._first_name; + } + + this.set_first_name = function (first_name) { + this._first_name = first_name; + } + + this._first_name = null; + + this.get_last_name = function () { + return this._last_name; + } + + this.set_last_name = function (last_name) { + this._last_name = last_name; + } + + this._last_name = null; + + + this.status_mapping = function () { + return this._entity.status_mapping(); + + } + + + this.to_json = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + list[key].status = this.status_mapping()[value.status]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["image"] = value["image"]; + clean_list_entry["email"] = value["credential"]["email"]; + clean_list_entry["status"] = value["status"]; + clean_list.push(clean_list_entry); + } + + return { + "page" : this.get_page(), + "num_page" : this.get_num_page(), + "num_item" : this.get_total_rows(), + "item" : clean_list + }; + }; + + this.to_csv = function () { + let list = this.get_list(); + + let clean_list = []; + + for (let key in list) { + let value = list[key]; + list[key].status = this.status_mapping()[value.status]; + let clean_list_entry = {}; + clean_list_entry["id"] = value["id"]; + clean_list_entry["image"] = value["image"]; + clean_list_entry["email"] = value["credential"]["email"]; + clean_list_entry["status"] = value["status"]; + clean_list.push(clean_list_entry); + } + + const columns = this.get_field_column(); + + const column_fields = this.get_readable_field_column(); + + const fields = column_fields.filter(function(v, index){ +if (v.length === 0) {columns.splice(index, 1); +} +return v.length > 0;}); + + let csv = columns.join(",") + "\n"; + for (let i = 0; i < clean_list.length; i++) { + let row = clean_list[i]; + let row_csv = []; + for (const key in row) { + let column = row[key]; + if (fields.includes(key)) { + row_csv.push('"' + column + '"'); + } + } + csv = csv + row_csv.join(',') + "\n"; + } + return csv; +} + + + return this; +}; \ No newline at end of file diff --git a/views/admin/Actives.eta b/views/admin/Actives.eta new file mode 100644 index 0000000..62250e8 --- /dev/null +++ b/views/admin/Actives.eta @@ -0,0 +1,156 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + \ No newline at end of file diff --git a/views/admin/Add_Actives.eta b/views/admin/Add_Actives.eta new file mode 100644 index 0000000..2f22003 --- /dev/null +++ b/views/admin/Add_Actives.eta @@ -0,0 +1,69 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + <%= it.heading %> +
        + +
        + + +
        + + + + + + +
        + +
        + + + This is used to create the qrcode. + + + +
        + +
        + + + + + + +
        + +
        + <% it.output_variables?.forEach(oVar => { %> +
        + + " oninput="weightScoreInputChange(this, event)" name="<%= oVar.name %>" /> +
        + <% }) %> + +
        + +
        + +
        +
        + +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/Add_Answers.eta b/views/admin/Add_Answers.eta new file mode 100644 index 0000000..d3b8415 --- /dev/null +++ b/views/admin/Add_Answers.eta @@ -0,0 +1,120 @@ +<% if(it.layout_clean_mode) {%> <% layout("../layouts/admin/Clean") %> <% } else {%> <% layout("../layouts/admin/Main") %> <%}%> + + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        <%= it.heading %>
        + +
        +
        + + <% const firstQuesType = it.questions[0].type; %> + Can select one + +
        + +
        + + + +
        + +
        + + + +
        + +
        + + Can select one + +
        + +
        + + + +
        + +
        + + + +
        + +
        + + + + + + +
        + +
        + + + +
        + +
        + + + +
        + + <% /* +
        + + + +
        + */ %> + +
        + + + Can select multiple + +
        + +
        + +
        +
        +
        +
        +
        +
        + \ No newline at end of file diff --git a/views/admin/Add_Output_variables.eta b/views/admin/Add_Output_variables.eta new file mode 100644 index 0000000..00de16a --- /dev/null +++ b/views/admin/Add_Output_variables.eta @@ -0,0 +1,70 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + <%= it.heading %> +
        + +
        +
        + + +
        + +
        + + Can select multiple + + +
        + +
        + + +
        +
        + + +
        +
        + + +
        + +
        + +
        + + +
        + +
        +
        + +
        +
        +
        +
        + + \ No newline at end of file diff --git a/views/admin/Add_Questions.eta b/views/admin/Add_Questions.eta new file mode 100644 index 0000000..c58b657 --- /dev/null +++ b/views/admin/Add_Questions.eta @@ -0,0 +1,222 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + <%= it.heading %> +
        + +
        + + +
        + + + Can select one + + +
        + +
        + + + + + +
        + +
        + + + + Can select one + + + +
        + +
        + + + + + + +
        + + + +
        + + + + + + + +
        + +
        + + + + Can select one + + + +
        + +
        +
        + If you want this question to depend on another question answer fill these. + + + +
        +
        + + +
        +
        + + +
        +
        +
        + + + +
        + + Can select one + + +
        + +
        + + + + + + +
        + +
        + + + + +
        +
        + + +
        +
        + + +
        +
        + + +
        + +
        + +
        +
        + +
        +
        +
        +
        + + \ No newline at end of file diff --git a/views/admin/Add_Quizzes.eta b/views/admin/Add_Quizzes.eta new file mode 100644 index 0000000..e81ba74 --- /dev/null +++ b/views/admin/Add_Quizzes.eta @@ -0,0 +1,57 @@ + + +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + <%= it.heading %> +
        + +
        + + +
        + + + + + + +
        + +
        + + + + + + +
        + + +
        + +
        +
        + +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/Add_Result_profile.eta b/views/admin/Add_Result_profile.eta new file mode 100644 index 0000000..dbdc8d1 --- /dev/null +++ b/views/admin/Add_Result_profile.eta @@ -0,0 +1,55 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + <%= it.heading %> +
        + +
        + + +
        + + + + + + +
        + +
        + + + Can select multiple + + + +
        + + +
        + +
        +
        + +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/Add_Rules.eta b/views/admin/Add_Rules.eta new file mode 100644 index 0000000..82910f7 --- /dev/null +++ b/views/admin/Add_Rules.eta @@ -0,0 +1,123 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + <%= it.heading %> +
        + +
        + + +
        + + Can select one + + +
        + +
        + + + Can select multiple + + +
        + +
        + + + + Can select one + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + Can select one + + + +
        + + +
        + +
        +
        + +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/Add_Users.eta b/views/admin/Add_Users.eta new file mode 100644 index 0000000..6dbd4c5 --- /dev/null +++ b/views/admin/Add_Users.eta @@ -0,0 +1,116 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + <%= it.heading %> +
        + +
        + + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + Can select one + + + +
        + + +
        + +
        +
        + +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/Answers.eta b/views/admin/Answers.eta new file mode 100644 index 0000000..4c9623a --- /dev/null +++ b/views/admin/Answers.eta @@ -0,0 +1,187 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + \ No newline at end of file diff --git a/views/admin/Dashboard.eta b/views/admin/Dashboard.eta new file mode 100644 index 0000000..2ca8bc5 --- /dev/null +++ b/views/admin/Dashboard.eta @@ -0,0 +1,93 @@ +<% if(it.layout_clean_mode) {%> <% layout("../layouts/admin/Clean", {get_page_name:()=> "Dashboard"}) %><% } else {%> <% layout("../layouts/admin/Main",{get_page_name:()=> "Dashboard"}) %><%}%> + + + + \ No newline at end of file diff --git a/views/admin/Edit_Actives.eta b/views/admin/Edit_Actives.eta new file mode 100644 index 0000000..2f1096c --- /dev/null +++ b/views/admin/Edit_Actives.eta @@ -0,0 +1,64 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + <%= it.heading %> +
        + +
        + + +
        + + + + + + +
        + +
        + + + This is used to create the qrcode. + + + +
        +
        + + + + + + +
        + +
        + <% it.output_variables?.forEach(oVar => { %> +
        + + " value="<%= it.form_fields[oVar.name] %>" name="<%= oVar.name %>" /> +
        + <% }) %> +
        + +
        + +
        +
        + +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/Edit_Answers.eta b/views/admin/Edit_Answers.eta new file mode 100644 index 0000000..b315eeb --- /dev/null +++ b/views/admin/Edit_Answers.eta @@ -0,0 +1,142 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + <%= it.heading %> +
        + +
        + + +
        + + Can select one + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        +
        + + Can select one + +
        + + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + + +
        + + + <% blActivesList = []; + if(it.answer['black_list_actives']){ + blActivesList= JSON.parse(it.answer['black_list_actives']) + } + %> + Can select multiple + +
        + + +
        + +
        +
        + +
        +
        +
        +
        + + \ No newline at end of file diff --git a/views/admin/Edit_Output_variables.eta b/views/admin/Edit_Output_variables.eta new file mode 100644 index 0000000..8422ac8 --- /dev/null +++ b/views/admin/Edit_Output_variables.eta @@ -0,0 +1,98 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + <%= it.heading %> +
        + +
        + + +
        + + + + + + +
        + +
        + + + Can select multiple + + +
        + +
        + + + <% if(it.outputVariable['ranges_response'] && JSON.parse(it.outputVariable['ranges_response']).length) {%> + <% JSON.parse(it.outputVariable['ranges_response']).forEach((rr,index) => { %> +
        +
        + + +
        +
        + + +
        + + <% if(index > 0){ %> + + <% } %> +
        + <% }) %> + <% } else { %> +
        +
        + + +
        +
        + + +
        + +
        + <% } %> + +
        + + +
        + +
        +
        + +
        +
        +
        +
        + + + \ No newline at end of file diff --git a/views/admin/Edit_Questions.eta b/views/admin/Edit_Questions.eta new file mode 100644 index 0000000..460e7b2 --- /dev/null +++ b/views/admin/Edit_Questions.eta @@ -0,0 +1,513 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + +
        +
        +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + <%= it.heading %> + >Next Question +
        +
        +
        +
        + Question +
        +
        + + + Can select one + + +
        +
        + + + + + + +
        +
        + + + + + + +
        +
        + + + + Can select one + + + +
        + +
        + + + + + + +
        + +
        id="image-dimensions"> +
        +
        +
        + + /> + +
        +
        + + /> +
        +
        +
        Demo box
        +
        +
        +
        +
        + + + + + +
        + +
        + + + + Can select one + + + +
        + + +
        +
        + If you want this question to depend on another question answer fill these. + + +
        +
        + + <% if(it.form_fields['depends_on']){ + var dependedQuesId = it.form_fields['depends_on'].split('|')[0]; + var dependedQuesAnswer = it.form_fields['depends_on'].split('|')[1]; + } %> + +
        +
        + + +
        +
        +
        + +
        id="slider-select"> + + + + + + <% if(it.form_fields['slider_range']){ + var min = it.form_fields['slider_range'].split('-')[0]; + var max = it.form_fields['slider_range'].split('-')[1]; + }%> + +
        +
        + + +
        +
        + + +
        +
        + +
        + +
        + + Can select one + + +
        + +
        + + +
        + + +
        + + + + <% if(it.form_fields['extra_output_variable']) + var extrasArray = JSON.parse(it.form_fields['extra_output_variable']); + %> + <% if(extrasArray && extrasArray.length > 0){ %> + <% extrasArray.forEach(extra => {%> +
        +
        + + +
        +
        + + +
        +
        + <% }) %> + <% } else { %> +
        +
        + + +
        +
        + + +
        +
        + <% } %> + +
        +
        +
        +
        + Answers +
        +
        ordered by order of showing
        + <% if(it.form_fields['id'] == 20) {%> + + <% } %> +
        + <% if(it.question?.answers?.length){ %> + <% it.question.answers.forEach((answer, index) => { %> +
        +
        +
        +

        + +

        + Delete +
        + + +
        +
        + +
        + + +
        + +
        + + <% if(it.form_fields['id'] == 20) {%> + + + + <% } else {%> + + <% } %> +
        + +
        + + + + + + +
        +
        + + Can select one + +
        + + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + + +
        + + <% let blActivesList = []; + if(answer.black_list_actives){ + blActivesList= JSON.parse(answer.black_list_actives) + } + %> + Can select multiple + +
        + +
        +
        +
        +
        + + <% }) %> + <% } %> +
        + +
        + +
        + +
        +
        +
        +
        +
        +
        + + + + + \ No newline at end of file diff --git a/views/admin/Edit_Quizzes.eta b/views/admin/Edit_Quizzes.eta new file mode 100644 index 0000000..42dfafd --- /dev/null +++ b/views/admin/Edit_Quizzes.eta @@ -0,0 +1,54 @@ + + +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + <%= it.heading %> +
        + +
        + + +
        + + + + + + +
        + +
        + + + + + + +
        + + +
        + +
        +
        + +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/Edit_Result_profile.eta b/views/admin/Edit_Result_profile.eta new file mode 100644 index 0000000..6f10706 --- /dev/null +++ b/views/admin/Edit_Result_profile.eta @@ -0,0 +1,50 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + <%= it.heading %> +
        + +
        + + +
        + + + + + + +
        + +
        + + + Can select multiple + +
        + + +
        + +
        +
        + +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/Edit_Rules.eta b/views/admin/Edit_Rules.eta new file mode 100644 index 0000000..767ece8 --- /dev/null +++ b/views/admin/Edit_Rules.eta @@ -0,0 +1,119 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + <%= it.heading %> +
        + +
        + + +
        + + + Can select one + + +
        + +
        + + + Can select multiple + +
        + +
        + + + + Can select one + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + Can select one + + + +
        + + +
        + +
        +
        + +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/Edit_Users.eta b/views/admin/Edit_Users.eta new file mode 100644 index 0000000..2bd40f1 --- /dev/null +++ b/views/admin/Edit_Users.eta @@ -0,0 +1,113 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + <%= it.heading %> +
        + +
        + + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + Can select one + + + +
        + + +
        + +
        +
        + +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/Letters/All.eta b/views/admin/Letters/All.eta new file mode 100644 index 0000000..14ac00b --- /dev/null +++ b/views/admin/Letters/All.eta @@ -0,0 +1,227 @@ + + + + + + + + + + + + + Letters + + + +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        +
        + +
        +
        +
        Welcome to your personalized skincare journey
        +
        +

        <%= it.firstName ? `${it.firstName.trim()}, you ` : 'You ' %>are one of a kind. we believe your skincare should be too.

        +

        A truly personalized skincare routine is based on science - not buzzwords. That's why our team of scientists, formulators and skincare experts have spent years + researching ingredients and analyzing data to provide the best recommendations for your skin. +

        +

        In this box, you'll find additional cards detailing your skin profile, formula and mixing directions to get you started.

        +

        Each formula is completely personalized using the results from your skin quiz. All that's missing to complete the product, is you.

        +

        Happy mixing!

        +
        + +
        +
        +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        + +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        +
        + <%= it.firstName ? `${it.firstName.trim()}'s` : "Your" %> skin profile +
        +
        + <% if(it.profileCharcteristics) { %> + <% Object.entries(it.profileCharcteristics).forEach(([name, values])=>{%> +
        +
        +

        <%= name %>

        +
        +
        + <% if(values && values.length) { %> + <% values?.forEach(profile => { %> +
        +
        + <%= profile.name %> +
        +
        +
        +
        +
        + <% }) %> + <% }%> +
        +
        + <%})%> + <% }%> +
        +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        + + +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        +
        + <%= it.firstName ? `${it.firstName.trim()}'s` : "Your" %> formula +
        +
        +
        +
        Step 1: Understanding your base
        +
        +
        + +
        + Derived of water, sunflower, olive, and banana, your base is the foundation of your new skincare routine. We kept it simple and included only the essentials. +
        +
        +
        +
        +
        Step 2: Sources of Your Active Ingredients*
        +
        + <% it.actives?.forEach(active => { %> +
        +
        + <%= active.name %> +
        + +
        +
        + <%= active.description ?? "" %> +
        +
        + <% }) %> + <% if(it.count < 10) { %> + <% for(let i=it.count; i < 10; i++){ %> +
        +
        + Blank +
        + +
        +
        + +
        +
        + <%}%> + <%}%> +
        +
        +
        + +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        + +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        +
        + Instructions +
        +
        +

        Items included:

        +
          +
        • (1) Jar with Base Cream
        • +
        • + (1) Bag Containing: +
            +
          • + (10) Actives Sachets +
          • +
          • + (1) Wooden Mixing Stick +
          • +
          • + (1) Marker +
          • +
          +
        • +
        +
        +
        +

        Step 3: Mixing Your Formula

        +
          +
        1. Open your jar of base cream.
        2. +
        3. Carefully empty all 10 sachets into your base cream.
        4. +
        5. Gently mix the base and sachet contents with the wooden mixing stick until a consistent color and texture is achieved.
        6. +
        7. Optional: Customize your jar using the included marker.
        8. +
        +
        +
        +

        * Things to make note of:

        +
          +
        • Your formula may include sachets labeled "Blank." These contain supplementary base meant to balance the final volume and active concentrations.
        • +
        • Actives may have some varying colors or scents coming from their natural plantsources.
        • +
        • If cream separation occurs, simply remix gently.
        • +
        • Do not throw out jar when done. All future orders will arrive in a refill pod.
        • +
        +
        +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        + + + + \ No newline at end of file diff --git a/views/admin/Letters/Formula_Letter.eta b/views/admin/Letters/Formula_Letter.eta new file mode 100644 index 0000000..81d2c50 --- /dev/null +++ b/views/admin/Letters/Formula_Letter.eta @@ -0,0 +1,113 @@ + + + + + + + + + + + + + Formula Letter + + + + +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        +
        + <%= it.firstName ? `${it.firstName.trim()}'s` : "Your" %> formula +
        +
        +
        +
        Step 1: Understanding your base
        +
        +
        + +
        + Derived of water, sunflower, olive, and banana, your base is the foundation of your new skincare routine. We kept it simple and included only the essentials. +
        +
        +
        +
        +
        Step 2: Sources of Your Active Ingredients*
        +
        + <% it.actives?.forEach(active => { %> +
        +
        + <%= active.name %> +
        + +
        +
        + <%= active.description ?? "" %> +
        +
        + <% }) %> + <% if(it.count < 10){%> + <% for(let i=it.count; i < 10; i++){ %> +
        +
        + Blank +
        + +
        +
        + +
        +
        + <%}%> + <%}%> +
        +
        +
        + +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        + + + \ No newline at end of file diff --git a/views/admin/Letters/Instructions_Letter.eta b/views/admin/Letters/Instructions_Letter.eta new file mode 100644 index 0000000..6661fc6 --- /dev/null +++ b/views/admin/Letters/Instructions_Letter.eta @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + Instructions Letter + + + +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        +
        + Instructions +
        +
        +

        Items included:

        +
          +
        • (1) Jar with Base Cream
        • +
        • + (1) Bag Containing: +
            +
          • + (10) Actives Sachets +
          • +
          • + (1) Wooden Mixing Stick +
          • +
          • + (1) Marker +
          • +
          +
        • +
        +
        +
        +

        Step 3: Mixing Your Formula

        +
          +
        1. Open your jar of base cream.
        2. +
        3. Carefully empty all 10 sachets into your base cream.
        4. +
        5. Gently mix the base and sachet contents with the wooden mixing stick until a consistent color and texture is achieved.
        6. +
        7. Optional: Customize your jar using the included marker.
        8. +
        +
        +
        +

        * Things to make note of:

        +
          +
        • Your formula may include sachets labeled "Blank." These contain supplementary base meant to balance the final volume and active concentrations.
        • +
        • Actives may have some varying colors or scents coming from their natural plantsources.
        • +
        • If cream separation occurs, simply remix gently.
        • +
        • Do not throw out jar when done. All future orders will arrive in a refill pod.
        • +
        +
        +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        + + + \ No newline at end of file diff --git a/views/admin/Letters/Main_Letter.eta b/views/admin/Letters/Main_Letter.eta new file mode 100644 index 0000000..fc62595 --- /dev/null +++ b/views/admin/Letters/Main_Letter.eta @@ -0,0 +1,58 @@ + + + + + + + + + + + + Main Letter + + + +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        +
        + +
        +
        +
        Welcome to your personalized skincare journey
        +
        +

        <%= it.firstName ? `${it.firstName.trim()}, you ` : 'You ' %>are one of a kind. we believe your skincare should be too.

        +

        A truly personalized skincare routine is based on science - not buzzwords. That's why our team of scientists, formulators and skincare experts have spent years + researching ingredients and analyzing data to provide the best recommendations for your skin. +

        +

        In this box, you'll find additional cards detailing your skin profile, formula and mixing directions to get you started.

        +

        Each formula is completely personalized using the results from your skin quiz. All that's missing to complete the product, is you.

        +

        Happy mixing!

        +
        + +
        +
        +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        + + + \ No newline at end of file diff --git a/views/admin/Letters/Profile_Letter.eta b/views/admin/Letters/Profile_Letter.eta new file mode 100644 index 0000000..c9b2f03 --- /dev/null +++ b/views/admin/Letters/Profile_Letter.eta @@ -0,0 +1,64 @@ + + + + + + + + + + + + Profile Letter + + + + +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        +
        + <%= it.firstName ? `${it.firstName.trim()}'s` : "Your" %> skin profile +
        +
        + <% if(it.profileCharcteristics) { %> + <% Object.entries(it.profileCharcteristics).forEach(([name, values])=>{%> +
        +
        +

        <%= name %>

        +
        +
        + <% if(values && values.length) { %> + <% values?.forEach(profile => { %> +
        +
        + <%= profile.name %> +
        +
        +
        +
        +
        + <% }) %> + <% }%> +
        +
        + <%})%> + <% }%> +
        +
        +
        made with you. made for you. made by you. made with you. made for you. made by you.
        +
        + + + \ No newline at end of file diff --git a/views/admin/Login.eta b/views/admin/Login.eta new file mode 100644 index 0000000..2b007e9 --- /dev/null +++ b/views/admin/Login.eta @@ -0,0 +1,62 @@ + +<% layout("../layouts/admin/Clean") %> + + +
        +
        +
        +
        +
        +

        Login

        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + + + <% if(it.validationError){ %> + <% if(it.validationError.email){ %> + + <%}%> + <%}%> +
        +
        + + + <% if(it.validationError){ %> + <% if(it.validationError.password){ %> + + <%}%> + <%}%> +
        + + +
        + +
        + + + + + +
        +
        + + + + +
        +
        + +
        + +
        +

        Copyright © 2021 Manaknightdigital Inc. All rights reserved.

        + +

        Powered By Manaknightdigital Inc.

        +
        \ No newline at end of file diff --git a/views/admin/Orders.eta b/views/admin/Orders.eta new file mode 100644 index 0000000..b206c32 --- /dev/null +++ b/views/admin/Orders.eta @@ -0,0 +1,207 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + \ No newline at end of file diff --git a/views/admin/Output_variables.eta b/views/admin/Output_variables.eta new file mode 100644 index 0000000..ee3dafd --- /dev/null +++ b/views/admin/Output_variables.eta @@ -0,0 +1,168 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + \ No newline at end of file diff --git a/views/admin/Profile.eta b/views/admin/Profile.eta new file mode 100644 index 0000000..c318a7f --- /dev/null +++ b/views/admin/Profile.eta @@ -0,0 +1,82 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + Profile +
        +
        + + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + Can select one + + + +
        + + +
        + +
        +
        + +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/Questions.eta b/views/admin/Questions.eta new file mode 100644 index 0000000..8c959ec --- /dev/null +++ b/views/admin/Questions.eta @@ -0,0 +1,181 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + \ No newline at end of file diff --git a/views/admin/Quizzes.eta b/views/admin/Quizzes.eta new file mode 100644 index 0000000..25ae3f3 --- /dev/null +++ b/views/admin/Quizzes.eta @@ -0,0 +1,141 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + \ No newline at end of file diff --git a/views/admin/Result_profile.eta b/views/admin/Result_profile.eta new file mode 100644 index 0000000..c445447 --- /dev/null +++ b/views/admin/Result_profile.eta @@ -0,0 +1,144 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + \ No newline at end of file diff --git a/views/admin/Rules.eta b/views/admin/Rules.eta new file mode 100644 index 0000000..4712630 --- /dev/null +++ b/views/admin/Rules.eta @@ -0,0 +1,204 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + \ No newline at end of file diff --git a/views/admin/Users.eta b/views/admin/Users.eta new file mode 100644 index 0000000..a751c10 --- /dev/null +++ b/views/admin/Users.eta @@ -0,0 +1,176 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + + \ No newline at end of file diff --git a/views/admin/View_Actives.eta b/views/admin/View_Actives.eta new file mode 100644 index 0000000..bad8c44 --- /dev/null +++ b/views/admin/View_Actives.eta @@ -0,0 +1,54 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        +

        + <%= it.heading %> +

        + + + + + + + + + + + + + + + + + + + + + + +
        ID: + <%= it.detail_fields["id"] %> +
        Name: + <%= it.detail_fields["name"] %> +
        Handle: + <%= it.detail_fields["handle"] %> +
        Description: + <%= it.detail_fields["description"] %> +
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/View_Answers.eta b/views/admin/View_Answers.eta new file mode 100644 index 0000000..feee7ea --- /dev/null +++ b/views/admin/View_Answers.eta @@ -0,0 +1,122 @@ + +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        +

        + <%= it.heading %> +

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        ID: + <%= it.answer["id"] || "N/A" %> +
        Question ID: + <%= it.answer["question_id"] || "N/A" %> +
        Question: + <%= it.answer.question?.question || "N/A" %> +
        Answer: + <%= it.answer["answer"] || "N/A" %> +
        Answer value: + <%= it.answer["answer_value"] || "N/A" %> +
        Order: + <%= it.answer["order"] || "N/A" %> +
        Explaination: + <%= it.answer["explaination"]|| "N/A" %> +
        Image: + <% if(it.answer.image){%> + + <% }else{%> + N/A + <% }%> +
        Response header: + <%= it.answer["response_header"] || "N/A" %> +
        Response body: + <%= it.answer["response_body"] || "N/A" %> +
        Black listed actives: + <% if(it.answer["black_list_actives"]) { %> + <% JSON.parse(it.answer["black_list_actives"]).forEach(active => { %> + <%= active %>
        + <% }) %> + <% } else { %> + N/A + <% } %> +
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/View_Output_variables.eta b/views/admin/View_Output_variables.eta new file mode 100644 index 0000000..78b6937 --- /dev/null +++ b/views/admin/View_Output_variables.eta @@ -0,0 +1,73 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        +

        + <%= it.heading %> +

        + + + + + + + + + + + + + + + + + + + + + + + + + +
        ID: + <%= it.detail_fields["id"] %> +
        Name: + <%= it.detail_fields["name"] %> +
        Actives list: + <% if(it.detail_fields.active_list !== "N/A") { %> + <% it.detail_fields.active_list.forEach(active => { %> + <%= `${active.id}: ${active.name}` %> +
        + <% }) %> + <% } else { %> + N/A + <% } %> +
        Ranges responses: + <% if(it.detail_fields.ranges_response) { %> + <% JSON.parse(it.detail_fields.ranges_response).forEach(range => { %> + <%= `Range: ${Object.keys(range)[0]}` %> + - + <%= `Response: ${range[Object.keys(range)[0]]}` %> +
        + <% }) %> + <% } else { %> + N/A + <% } %> +
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/View_Questions.eta b/views/admin/View_Questions.eta new file mode 100644 index 0000000..d448e8b --- /dev/null +++ b/views/admin/View_Questions.eta @@ -0,0 +1,118 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        +

        + <%= it.heading %> +

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        ID: + <%= it.detail_fields["id"] %> +
        Name: + <%= it.detail_fields["quiz.name"] %> +
        Question: + <%= it.detail_fields["question"] %> +
        Order: + <%= it.detail_fields["order"] %> +
        Note: + <%= it.detail_fields["note"] %> +
        Note type: + <%= it.detail_fields["note_type"] %> +
        Depends on question: + <%= it.detail_fields["depends_on"] %> +
        Slider range: + <%= it.detail_fields["slider_range"] %> +
        Main output variable: + <%= it.detail_fields["output_variable_name"] %>: <%= it.detail_fields["weight"] %> +
        Extra output variables: + <% if(it.detail_fields["extra_output_variable"] && it.detail_fields["extra_output_variable"] !== "N/A") { %> + <% JSON.parse(it.detail_fields["extra_output_variable"]).forEach(oV => { %> + <%= oV.name + ': ' + oV.weight %>
        + <% }) %> + <% } else { %> + N/A + <% } %> +
        Type: + <%= it.detail_fields["type"] %> +
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/View_Quizzes.eta b/views/admin/View_Quizzes.eta new file mode 100644 index 0000000..ee9beb3 --- /dev/null +++ b/views/admin/View_Quizzes.eta @@ -0,0 +1,50 @@ + +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        +

        + <%= it.heading %> +

        + + + + + + + + + + + + + + + + + + + +
        ID: + <%= it.detail_fields["id"] %> +
        Name: + <%= it.detail_fields["name"] %> +
        Description: + <%= it.detail_fields["description"] %> +
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/View_Result_profile.eta b/views/admin/View_Result_profile.eta new file mode 100644 index 0000000..329fb32 --- /dev/null +++ b/views/admin/View_Result_profile.eta @@ -0,0 +1,55 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        +

        + <%= it.heading %> +

        + + + + + + + + + + + + + + + + + + + +
        ID: + <%= it.detail_fields["id"] %> +
        Section title: + <%= it.detail_fields["section_title"] %> +
        Variables List: + <% if(it.detail_fields["output_variable_list"] !== 'N/A' && it.detail_fields["output_variable_list"].length){ %> + <% it.detail_fields["output_variable_list"].forEach(ovar => { %> + <%= ovar %>
        + <% }) %> + <% }else{ %> + N/A + <% } %> +
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/View_Rules.eta b/views/admin/View_Rules.eta new file mode 100644 index 0000000..756b99a --- /dev/null +++ b/views/admin/View_Rules.eta @@ -0,0 +1,96 @@ + +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        +

        + <%= it.heading %> +

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        ID: + <%= it.detail_fields["id"] %> +
        Output variable: + <%= it.detail_fields["output_variable_name"] %> +
        Actives: + <% if(it.detail_fields["actives"]) { %> + <% JSON.parse(it.detail_fields["actives"]).forEach(active => { %> + <%= active %>
        + <% }) %> + <% } else { %> + N/A + <% } %> +
        Condition operator: + <%= it.detail_fields["operator"] %> +
        Compare value: + <%= it.detail_fields["compare_value"] %> +
        Between Min: + <%= it.detail_fields["min"] %> +
        Between Max: + <%= it.detail_fields["max"] %> +
        Action: + <%= it.detail_fields["action"] %> +
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/views/admin/View_Users.eta b/views/admin/View_Users.eta new file mode 100644 index 0000000..d25d777 --- /dev/null +++ b/views/admin/View_Users.eta @@ -0,0 +1,74 @@ + +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/admin/Clean") %> +<% } else {%> +<% layout("../layouts/admin/Main") %> +<%}%> + + +<%~ includeFile("../partials/admin/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        +

        + <%= it.heading %> +

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        ID: + <%= it.detail_fields["id"] %> +
        Email: + <%= it.detail_fields["credential.email"] %> +
        First Name: + <%= it.detail_fields["first_name"] %> +
        Last Name: + <%= it.detail_fields["last_name"] %> +
        Role ID: + <%= it.detail_fields["role_id"] %> +
        Status: + <%= it.detail_fields["status"] %> +
        +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/views/layouts/admin/Clean.eta b/views/layouts/admin/Clean.eta new file mode 100644 index 0000000..feff97f --- /dev/null +++ b/views/layouts/admin/Clean.eta @@ -0,0 +1,6 @@ +<%~ includeFile("../../partials/admin/Header",it)%> +
        + <%~ it.body %> +
        + + \ No newline at end of file diff --git a/views/layouts/admin/Main.eta b/views/layouts/admin/Main.eta new file mode 100644 index 0000000..663b155 --- /dev/null +++ b/views/layouts/admin/Main.eta @@ -0,0 +1,20 @@ +<%~ includeFile("../../partials/admin/Header",it)%> +
        +
        + +
        + + <%~ it.body %> +
        +
        +
        +<% /* Footer */ %> +<%~ includeFile("../../partials/admin/Footer", it)%> diff --git a/views/layouts/member/Clean.eta b/views/layouts/member/Clean.eta new file mode 100644 index 0000000..8dcf205 --- /dev/null +++ b/views/layouts/member/Clean.eta @@ -0,0 +1,6 @@ +<%~ includeFile("../../partials/member/Header",it)%> +
        + <%~ it.body %> +
        + + \ No newline at end of file diff --git a/views/layouts/member/Main.eta b/views/layouts/member/Main.eta new file mode 100644 index 0000000..163630f --- /dev/null +++ b/views/layouts/member/Main.eta @@ -0,0 +1,20 @@ +<%~ includeFile("../../partials/member/Header",it)%> +
        +
        + +
        + + <%~ it.body %> +
        +
        +
        +<% /* Footer */ %> +<%~ includeFile("../../partials/member/Footer", it)%> diff --git a/views/member/Dashboard.eta b/views/member/Dashboard.eta new file mode 100644 index 0000000..88c25a7 --- /dev/null +++ b/views/member/Dashboard.eta @@ -0,0 +1,11 @@ + +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/member/Clean", {get_page_name:() => "Dashboard"}) %> +<% } else {%> +<% layout("../layouts/member/Main",{get_page_name:() => "Dashboard"}) %> +<%}%> + + + \ No newline at end of file diff --git a/views/member/Forgot.eta b/views/member/Forgot.eta new file mode 100644 index 0000000..9b390a9 --- /dev/null +++ b/views/member/Forgot.eta @@ -0,0 +1,39 @@ + +<% layout("../layouts/member/Clean") %> + + + +
        +
        +
        +
        +
        +

        Forgot Password

        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + + + <% if(it.validationError){ %> + <% if(it.validationError.email){ %> + + <%}%> + <%}%> + +
        +
        + +
        +
        + +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/views/member/Login.eta b/views/member/Login.eta new file mode 100644 index 0000000..084d9e2 --- /dev/null +++ b/views/member/Login.eta @@ -0,0 +1,88 @@ + +<% layout("../layouts/member/Clean") %> + + +
        +
        +
        +
        +
        +

        Login

        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + + + <% if(it.validationError){ %> + <% if(it.validationError.email){ %> + + <%}%> + <%}%> +
        +
        + + + <% if(it.validationError){ %> + <% if(it.validationError.password){ %> + + <%}%> + <%}%> +
        + + +
        + +
        + + +
        + + +
        + + +
        + OR +
        + + + + +
        +
        + + +
        +Don't have an account yet? + Register + +
        + +
        +
        + +
        + +
        +

        Copyright © 2021 Manaknightdigital Inc. All rights reserved.

        + +

        Powered By Manaknightdigital Inc.

        +
        \ No newline at end of file diff --git a/views/member/Profile.eta b/views/member/Profile.eta new file mode 100644 index 0000000..7593e9b --- /dev/null +++ b/views/member/Profile.eta @@ -0,0 +1,82 @@ +<% if(it.layout_clean_mode) {%> +<% layout("../layouts/member/Clean") %> +<% } else {%> +<% layout("../layouts/member/Main") %> +<%}%> + +<%~ includeFile("../partials/member/Breadcrumb", it)%> + +
        +
        +
        + <%~ includeFile("../partials/member/GlobalResponse.eta", it) %> +
        +
        + Profile +
        +
        + + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + + + +
        + +
        + + + + Can select one + + + +
        + + +
        + +
        +
        + +
        +
        +
        +
        \ No newline at end of file diff --git a/views/member/Register.eta b/views/member/Register.eta new file mode 100644 index 0000000..95e8fb6 --- /dev/null +++ b/views/member/Register.eta @@ -0,0 +1,107 @@ + +<% layout("../layouts/member/Clean") %> + + +
        +
        +
        +
        +
        +

        Register

        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + + + <% if(it.validationError){ %> + <% if(it.validationError.first_name){ %> + + <%}%> + <%}%> +
        +
        + + + <% if(it.validationError){ %> + <% if(it.validationError.last_name){ %> + + <%}%> + <%}%> +
        +
        + + + + <% if(it.validationError){ %> + <% if(it.validationError.email){ %> + + <%}%> + <%}%> +
        +
        + + + + <% if(it.validationError){ %> + <% if(it.validationError.password){ %> + + <%}%> + <%}%> +
        +
        + + + + <% if(it.validationError){ %> + <% if(it.validationError.confirm_password){ %> + + <%}%> + <%}%> +
        + + +
        + +
        + OR +
        + + + + +
        +Already have an account? + Login + +
        +
        +
        +
        +
        +
        + +
        +

        Copyright © 2021 Manaknightdigital Inc. All rights reserved.

        + +

        Powered By Manaknightdigital Inc.

        +
        \ No newline at end of file diff --git a/views/member/Reset.eta b/views/member/Reset.eta new file mode 100644 index 0000000..bb5961f --- /dev/null +++ b/views/member/Reset.eta @@ -0,0 +1,49 @@ + +<% layout("../layouts/member/Clean") %> + + +
        +
        +
        +
        +
        +

        Reset Password

        +
        +
        + <%~ includeFile("../partials/admin/GlobalResponse.eta", it) %> +
        +
        + + + <% if(it.validationError){ %> + <% if(it.validationError.password){ %> + + <%}%> + <%}%> +
        +
        + + + <% if(it.validationError){ %> + <% if(it.validationError.confirm_password){ %> + + <%}%> + <%}%> +
        +
        + +
        +
        + + +
        +
        +
        +
        +
        \ No newline at end of file diff --git a/views/partials/admin/Breadcrumb.eta b/views/partials/admin/Breadcrumb.eta new file mode 100644 index 0000000..b79ba19 --- /dev/null +++ b/views/partials/admin/Breadcrumb.eta @@ -0,0 +1,13 @@ + +
        + +
        \ No newline at end of file diff --git a/views/partials/admin/Footer.eta b/views/partials/admin/Footer.eta new file mode 100644 index 0000000..045a1c2 --- /dev/null +++ b/views/partials/admin/Footer.eta @@ -0,0 +1,91 @@ + + + + + \ No newline at end of file diff --git a/views/partials/admin/GlobalResponse.eta b/views/partials/admin/GlobalResponse.eta new file mode 100644 index 0000000..a049faf --- /dev/null +++ b/views/partials/admin/GlobalResponse.eta @@ -0,0 +1,31 @@ +<% if (it.error) { %> + <% if (typeof it.error === "object") { %> + <% Object.keys(it.error).forEach(function(key) { %> +
        +
        + +
        +
        + <% }) %> + <% } else { %> +
        +
        + +
        +
        + <% } %> +<% } %> + +<% if (it.success) { %> +
        +
        +
        + <%= it.success %> +
        +
        +
        +<% } %> \ No newline at end of file diff --git a/views/partials/admin/Header.eta b/views/partials/admin/Header.eta new file mode 100644 index 0000000..0c761bb --- /dev/null +++ b/views/partials/admin/Header.eta @@ -0,0 +1,41 @@ + + + + + + + + + + <%= it.get_page_name() %> + + + + + <% /* css */ %> + + + + + + + <% /* script */ %> + + + + + + + + + + <% /* JS */ %> + + + + + + + + + \ No newline at end of file diff --git a/views/partials/admin/Nav.eta b/views/partials/admin/Nav.eta new file mode 100644 index 0000000..ba8d4cc --- /dev/null +++ b/views/partials/admin/Nav.eta @@ -0,0 +1,26 @@ + + \ No newline at end of file diff --git a/views/partials/member/Breadcrumb.eta b/views/partials/member/Breadcrumb.eta new file mode 100644 index 0000000..b79ba19 --- /dev/null +++ b/views/partials/member/Breadcrumb.eta @@ -0,0 +1,13 @@ + +
        + +
        \ No newline at end of file diff --git a/views/partials/member/Footer.eta b/views/partials/member/Footer.eta new file mode 100644 index 0000000..045a1c2 --- /dev/null +++ b/views/partials/member/Footer.eta @@ -0,0 +1,91 @@ + + + + + \ No newline at end of file diff --git a/views/partials/member/GlobalResponse.eta b/views/partials/member/GlobalResponse.eta new file mode 100644 index 0000000..a049faf --- /dev/null +++ b/views/partials/member/GlobalResponse.eta @@ -0,0 +1,31 @@ +<% if (it.error) { %> + <% if (typeof it.error === "object") { %> + <% Object.keys(it.error).forEach(function(key) { %> +
        +
        + +
        +
        + <% }) %> + <% } else { %> +
        +
        + +
        +
        + <% } %> +<% } %> + +<% if (it.success) { %> +
        +
        +
        + <%= it.success %> +
        +
        +
        +<% } %> \ No newline at end of file diff --git a/views/partials/member/Header.eta b/views/partials/member/Header.eta new file mode 100644 index 0000000..d59250a --- /dev/null +++ b/views/partials/member/Header.eta @@ -0,0 +1,40 @@ + + + + + + + + + + <%= it.get_page_name() %> + + + + + <% /* css */ %> + + + + + + <% /* script */ %> + + + + + + + + + <% /* JS */ %> + + + + + + + + + + \ No newline at end of file diff --git a/views/partials/member/Nav.eta b/views/partials/member/Nav.eta new file mode 100644 index 0000000..705ffa3 --- /dev/null +++ b/views/partials/member/Nav.eta @@ -0,0 +1,17 @@ + + \ No newline at end of file