From abd99e71b31f7ec219794b55a1b6b6b0d54d6090 Mon Sep 17 00:00:00 2001 From: sigu Date: Wed, 22 Jul 2020 08:15:04 +0300 Subject: [PATCH 01/43] setup live view --- .formatter.exs | 5 + .gitignore | 40 +- .tool-versions | 1 + README.md | 22 +- assets/.babelrc | 5 + assets/css/app.scss | 91 + assets/css/phoenix.css | 101 + assets/js/app.js | 33 + assets/package-lock.json | 7937 +++++++++++++++++ assets/package.json | 29 + assets/static/favicon.ico | Bin 0 -> 1258 bytes assets/static/images/phoenix.png | Bin 0 -> 13900 bytes assets/static/robots.txt | 5 + assets/webpack.config.js | 51 + config/config.exs | 31 + config/dev.exs | 76 + config/prod.exs | 55 + config/prod.secret.exs | 41 + config/test.exs | 22 + lib/sbomPoc.ex | 9 + lib/sbomPoc/application.ex | 34 + lib/sbomPoc/repo.ex | 5 + lib/sbomPoc_web.ex | 102 + lib/sbomPoc_web/channels/user_socket.ex | 35 + lib/sbomPoc_web/endpoint.ex | 54 + lib/sbomPoc_web/gettext.ex | 24 + lib/sbomPoc_web/live/page_live.ex | 39 + lib/sbomPoc_web/live/page_live.html.leex | 48 + lib/sbomPoc_web/router.ex | 43 + lib/sbomPoc_web/telemetry.ex | 55 + lib/sbomPoc_web/templates/layout/app.html.eex | 5 + .../templates/layout/live.html.leex | 11 + .../templates/layout/root.html.leex | 30 + lib/sbomPoc_web/views/error_helpers.ex | 47 + lib/sbomPoc_web/views/error_view.ex | 16 + lib/sbomPoc_web/views/layout_view.ex | 3 + mix.exs | 68 + mix.lock | 30 + priv/gettext/en/LC_MESSAGES/errors.po | 97 + priv/gettext/errors.pot | 95 + priv/repo/migrations/.formatter.exs | 4 + priv/repo/seeds.exs | 11 + test/sbomPoc_web/live/page_live_test.exs | 11 + test/sbomPoc_web/views/error_view_test.exs | 14 + test/sbomPoc_web/views/layout_view_test.exs | 8 + test/support/channel_case.ex | 40 + test/support/conn_case.ex | 43 + test/support/data_case.ex | 55 + test/test_helper.exs | 2 + 49 files changed, 9574 insertions(+), 9 deletions(-) create mode 100644 .formatter.exs create mode 100644 .tool-versions create mode 100644 assets/.babelrc create mode 100644 assets/css/app.scss create mode 100644 assets/css/phoenix.css create mode 100644 assets/js/app.js create mode 100644 assets/package-lock.json create mode 100644 assets/package.json create mode 100644 assets/static/favicon.ico create mode 100644 assets/static/images/phoenix.png create mode 100644 assets/static/robots.txt create mode 100644 assets/webpack.config.js create mode 100644 config/config.exs create mode 100644 config/dev.exs create mode 100644 config/prod.exs create mode 100644 config/prod.secret.exs create mode 100644 config/test.exs create mode 100644 lib/sbomPoc.ex create mode 100644 lib/sbomPoc/application.ex create mode 100644 lib/sbomPoc/repo.ex create mode 100644 lib/sbomPoc_web.ex create mode 100644 lib/sbomPoc_web/channels/user_socket.ex create mode 100644 lib/sbomPoc_web/endpoint.ex create mode 100644 lib/sbomPoc_web/gettext.ex create mode 100644 lib/sbomPoc_web/live/page_live.ex create mode 100644 lib/sbomPoc_web/live/page_live.html.leex create mode 100644 lib/sbomPoc_web/router.ex create mode 100644 lib/sbomPoc_web/telemetry.ex create mode 100644 lib/sbomPoc_web/templates/layout/app.html.eex create mode 100644 lib/sbomPoc_web/templates/layout/live.html.leex create mode 100644 lib/sbomPoc_web/templates/layout/root.html.leex create mode 100644 lib/sbomPoc_web/views/error_helpers.ex create mode 100644 lib/sbomPoc_web/views/error_view.ex create mode 100644 lib/sbomPoc_web/views/layout_view.ex create mode 100644 mix.exs create mode 100644 mix.lock create mode 100644 priv/gettext/en/LC_MESSAGES/errors.po create mode 100644 priv/gettext/errors.pot create mode 100644 priv/repo/migrations/.formatter.exs create mode 100644 priv/repo/seeds.exs create mode 100644 test/sbomPoc_web/live/page_live_test.exs create mode 100644 test/sbomPoc_web/views/error_view_test.exs create mode 100644 test/sbomPoc_web/views/layout_view_test.exs create mode 100644 test/support/channel_case.ex create mode 100644 test/support/conn_case.ex create mode 100644 test/support/data_case.ex create mode 100644 test/test_helper.exs diff --git a/.formatter.exs b/.formatter.exs new file mode 100644 index 0000000..8a6391c --- /dev/null +++ b/.formatter.exs @@ -0,0 +1,5 @@ +[ + import_deps: [:ecto, :phoenix], + inputs: ["*.{ex,exs}", "priv/*/seeds.exs", "{config,lib,test}/**/*.{ex,exs}"], + subdirectories: ["priv/*/migrations"] +] diff --git a/.gitignore b/.gitignore index b263cd1..97fa82e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,36 @@ -/_build -/cover -/deps -/doc +# The directory Mix will write compiled artifacts to. +/_build/ + +/.elixir_ls/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where 3rd-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. /.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). *.ez -*.beam -/config/*.secret.exs -.elixir_ls/ + +# Ignore package tarball (built via "mix hex.build"). +sbomPoc-*.tar + +# If NPM crashes, it generates a log, let's ignore it too. +npm-debug.log + +# The directory NPM downloads your dependencies sources to. +/assets/node_modules/ + +# Since we are building assets from assets/, +# we ignore priv/static. You may want to comment +# this depending on your deployment strategy. +/priv/static/ diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..bee1b6f --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +elixir 1.10.4-otp-22 diff --git a/README.md b/README.md index c1b6b9a..96a250d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,20 @@ -# SbomPoc-sFractal -webserver with status of SBOM Poc +# SbomPoc + +To start your Phoenix server: + + * Install dependencies with `mix deps.get` + * Create and migrate your database with `mix ecto.setup` + * Install Node.js dependencies with `npm install` inside the `assets` directory + * Start Phoenix endpoint with `mix phx.server` + +Now you can visit [`localhost:4000`](http://localhost:4000) from your browser. + +Ready to run in production? Please [check our deployment guides](https://hexdocs.pm/phoenix/deployment.html). + +## Learn more + + * Official website: https://www.phoenixframework.org/ + * Guides: https://hexdocs.pm/phoenix/overview.html + * Docs: https://hexdocs.pm/phoenix + * Forum: https://elixirforum.com/c/phoenix-forum + * Source: https://github.com/phoenixframework/phoenix diff --git a/assets/.babelrc b/assets/.babelrc new file mode 100644 index 0000000..ce33b24 --- /dev/null +++ b/assets/.babelrc @@ -0,0 +1,5 @@ +{ + "presets": [ + "@babel/preset-env" + ] +} diff --git a/assets/css/app.scss b/assets/css/app.scss new file mode 100644 index 0000000..bccd4fa --- /dev/null +++ b/assets/css/app.scss @@ -0,0 +1,91 @@ +/* This file is for your main application css. */ +@import "./phoenix.css"; +@import "../node_modules/nprogress/nprogress.css"; + +/* LiveView specific classes for your customizations */ +.invalid-feedback { + color: #a94442; + display: block; + margin: -1rem 0 2rem; +} + +.phx-no-feedback.invalid-feedback, .phx-no-feedback .invalid-feedback { + display: none; +} + +.phx-click-loading { + opacity: 0.5; + transition: opacity 1s ease-out; +} + +.phx-disconnected{ + cursor: wait; +} +.phx-disconnected *{ + pointer-events: none; +} + +.phx-modal { + opacity: 1!important; + position: fixed; + z-index: 1; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgb(0,0,0); + background-color: rgba(0,0,0,0.4); +} + +.phx-modal-content { + background-color: #fefefe; + margin: 15% auto; + padding: 20px; + border: 1px solid #888; + width: 80%; +} + +.phx-modal-close { + color: #aaa; + float: right; + font-size: 28px; + font-weight: bold; +} + +.phx-modal-close:hover, +.phx-modal-close:focus { + color: black; + text-decoration: none; + cursor: pointer; +} + + +/* Alerts and form errors */ +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert-info { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.alert-warning { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.alert-danger { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.alert p { + margin-bottom: 0; +} +.alert:empty { + display: none; +} diff --git a/assets/css/phoenix.css b/assets/css/phoenix.css new file mode 100644 index 0000000..3767b31 --- /dev/null +++ b/assets/css/phoenix.css @@ -0,0 +1,101 @@ +/* Includes some default style for the starter application. + * This can be safely deleted to start fresh. + */ + +/* Milligram v1.3.0 https://milligram.github.io + * Copyright (c) 2017 CJ Patoilo Licensed under the MIT license + */ + +*,*:after,*:before{box-sizing:inherit}html{box-sizing:border-box;font-size:62.5%}body{color:#000000;font-family:'Helvetica', 'Arial', sans-serif;font-size:1.6em;font-weight:300;line-height:1.6}blockquote{border-left:0.3rem solid #d1d1d1;margin-left:0;margin-right:0;padding:1rem 1.5rem}blockquote *:last-child{margin-bottom:0}.button,button,input[type='button'],input[type='reset'],input[type='submit']{background-color:#0069d9;border:0.1rem solid #0069d9;border-radius:.4rem;color:#fff;cursor:pointer;display:inline-block;font-size:1.1rem;font-weight:700;height:3.8rem;letter-spacing:.1rem;line-height:3.8rem;padding:0 3.0rem;text-align:center;text-decoration:none;text-transform:uppercase;white-space:nowrap}.button:focus,.button:hover,button:focus,button:hover,input[type='button']:focus,input[type='button']:hover,input[type='reset']:focus,input[type='reset']:hover,input[type='submit']:focus,input[type='submit']:hover{background-color:#606c76;border-color:#606c76;color:#fff;outline:0}.button[disabled],button[disabled],input[type='button'][disabled],input[type='reset'][disabled],input[type='submit'][disabled]{cursor:default;opacity:.5}.button[disabled]:focus,.button[disabled]:hover,button[disabled]:focus,button[disabled]:hover,input[type='button'][disabled]:focus,input[type='button'][disabled]:hover,input[type='reset'][disabled]:focus,input[type='reset'][disabled]:hover,input[type='submit'][disabled]:focus,input[type='submit'][disabled]:hover{background-color:#0069d9;border-color:#0069d9}.button.button-outline,button.button-outline,input[type='button'].button-outline,input[type='reset'].button-outline,input[type='submit'].button-outline{background-color:transparent;color:#0069d9}.button.button-outline:focus,.button.button-outline:hover,button.button-outline:focus,button.button-outline:hover,input[type='button'].button-outline:focus,input[type='button'].button-outline:hover,input[type='reset'].button-outline:focus,input[type='reset'].button-outline:hover,input[type='submit'].button-outline:focus,input[type='submit'].button-outline:hover{background-color:transparent;border-color:#606c76;color:#606c76}.button.button-outline[disabled]:focus,.button.button-outline[disabled]:hover,button.button-outline[disabled]:focus,button.button-outline[disabled]:hover,input[type='button'].button-outline[disabled]:focus,input[type='button'].button-outline[disabled]:hover,input[type='reset'].button-outline[disabled]:focus,input[type='reset'].button-outline[disabled]:hover,input[type='submit'].button-outline[disabled]:focus,input[type='submit'].button-outline[disabled]:hover{border-color:inherit;color:#0069d9}.button.button-clear,button.button-clear,input[type='button'].button-clear,input[type='reset'].button-clear,input[type='submit'].button-clear{background-color:transparent;border-color:transparent;color:#0069d9}.button.button-clear:focus,.button.button-clear:hover,button.button-clear:focus,button.button-clear:hover,input[type='button'].button-clear:focus,input[type='button'].button-clear:hover,input[type='reset'].button-clear:focus,input[type='reset'].button-clear:hover,input[type='submit'].button-clear:focus,input[type='submit'].button-clear:hover{background-color:transparent;border-color:transparent;color:#606c76}.button.button-clear[disabled]:focus,.button.button-clear[disabled]:hover,button.button-clear[disabled]:focus,button.button-clear[disabled]:hover,input[type='button'].button-clear[disabled]:focus,input[type='button'].button-clear[disabled]:hover,input[type='reset'].button-clear[disabled]:focus,input[type='reset'].button-clear[disabled]:hover,input[type='submit'].button-clear[disabled]:focus,input[type='submit'].button-clear[disabled]:hover{color:#0069d9}code{background:#f4f5f6;border-radius:.4rem;font-size:86%;margin:0 .2rem;padding:.2rem .5rem;white-space:nowrap}pre{background:#f4f5f6;border-left:0.3rem solid #0069d9;overflow-y:hidden}pre>code{border-radius:0;display:block;padding:1rem 1.5rem;white-space:pre}hr{border:0;border-top:0.1rem solid #f4f5f6;margin:3.0rem 0}input[type='email'],input[type='number'],input[type='password'],input[type='search'],input[type='tel'],input[type='text'],input[type='url'],textarea,select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;border:0.1rem solid #d1d1d1;border-radius:.4rem;box-shadow:none;box-sizing:inherit;height:3.8rem;padding:.6rem 1.0rem;width:100%}input[type='email']:focus,input[type='number']:focus,input[type='password']:focus,input[type='search']:focus,input[type='tel']:focus,input[type='text']:focus,input[type='url']:focus,textarea:focus,select:focus{border-color:#0069d9;outline:0}select{background:url('data:image/svg+xml;utf8,') center right no-repeat;padding-right:3.0rem}select:focus{background-image:url('data:image/svg+xml;utf8,')}textarea{min-height:6.5rem}label,legend{display:block;font-size:1.6rem;font-weight:700;margin-bottom:.5rem}fieldset{border-width:0;padding:0}input[type='checkbox'],input[type='radio']{display:inline}.label-inline{display:inline-block;font-weight:normal;margin-left:.5rem}.row{display:flex;flex-direction:column;padding:0;width:100%}.row.row-no-padding{padding:0}.row.row-no-padding>.column{padding:0}.row.row-wrap{flex-wrap:wrap}.row.row-top{align-items:flex-start}.row.row-bottom{align-items:flex-end}.row.row-center{align-items:center}.row.row-stretch{align-items:stretch}.row.row-baseline{align-items:baseline}.row .column{display:block;flex:1 1 auto;margin-left:0;max-width:100%;width:100%}.row .column.column-offset-10{margin-left:10%}.row .column.column-offset-20{margin-left:20%}.row .column.column-offset-25{margin-left:25%}.row .column.column-offset-33,.row .column.column-offset-34{margin-left:33.3333%}.row .column.column-offset-50{margin-left:50%}.row .column.column-offset-66,.row .column.column-offset-67{margin-left:66.6666%}.row .column.column-offset-75{margin-left:75%}.row .column.column-offset-80{margin-left:80%}.row .column.column-offset-90{margin-left:90%}.row .column.column-10{flex:0 0 10%;max-width:10%}.row .column.column-20{flex:0 0 20%;max-width:20%}.row .column.column-25{flex:0 0 25%;max-width:25%}.row .column.column-33,.row .column.column-34{flex:0 0 33.3333%;max-width:33.3333%}.row .column.column-40{flex:0 0 40%;max-width:40%}.row .column.column-50{flex:0 0 50%;max-width:50%}.row .column.column-60{flex:0 0 60%;max-width:60%}.row .column.column-66,.row .column.column-67{flex:0 0 66.6666%;max-width:66.6666%}.row .column.column-75{flex:0 0 75%;max-width:75%}.row .column.column-80{flex:0 0 80%;max-width:80%}.row .column.column-90{flex:0 0 90%;max-width:90%}.row .column .column-top{align-self:flex-start}.row .column .column-bottom{align-self:flex-end}.row .column .column-center{-ms-grid-row-align:center;align-self:center}@media (min-width: 40rem){.row{flex-direction:row;margin-left:-1.0rem;width:calc(100% + 2.0rem)}.row .column{margin-bottom:inherit;padding:0 1.0rem}}a{color:#0069d9;text-decoration:none}a:focus,a:hover{color:#606c76}dl,ol,ul{list-style:none;margin-top:0;padding-left:0}dl dl,dl ol,dl ul,ol dl,ol ol,ol ul,ul dl,ul ol,ul ul{font-size:90%;margin:1.5rem 0 1.5rem 3.0rem}ol{list-style:decimal inside}ul{list-style:circle inside}.button,button,dd,dt,li{margin-bottom:1.0rem}fieldset,input,select,textarea{margin-bottom:1.5rem}blockquote,dl,figure,form,ol,p,pre,table,ul{margin-bottom:2.5rem}table{border-spacing:0;width:100%}td,th{border-bottom:0.1rem solid #e1e1e1;padding:1.2rem 1.5rem;text-align:left}td:first-child,th:first-child{padding-left:0}td:last-child,th:last-child{padding-right:0}b,strong{font-weight:bold}p{margin-top:0}h1,h2,h3,h4,h5,h6{font-weight:300;letter-spacing:-.1rem;margin-bottom:2.0rem;margin-top:0}h1{font-size:4.6rem;line-height:1.2}h2{font-size:3.6rem;line-height:1.25}h3{font-size:2.8rem;line-height:1.3}h4{font-size:2.2rem;letter-spacing:-.08rem;line-height:1.35}h5{font-size:1.8rem;letter-spacing:-.05rem;line-height:1.5}h6{font-size:1.6rem;letter-spacing:0;line-height:1.4}img{max-width:100%}.clearfix:after{clear:both;content:' ';display:table}.float-left{float:left}.float-right{float:right} + +/* General style */ +h1{font-size: 3.6rem; line-height: 1.25} +h2{font-size: 2.8rem; line-height: 1.3} +h3{font-size: 2.2rem; letter-spacing: -.08rem; line-height: 1.35} +h4{font-size: 1.8rem; letter-spacing: -.05rem; line-height: 1.5} +h5{font-size: 1.6rem; letter-spacing: 0; line-height: 1.4} +h6{font-size: 1.4rem; letter-spacing: 0; line-height: 1.2} +pre{padding: 1em;} + +.container{ + margin: 0 auto; + max-width: 80.0rem; + padding: 0 2.0rem; + position: relative; + width: 100% +} +select { + width: auto; +} + +/* Phoenix promo and logo */ +.phx-hero { + text-align: center; + border-bottom: 1px solid #e3e3e3; + background: #eee; + border-radius: 6px; + padding: 3em 3em 1em; + margin-bottom: 3rem; + font-weight: 200; + font-size: 120%; +} +.phx-hero input { + background: #ffffff; +} +.phx-logo { + min-width: 300px; + margin: 1rem; + display: block; +} +.phx-logo img { + width: auto; + display: block; +} + +/* Headers */ +header { + width: 100%; + background: #fdfdfd; + border-bottom: 1px solid #eaeaea; + margin-bottom: 2rem; +} +header section { + align-items: center; + display: flex; + flex-direction: column; + justify-content: space-between; +} +header section :first-child { + order: 2; +} +header section :last-child { + order: 1; +} +header nav ul, +header nav li { + margin: 0; + padding: 0; + display: block; + text-align: right; + white-space: nowrap; +} +header nav ul { + margin: 1rem; + margin-top: 0; +} +header nav a { + display: block; +} + +@media (min-width: 40.0rem) { /* Small devices (landscape phones, 576px and up) */ + header section { + flex-direction: row; + } + header nav ul { + margin: 1rem; + } + .phx-logo { + flex-basis: 527px; + margin: 2rem 1rem; + } +} diff --git a/assets/js/app.js b/assets/js/app.js new file mode 100644 index 0000000..dc8033b --- /dev/null +++ b/assets/js/app.js @@ -0,0 +1,33 @@ +// We need to import the CSS so that webpack will load it. +// The MiniCssExtractPlugin is used to separate it out into +// its own CSS file. +import "../css/app.scss" + +// webpack automatically bundles all modules in your +// entry points. Those entry points can be configured +// in "webpack.config.js". +// +// Import deps with the dep name or local files with a relative path, for example: +// +// import {Socket} from "phoenix" +// import socket from "./socket" +// +import "phoenix_html" +import {Socket} from "phoenix" +import NProgress from "nprogress" +import {LiveSocket} from "phoenix_live_view" + +let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") +let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}}) + +// Show progress bar on live navigation and form submits +window.addEventListener("phx:page-loading-start", info => NProgress.start()) +window.addEventListener("phx:page-loading-stop", info => NProgress.done()) + +// connect if there are any LiveViews on the page +liveSocket.connect() + +// expose liveSocket on window for web console debug logs and latency simulation: +// >> liveSocket.enableDebug() +// >> liveSocket.enableLatencySim(1000) +window.liveSocket = liveSocket diff --git a/assets/package-lock.json b/assets/package-lock.json new file mode 100644 index 0000000..c3bab08 --- /dev/null +++ b/assets/package-lock.json @@ -0,0 +1,7937 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/compat-data": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.10.5.tgz", + "integrity": "sha512-mPVoWNzIpYJHbWje0if7Ck36bpbtTvIxOi9+6WSK9wjGEXearAqlwBoTQvVjsAY2VIwgcs8V940geY3okzRCEw==", + "dev": true, + "requires": { + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "semver": "^5.5.0" + } + }, + "@babel/core": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.5.tgz", + "integrity": "sha512-O34LQooYVDXPl7QWCdW9p4NR+QlzOr7xShPPJz8GsuCU3/8ua/wqTr7gmnxXv+WBESiGU/G5s16i6tUvHkNb+w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.10.5", + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helpers": "^7.10.4", + "@babel/parser": "^7.10.5", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.5", + "@babel/types": "^7.10.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/generator": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.5.tgz", + "integrity": "sha512-3vXxr3FEW7E7lJZiWQ3bM4+v/Vyr9C+hpolQ8BGFr9Y8Ri2tFLWTixmwKBafDujO1WVah4fhZBeU1bieKdghig==", + "dev": true, + "requires": { + "@babel/types": "^7.10.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", + "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", + "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz", + "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.10.4", + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "levenary": "^1.1.1", + "semver": "^5.5.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz", + "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-member-expression-to-functions": "^7.10.5", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz", + "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-regex": "^7.10.4", + "regexpu-core": "^4.7.0" + } + }, + "@babel/helper-define-map": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", + "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz", + "integrity": "sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A==", + "dev": true, + "requires": { + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", + "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.5.tgz", + "integrity": "sha512-HiqJpYD5+WopCXIAbQDG0zye5XYVvcO9w/DHp5GsaGkRUaamLj2bEtu6i8rnGGprAhHM3qidCMgp71HF4endhA==", + "dev": true, + "requires": { + "@babel/types": "^7.10.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", + "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-module-transforms": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.5.tgz", + "integrity": "sha512-4P+CWMJ6/j1W915ITJaUkadLObmCRRSC234uctJfn/vHrsLNxsR8dwlcXv9ZhJWzl77awf+mWXSZEKt5t0OnlA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + }, + "@babel/helper-regex": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", + "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", + "dev": true, + "requires": { + "lodash": "^4.17.19" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz", + "integrity": "sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-wrap-function": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-replace-supers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", + "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-simple-access": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", + "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", + "dev": true, + "requires": { + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz", + "integrity": "sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz", + "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helpers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", + "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", + "dev": true, + "requires": { + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.5.tgz", + "integrity": "sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz", + "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4", + "@babel/plugin-syntax-async-generators": "^7.8.0" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz", + "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz", + "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz", + "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.0" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz", + "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz", + "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.4.tgz", + "integrity": "sha512-6vh4SqRuLLarjgeOf4EaROJAHjvu9Gl+/346PbDH9yWbJyfnJ/ah3jmYKYtswEyCoWZiidvVHjHshd4WgjB9BA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.10.4" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz", + "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz", + "integrity": "sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz", + "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz", + "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz", + "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz", + "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz", + "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz", + "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz", + "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.5.tgz", + "integrity": "sha512-6Ycw3hjpQti0qssQcA6AMSFDHeNJ++R6dIMnpRqUjFeBBTmTDPa8zgF90OVfTvAo11mXZTlVUViY1g8ffrURLg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz", + "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-define-map": "^7.10.4", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz", + "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz", + "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz", + "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz", + "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz", + "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz", + "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz", + "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz", + "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz", + "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz", + "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz", + "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz", + "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.10.4", + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz", + "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz", + "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz", + "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz", + "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz", + "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz", + "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz", + "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz", + "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz", + "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.4.tgz", + "integrity": "sha512-1e/51G/Ni+7uH5gktbWv+eCED9pP8ZpRhZB3jOaI3mmzfvJTWHkuyYTv0Z5PYtyM+Tr2Ccr9kUdQxn60fI5WuQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz", + "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-regex": "^7.10.4" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz", + "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz", + "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz", + "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz", + "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/preset-env": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.10.4.tgz", + "integrity": "sha512-tcmuQ6vupfMZPrLrc38d0sF2OjLT3/bZ0dry5HchNCQbrokoQi4reXqclvkkAT5b+gWc23meVWpve5P/7+w/zw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.10.4", + "@babel/helper-compilation-targets": "^7.10.4", + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-proposal-async-generator-functions": "^7.10.4", + "@babel/plugin-proposal-class-properties": "^7.10.4", + "@babel/plugin-proposal-dynamic-import": "^7.10.4", + "@babel/plugin-proposal-json-strings": "^7.10.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", + "@babel/plugin-proposal-numeric-separator": "^7.10.4", + "@babel/plugin-proposal-object-rest-spread": "^7.10.4", + "@babel/plugin-proposal-optional-catch-binding": "^7.10.4", + "@babel/plugin-proposal-optional-chaining": "^7.10.4", + "@babel/plugin-proposal-private-methods": "^7.10.4", + "@babel/plugin-proposal-unicode-property-regex": "^7.10.4", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.10.4", + "@babel/plugin-transform-arrow-functions": "^7.10.4", + "@babel/plugin-transform-async-to-generator": "^7.10.4", + "@babel/plugin-transform-block-scoped-functions": "^7.10.4", + "@babel/plugin-transform-block-scoping": "^7.10.4", + "@babel/plugin-transform-classes": "^7.10.4", + "@babel/plugin-transform-computed-properties": "^7.10.4", + "@babel/plugin-transform-destructuring": "^7.10.4", + "@babel/plugin-transform-dotall-regex": "^7.10.4", + "@babel/plugin-transform-duplicate-keys": "^7.10.4", + "@babel/plugin-transform-exponentiation-operator": "^7.10.4", + "@babel/plugin-transform-for-of": "^7.10.4", + "@babel/plugin-transform-function-name": "^7.10.4", + "@babel/plugin-transform-literals": "^7.10.4", + "@babel/plugin-transform-member-expression-literals": "^7.10.4", + "@babel/plugin-transform-modules-amd": "^7.10.4", + "@babel/plugin-transform-modules-commonjs": "^7.10.4", + "@babel/plugin-transform-modules-systemjs": "^7.10.4", + "@babel/plugin-transform-modules-umd": "^7.10.4", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4", + "@babel/plugin-transform-new-target": "^7.10.4", + "@babel/plugin-transform-object-super": "^7.10.4", + "@babel/plugin-transform-parameters": "^7.10.4", + "@babel/plugin-transform-property-literals": "^7.10.4", + "@babel/plugin-transform-regenerator": "^7.10.4", + "@babel/plugin-transform-reserved-words": "^7.10.4", + "@babel/plugin-transform-shorthand-properties": "^7.10.4", + "@babel/plugin-transform-spread": "^7.10.4", + "@babel/plugin-transform-sticky-regex": "^7.10.4", + "@babel/plugin-transform-template-literals": "^7.10.4", + "@babel/plugin-transform-typeof-symbol": "^7.10.4", + "@babel/plugin-transform-unicode-escapes": "^7.10.4", + "@babel/plugin-transform-unicode-regex": "^7.10.4", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.10.4", + "browserslist": "^4.12.0", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.1", + "semver": "^5.5.0" + } + }, + "@babel/preset-modules": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz", + "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/runtime": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz", + "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/traverse": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.5.tgz", + "integrity": "sha512-yc/fyv2gUjPqzTz0WHeRJH2pv7jA9kA7mBX2tXl/x5iOE81uaVPuGPtaYk7wmkx4b67mQ7NqI8rmT2pF47KYKQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.10.5", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4", + "@babel/parser": "^7.10.5", + "@babel/types": "^7.10.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + } + }, + "@babel/types": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.5.tgz", + "integrity": "sha512-ixV66KWfCI6GKoA/2H9v6bQdbfXEwwpOdQ8cRvb4F+eyvhlaHxWFMQB4+3d9QFJXZsiiiqVrewNV0DFEQpyT4Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "@types/json-schema": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", + "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==", + "dev": true + }, + "@types/q": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", + "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", + "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", + "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", + "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", + "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", + "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", + "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", + "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "mamacro": "^0.0.3" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", + "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", + "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", + "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", + "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", + "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", + "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/helper-wasm-section": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-opt": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", + "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", + "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", + "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", + "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/floating-point-hex-parser": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-code-frame": "1.8.5", + "@webassemblyjs/helper-fsm": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", + "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "dev": true + }, + "aggregate-error": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", + "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "dependencies": { + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + } + } + }, + "ajv": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", + "dev": true, + "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" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "ajv-keywords": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.1.tgz", + "integrity": "sha512-KWcq3xN8fDjSB+IMoh2VaXVhRI0BBGxoYp3rx7Pkb6z0cFjYR9Q9l4yZqqals0/zsioCmocC5H6UvsGD4MoIBA==", + "dev": true + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": 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==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "optional": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "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=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "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=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true, + "optional": true + }, + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz", + "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==", + "dev": true + }, + "babel-loader": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", + "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==", + "dev": true, + "requires": { + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.4.0", + "mkdirp": "^0.5.3", + "pify": "^4.0.1", + "schema-utils": "^2.6.5" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "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==", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true, + "optional": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "bn.js": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz", + "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==", + "dev": true + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "browserify-sign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.0.tgz", + "integrity": "sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA==", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.2", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "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==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.13.0.tgz", + "integrity": "sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001093", + "electron-to-chromium": "^1.3.488", + "escalade": "^3.0.1", + "node-releases": "^1.1.58" + } + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "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==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "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=", + "dev": true + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + } + } + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001104", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001104.tgz", + "integrity": "sha512-pkpCg7dmI/a7WcqM2yfdOiT4Xx5tzyoHAXWsX5/HxZ3TemwDZs0QXdqbE0UPLPVy/7BeK7693YfzfRYfu1YVpg==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chokidar": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.1.tgz", + "integrity": "sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "optional": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "optional": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "optional": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "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==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.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==", + "dev": 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=", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.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==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dev": true, + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", + "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", + "dev": true, + "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==", + "dev": 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=", + "dev": true + }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "dev": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-webpack-plugin": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz", + "integrity": "sha512-P15M5ZC8dyCjQHWwd4Ia/dm0SgVvZJMYeykVIVYXbGyqO4dWB5oyPHp9i7wjwo5LhtlhKbiBCdS2NvM07Wlybg==", + "dev": true, + "requires": { + "cacache": "^12.0.3", + "find-cache-dir": "^2.1.0", + "glob-parent": "^3.1.0", + "globby": "^7.1.1", + "is-glob": "^4.0.1", + "loader-utils": "^1.2.3", + "minimatch": "^3.0.4", + "normalize-path": "^3.0.0", + "p-limit": "^2.2.1", + "schema-utils": "^1.0.0", + "serialize-javascript": "^2.1.2", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "core-js-compat": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", + "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==", + "dev": true, + "requires": { + "browserslist": "^4.8.5", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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" + } + }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + }, + "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==", + "dev": true, + "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=", + "dev": true + } + } + }, + "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==", + "dev": true, + "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" + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true + }, + "css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "dev": true, + "requires": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + } + }, + "css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "dev": true + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dev": true, + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-what": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.3.0.tgz", + "integrity": "sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg==", + "dev": true + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "cssnano": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", + "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.7", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "cssnano-preset-default": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", + "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", + "dev": true, + "requires": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.2", + "postcss-unique-selectors": "^4.0.1" + } + }, + "cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", + "dev": true + }, + "cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", + "dev": true + }, + "cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", + "dev": true + }, + "csso": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.3.tgz", + "integrity": "sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ==", + "dev": true, + "requires": { + "css-tree": "1.0.0-alpha.39" + }, + "dependencies": { + "css-tree": { + "version": "1.0.0-alpha.39", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz", + "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==", + "dev": true, + "requires": { + "mdn-data": "2.0.6", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz", + "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "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=", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "dev": true + } + } + }, + "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==", + "dev": true + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "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==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "electron-to-chromium": { + "version": "1.3.502", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.502.tgz", + "integrity": "sha512-TIeXOaHAvfP7FemGUtAJxStmOc1YFGWFNqdey/4Nk41L9b1nMmDVDGNMIWhZJvOfJxix6Cv5FGEnBK+yvw3UTg==", + "dev": true + }, + "elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", + "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "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-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escalade": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", + "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": 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==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "events": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", + "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "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==", + "dev": true + }, + "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==", + "dev": true + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "requires": { + "globule": "^1.0.0" + } + }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true + }, + "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==", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "requires": { + "global-prefix": "^3.0.0" + }, + "dependencies": { + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + } + } + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "globule": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", + "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", + "dev": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, + "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==", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "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==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "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==", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "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==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", + "dev": true + }, + "hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", + "dev": true + }, + "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==", + "dev": true + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "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=", + "dev": true + }, + "icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, + "requires": { + "postcss": "^7.0.14" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "in-publish": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz", + "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", + "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", + "dev": true + }, + "is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "dev": true, + "requires": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "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==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "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=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", + "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-svg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", + "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", + "dev": true, + "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==", + "dev": true, + "requires": { + "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=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "jest-worker": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.5.0.tgz", + "integrity": "sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-base64": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.3.tgz", + "integrity": "sha512-fiUvdfCaAXoQTHdKMgTvg6IkecXDcVz6V5rlftUTclF9IKBjMizvSdQaCl/z/6TApDeby5NL+axYou3i0mu1Pg==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "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==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "last-call-webpack-plugin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", + "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", + "dev": true, + "requires": { + "lodash": "^4.17.5", + "webpack-sources": "^1.1.0" + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "levenary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", + "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", + "dev": true, + "requires": { + "leven": "^3.1.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "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==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", + "dev": true + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.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==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "dev": true + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "mini-css-extract-plugin": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz", + "integrity": "sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "normalize-url": "1.9.1", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "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==", + "dev": true + }, + "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=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "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==", + "dev": true + }, + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.3.tgz", + "integrity": "sha512-cFOknTvng5vqnwOpDsZTWhNll6Jf8o2x+/diplafmxpuIymAjzoOolZG0VvQf3V2HgqzJNhnuKHYp2BqDgz8IQ==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "dev": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "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==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "dev": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "node-releases": { + "version": "1.1.59", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.59.tgz", + "integrity": "sha512-H3JrdUczbdiwxN5FuJPyCHnGHIFqQ0wWxo+9j1kAXAzqNMAHlo+4I/sYYxpyK0irQ73HgdiyzD32oqQDcU2Osw==", + "dev": true + }, + "node-sass": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz", + "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==", + "dev": true, + "requires": { + "async-foreach": "^0.1.3", + "chalk": "^1.1.1", + "cross-spawn": "^3.0.0", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "in-publish": "^2.0.0", + "lodash": "^4.17.15", + "meow": "^3.7.0", + "mkdirp": "^0.5.1", + "nan": "^2.13.2", + "node-gyp": "^3.8.0", + "npmlog": "^4.0.0", + "request": "^2.88.0", + "sass-graph": "2.2.5", + "stdout-stream": "^1.4.0", + "true-case-path": "^1.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E=" + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "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==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optimize-css-assets-webpack-plugin": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz", + "integrity": "sha512-q9fbvCRS6EYtUKKSwI87qm2IxlyJK5b4dygW1rKUBT6mMDhdG5e5bZT63v6tnJR9F9FB/H5a0HTmtw+laUBxKA==", + "dev": true, + "requires": { + "cssnano": "^4.1.10", + "last-call-webpack-plugin": "^3.0.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=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "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=", + "dev": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.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==", + "dev": true + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "parse-asn1": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", + "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": 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=", + "dev": true + } + } + }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "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" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "phoenix": { + "version": "file:../deps/phoenix" + }, + "phoenix_html": { + "version": "file:../deps/phoenix_html" + }, + "phoenix_live_view": { + "version": "file:../deps/phoenix_live_view" + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true, + "optional": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "7.0.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", + "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-calc": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.2.tgz", + "integrity": "sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ==", + "dev": true, + "requires": { + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + } + }, + "postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", + "dev": true, + "requires": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + } + }, + "postcss-modules-local-by-default": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz", + "integrity": "sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ==", + "dev": true, + "requires": { + "icss-utils": "^4.1.1", + "postcss": "^7.0.16", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.0" + } + }, + "postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + } + }, + "postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "dev": true, + "requires": { + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + } + }, + "postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", + "dev": true, + "requires": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "dev": true, + "requires": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-selector-parser": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", + "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "postcss-svgo": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", + "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", + "dev": true, + "requires": { + "is-svg": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "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==", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "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.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "dev": true, + "requires": { + "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=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "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==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "dependencies": { + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, + "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==", + "dev": 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" + } + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "dev": true, + "optional": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "regenerate": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", + "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.6.tgz", + "integrity": "sha512-GmwlGiazQEbOwQWDdbbaP10i15pGtScYWLbMZuu+RKRz0cZ+g8IUONazBnaZqe7j1670IV1HgE4/8iy7CQPf4Q==", + "dev": true + }, + "regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpu-core": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", + "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + } + }, + "regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "dev": true + }, + "regjsparser": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", + "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": 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=", + "dev": true, + "optional": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "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" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "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==", + "dev": true + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "dependencies": { + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + } + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", + "dev": true + }, + "rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "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==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.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==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sass-graph": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz", + "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^13.3.2" + } + }, + "sass-loader": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz", + "integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "loader-utils": "^1.2.3", + "neo-async": "^2.6.1", + "schema-utils": "^2.6.1", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + }, + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "dev": true, + "requires": { + "js-base64": "^2.1.8", + "source-map": "^0.4.2" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": 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=", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "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==", + "dev": true + } + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "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==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "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=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "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==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "dev": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.7.tgz", + "integrity": "sha512-xzYyaHUNhzgaAdBsXxk2Yvo/x1NJdslUaussK3fdpBbvttm1iIwU+c26dj9UxJcwk2c5UWt5F55MUTIA8BE7Dg==", + "dev": true, + "requires": { + "cacache": "^13.0.1", + "find-cache-dir": "^3.3.1", + "jest-worker": "^25.4.0", + "p-limit": "^2.3.0", + "schema-utils": "^2.6.6", + "serialize-javascript": "^3.1.0", + "source-map": "^0.6.1", + "terser": "^4.6.12", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "cacache": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz", + "integrity": "sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==", + "dev": true, + "requires": { + "chownr": "^1.1.2", + "figgy-pudding": "^3.5.1", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.2", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "minipass": "^3.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "p-map": "^3.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^2.7.1", + "ssri": "^7.0.0", + "unique-filename": "^1.1.1" + } + }, + "find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.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==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "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==", + "dev": true, + "requires": { + "semver": "^6.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==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "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==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "serialize-javascript": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", + "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "ssri": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.0.tgz", + "integrity": "sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1", + "minipass": "^3.1.1" + } + } + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "timers-browserify": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", + "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "dev": true, + "requires": { + "glob": "^7.1.2" + } + }, + "tslib": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "dev": true + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "optional": true + }, + "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==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vendors": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "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==", + "dev": true + }, + "watchpack": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.2.tgz", + "integrity": "sha512-ymVbbQP40MFTp+cNMvpyBpBtygHnPzPkHqoIwRRj/0B8KhqQwV8LaKjtbaxF2lK4vl8zN9wCxS46IFCU5K4W0g==", + "dev": true, + "requires": { + "chokidar": "^3.4.0", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.0" + } + }, + "watchpack-chokidar2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", + "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + } + } + }, + "webpack": { + "version": "4.41.5", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.5.tgz", + "integrity": "sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/wasm-edit": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "acorn": "^6.2.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.6.0", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "serialize-javascript": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", + "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "terser-webpack-plugin": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz", + "integrity": "sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^3.1.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + } + } + } + }, + "webpack-cli": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz", + "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "enhanced-resolve": "^4.1.1", + "findup-sync": "^3.0.0", + "global-modules": "^2.0.0", + "import-local": "^2.0.0", + "interpret": "^1.4.0", + "loader-utils": "^1.4.0", + "supports-color": "^6.1.0", + "v8-compile-cache": "^2.1.1", + "yargs": "^13.3.2" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": 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" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.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==", + "dev": 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=", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.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==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.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": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "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==", + "dev": 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=", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.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==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } +} diff --git a/assets/package.json b/assets/package.json new file mode 100644 index 0000000..8f7026f --- /dev/null +++ b/assets/package.json @@ -0,0 +1,29 @@ +{ + "repository": {}, + "description": " ", + "license": "MIT", + "scripts": { + "deploy": "webpack --mode production", + "watch": "webpack --mode development --watch" + }, + "dependencies": { + "phoenix": "file:../deps/phoenix", + "phoenix_html": "file:../deps/phoenix_html", + "phoenix_live_view": "file:../deps/phoenix_live_view", + "nprogress": "^0.2.0" + }, + "devDependencies": { + "@babel/core": "^7.0.0", + "@babel/preset-env": "^7.0.0", + "babel-loader": "^8.0.0", + "copy-webpack-plugin": "^5.1.1", + "css-loader": "^3.4.2", + "sass-loader": "^8.0.2", + "node-sass": "^4.13.1", + "mini-css-extract-plugin": "^0.9.0", + "optimize-css-assets-webpack-plugin": "^5.0.1", + "terser-webpack-plugin": "^2.3.2", + "webpack": "4.41.5", + "webpack-cli": "^3.3.2" + } +} diff --git a/assets/static/favicon.ico b/assets/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..73de524aaadcf60fbe9d32881db0aa86b58b5cb9 GIT binary patch literal 1258 zcmbtUO>fgM7{=qN=;Mz_82;lvPEdVaxv-<-&=sZLwab?3I zBP>U*&(Hv<5n@9ZQ$vhg#|u$Zmtq8BV;+W*7(?jOx-{r?#TE&$Sdq77MbdJjD5`-q zMm_z(jLv3t>5NhzK{%aG(Yudfpjd3AFdKe2U7&zdepTe>^s(@!&0X8TJ`h+-I?84Ml# literal 0 HcmV?d00001 diff --git a/assets/static/images/phoenix.png b/assets/static/images/phoenix.png new file mode 100644 index 0000000000000000000000000000000000000000..9c81075f63d2151e6f40e9aa66f665749a87cc6a GIT binary patch literal 13900 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 UWxWXg`G1#+f~I_}taaG`2PLnS&Hw-a literal 0 HcmV?d00001 diff --git a/assets/static/robots.txt b/assets/static/robots.txt new file mode 100644 index 0000000..3c9c7c0 --- /dev/null +++ b/assets/static/robots.txt @@ -0,0 +1,5 @@ +# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file +# +# To ban all spiders from the entire site uncomment the next two lines: +# User-agent: * +# Disallow: / diff --git a/assets/webpack.config.js b/assets/webpack.config.js new file mode 100644 index 0000000..dd77c3d --- /dev/null +++ b/assets/webpack.config.js @@ -0,0 +1,51 @@ +const path = require('path'); +const glob = require('glob'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const TerserPlugin = require('terser-webpack-plugin'); +const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); + +module.exports = (env, options) => { + const devMode = options.mode !== 'production'; + + return { + optimization: { + minimizer: [ + new TerserPlugin({ cache: true, parallel: true, sourceMap: devMode }), + new OptimizeCSSAssetsPlugin({}) + ] + }, + entry: { + 'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js']) + }, + output: { + filename: '[name].js', + path: path.resolve(__dirname, '../priv/static/js'), + publicPath: '/js/' + }, + devtool: devMode ? 'source-map' : undefined, + module: { + rules: [ + { + test: /\.js$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader' + } + }, + { + test: /\.[s]?css$/, + use: [ + MiniCssExtractPlugin.loader, + 'css-loader', + 'sass-loader', + ], + } + ] + }, + plugins: [ + new MiniCssExtractPlugin({ filename: '../css/app.css' }), + new CopyWebpackPlugin([{ from: 'static/', to: '../' }]) + ] + } +}; diff --git a/config/config.exs b/config/config.exs new file mode 100644 index 0000000..fe5a751 --- /dev/null +++ b/config/config.exs @@ -0,0 +1,31 @@ +# This file is responsible for configuring your application +# and its dependencies with the aid of the Mix.Config module. +# +# This configuration file is loaded before any dependency and +# is restricted to this project. + +# General application configuration +use Mix.Config + +config :sbomPoc, + ecto_repos: [SbomPoc.Repo] + +# Configures the endpoint +config :sbomPoc, SbomPocWeb.Endpoint, + url: [host: "localhost"], + secret_key_base: "CXruorR0OIs0Zn+Ue2oTYTkTM/jUU3tTL9LVJWgd7QR/FFMc4G5WE9Wft56wNpgC", + render_errors: [view: SbomPocWeb.ErrorView, accepts: ~w(html json), layout: false], + pubsub_server: SbomPoc.PubSub, + live_view: [signing_salt: "MOt4K6sZ"] + +# Configures Elixir's Logger +config :logger, :console, + format: "$time $metadata[$level] $message\n", + metadata: [:request_id] + +# Use Jason for JSON parsing in Phoenix +config :phoenix, :json_library, Jason + +# Import environment specific config. This must remain at the bottom +# of this file so it overrides the configuration defined above. +import_config "#{Mix.env()}.exs" diff --git a/config/dev.exs b/config/dev.exs new file mode 100644 index 0000000..13ea7f5 --- /dev/null +++ b/config/dev.exs @@ -0,0 +1,76 @@ +use Mix.Config + +# Configure your database +config :sbomPoc, SbomPoc.Repo, + username: "postgres", + password: "postgres", + database: "sbompoc_dev", + hostname: "localhost", + show_sensitive_data_on_connection_error: true, + pool_size: 10 + +# For development, we disable any cache and enable +# debugging and code reloading. +# +# The watchers configuration can be used to run external +# watchers to your application. For example, we use it +# with webpack to recompile .js and .css sources. +config :sbomPoc, SbomPocWeb.Endpoint, + http: [port: 4000], + debug_errors: true, + code_reloader: true, + check_origin: false, + watchers: [ + node: [ + "node_modules/webpack/bin/webpack.js", + "--mode", + "development", + "--watch-stdin", + cd: Path.expand("../assets", __DIR__) + ] + ] + +# ## SSL Support +# +# In order to use HTTPS in development, a self-signed +# certificate can be generated by running the following +# Mix task: +# +# mix phx.gen.cert +# +# Note that this task requires Erlang/OTP 20 or later. +# Run `mix help phx.gen.cert` for more information. +# +# The `http:` config above can be replaced with: +# +# https: [ +# port: 4001, +# cipher_suite: :strong, +# keyfile: "priv/cert/selfsigned_key.pem", +# certfile: "priv/cert/selfsigned.pem" +# ], +# +# If desired, both `http:` and `https:` keys can be +# configured to run both http and https servers on +# different ports. + +# Watch static and templates for browser reloading. +config :sbomPoc, SbomPocWeb.Endpoint, + live_reload: [ + patterns: [ + ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$", + ~r"priv/gettext/.*(po)$", + ~r"lib/sbomPoc_web/(live|views)/.*(ex)$", + ~r"lib/sbomPoc_web/templates/.*(eex)$" + ] + ] + +# Do not include metadata nor timestamps in development logs +config :logger, :console, format: "[$level] $message\n" + +# Set a higher stacktrace during development. Avoid configuring such +# in production as building large stacktraces may be expensive. +config :phoenix, :stacktrace_depth, 20 + +# Initialize plugs at runtime for faster development compilation +config :phoenix, :plug_init_mode, :runtime diff --git a/config/prod.exs b/config/prod.exs new file mode 100644 index 0000000..bf4662c --- /dev/null +++ b/config/prod.exs @@ -0,0 +1,55 @@ +use Mix.Config + +# For production, don't forget to configure the url host +# to something meaningful, Phoenix uses this information +# when generating URLs. +# +# Note we also include the path to a cache manifest +# containing the digested version of static files. This +# manifest is generated by the `mix phx.digest` task, +# which you should run after static files are built and +# before starting your production server. +config :sbomPoc, SbomPocWeb.Endpoint, + url: [host: "example.com", port: 80], + cache_static_manifest: "priv/static/cache_manifest.json" + +# Do not print debug messages in production +config :logger, level: :info + +# ## SSL Support +# +# To get SSL working, you will need to add the `https` key +# to the previous section and set your `:url` port to 443: +# +# config :sbomPoc, SbomPocWeb.Endpoint, +# ... +# url: [host: "example.com", port: 443], +# https: [ +# port: 443, +# cipher_suite: :strong, +# keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"), +# certfile: System.get_env("SOME_APP_SSL_CERT_PATH"), +# transport_options: [socket_opts: [:inet6]] +# ] +# +# The `cipher_suite` is set to `:strong` to support only the +# latest and more secure SSL ciphers. This means old browsers +# and clients may not be supported. You can set it to +# `:compatible` for wider support. +# +# `:keyfile` and `:certfile` expect an absolute path to the key +# and cert in disk or a relative path inside priv, for example +# "priv/ssl/server.key". For all supported SSL configuration +# options, see https://hexdocs.pm/plug/Plug.SSL.html#configure/1 +# +# We also recommend setting `force_ssl` in your endpoint, ensuring +# no data is ever sent via http, always redirecting to https: +# +# config :sbomPoc, SbomPocWeb.Endpoint, +# force_ssl: [hsts: true] +# +# Check `Plug.SSL` for all available options in `force_ssl`. + +# Finally import the config/prod.secret.exs which loads secrets +# and configuration from environment variables. +import_config "prod.secret.exs" diff --git a/config/prod.secret.exs b/config/prod.secret.exs new file mode 100644 index 0000000..4b02fe2 --- /dev/null +++ b/config/prod.secret.exs @@ -0,0 +1,41 @@ +# In this file, we load production configuration and secrets +# from environment variables. You can also hardcode secrets, +# although such is generally not recommended and you have to +# remember to add this file to your .gitignore. +use Mix.Config + +database_url = + System.get_env("DATABASE_URL") || + raise """ + environment variable DATABASE_URL is missing. + For example: ecto://USER:PASS@HOST/DATABASE + """ + +config :sbomPoc, SbomPoc.Repo, + # ssl: true, + url: database_url, + pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10") + +secret_key_base = + System.get_env("SECRET_KEY_BASE") || + raise """ + environment variable SECRET_KEY_BASE is missing. + You can generate one by calling: mix phx.gen.secret + """ + +config :sbomPoc, SbomPocWeb.Endpoint, + http: [ + port: String.to_integer(System.get_env("PORT") || "4000"), + transport_options: [socket_opts: [:inet6]] + ], + secret_key_base: secret_key_base + +# ## Using releases (Elixir v1.9+) +# +# If you are doing OTP releases, you need to instruct Phoenix +# to start each relevant endpoint: +# +# config :sbomPoc, SbomPocWeb.Endpoint, server: true +# +# Then you can assemble a release by calling `mix release`. +# See `mix help release` for more information. diff --git a/config/test.exs b/config/test.exs new file mode 100644 index 0000000..1c0ae76 --- /dev/null +++ b/config/test.exs @@ -0,0 +1,22 @@ +use Mix.Config + +# Configure your database +# +# The MIX_TEST_PARTITION environment variable can be used +# to provide built-in test partitioning in CI environment. +# Run `mix help test` for more information. +config :sbomPoc, SbomPoc.Repo, + username: "postgres", + password: "postgres", + database: "sbompoc_test#{System.get_env("MIX_TEST_PARTITION")}", + hostname: "localhost", + pool: Ecto.Adapters.SQL.Sandbox + +# We don't run a server during test. If one is required, +# you can enable the server option below. +config :sbomPoc, SbomPocWeb.Endpoint, + http: [port: 4002], + server: false + +# Print only warnings and errors during test +config :logger, level: :warn diff --git a/lib/sbomPoc.ex b/lib/sbomPoc.ex new file mode 100644 index 0000000..8a4dd0a --- /dev/null +++ b/lib/sbomPoc.ex @@ -0,0 +1,9 @@ +defmodule SbomPoc do + @moduledoc """ + SbomPoc keeps the contexts that define your domain + and business logic. + + Contexts are also responsible for managing your data, regardless + if it comes from the database, an external API or others. + """ +end diff --git a/lib/sbomPoc/application.ex b/lib/sbomPoc/application.ex new file mode 100644 index 0000000..38bc9dd --- /dev/null +++ b/lib/sbomPoc/application.ex @@ -0,0 +1,34 @@ +defmodule SbomPoc.Application do + # See https://hexdocs.pm/elixir/Application.html + # for more information on OTP Applications + @moduledoc false + + use Application + + def start(_type, _args) do + children = [ + # Start the Ecto repository + SbomPoc.Repo, + # Start the Telemetry supervisor + SbomPocWeb.Telemetry, + # Start the PubSub system + {Phoenix.PubSub, name: SbomPoc.PubSub}, + # Start the Endpoint (http/https) + SbomPocWeb.Endpoint + # Start a worker by calling: SbomPoc.Worker.start_link(arg) + # {SbomPoc.Worker, arg} + ] + + # See https://hexdocs.pm/elixir/Supervisor.html + # for other strategies and supported options + opts = [strategy: :one_for_one, name: SbomPoc.Supervisor] + Supervisor.start_link(children, opts) + end + + # Tell Phoenix to update the endpoint configuration + # whenever the application is updated. + def config_change(changed, _new, removed) do + SbomPocWeb.Endpoint.config_change(changed, removed) + :ok + end +end diff --git a/lib/sbomPoc/repo.ex b/lib/sbomPoc/repo.ex new file mode 100644 index 0000000..0571827 --- /dev/null +++ b/lib/sbomPoc/repo.ex @@ -0,0 +1,5 @@ +defmodule SbomPoc.Repo do + use Ecto.Repo, + otp_app: :sbomPoc, + adapter: Ecto.Adapters.Postgres +end diff --git a/lib/sbomPoc_web.ex b/lib/sbomPoc_web.ex new file mode 100644 index 0000000..140ed6a --- /dev/null +++ b/lib/sbomPoc_web.ex @@ -0,0 +1,102 @@ +defmodule SbomPocWeb do + @moduledoc """ + The entrypoint for defining your web interface, such + as controllers, views, channels and so on. + + This can be used in your application as: + + use SbomPocWeb, :controller + use SbomPocWeb, :view + + The definitions below will be executed for every view, + controller, etc, so keep them short and clean, focused + on imports, uses and aliases. + + Do NOT define functions inside the quoted expressions + below. Instead, define any helper function in modules + and import those modules here. + """ + + def controller do + quote do + use Phoenix.Controller, namespace: SbomPocWeb + + import Plug.Conn + import SbomPocWeb.Gettext + alias SbomPocWeb.Router.Helpers, as: Routes + end + end + + def view do + quote do + use Phoenix.View, + root: "lib/sbomPoc_web/templates", + namespace: SbomPocWeb + + # Import convenience functions from controllers + import Phoenix.Controller, + only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1] + + # Include shared imports and aliases for views + unquote(view_helpers()) + end + end + + def live_view do + quote do + use Phoenix.LiveView, + layout: {SbomPocWeb.LayoutView, "live.html"} + + unquote(view_helpers()) + end + end + + def live_component do + quote do + use Phoenix.LiveComponent + + unquote(view_helpers()) + end + end + + def router do + quote do + use Phoenix.Router + + import Plug.Conn + import Phoenix.Controller + import Phoenix.LiveView.Router + end + end + + def channel do + quote do + use Phoenix.Channel + import SbomPocWeb.Gettext + end + end + + defp view_helpers do + quote do + # Use all HTML functionality (forms, tags, etc) + use Phoenix.HTML + + # Import LiveView helpers (live_render, live_component, live_patch, etc) + import Phoenix.LiveView.Helpers + + # Import basic rendering functionality (render, render_layout, etc) + import Phoenix.View + + import SbomPocWeb.ErrorHelpers + import SbomPocWeb.Gettext + alias SbomPocWeb.Router.Helpers, as: Routes + end + end + + @doc """ + When used, dispatch to the appropriate controller/view/etc. + """ + defmacro __using__(which) when is_atom(which) do + apply(__MODULE__, which, []) + end +end diff --git a/lib/sbomPoc_web/channels/user_socket.ex b/lib/sbomPoc_web/channels/user_socket.ex new file mode 100644 index 0000000..394b154 --- /dev/null +++ b/lib/sbomPoc_web/channels/user_socket.ex @@ -0,0 +1,35 @@ +defmodule SbomPocWeb.UserSocket do + use Phoenix.Socket + + ## Channels + # channel "room:*", SbomPocWeb.RoomChannel + + # Socket params are passed from the client and can + # be used to verify and authenticate a user. After + # verification, you can put default assigns into + # the socket that will be set for all channels, ie + # + # {:ok, assign(socket, :user_id, verified_user_id)} + # + # To deny connection, return `:error`. + # + # See `Phoenix.Token` documentation for examples in + # performing token verification on connect. + @impl true + def connect(_params, socket, _connect_info) do + {:ok, socket} + end + + # Socket id's are topics that allow you to identify all sockets for a given user: + # + # def id(socket), do: "user_socket:#{socket.assigns.user_id}" + # + # Would allow you to broadcast a "disconnect" event and terminate + # all active sockets and channels for a given user: + # + # SbomPocWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{}) + # + # Returning `nil` makes this socket anonymous. + @impl true + def id(_socket), do: nil +end diff --git a/lib/sbomPoc_web/endpoint.ex b/lib/sbomPoc_web/endpoint.ex new file mode 100644 index 0000000..87d7354 --- /dev/null +++ b/lib/sbomPoc_web/endpoint.ex @@ -0,0 +1,54 @@ +defmodule SbomPocWeb.Endpoint do + use Phoenix.Endpoint, otp_app: :sbomPoc + + # The session will be stored in the cookie and signed, + # this means its contents can be read but not tampered with. + # Set :encryption_salt if you would also like to encrypt it. + @session_options [ + store: :cookie, + key: "_sbomPoc_key", + signing_salt: "3y5dtEWj" + ] + + socket "/socket", SbomPocWeb.UserSocket, + websocket: true, + longpoll: false + + socket "/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]] + + # Serve at "/" the static files from "priv/static" directory. + # + # You should set gzip to true if you are running phx.digest + # when deploying your static files in production. + plug Plug.Static, + at: "/", + from: :sbomPoc, + gzip: false, + only: ~w(css fonts images js favicon.ico robots.txt) + + # Code reloading can be explicitly enabled under the + # :code_reloader configuration of your endpoint. + if code_reloading? do + socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket + plug Phoenix.LiveReloader + plug Phoenix.CodeReloader + plug Phoenix.Ecto.CheckRepoStatus, otp_app: :sbomPoc + end + + plug Phoenix.LiveDashboard.RequestLogger, + param_key: "request_logger", + cookie_key: "request_logger" + + plug Plug.RequestId + plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint] + + plug Plug.Parsers, + parsers: [:urlencoded, :multipart, :json], + pass: ["*/*"], + json_decoder: Phoenix.json_library() + + plug Plug.MethodOverride + plug Plug.Head + plug Plug.Session, @session_options + plug SbomPocWeb.Router +end diff --git a/lib/sbomPoc_web/gettext.ex b/lib/sbomPoc_web/gettext.ex new file mode 100644 index 0000000..3346875 --- /dev/null +++ b/lib/sbomPoc_web/gettext.ex @@ -0,0 +1,24 @@ +defmodule SbomPocWeb.Gettext do + @moduledoc """ + A module providing Internationalization with a gettext-based API. + + By using [Gettext](https://hexdocs.pm/gettext), + your module gains a set of macros for translations, for example: + + import SbomPocWeb.Gettext + + # Simple translation + gettext("Here is the string to translate") + + # Plural translation + ngettext("Here is the string to translate", + "Here are the strings to translate", + 3) + + # Domain-based translation + dgettext("errors", "Here is the error message to translate") + + See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage. + """ + use Gettext, otp_app: :sbomPoc +end diff --git a/lib/sbomPoc_web/live/page_live.ex b/lib/sbomPoc_web/live/page_live.ex new file mode 100644 index 0000000..d9a6545 --- /dev/null +++ b/lib/sbomPoc_web/live/page_live.ex @@ -0,0 +1,39 @@ +defmodule SbomPocWeb.PageLive do + use SbomPocWeb, :live_view + + @impl true + def mount(_params, _session, socket) do + {:ok, assign(socket, query: "", results: %{})} + end + + @impl true + def handle_event("suggest", %{"q" => query}, socket) do + {:noreply, assign(socket, results: search(query), query: query)} + end + + @impl true + def handle_event("search", %{"q" => query}, socket) do + case search(query) do + %{^query => vsn} -> + {:noreply, redirect(socket, external: "https://hexdocs.pm/#{query}/#{vsn}")} + + _ -> + {:noreply, + socket + |> put_flash(:error, "No dependencies found matching \"#{query}\"") + |> assign(results: %{}, query: query)} + end + end + + defp search(query) do + if not SbomPocWeb.Endpoint.config(:code_reloader) do + raise "action disabled when not in development" + end + + for {app, desc, vsn} <- Application.started_applications(), + app = to_string(app), + String.starts_with?(app, query) and not List.starts_with?(desc, ~c"ERTS"), + into: %{}, + do: {app, vsn} + end +end diff --git a/lib/sbomPoc_web/live/page_live.html.leex b/lib/sbomPoc_web/live/page_live.html.leex new file mode 100644 index 0000000..65cf576 --- /dev/null +++ b/lib/sbomPoc_web/live/page_live.html.leex @@ -0,0 +1,48 @@ +
+

<%= gettext "Welcome to %{name}!", name: "Phoenix" %>

+

Peace-of-mind from prototype to production

+ +
+ + + <%= for {app, _vsn} <- @results do %> + + <% end %> + + +
+
+ +
+ + +
diff --git a/lib/sbomPoc_web/router.ex b/lib/sbomPoc_web/router.ex new file mode 100644 index 0000000..c41b9e8 --- /dev/null +++ b/lib/sbomPoc_web/router.ex @@ -0,0 +1,43 @@ +defmodule SbomPocWeb.Router do + use SbomPocWeb, :router + + pipeline :browser do + plug :accepts, ["html"] + plug :fetch_session + plug :fetch_live_flash + plug :put_root_layout, {SbomPocWeb.LayoutView, :root} + plug :protect_from_forgery + plug :put_secure_browser_headers + end + + pipeline :api do + plug :accepts, ["json"] + end + + scope "/", SbomPocWeb do + pipe_through :browser + + live "/", PageLive, :index + end + + # Other scopes may use custom stacks. + # scope "/api", SbomPocWeb do + # pipe_through :api + # end + + # Enables LiveDashboard only for development + # + # If you want to use the LiveDashboard in production, you should put + # it behind authentication and allow only admins to access it. + # If your application does not have an admins-only section yet, + # you can use Plug.BasicAuth to set up some basic authentication + # as long as you are also using SSL (which you should anyway). + if Mix.env() in [:dev, :test] do + import Phoenix.LiveDashboard.Router + + scope "/" do + pipe_through :browser + live_dashboard "/dashboard", metrics: SbomPocWeb.Telemetry + end + end +end diff --git a/lib/sbomPoc_web/telemetry.ex b/lib/sbomPoc_web/telemetry.ex new file mode 100644 index 0000000..b971417 --- /dev/null +++ b/lib/sbomPoc_web/telemetry.ex @@ -0,0 +1,55 @@ +defmodule SbomPocWeb.Telemetry do + use Supervisor + import Telemetry.Metrics + + def start_link(arg) do + Supervisor.start_link(__MODULE__, arg, name: __MODULE__) + end + + @impl true + def init(_arg) do + children = [ + # Telemetry poller will execute the given period measurements + # every 10_000ms. Learn more here: https://hexdocs.pm/telemetry_metrics + {:telemetry_poller, measurements: periodic_measurements(), period: 10_000} + # Add reporters as children of your supervision tree. + # {Telemetry.Metrics.ConsoleReporter, metrics: metrics()} + ] + + Supervisor.init(children, strategy: :one_for_one) + end + + def metrics do + [ + # Phoenix Metrics + summary("phoenix.endpoint.stop.duration", + unit: {:native, :millisecond} + ), + summary("phoenix.router_dispatch.stop.duration", + tags: [:route], + unit: {:native, :millisecond} + ), + + # Database Metrics + summary("sbomPoc.repo.query.total_time", unit: {:native, :millisecond}), + summary("sbomPoc.repo.query.decode_time", unit: {:native, :millisecond}), + summary("sbomPoc.repo.query.query_time", unit: {:native, :millisecond}), + summary("sbomPoc.repo.query.queue_time", unit: {:native, :millisecond}), + summary("sbomPoc.repo.query.idle_time", unit: {:native, :millisecond}), + + # VM Metrics + summary("vm.memory.total", unit: {:byte, :kilobyte}), + summary("vm.total_run_queue_lengths.total"), + summary("vm.total_run_queue_lengths.cpu"), + summary("vm.total_run_queue_lengths.io") + ] + end + + defp periodic_measurements do + [ + # A module, function and arguments to be invoked periodically. + # This function must call :telemetry.execute/3 and a metric must be added above. + # {SbomPocWeb, :count_users, []} + ] + end +end diff --git a/lib/sbomPoc_web/templates/layout/app.html.eex b/lib/sbomPoc_web/templates/layout/app.html.eex new file mode 100644 index 0000000..09ffdad --- /dev/null +++ b/lib/sbomPoc_web/templates/layout/app.html.eex @@ -0,0 +1,5 @@ +
+ + + <%= @inner_content %> +
diff --git a/lib/sbomPoc_web/templates/layout/live.html.leex b/lib/sbomPoc_web/templates/layout/live.html.leex new file mode 100644 index 0000000..8dcded5 --- /dev/null +++ b/lib/sbomPoc_web/templates/layout/live.html.leex @@ -0,0 +1,11 @@ +
+ + + + + <%= @inner_content %> +
diff --git a/lib/sbomPoc_web/templates/layout/root.html.leex b/lib/sbomPoc_web/templates/layout/root.html.leex new file mode 100644 index 0000000..fe78478 --- /dev/null +++ b/lib/sbomPoc_web/templates/layout/root.html.leex @@ -0,0 +1,30 @@ + + + + + + + <%= csrf_meta_tag() %> + <%= live_title_tag assigns[:page_title] || "SbomPoc", suffix: " · Phoenix Framework" %> + "/> + + + +
+
+ + +
+
+ <%= @inner_content %> + + diff --git a/lib/sbomPoc_web/views/error_helpers.ex b/lib/sbomPoc_web/views/error_helpers.ex new file mode 100644 index 0000000..8480f6a --- /dev/null +++ b/lib/sbomPoc_web/views/error_helpers.ex @@ -0,0 +1,47 @@ +defmodule SbomPocWeb.ErrorHelpers do + @moduledoc """ + Conveniences for translating and building error messages. + """ + + use Phoenix.HTML + + @doc """ + Generates tag for inlined form input errors. + """ + def error_tag(form, field) do + Enum.map(Keyword.get_values(form.errors, field), fn error -> + content_tag(:span, translate_error(error), + class: "invalid-feedback", + phx_feedback_for: input_id(form, field) + ) + end) + end + + @doc """ + Translates an error message using gettext. + """ + def translate_error({msg, opts}) do + # When using gettext, we typically pass the strings we want + # to translate as a static argument: + # + # # Translate "is invalid" in the "errors" domain + # dgettext("errors", "is invalid") + # + # # Translate the number of files with plural rules + # dngettext("errors", "1 file", "%{count} files", count) + # + # Because the error messages we show in our forms and APIs + # are defined inside Ecto, we need to translate them dynamically. + # This requires us to call the Gettext module passing our gettext + # backend as first argument. + # + # Note we use the "errors" domain, which means translations + # should be written to the errors.po file. The :count option is + # set by Ecto and indicates we should also apply plural rules. + if count = opts[:count] do + Gettext.dngettext(SbomPocWeb.Gettext, "errors", msg, msg, count, opts) + else + Gettext.dgettext(SbomPocWeb.Gettext, "errors", msg, opts) + end + end +end diff --git a/lib/sbomPoc_web/views/error_view.ex b/lib/sbomPoc_web/views/error_view.ex new file mode 100644 index 0000000..931f287 --- /dev/null +++ b/lib/sbomPoc_web/views/error_view.ex @@ -0,0 +1,16 @@ +defmodule SbomPocWeb.ErrorView do + use SbomPocWeb, :view + + # If you want to customize a particular status code + # for a certain format, you may uncomment below. + # def render("500.html", _assigns) do + # "Internal Server Error" + # end + + # By default, Phoenix returns the status message from + # the template name. For example, "404.html" becomes + # "Not Found". + def template_not_found(template, _assigns) do + Phoenix.Controller.status_message_from_template(template) + end +end diff --git a/lib/sbomPoc_web/views/layout_view.ex b/lib/sbomPoc_web/views/layout_view.ex new file mode 100644 index 0000000..0c2e0b3 --- /dev/null +++ b/lib/sbomPoc_web/views/layout_view.ex @@ -0,0 +1,3 @@ +defmodule SbomPocWeb.LayoutView do + use SbomPocWeb, :view +end diff --git a/mix.exs b/mix.exs new file mode 100644 index 0000000..76fab45 --- /dev/null +++ b/mix.exs @@ -0,0 +1,68 @@ +defmodule SbomPoc.MixProject do + use Mix.Project + + def project do + [ + app: :sbomPoc, + version: "0.1.0", + elixir: "~> 1.7", + elixirc_paths: elixirc_paths(Mix.env()), + compilers: [:phoenix, :gettext] ++ Mix.compilers(), + start_permanent: Mix.env() == :prod, + aliases: aliases(), + deps: deps() + ] + end + + # Configuration for the OTP application. + # + # Type `mix help compile.app` for more information. + def application do + [ + mod: {SbomPoc.Application, []}, + extra_applications: [:logger, :runtime_tools] + ] + end + + # Specifies which paths to compile per environment. + defp elixirc_paths(:test), do: ["lib", "test/support"] + defp elixirc_paths(_), do: ["lib"] + + # Specifies your project dependencies. + # + # Type `mix help deps` for examples and options. + defp deps do + [ + {:phoenix, "~> 1.5.3"}, + {:phoenix_ecto, "~> 4.1"}, + {:ecto, ">= 3.4.4 and < 3.4.5"}, + {:ecto_sql, ">= 3.4.4 and < 3.4.5"}, + {:postgrex, ">= 0.0.0"}, + {:phoenix_live_view, "~> 0.13.0"}, + {:floki, ">= 0.0.0", only: :test}, + {:phoenix_html, "~> 2.11"}, + {:phoenix_live_reload, "~> 1.2", only: :dev}, + {:phoenix_live_dashboard, "~> 0.2.0"}, + {:telemetry_metrics, "~> 0.4"}, + {:telemetry_poller, "~> 0.4"}, + {:gettext, "~> 0.11"}, + {:jason, "~> 1.0"}, + {:plug_cowboy, "~> 2.0"} + ] + end + + # Aliases are shortcuts or tasks specific to the current project. + # For example, to install project dependencies and perform other setup tasks, run: + # + # $ mix setup + # + # See the documentation for `Mix` for more info on aliases. + defp aliases do + [ + setup: ["deps.get", "ecto.setup", "cmd npm install --prefix assets"], + "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"], + "ecto.reset": ["ecto.drop", "ecto.setup"], + test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"] + ] + end +end diff --git a/mix.lock b/mix.lock new file mode 100644 index 0000000..55a77ba --- /dev/null +++ b/mix.lock @@ -0,0 +1,30 @@ +%{ + "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm", "4a0850c9be22a43af9920a71ab17c051f5f7d45c209e40269a1938832510e4d9"}, + "cowboy": {:hex, :cowboy, "2.8.0", "f3dc62e35797ecd9ac1b50db74611193c29815401e53bac9a5c0577bd7bc667d", [:rebar3], [{:cowlib, "~> 2.9.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "4643e4fba74ac96d4d152c75803de6fad0b3fa5df354c71afdd6cbeeb15fac8a"}, + "cowlib": {:hex, :cowlib, "2.9.1", "61a6c7c50cf07fdd24b2f45b89500bb93b6686579b069a89f88cb211e1125c78", [:rebar3], [], "hexpm", "e4175dc240a70d996156160891e1c62238ede1729e45740bdd38064dad476170"}, + "db_connection": {:hex, :db_connection, "2.2.2", "3bbca41b199e1598245b716248964926303b5d4609ff065125ce98bcd368939e", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "642af240d8a8affb93b4ba5a6fcd2bbcbdc327e1a524b825d383711536f8070c"}, + "decimal": {:hex, :decimal, "1.8.1", "a4ef3f5f3428bdbc0d35374029ffcf4ede8533536fa79896dd450168d9acdf3c", [:mix], [], "hexpm", "3cb154b00225ac687f6cbd4acc4b7960027c757a5152b369923ead9ddbca7aec"}, + "ecto": {:hex, :ecto, "3.4.4", "a2c881e80dc756d648197ae0d936216c0308370332c5e77a2325a10293eef845", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cc4bd3ad62abc3b21fb629f0f7a3dab23a192fca837d257dd08449fba7373561"}, + "ecto_sql": {:hex, :ecto_sql, "3.4.4", "d28bac2d420f708993baed522054870086fd45016a9d09bb2cd521b9c48d32ea", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.4.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.0", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "edb49af715dd72f213b66adfd0f668a43c17ed510b5d9ac7528569b23af57fe8"}, + "file_system": {:hex, :file_system, "0.2.8", "f632bd287927a1eed2b718f22af727c5aeaccc9a98d8c2bd7bff709e851dc986", [:mix], [], "hexpm", "97a3b6f8d63ef53bd0113070102db2ce05352ecf0d25390eb8d747c2bde98bca"}, + "floki": {:hex, :floki, "0.27.0", "6b29a14283f1e2e8fad824bc930eaa9477c462022075df6bea8f0ad811c13599", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "583b8c13697c37179f1f82443bcc7ad2f76fbc0bf4c186606eebd658f7f2631b"}, + "gettext": {:hex, :gettext, "0.18.0", "406d6b9e0e3278162c2ae1de0a60270452c553536772167e2d701f028116f870", [:mix], [], "hexpm", "c3f850be6367ebe1a08616c2158affe4a23231c70391050bf359d5f92f66a571"}, + "html_entities": {:hex, :html_entities, "0.5.1", "1c9715058b42c35a2ab65edc5b36d0ea66dd083767bef6e3edb57870ef556549", [:mix], [], "hexpm", "30efab070904eb897ff05cd52fa61c1025d7f8ef3a9ca250bc4e6513d16c32de"}, + "jason": {:hex, :jason, "1.2.1", "12b22825e22f468c02eb3e4b9985f3d0cb8dc40b9bd704730efa11abd2708c44", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b659b8571deedf60f79c5a608e15414085fa141344e2716fbd6988a084b5f993"}, + "mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm", "6cbe761d6a0ca5a31a0931bf4c63204bceb64538e664a8ecf784a9a6f3b875f1"}, + "phoenix": {:hex, :phoenix, "1.5.4", "0fca9ce7e960f9498d6315e41fcd0c80bfa6fbeb5fa3255b830c67fdfb7e703f", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4e516d131fde87b568abd62e1b14aa07ba7d5edfd230bab4e25cc9dedbb39135"}, + "phoenix_ecto": {:hex, :phoenix_ecto, "4.1.0", "a044d0756d0464c5a541b4a0bf4bcaf89bffcaf92468862408290682c73ae50d", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "c5e666a341ff104d0399d8f0e4ff094559b2fde13a5985d4cb5023b2c2ac558b"}, + "phoenix_html": {:hex, :phoenix_html, "2.14.2", "b8a3899a72050f3f48a36430da507dd99caf0ac2d06c77529b1646964f3d563e", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "58061c8dfd25da5df1ea0ca47c972f161beb6c875cd293917045b92ffe1bf617"}, + "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.2.6", "1b4e1b7d797386b7f9d70d2af931dc9843a5f2f2423609d22cef1eec4e4dba7d", [:mix], [{:phoenix_html, "~> 2.14.1 or ~> 2.15", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.13.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.4.0 or ~> 0.5.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "b20dcad98c4ca63d38a7f5e7a40936e1e8e9da983d3d722b88ae33afb866c9ca"}, + "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.4", "940c0344b1d66a2e46eef02af3a70e0c5bb45a4db0bf47917add271b76cd3914", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "38f9308357dea4cc77f247e216da99fcb0224e05ada1469167520bed4cb8cccd"}, + "phoenix_live_view": {:hex, :phoenix_live_view, "0.13.3", "2186c55cc7c54ca45b97c6f28cfd267d1c61b5f205f3c83533704cd991bdfdec", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.4.17 or ~> 1.5.2", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm", "c6309a7da2e779cb9cdf2fb603d75f38f49ef324bedc7a81825998bd1744ff8a"}, + "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"}, + "plug": {:hex, :plug, "1.10.3", "c9cebe917637d8db0e759039cc106adca069874e1a9034fd6e3fdd427fd3c283", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "01f9037a2a1de1d633b5a881101e6a444bcabb1d386ca1e00bb273a1f1d9d939"}, + "plug_cowboy": {:hex, :plug_cowboy, "2.3.0", "149a50e05cb73c12aad6506a371cd75750c0b19a32f81866e1a323dda9e0e99d", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "bc595a1870cef13f9c1e03df56d96804db7f702175e4ccacdb8fc75c02a7b97e"}, + "plug_crypto": {:hex, :plug_crypto, "1.1.2", "bdd187572cc26dbd95b87136290425f2b580a116d3fb1f564216918c9730d227", [:mix], [], "hexpm", "6b8b608f895b6ffcfad49c37c7883e8df98ae19c6a28113b02aa1e9c5b22d6b5"}, + "postgrex": {:hex, :postgrex, "0.15.5", "aec40306a622d459b01bff890fa42f1430dac61593b122754144ad9033a2152f", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "ed90c81e1525f65a2ba2279dbcebf030d6d13328daa2f8088b9661eb9143af7f"}, + "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"}, + "telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"}, + "telemetry_metrics": {:hex, :telemetry_metrics, "0.5.0", "1b796e74add83abf844e808564275dfb342bcc930b04c7577ab780e262b0d998", [:mix], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "31225e6ce7a37a421a0a96ec55244386aec1c190b22578bd245188a4a33298fd"}, + "telemetry_poller": {:hex, :telemetry_poller, "0.5.1", "21071cc2e536810bac5628b935521ff3e28f0303e770951158c73eaaa01e962a", [:rebar3], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4cab72069210bc6e7a080cec9afffad1b33370149ed5d379b81c7c5f0c663fd4"}, +} diff --git a/priv/gettext/en/LC_MESSAGES/errors.po b/priv/gettext/en/LC_MESSAGES/errors.po new file mode 100644 index 0000000..a589998 --- /dev/null +++ b/priv/gettext/en/LC_MESSAGES/errors.po @@ -0,0 +1,97 @@ +## `msgid`s in this file come from POT (.pot) files. +## +## Do not add, change, or remove `msgid`s manually here as +## they're tied to the ones in the corresponding POT file +## (with the same domain). +## +## Use `mix gettext.extract --merge` or `mix gettext.merge` +## to merge POT files into PO files. +msgid "" +msgstr "" +"Language: en\n" + +## From Ecto.Changeset.cast/4 +msgid "can't be blank" +msgstr "" + +## From Ecto.Changeset.unique_constraint/3 +msgid "has already been taken" +msgstr "" + +## From Ecto.Changeset.put_change/3 +msgid "is invalid" +msgstr "" + +## From Ecto.Changeset.validate_acceptance/3 +msgid "must be accepted" +msgstr "" + +## From Ecto.Changeset.validate_format/3 +msgid "has invalid format" +msgstr "" + +## From Ecto.Changeset.validate_subset/3 +msgid "has an invalid entry" +msgstr "" + +## From Ecto.Changeset.validate_exclusion/3 +msgid "is reserved" +msgstr "" + +## From Ecto.Changeset.validate_confirmation/3 +msgid "does not match confirmation" +msgstr "" + +## From Ecto.Changeset.no_assoc_constraint/3 +msgid "is still associated with this entry" +msgstr "" + +msgid "are still associated with this entry" +msgstr "" + +## From Ecto.Changeset.validate_length/3 +msgid "should be %{count} character(s)" +msgid_plural "should be %{count} character(s)" +msgstr[0] "" +msgstr[1] "" + +msgid "should have %{count} item(s)" +msgid_plural "should have %{count} item(s)" +msgstr[0] "" +msgstr[1] "" + +msgid "should be at least %{count} character(s)" +msgid_plural "should be at least %{count} character(s)" +msgstr[0] "" +msgstr[1] "" + +msgid "should have at least %{count} item(s)" +msgid_plural "should have at least %{count} item(s)" +msgstr[0] "" +msgstr[1] "" + +msgid "should be at most %{count} character(s)" +msgid_plural "should be at most %{count} character(s)" +msgstr[0] "" +msgstr[1] "" + +msgid "should have at most %{count} item(s)" +msgid_plural "should have at most %{count} item(s)" +msgstr[0] "" +msgstr[1] "" + +## From Ecto.Changeset.validate_number/3 +msgid "must be less than %{number}" +msgstr "" + +msgid "must be greater than %{number}" +msgstr "" + +msgid "must be less than or equal to %{number}" +msgstr "" + +msgid "must be greater than or equal to %{number}" +msgstr "" + +msgid "must be equal to %{number}" +msgstr "" diff --git a/priv/gettext/errors.pot b/priv/gettext/errors.pot new file mode 100644 index 0000000..39a220b --- /dev/null +++ b/priv/gettext/errors.pot @@ -0,0 +1,95 @@ +## This is a PO Template file. +## +## `msgid`s here are often extracted from source code. +## Add new translations manually only if they're dynamic +## translations that can't be statically extracted. +## +## Run `mix gettext.extract` to bring this file up to +## date. Leave `msgstr`s empty as changing them here has no +## effect: edit them in PO (`.po`) files instead. + +## From Ecto.Changeset.cast/4 +msgid "can't be blank" +msgstr "" + +## From Ecto.Changeset.unique_constraint/3 +msgid "has already been taken" +msgstr "" + +## From Ecto.Changeset.put_change/3 +msgid "is invalid" +msgstr "" + +## From Ecto.Changeset.validate_acceptance/3 +msgid "must be accepted" +msgstr "" + +## From Ecto.Changeset.validate_format/3 +msgid "has invalid format" +msgstr "" + +## From Ecto.Changeset.validate_subset/3 +msgid "has an invalid entry" +msgstr "" + +## From Ecto.Changeset.validate_exclusion/3 +msgid "is reserved" +msgstr "" + +## From Ecto.Changeset.validate_confirmation/3 +msgid "does not match confirmation" +msgstr "" + +## From Ecto.Changeset.no_assoc_constraint/3 +msgid "is still associated with this entry" +msgstr "" + +msgid "are still associated with this entry" +msgstr "" + +## From Ecto.Changeset.validate_length/3 +msgid "should be %{count} character(s)" +msgid_plural "should be %{count} character(s)" +msgstr[0] "" +msgstr[1] "" + +msgid "should have %{count} item(s)" +msgid_plural "should have %{count} item(s)" +msgstr[0] "" +msgstr[1] "" + +msgid "should be at least %{count} character(s)" +msgid_plural "should be at least %{count} character(s)" +msgstr[0] "" +msgstr[1] "" + +msgid "should have at least %{count} item(s)" +msgid_plural "should have at least %{count} item(s)" +msgstr[0] "" +msgstr[1] "" + +msgid "should be at most %{count} character(s)" +msgid_plural "should be at most %{count} character(s)" +msgstr[0] "" +msgstr[1] "" + +msgid "should have at most %{count} item(s)" +msgid_plural "should have at most %{count} item(s)" +msgstr[0] "" +msgstr[1] "" + +## From Ecto.Changeset.validate_number/3 +msgid "must be less than %{number}" +msgstr "" + +msgid "must be greater than %{number}" +msgstr "" + +msgid "must be less than or equal to %{number}" +msgstr "" + +msgid "must be greater than or equal to %{number}" +msgstr "" + +msgid "must be equal to %{number}" +msgstr "" diff --git a/priv/repo/migrations/.formatter.exs b/priv/repo/migrations/.formatter.exs new file mode 100644 index 0000000..49f9151 --- /dev/null +++ b/priv/repo/migrations/.formatter.exs @@ -0,0 +1,4 @@ +[ + import_deps: [:ecto_sql], + inputs: ["*.exs"] +] diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs new file mode 100644 index 0000000..785b3a2 --- /dev/null +++ b/priv/repo/seeds.exs @@ -0,0 +1,11 @@ +# Script for populating the database. You can run it as: +# +# mix run priv/repo/seeds.exs +# +# Inside the script, you can read and write to any of your +# repositories directly: +# +# SbomPoc.Repo.insert!(%SbomPoc.SomeSchema{}) +# +# We recommend using the bang functions (`insert!`, `update!` +# and so on) as they will fail if something goes wrong. diff --git a/test/sbomPoc_web/live/page_live_test.exs b/test/sbomPoc_web/live/page_live_test.exs new file mode 100644 index 0000000..c81e653 --- /dev/null +++ b/test/sbomPoc_web/live/page_live_test.exs @@ -0,0 +1,11 @@ +defmodule SbomPocWeb.PageLiveTest do + use SbomPocWeb.ConnCase + + import Phoenix.LiveViewTest + + test "disconnected and connected render", %{conn: conn} do + {:ok, page_live, disconnected_html} = live(conn, "/") + assert disconnected_html =~ "Welcome to Phoenix!" + assert render(page_live) =~ "Welcome to Phoenix!" + end +end diff --git a/test/sbomPoc_web/views/error_view_test.exs b/test/sbomPoc_web/views/error_view_test.exs new file mode 100644 index 0000000..4d0a10c --- /dev/null +++ b/test/sbomPoc_web/views/error_view_test.exs @@ -0,0 +1,14 @@ +defmodule SbomPocWeb.ErrorViewTest do + use SbomPocWeb.ConnCase, async: true + + # Bring render/3 and render_to_string/3 for testing custom views + import Phoenix.View + + test "renders 404.html" do + assert render_to_string(SbomPocWeb.ErrorView, "404.html", []) == "Not Found" + end + + test "renders 500.html" do + assert render_to_string(SbomPocWeb.ErrorView, "500.html", []) == "Internal Server Error" + end +end diff --git a/test/sbomPoc_web/views/layout_view_test.exs b/test/sbomPoc_web/views/layout_view_test.exs new file mode 100644 index 0000000..7738832 --- /dev/null +++ b/test/sbomPoc_web/views/layout_view_test.exs @@ -0,0 +1,8 @@ +defmodule SbomPocWeb.LayoutViewTest do + use SbomPocWeb.ConnCase, async: true + + # When testing helpers, you may want to import Phoenix.HTML and + # use functions such as safe_to_string() to convert the helper + # result into an HTML string. + # import Phoenix.HTML +end diff --git a/test/support/channel_case.ex b/test/support/channel_case.ex new file mode 100644 index 0000000..253aa9f --- /dev/null +++ b/test/support/channel_case.ex @@ -0,0 +1,40 @@ +defmodule SbomPocWeb.ChannelCase do + @moduledoc """ + This module defines the test case to be used by + channel tests. + + Such tests rely on `Phoenix.ChannelTest` and also + import other functionality to make it easier + to build common data structures and query the data layer. + + Finally, if the test case interacts with the database, + we enable the SQL sandbox, so changes done to the database + are reverted at the end of every test. If you are using + PostgreSQL, you can even run database tests asynchronously + by setting `use SbomPocWeb.ChannelCase, async: true`, although + this option is not recommended for other databases. + """ + + use ExUnit.CaseTemplate + + using do + quote do + # Import conveniences for testing with channels + import Phoenix.ChannelTest + import SbomPocWeb.ChannelCase + + # The default endpoint for testing + @endpoint SbomPocWeb.Endpoint + end + end + + setup tags do + :ok = Ecto.Adapters.SQL.Sandbox.checkout(SbomPoc.Repo) + + unless tags[:async] do + Ecto.Adapters.SQL.Sandbox.mode(SbomPoc.Repo, {:shared, self()}) + end + + :ok + end +end diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex new file mode 100644 index 0000000..a8f333d --- /dev/null +++ b/test/support/conn_case.ex @@ -0,0 +1,43 @@ +defmodule SbomPocWeb.ConnCase do + @moduledoc """ + This module defines the test case to be used by + tests that require setting up a connection. + + Such tests rely on `Phoenix.ConnTest` and also + import other functionality to make it easier + to build common data structures and query the data layer. + + Finally, if the test case interacts with the database, + we enable the SQL sandbox, so changes done to the database + are reverted at the end of every test. If you are using + PostgreSQL, you can even run database tests asynchronously + by setting `use SbomPocWeb.ConnCase, async: true`, although + this option is not recommended for other databases. + """ + + use ExUnit.CaseTemplate + + using do + quote do + # Import conveniences for testing with connections + import Plug.Conn + import Phoenix.ConnTest + import SbomPocWeb.ConnCase + + alias SbomPocWeb.Router.Helpers, as: Routes + + # The default endpoint for testing + @endpoint SbomPocWeb.Endpoint + end + end + + setup tags do + :ok = Ecto.Adapters.SQL.Sandbox.checkout(SbomPoc.Repo) + + unless tags[:async] do + Ecto.Adapters.SQL.Sandbox.mode(SbomPoc.Repo, {:shared, self()}) + end + + {:ok, conn: Phoenix.ConnTest.build_conn()} + end +end diff --git a/test/support/data_case.ex b/test/support/data_case.ex new file mode 100644 index 0000000..d487908 --- /dev/null +++ b/test/support/data_case.ex @@ -0,0 +1,55 @@ +defmodule SbomPoc.DataCase do + @moduledoc """ + This module defines the setup for tests requiring + access to the application's data layer. + + You may define functions here to be used as helpers in + your tests. + + Finally, if the test case interacts with the database, + we enable the SQL sandbox, so changes done to the database + are reverted at the end of every test. If you are using + PostgreSQL, you can even run database tests asynchronously + by setting `use SbomPoc.DataCase, async: true`, although + this option is not recommended for other databases. + """ + + use ExUnit.CaseTemplate + + using do + quote do + alias SbomPoc.Repo + + import Ecto + import Ecto.Changeset + import Ecto.Query + import SbomPoc.DataCase + end + end + + setup tags do + :ok = Ecto.Adapters.SQL.Sandbox.checkout(SbomPoc.Repo) + + unless tags[:async] do + Ecto.Adapters.SQL.Sandbox.mode(SbomPoc.Repo, {:shared, self()}) + end + + :ok + end + + @doc """ + A helper that transforms changeset errors into a map of messages. + + assert {:error, changeset} = Accounts.create_user(%{password: "short"}) + assert "password is too short" in errors_on(changeset).password + assert %{password: ["password is too short"]} = errors_on(changeset) + + """ + def errors_on(changeset) do + Ecto.Changeset.traverse_errors(changeset, fn {message, opts} -> + Regex.replace(~r"%{(\w+)}", message, fn _, key -> + opts |> Keyword.get(String.to_existing_atom(key), key) |> to_string() + end) + end) + end +end diff --git a/test/test_helper.exs b/test/test_helper.exs new file mode 100644 index 0000000..295458d --- /dev/null +++ b/test/test_helper.exs @@ -0,0 +1,2 @@ +ExUnit.start() +Ecto.Adapters.SQL.Sandbox.mode(SbomPoc.Repo, :manual) From 92f0406a4b89f5bb74b7149f7af19bdadd525f52 Mon Sep 17 00:00:00 2001 From: sigu Date: Wed, 22 Jul 2020 08:25:39 +0300 Subject: [PATCH 02/43] setup linting --- .credo.exs | 185 ++++++++++++++++++++++++++++++ .github/workflows/elixir.yml | 51 ++++++++ Makefile | 63 ++++++++++ lib/sbomPoc_web/live/page_live.ex | 1 + lib/sbomPoc_web/telemetry.ex | 1 + mix.exs | 5 +- mix.lock | 2 + 7 files changed, 306 insertions(+), 2 deletions(-) create mode 100644 .credo.exs create mode 100644 .github/workflows/elixir.yml create mode 100644 Makefile diff --git a/.credo.exs b/.credo.exs new file mode 100644 index 0000000..900f834 --- /dev/null +++ b/.credo.exs @@ -0,0 +1,185 @@ +# This file contains the configuration for Credo and you are probably reading +# this after creating it with `mix credo.gen.config`. +# +# If you find anything wrong or unclear in this file, please report an +# issue on GitHub: https://github.com/rrrene/credo/issues +# +%{ + # + # You can have as many configs as you like in the `configs:` field. + configs: [ + %{ + # + # Run any config using `mix credo -C `. If no config name is given + # "default" is used. + # + name: "default", + # + # These are the files included in the analysis: + files: %{ + # + # You can give explicit globs or simply directories. + # In the latter case `**/*.{ex,exs}` will be used. + # + included: [ + "lib/", + "src/", + "test/", + "web/", + "apps/*/lib/", + "apps/*/src/", + "apps/*/test/", + "apps/*/web/" + ], + excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"] + }, + # + # Load and configure plugins here: + # + plugins: [], + # + # If you create your own checks, you must specify the source files for + # them here, so they can be loaded by Credo before running the analysis. + # + requires: [], + # + # If you want to enforce a style guide and need a more traditional linting + # experience, you can change `strict` to `true` below: + # + strict: false, + # + # To modify the timeout for parsing files, change this value: + # + parse_timeout: 5000, + # + # If you want to use uncolored output by default, you can change `color` + # to `false` below: + # + color: true, + # + # You can customize the parameters of any check by adding a second element + # to the tuple. + # + # To disable a check put `false` as second element: + # + # {Credo.Check.Design.DuplicatedCode, false} + # + checks: [ + # + ## Consistency Checks + # + {Credo.Check.Consistency.ExceptionNames, []}, + {Credo.Check.Consistency.LineEndings, []}, + {Credo.Check.Consistency.ParameterPatternMatching, []}, + {Credo.Check.Consistency.SpaceAroundOperators, []}, + {Credo.Check.Consistency.SpaceInParentheses, []}, + {Credo.Check.Consistency.TabsOrSpaces, []}, + + # + ## Design Checks + # + # You can customize the priority of any check + # Priority values are: `low, normal, high, higher` + # + {Credo.Check.Design.AliasUsage, + [priority: :low, if_nested_deeper_than: 2, if_called_more_often_than: 2]}, + # You can also customize the exit_status of each check. + # If you don't want TODO comments to cause `mix credo` to fail, just + # set this value to 0 (zero). + # + {Credo.Check.Design.TagTODO, [exit_status: 2]}, + {Credo.Check.Design.TagFIXME, []}, + + # + ## Readability Checks + # + {Credo.Check.Readability.AliasOrder, []}, + {Credo.Check.Readability.FunctionNames, []}, + {Credo.Check.Readability.LargeNumbers, []}, + {Credo.Check.Readability.MaxLineLength, [priority: :low, max_length: 120]}, + {Credo.Check.Readability.ModuleAttributeNames, []}, + {Credo.Check.Readability.ModuleDoc, []}, + {Credo.Check.Readability.ModuleNames, []}, + {Credo.Check.Readability.ParenthesesInCondition, []}, + {Credo.Check.Readability.ParenthesesOnZeroArityDefs, []}, + {Credo.Check.Readability.PredicateFunctionNames, []}, + {Credo.Check.Readability.PreferImplicitTry, []}, + {Credo.Check.Readability.RedundantBlankLines, []}, + {Credo.Check.Readability.Semicolons, []}, + {Credo.Check.Readability.SpaceAfterCommas, []}, + {Credo.Check.Readability.StringSigils, []}, + {Credo.Check.Readability.TrailingBlankLine, []}, + {Credo.Check.Readability.TrailingWhiteSpace, []}, + {Credo.Check.Readability.UnnecessaryAliasExpansion, []}, + {Credo.Check.Readability.VariableNames, []}, + + # + ## Refactoring Opportunities + # + {Credo.Check.Refactor.CondStatements, []}, + {Credo.Check.Refactor.CyclomaticComplexity, []}, + {Credo.Check.Refactor.FunctionArity, []}, + {Credo.Check.Refactor.LongQuoteBlocks, []}, + {Credo.Check.Refactor.MapInto, []}, + {Credo.Check.Refactor.MatchInCondition, []}, + {Credo.Check.Refactor.NegatedConditionsInUnless, []}, + {Credo.Check.Refactor.NegatedConditionsWithElse, []}, + {Credo.Check.Refactor.Nesting, []}, + {Credo.Check.Refactor.UnlessWithElse, []}, + {Credo.Check.Refactor.WithClauses, []}, + + # + ## Warnings + # + {Credo.Check.Warning.BoolOperationOnSameValues, []}, + {Credo.Check.Warning.ExpensiveEmptyEnumCheck, []}, + {Credo.Check.Warning.IExPry, []}, + {Credo.Check.Warning.IoInspect, []}, + {Credo.Check.Warning.LazyLogging, []}, + {Credo.Check.Warning.MixEnv, false}, + {Credo.Check.Warning.OperationOnSameValues, []}, + {Credo.Check.Warning.OperationWithConstantResult, []}, + {Credo.Check.Warning.RaiseInsideRescue, []}, + {Credo.Check.Warning.UnusedEnumOperation, []}, + {Credo.Check.Warning.UnusedFileOperation, []}, + {Credo.Check.Warning.UnusedKeywordOperation, []}, + {Credo.Check.Warning.UnusedListOperation, []}, + {Credo.Check.Warning.UnusedPathOperation, []}, + {Credo.Check.Warning.UnusedRegexOperation, []}, + {Credo.Check.Warning.UnusedStringOperation, []}, + {Credo.Check.Warning.UnusedTupleOperation, []}, + {Credo.Check.Warning.UnsafeExec, []}, + + # + # Checks scheduled for next check update (opt-in for now, just replace `false` with `[]`) + + # + # Controversial and experimental checks (opt-in, just replace `false` with `[]`) + # + {Credo.Check.Readability.StrictModuleLayout, false}, + {Credo.Check.Consistency.MultiAliasImportRequireUse, false}, + {Credo.Check.Consistency.UnusedVariableNames, false}, + {Credo.Check.Design.DuplicatedCode, false}, + {Credo.Check.Readability.AliasAs, false}, + {Credo.Check.Readability.MultiAlias, false}, + {Credo.Check.Readability.Specs, false}, + {Credo.Check.Readability.SinglePipe, false}, + {Credo.Check.Readability.WithCustomTaggedTuple, false}, + {Credo.Check.Refactor.ABCSize, false}, + {Credo.Check.Refactor.AppendSingleItem, false}, + {Credo.Check.Refactor.DoubleBooleanNegation, false}, + {Credo.Check.Refactor.ModuleDependencies, false}, + {Credo.Check.Refactor.NegatedIsNil, false}, + {Credo.Check.Refactor.PipeChainStart, false}, + {Credo.Check.Refactor.VariableRebinding, false}, + {Credo.Check.Warning.LeakyEnvironment, false}, + {Credo.Check.Warning.MapGetUnsafePass, false}, + {Credo.Check.Warning.UnsafeToAtom, false} + + # + # Custom checks can be created using `mix credo.gen.check`. + # + ] + } + ] +} diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml new file mode 100644 index 0000000..c01da1c --- /dev/null +++ b/.github/workflows/elixir.yml @@ -0,0 +1,51 @@ +name: Elixir CI + +on: + push: + branches: + - develop + - main + pull_request: + branches: + - main + - develop + +jobs: + build: + + name: Build and test + runs-on: ubuntu-latest + + services: + db: + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + image: postgres:11 + ports: ['5432:5432'] + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - uses: actions/checkout@v2 + - name: Set up Elixir + uses: actions/setup-elixir@v1 + with: + elixir-version: '1.10.4' # Define the elixir version [required] + otp-version: '22.3' # Define the OTP version [required] + - name: Restore dependencies cache + uses: actions/cache@v2 + with: + path: deps + key: ${{ runner.os }}-mix-${{ hashFiles('**/mix.lock') }} + restore-keys: ${{ runner.os }}-mix- + - name: Install dependencies + run: mix deps.get + - name: Run tests + run: mix test + - name: Check lints + run: make lint diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ab395e2 --- /dev/null +++ b/Makefile @@ -0,0 +1,63 @@ +# Configuration + # ------------- + +APP_NAME ?= `grep 'app:' mix.exs | sed -e 's/\[//g' -e 's/ //g' -e 's/app://' -e 's/[:,]//g'` +APP_VERSION ?= `grep 'version:' mix.exs | cut -d '"' -f2` +DOCKER_IMAGE_TAG ?= latest +GIT_REVISION ?= `git rev-parse HEAD` + +# Introspection targets +# --------------------- + +.PHONY: help +help: header targets + +.PHONY: header +header: + @echo "\033[34mEnvironment\033[0m" + @echo "\033[34m---------------------------------------------------------------\033[0m" + @printf "\033[33m%-23s\033[0m" "APP_NAME" + @printf "\033[35m%s\033[0m" $(APP_NAME) + @echo "" + @printf "\033[33m%-23s\033[0m" "APP_VERSION" + @printf "\033[35m%s\033[0m" $(APP_VERSION) + @echo "" + @printf "\033[33m%-23s\033[0m" "GIT_REVISION" + @printf "\033[35m%s\033[0m" $(GIT_REVISION) + @echo "" + @printf "\033[33m%-23s\033[0m" "DOCKER_IMAGE_TAG" + @printf "\033[35m%s\033[0m" $(DOCKER_IMAGE_TAG) + @echo "\n" + +.PHONY: targets +targets: + @echo "\033[34mTargets\033[0m" + @echo "\033[34m---------------------------------------------------------------\033[0m" + @perl -nle'print $& if m{^[a-zA-Z_-]+:.*?## .*$$}' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-22s\033[0m %s\n", $$1, $$2}' + +.PHONY: compile +compile: ## compile the project + mix compile + +.PHONY: lint-compile +lint-compile: ## check for warnings in functions used in the project + mix compile --warnings-as-errors --force + +.PHONY: lint-format +lint-format: ## Check if the project is well formated using elixir formatter + mix format --dry-run --check-formatted + +.PHONY: lint-credo +lint-credo: ## Use credo to ensure formatting styles + mix credo --strict + +.PHONY: lint +lint: lint-compile lint-format lint-credo ## Check if the project follows set conventions such as formatting + + +.PHONY: test +test: ## Run the test suite + mix test + +.PHONY: format +format: mix format ## Run formatting tools on the code diff --git a/lib/sbomPoc_web/live/page_live.ex b/lib/sbomPoc_web/live/page_live.ex index d9a6545..98d6c9b 100644 --- a/lib/sbomPoc_web/live/page_live.ex +++ b/lib/sbomPoc_web/live/page_live.ex @@ -1,4 +1,5 @@ defmodule SbomPocWeb.PageLive do + @moduledoc "Landing page live view" use SbomPocWeb, :live_view @impl true diff --git a/lib/sbomPoc_web/telemetry.ex b/lib/sbomPoc_web/telemetry.ex index b971417..ccbf41b 100644 --- a/lib/sbomPoc_web/telemetry.ex +++ b/lib/sbomPoc_web/telemetry.ex @@ -1,4 +1,5 @@ defmodule SbomPocWeb.Telemetry do + @moduledoc "Telemetry" use Supervisor import Telemetry.Metrics diff --git a/mix.exs b/mix.exs index 76fab45..a3fdde9 100644 --- a/mix.exs +++ b/mix.exs @@ -5,7 +5,7 @@ defmodule SbomPoc.MixProject do [ app: :sbomPoc, version: "0.1.0", - elixir: "~> 1.7", + elixir: "~> 1.10", elixirc_paths: elixirc_paths(Mix.env()), compilers: [:phoenix, :gettext] ++ Mix.compilers(), start_permanent: Mix.env() == :prod, @@ -47,7 +47,8 @@ defmodule SbomPoc.MixProject do {:telemetry_poller, "~> 0.4"}, {:gettext, "~> 0.11"}, {:jason, "~> 1.0"}, - {:plug_cowboy, "~> 2.0"} + {:plug_cowboy, "~> 2.0"}, + {:credo, "~> 1.4", only: [:dev, :test], runtime: false} ] end diff --git a/mix.lock b/mix.lock index 55a77ba..de6a847 100644 --- a/mix.lock +++ b/mix.lock @@ -1,7 +1,9 @@ %{ + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm", "4a0850c9be22a43af9920a71ab17c051f5f7d45c209e40269a1938832510e4d9"}, "cowboy": {:hex, :cowboy, "2.8.0", "f3dc62e35797ecd9ac1b50db74611193c29815401e53bac9a5c0577bd7bc667d", [:rebar3], [{:cowlib, "~> 2.9.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "4643e4fba74ac96d4d152c75803de6fad0b3fa5df354c71afdd6cbeeb15fac8a"}, "cowlib": {:hex, :cowlib, "2.9.1", "61a6c7c50cf07fdd24b2f45b89500bb93b6686579b069a89f88cb211e1125c78", [:rebar3], [], "hexpm", "e4175dc240a70d996156160891e1c62238ede1729e45740bdd38064dad476170"}, + "credo": {:hex, :credo, "1.4.0", "92339d4cbadd1e88b5ee43d427b639b68a11071b6f73854e33638e30a0ea11f5", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1fd3b70dce216574ce3c18bdf510b57e7c4c85c2ec9cad4bff854abaf7e58658"}, "db_connection": {:hex, :db_connection, "2.2.2", "3bbca41b199e1598245b716248964926303b5d4609ff065125ce98bcd368939e", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "642af240d8a8affb93b4ba5a6fcd2bbcbdc327e1a524b825d383711536f8070c"}, "decimal": {:hex, :decimal, "1.8.1", "a4ef3f5f3428bdbc0d35374029ffcf4ede8533536fa79896dd450168d9acdf3c", [:mix], [], "hexpm", "3cb154b00225ac687f6cbd4acc4b7960027c757a5152b369923ead9ddbca7aec"}, "ecto": {:hex, :ecto, "3.4.4", "a2c881e80dc756d648197ae0d936216c0308370332c5e77a2325a10293eef845", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cc4bd3ad62abc3b21fb629f0f7a3dab23a192fca837d257dd08449fba7373561"}, From 36e92d4624fb87ead872585b727d50a7996de91c Mon Sep 17 00:00:00 2001 From: sigu Date: Wed, 22 Jul 2020 08:31:19 +0300 Subject: [PATCH 03/43] update readme --- README.md | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 96a250d..c76f3fb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,15 @@ # SbomPoc +Webserver with status of SBOM Poc + +## Setup guide +First ensure you have the following set up in your computer +- elixir 1.10.4 +- nodejs > 12 LTS +- Postgresql > 11 + +You can use [the phoenix installation guide](https://hexdocs.pm/phoenix/installation.html#content) to ensure you +have everything set up as expected + To start your Phoenix server: @@ -9,12 +20,18 @@ To start your Phoenix server: Now you can visit [`localhost:4000`](http://localhost:4000) from your browser. -Ready to run in production? Please [check our deployment guides](https://hexdocs.pm/phoenix/deployment.html). - -## Learn more +## Convenience make tasks +This project includes a couple of convenience `make` tasks. To get the full list +of the tasks run the command `make targets` to see a list of current tasks. For example - * Official website: https://www.phoenixframework.org/ - * Guides: https://hexdocs.pm/phoenix/overview.html - * Docs: https://hexdocs.pm/phoenix - * Forum: https://elixirforum.com/c/phoenix-forum - * Source: https://github.com/phoenixframework/phoenix +```shell +Targets +--------------------------------------------------------------- +compile compile the project +format Run formatting tools on the code +lint-compile check for warnings in functions used in the project +lint-credo Use credo to ensure formatting styles +lint-format Check if the project is well formated using elixir formatter +lint Check if the project follows set conventions such as formatting +test Run the test suite +``` From e2d806d21a87b0ba85ab1d3c3246a01316d2b7fd Mon Sep 17 00:00:00 2001 From: sigu Date: Tue, 1 Sep 2020 16:45:40 +0300 Subject: [PATCH 04/43] deploy to gcp --- .gitlab-ci.yml | 28 ++++++++++++++++++++++++++++ Makefile | 9 +++++++++ config/config.exs | 4 ++-- config/dev.exs | 6 +++--- config/prod.exs | 10 ++++++---- config/prod.secret.exs | 6 +++--- config/test.exs | 4 ++-- lib/release.ex | 32 ++++++++++++++++++++++++++++++++ lib/sbomPoc/repo.ex | 2 +- lib/sbomPoc_web/endpoint.ex | 6 +++--- lib/sbomPoc_web/gettext.ex | 2 +- mix.exs | 10 ++++++++-- 12 files changed, 98 insertions(+), 21 deletions(-) create mode 100644 .gitlab-ci.yml create mode 100644 lib/release.ex diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..2795d1a --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,28 @@ +deploy_to_production: + image: elixir:1.10.3 + + stage: deploy + before_script: + - mix local.rebar --force + - mix local.hex --force + - apt update -y > /dev/null && apt install nodejs npm -y > /dev/null + - npm i -g webpack webpack-cli + + script: + - export APP_NAME="$(grep 'app:' mix.exs | sed -e 's/\[//g' -e 's/ //g' -e 's/app://' -e 's/[:,]//g')" + - export APP_VSN="$(grep 'version:' mix.exs | cut -d '"' -f2)" + - export CURRENT_APP=$APP_NAME-$APP_VSN + - echo "$PRODSECRETS" > config/prod.secret.exs + - make release + - eval $(ssh-agent -s) + - ssh-add <(echo "$PROD_SSH_KEY") + - scp -T -o StrictHostKeyChecking=no "_build/prod/$CURRENT_APP.tar.gz" sigumagwa@$PROD_IP:/home/sigumagwa/$CURRENT_APP.tar.gz + - ssh -T -o StrictHostKeyChecking=no sigumagwa@$PROD_IP < 1.10", elixirc_paths: elixirc_paths(Mix.env()), compilers: [:phoenix, :gettext] ++ Mix.compilers(), start_permanent: Mix.env() == :prod, aliases: aliases(), - deps: deps() + deps: deps(), + releases: [ + sbom_poc: [ + include_executables_for: [:unix], + steps: [:assemble, :tar] + ] + ] ] end From aa0ae4b58c508a4c1c689c8d49683ada11c31b65 Mon Sep 17 00:00:00 2001 From: sigu Date: Tue, 6 Oct 2020 08:34:48 +0300 Subject: [PATCH 05/43] upgrade npm packages --- assets/package-lock.json | 497 ++++++++++++++++++++++++++------------- assets/package.json | 14 +- 2 files changed, 334 insertions(+), 177 deletions(-) diff --git a/assets/package-lock.json b/assets/package-lock.json index c3bab08..7ac956f 100644 --- a/assets/package-lock.json +++ b/assets/package-lock.json @@ -12,9 +12,9 @@ } }, "@babel/compat-data": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.10.5.tgz", - "integrity": "sha512-mPVoWNzIpYJHbWje0if7Ck36bpbtTvIxOi9+6WSK9wjGEXearAqlwBoTQvVjsAY2VIwgcs8V940geY3okzRCEw==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz", + "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==", "dev": true, "requires": { "browserslist": "^4.12.0", @@ -23,19 +23,19 @@ } }, "@babel/core": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.5.tgz", - "integrity": "sha512-O34LQooYVDXPl7QWCdW9p4NR+QlzOr7xShPPJz8GsuCU3/8ua/wqTr7gmnxXv+WBESiGU/G5s16i6tUvHkNb+w==", + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz", + "integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.10.5", - "@babel/helper-module-transforms": "^7.10.5", + "@babel/generator": "^7.11.6", + "@babel/helper-module-transforms": "^7.11.0", "@babel/helpers": "^7.10.4", - "@babel/parser": "^7.10.5", + "@babel/parser": "^7.11.5", "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.5", - "@babel/types": "^7.10.5", + "@babel/traverse": "^7.11.5", + "@babel/types": "^7.11.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.1", @@ -47,12 +47,12 @@ } }, "@babel/generator": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.5.tgz", - "integrity": "sha512-3vXxr3FEW7E7lJZiWQ3bM4+v/Vyr9C+hpolQ8BGFr9Y8Ri2tFLWTixmwKBafDujO1WVah4fhZBeU1bieKdghig==", + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", + "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", "dev": true, "requires": { - "@babel/types": "^7.10.5", + "@babel/types": "^7.11.5", "jsesc": "^2.5.1", "source-map": "^0.5.0" } @@ -126,12 +126,11 @@ } }, "@babel/helper-explode-assignable-expression": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz", - "integrity": "sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A==", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz", + "integrity": "sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==", "dev": true, "requires": { - "@babel/traverse": "^7.10.4", "@babel/types": "^7.10.4" } }, @@ -165,12 +164,12 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.5.tgz", - "integrity": "sha512-HiqJpYD5+WopCXIAbQDG0zye5XYVvcO9w/DHp5GsaGkRUaamLj2bEtu6i8rnGGprAhHM3qidCMgp71HF4endhA==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", + "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", "dev": true, "requires": { - "@babel/types": "^7.10.5" + "@babel/types": "^7.11.0" } }, "@babel/helper-module-imports": { @@ -183,17 +182,17 @@ } }, "@babel/helper-module-transforms": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.5.tgz", - "integrity": "sha512-4P+CWMJ6/j1W915ITJaUkadLObmCRRSC234uctJfn/vHrsLNxsR8dwlcXv9ZhJWzl77awf+mWXSZEKt5t0OnlA==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", + "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.10.4", "@babel/helper-replace-supers": "^7.10.4", "@babel/helper-simple-access": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", "@babel/template": "^7.10.4", - "@babel/types": "^7.10.5", + "@babel/types": "^7.11.0", "lodash": "^4.17.19" } }, @@ -222,15 +221,14 @@ } }, "@babel/helper-remap-async-to-generator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz", - "integrity": "sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg==", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz", + "integrity": "sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.10.4", "@babel/helper-wrap-function": "^7.10.4", "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", "@babel/types": "^7.10.4" } }, @@ -256,13 +254,22 @@ "@babel/types": "^7.10.4" } }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz", + "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, "@babel/helper-split-export-declaration": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz", - "integrity": "sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", "dev": true, "requires": { - "@babel/types": "^7.10.4" + "@babel/types": "^7.11.0" } }, "@babel/helper-validator-identifier": { @@ -306,9 +313,9 @@ } }, "@babel/parser": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.5.tgz", - "integrity": "sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -342,6 +349,16 @@ "@babel/plugin-syntax-dynamic-import": "^7.8.0" } }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz", + "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, "@babel/plugin-proposal-json-strings": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz", @@ -352,6 +369,16 @@ "@babel/plugin-syntax-json-strings": "^7.8.0" } }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz", + "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, "@babel/plugin-proposal-nullish-coalescing-operator": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz", @@ -373,9 +400,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.4.tgz", - "integrity": "sha512-6vh4SqRuLLarjgeOf4EaROJAHjvu9Gl+/346PbDH9yWbJyfnJ/ah3jmYKYtswEyCoWZiidvVHjHshd4WgjB9BA==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz", + "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4", @@ -394,12 +421,13 @@ } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz", - "integrity": "sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz", + "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0", "@babel/plugin-syntax-optional-chaining": "^7.8.0" } }, @@ -450,6 +478,15 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, "@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", @@ -459,6 +496,15 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, "@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", @@ -543,9 +589,9 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.5.tgz", - "integrity": "sha512-6Ycw3hjpQti0qssQcA6AMSFDHeNJ++R6dIMnpRqUjFeBBTmTDPa8zgF90OVfTvAo11mXZTlVUViY1g8ffrURLg==", + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz", + "integrity": "sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4" @@ -771,12 +817,13 @@ } }, "@babel/plugin-transform-spread": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.4.tgz", - "integrity": "sha512-1e/51G/Ni+7uH5gktbWv+eCED9pP8ZpRhZB3jOaI3mmzfvJTWHkuyYTv0Z5PYtyM+Tr2Ccr9kUdQxn60fI5WuQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz", + "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0" } }, "@babel/plugin-transform-sticky-regex": { @@ -828,30 +875,34 @@ } }, "@babel/preset-env": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.10.4.tgz", - "integrity": "sha512-tcmuQ6vupfMZPrLrc38d0sF2OjLT3/bZ0dry5HchNCQbrokoQi4reXqclvkkAT5b+gWc23meVWpve5P/7+w/zw==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.5.tgz", + "integrity": "sha512-kXqmW1jVcnB2cdueV+fyBM8estd5mlNfaQi6lwLgRwCby4edpavgbFhiBNjmWA3JpB/yZGSISa7Srf+TwxDQoA==", "dev": true, "requires": { - "@babel/compat-data": "^7.10.4", + "@babel/compat-data": "^7.11.0", "@babel/helper-compilation-targets": "^7.10.4", "@babel/helper-module-imports": "^7.10.4", "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-proposal-async-generator-functions": "^7.10.4", "@babel/plugin-proposal-class-properties": "^7.10.4", "@babel/plugin-proposal-dynamic-import": "^7.10.4", + "@babel/plugin-proposal-export-namespace-from": "^7.10.4", "@babel/plugin-proposal-json-strings": "^7.10.4", + "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", "@babel/plugin-proposal-numeric-separator": "^7.10.4", - "@babel/plugin-proposal-object-rest-spread": "^7.10.4", + "@babel/plugin-proposal-object-rest-spread": "^7.11.0", "@babel/plugin-proposal-optional-catch-binding": "^7.10.4", - "@babel/plugin-proposal-optional-chaining": "^7.10.4", + "@babel/plugin-proposal-optional-chaining": "^7.11.0", "@babel/plugin-proposal-private-methods": "^7.10.4", "@babel/plugin-proposal-unicode-property-regex": "^7.10.4", "@babel/plugin-syntax-async-generators": "^7.8.0", "@babel/plugin-syntax-class-properties": "^7.10.4", "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.0", @@ -884,14 +935,14 @@ "@babel/plugin-transform-regenerator": "^7.10.4", "@babel/plugin-transform-reserved-words": "^7.10.4", "@babel/plugin-transform-shorthand-properties": "^7.10.4", - "@babel/plugin-transform-spread": "^7.10.4", + "@babel/plugin-transform-spread": "^7.11.0", "@babel/plugin-transform-sticky-regex": "^7.10.4", "@babel/plugin-transform-template-literals": "^7.10.4", "@babel/plugin-transform-typeof-symbol": "^7.10.4", "@babel/plugin-transform-unicode-escapes": "^7.10.4", "@babel/plugin-transform-unicode-regex": "^7.10.4", "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.10.4", + "@babel/types": "^7.11.5", "browserslist": "^4.12.0", "core-js-compat": "^3.6.2", "invariant": "^2.2.2", @@ -900,9 +951,9 @@ } }, "@babel/preset-modules": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz", - "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -913,9 +964,9 @@ } }, "@babel/runtime": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz", - "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==", + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", + "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", "dev": true, "requires": { "regenerator-runtime": "^0.13.4" @@ -933,26 +984,26 @@ } }, "@babel/traverse": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.5.tgz", - "integrity": "sha512-yc/fyv2gUjPqzTz0WHeRJH2pv7jA9kA7mBX2tXl/x5iOE81uaVPuGPtaYk7wmkx4b67mQ7NqI8rmT2pF47KYKQ==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", + "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.10.5", + "@babel/generator": "^7.11.5", "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.10.4", - "@babel/parser": "^7.10.5", - "@babel/types": "^7.10.5", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.5", + "@babel/types": "^7.11.5", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.19" } }, "@babel/types": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.5.tgz", - "integrity": "sha512-ixV66KWfCI6GKoA/2H9v6bQdbfXEwwpOdQ8cRvb4F+eyvhlaHxWFMQB4+3d9QFJXZsiiiqVrewNV0DFEQpyT4Q==", + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -1173,9 +1224,9 @@ "dev": true }, "aggregate-error": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", - "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "requires": { "clean-stack": "^2.0.0", @@ -1726,15 +1777,15 @@ } }, "browserslist": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.13.0.tgz", - "integrity": "sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ==", + "version": "4.14.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.5.tgz", + "integrity": "sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001093", - "electron-to-chromium": "^1.3.488", - "escalade": "^3.0.1", - "node-releases": "^1.1.58" + "caniuse-lite": "^1.0.30001135", + "electron-to-chromium": "^1.3.571", + "escalade": "^3.1.0", + "node-releases": "^1.1.61" } }, "buffer": { @@ -1867,9 +1918,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001104", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001104.tgz", - "integrity": "sha512-pkpCg7dmI/a7WcqM2yfdOiT4Xx5tzyoHAXWsX5/HxZ3TemwDZs0QXdqbE0UPLPVy/7BeK7693YfzfRYfu1YVpg==", + "version": "1.0.30001143", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001143.tgz", + "integrity": "sha512-p/PO5YbwmCpBJPxjOiKBvAlUPgF8dExhfEpnsH+ys4N/791WHrYrGg0cyHiAURl5hSbx5vIcjKmQAP6sHDYH3w==", "dev": true }, "caseless": { @@ -2220,9 +2271,9 @@ "dev": true }, "copy-webpack-plugin": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz", - "integrity": "sha512-P15M5ZC8dyCjQHWwd4Ia/dm0SgVvZJMYeykVIVYXbGyqO4dWB5oyPHp9i7wjwo5LhtlhKbiBCdS2NvM07Wlybg==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.1.2.tgz", + "integrity": "sha512-Uh7crJAco3AjBvgAy9Z75CjK8IG+gxaErro71THQ+vv/bl4HaQcpkexAY8KVW/T6D2W2IRr+couF/knIRkZMIQ==", "dev": true, "requires": { "cacache": "^12.0.3", @@ -2235,7 +2286,7 @@ "normalize-path": "^3.0.0", "p-limit": "^2.2.1", "schema-utils": "^1.0.0", - "serialize-javascript": "^2.1.2", + "serialize-javascript": "^4.0.0", "webpack-log": "^2.0.0" }, "dependencies": { @@ -2474,9 +2525,9 @@ } }, "css-what": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.3.0.tgz", - "integrity": "sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.1.tgz", + "integrity": "sha512-wHOppVDKl4vTAOWzJt5Ek37Sgd9qq1Bmj/T1OjvicWbU5W7ru7Pqbn0Jdqii3Drx/h+dixHKXNhZYx7blthL7g==", "dev": true }, "cssesc": { @@ -2620,12 +2671,12 @@ } }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "decamelize": { @@ -2757,9 +2808,9 @@ }, "dependencies": { "domelementtype": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", - "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", + "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==", "dev": true } } @@ -2787,9 +2838,9 @@ } }, "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==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, "requires": { "is-obj": "^2.0.0" @@ -2818,9 +2869,9 @@ } }, "electron-to-chromium": { - "version": "1.3.502", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.502.tgz", - "integrity": "sha512-TIeXOaHAvfP7FemGUtAJxStmOc1YFGWFNqdey/4Nk41L9b1nMmDVDGNMIWhZJvOfJxix6Cv5FGEnBK+yvw3UTg==", + "version": "1.3.577", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.577.tgz", + "integrity": "sha512-dSb64JQSFif/pD8mpVAgSFkbVi6YHbK6JeEziwNNmXlr/Ne2rZtseFK5SM7JoWSLf6gP0gVvRGi4/2ZRhSX/rA==", "dev": true }, "elliptic": { @@ -2915,20 +2966,21 @@ } }, "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", "dev": true, "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", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", + "object.assign": "^4.1.1", "string.prototype.trimend": "^1.0.1", "string.prototype.trimstart": "^1.0.1" } @@ -2945,9 +2997,9 @@ } }, "escalade": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", - "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz", + "integrity": "sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==", "dev": true }, "escape-string-regexp": { @@ -3880,9 +3932,9 @@ "dev": true }, "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", "dev": true }, "is-color-stop": { @@ -3986,6 +4038,12 @@ "is-extglob": "^2.1.1" } }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -4028,9 +4086,9 @@ } }, "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", "dev": true, "requires": { "has-symbols": "^1.0.1" @@ -4125,9 +4183,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -4580,9 +4638,9 @@ } }, "minipass-pipeline": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.3.tgz", - "integrity": "sha512-cFOknTvng5vqnwOpDsZTWhNll6Jf8o2x+/diplafmxpuIymAjzoOolZG0VvQf3V2HgqzJNhnuKHYp2BqDgz8IQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, "requires": { "minipass": "^3.0.0" @@ -4761,9 +4819,9 @@ } }, "node-releases": { - "version": "1.1.59", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.59.tgz", - "integrity": "sha512-H3JrdUczbdiwxN5FuJPyCHnGHIFqQ0wWxo+9j1kAXAzqNMAHlo+4I/sYYxpyK0irQ73HgdiyzD32oqQDcU2Osw==", + "version": "1.1.61", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz", + "integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==", "dev": true }, "node-sass": { @@ -4954,15 +5012,15 @@ } }, "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" } }, "object.getownpropertydescriptors": { @@ -4973,6 +5031,27 @@ "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "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.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "object.pick": { @@ -4994,6 +5073,27 @@ "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "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.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "once": { @@ -5006,9 +5106,9 @@ } }, "optimize-css-assets-webpack-plugin": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz", - "integrity": "sha512-q9fbvCRS6EYtUKKSwI87qm2IxlyJK5b4dygW1rKUBT6mMDhdG5e5bZT63v6tnJR9F9FB/H5a0HTmtw+laUBxKA==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.4.tgz", + "integrity": "sha512-wqd6FdI2a5/FdoiCNNkEvLeA//lHHfG24Ln2Xm2qqdIk4aOlsR18jwpyOihqQ8849W3qu2DX8fOYxpvTMj+93A==", "dev": true, "requires": { "cssnano": "^4.1.10", @@ -5281,9 +5381,9 @@ } }, "postcss-calc": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.2.tgz", - "integrity": "sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.5.tgz", + "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==", "dev": true, "requires": { "postcss": "^7.0.27", @@ -6075,9 +6175,9 @@ } }, "regenerator-runtime": { - "version": "0.13.6", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.6.tgz", - "integrity": "sha512-GmwlGiazQEbOwQWDdbbaP10i15pGtScYWLbMZuu+RKRz0cZ+g8IUONazBnaZqe7j1670IV1HgE4/8iy7CQPf4Q==", + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", "dev": true }, "regenerator-transform": { @@ -6100,9 +6200,9 @@ } }, "regexpu-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", - "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", "dev": true, "requires": { "regenerate": "^1.4.0", @@ -6402,10 +6502,13 @@ "dev": true }, "serialize-javascript": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", - "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } }, "set-blocking": { "version": "2.0.0", @@ -6858,6 +6961,27 @@ "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "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.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "string.prototype.trimstart": { @@ -6868,6 +6992,27 @@ "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "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.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "string_decoder": { @@ -6997,9 +7142,9 @@ } }, "terser-webpack-plugin": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.7.tgz", - "integrity": "sha512-xzYyaHUNhzgaAdBsXxk2Yvo/x1NJdslUaussK3fdpBbvttm1iIwU+c26dj9UxJcwk2c5UWt5F55MUTIA8BE7Dg==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz", + "integrity": "sha512-/fKw3R+hWyHfYx7Bv6oPqmk4HGQcrWLtV3X6ggvPuwPNHSnzvVV51z6OaaCOus4YLjutYGOz3pEpbhe6Up2s1w==", "dev": true, "requires": { "cacache": "^13.0.1", @@ -7007,7 +7152,7 @@ "jest-worker": "^25.4.0", "p-limit": "^2.3.0", "schema-utils": "^2.6.6", - "serialize-javascript": "^3.1.0", + "serialize-javascript": "^4.0.0", "source-map": "^0.6.1", "terser": "^4.6.12", "webpack-sources": "^1.4.3" @@ -7108,15 +7253,6 @@ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, - "serialize-javascript": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", - "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -7467,6 +7603,27 @@ "es-abstract": "^1.17.2", "has-symbols": "^1.0.1", "object.getownpropertydescriptors": "^2.1.0" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "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.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "uuid": { diff --git a/assets/package.json b/assets/package.json index 8f7026f..2711e6e 100644 --- a/assets/package.json +++ b/assets/package.json @@ -13,16 +13,16 @@ "nprogress": "^0.2.0" }, "devDependencies": { - "@babel/core": "^7.0.0", - "@babel/preset-env": "^7.0.0", + "@babel/core": "^7.11.6", + "@babel/preset-env": "^7.11.5", "babel-loader": "^8.0.0", - "copy-webpack-plugin": "^5.1.1", + "copy-webpack-plugin": "^5.1.2", "css-loader": "^3.4.2", - "sass-loader": "^8.0.2", - "node-sass": "^4.13.1", "mini-css-extract-plugin": "^0.9.0", - "optimize-css-assets-webpack-plugin": "^5.0.1", - "terser-webpack-plugin": "^2.3.2", + "node-sass": "^4.13.1", + "optimize-css-assets-webpack-plugin": "^5.0.4", + "sass-loader": "^8.0.2", + "terser-webpack-plugin": "^2.3.8", "webpack": "4.41.5", "webpack-cli": "^3.3.2" } From dae02b507573589a5765fc955d458e7018194ae3 Mon Sep 17 00:00:00 2001 From: sigu Date: Tue, 6 Oct 2020 08:35:02 +0300 Subject: [PATCH 06/43] dependabot to check automatically --- .github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..3aec8dc --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/assets" + schedule: + interval: "daily" + + - package-ecosystem: "elixir" + directory: "/" + schedule: + interval: "daily" From 076d726be21d74e51053abf9626da900e651cbce Mon Sep 17 00:00:00 2001 From: sigu Date: Thu, 15 Oct 2020 10:11:19 +0300 Subject: [PATCH 07/43] enable deploy via makefile --- .dockerignore | 8 +++++++ Dockerfile | 47 ++++++++++++++++++++++++++++++++++++ Makefile | 36 ++++++++++++++++++++++++++-- README.md | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0f79f45 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +_build/ +assets/node_modules/ +deps/ +doc/ +docs/ +priv/static/ +test/ +tmp/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c533f7a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +# heavily borrowed from https://elixirforum.com/t/cannot-find-libtinfo-so-6-when-launching-elixir-app/24101/11?u=sigu +FROM elixir:1.10.4 AS app_builder + +ARG env=prod + +ENV LANG=C.UTF-8 \ + TERM=xterm \ + MIX_ENV=$env + +RUN mkdir /opt/release +WORKDIR /opt/release + +RUN mix local.hex --force && mix local.rebar --force + +COPY mix.exs . +COPY mix.lock . +RUN mix deps.get && mix deps.compile + +# Let's make sure we have node +RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - && \ + apt-get install -y nodejs + +# Compile assets +COPY assets ./assets +RUN npm install --prefix ./assets && \ + npm run deploy --prefix ./assets + +# Now, let's go with the actual elixir code. The order matters: if we only +# change elixir code, all the above layers will be cached ~ less image build time. +COPY config ./config +COPY lib ./lib +COPY priv ./priv + +# Final build step: digest static assets and generate the release +RUN mix phx.digest && mix release + +FROM debian:buster-slim AS app + +RUN apt-get update && apt-get install -y openssl + +RUN useradd --create-home app +WORKDIR /home/app +COPY --from=app_builder /opt/release/_build . +RUN chown -R app: ./prod +USER app + +CMD ["./prod/rel/sbom_poc/bin/sbom_poc", "start"] diff --git a/Makefile b/Makefile index 28c7003..73bb669 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,8 @@ # ------------- APP_NAME ?= `grep 'app:' mix.exs | sed -e 's/\[//g' -e 's/ //g' -e 's/app://' -e 's/[:,]//g'` -APP_VERSION ?= `grep 'version:' mix.exs | cut -d '"' -f2` -DOCKER_IMAGE_TAG ?= latest +APP_VERSION := $(shell grep 'version:' mix.exs | cut -d '"' -f2) +DOCKER_IMAGE_TAG ?= $(APP_VERSION) GIT_REVISION ?= `git rev-parse HEAD` # Introspection targets @@ -62,6 +62,7 @@ test: ## Run the test suite .PHONY: format format: mix format ## Run formatting tools on the code + release: ## Build a release of the application with MIX_ENV=prod MIX_ENV=prod mix deps.get --only prod MIX_ENV=prod mix compile @@ -70,3 +71,34 @@ release: ## Build a release of the application with MIX_ENV=prod mkdir -p priv/static MIX_ENV=prod mix phx.digest MIX_ENV=prod mix release + +.PHONY: docker-image +docker-image: + docker build . -t sbom:$(APP_VERSION) --no-cache + +.PHONY: push-image-gcp push-and-serve deploy-existing-image +push-image-gcp: ## push image to gcp + @if [[ "$(docker images -q gcr.io/twinklymaha/sbom:$(APP_VERSION)> /dev/null)" != "" ]]; then \ + @echo "Removing previous image $(APP_VERSION) from your machine..."; \ + docker rmi gcr.io/twinklymaha/sbom:$(APP_VERSION);\ + fi + docker build . -t gcr.io/twinklymaha/sbom:$(APP_VERSION) #--no-cache + + gcloud container images delete gcr.io/twinklymaha/sbom:$(APP_VERSION) --force-delete-tags || echo "no image to delete on the remote" + docker push gcr.io/twinklymaha/sbom:$(APP_VERSION) + +push-and-serve-gcp: push-image-gcp deploy-existing-image + +deploy-existing-image: + gcloud compute instances create-with-container $(instance-name) \ + --container-image=gcr.io/twinklymaha/sbom:$(DOCKER_IMAGE_TAG) \ + --machine-type=e2-micro \ + --subnet=default \ + --network-tier=PREMIUM \ + --metadata=google-logging-enabled=true \ + --tags=http-server,https-server \ + --labels=project=sbom + +.PHONY: update-instance +update-instance: + gcloud compute instances update-container $(instance-name) --container-image gcr.io/twinklymaha/sbom:$(image-tag) diff --git a/README.md b/README.md index c76f3fb..e46fe0e 100644 --- a/README.md +++ b/README.md @@ -35,3 +35,69 @@ lint-format Check if the project is well formated using elixir format lint Check if the project follows set conventions such as formatting test Run the test suite ``` + +## Deployment to GCP +The deployment is done using docker images with the help of make tasks. We can create a docker image, push it to container registry on gcp and then launch +an instance using this docker image + +The docker image is automatically tagged with the application version from your mix file + +### Deployment from local machine +**Before you begin:** +- Make sure you have write access to the docker registry +- You will need the necessary permissions to create an instance +- Docker should be installed in your computer and running +- GCloud should be well set up, authenticated and initialised to use docker +- access to production secrets in the `prod.secrets.exs` file (look at `config/prod.sample.exs` to see an example) + + +#### creating an image for use in your laptop +If you want to create a docker image for use in your laptop then you can use the command +```shell +make docker-image +``` + +#### Creating an image and pushing to GCP +You can optionally create an image on your laptop and push it up to GCP container registry using the following command +```shell +make push-image-gcp +``` +This will create the image and tag it with the current application version then push the created image to GCP + +#### creating an image and lauching an instance on GCP +You can also run a server on GCP using the docker image by running the following command +```shell +make push-and-serve-gcp instance-name= +``` + +If you had created an image before and would like to create a running server using the image run: +```shell +make deploy-existing-image instance-name= +``` + +The instance name you provide above should be unique and should not be existing on GCP already otherwise you will get an error + +#### updating a running instance +If you want to update an already running instance with a different version of the application, you need +to ensure that the image is created and pushed to gcr.io using `make push-image-gcp` after which you can update an instance to use the image. + +This is done by specifying the tag to the image you want to use (`image-tag`) and the running instance you want to update (`instance-name`) + +```shell +make update-instance instance-name= image-tag= +``` + +An example would be: +```shell +make update-instance instance-name=testinstance image-tag=0.5.0 +``` + +### Accessing from GCP +The above procedures create an instance of this project +on GCP with the name you gave it. +Using console.cloud.google.compute, +go to your virtual machine instances, +and look up the external ip (a.b.c.d5) of the instance you just created (if you used one of the make commands then the ip address will be listed upon successful startup of the instance). +Note the phoenix webserver is running on port 4000 +Go to http://a.b.c.d:4000/ +Note it is http not https From fc081d97530c2fa6a4e9fe2e72ac9ae43fbe1183 Mon Sep 17 00:00:00 2001 From: sigu Date: Mon, 19 Oct 2020 12:52:56 +0300 Subject: [PATCH 08/43] fix failing config --- .gitignore | 2 ++ Makefile | 2 +- config/prod.sample.exs | 28 ++++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 config/prod.sample.exs diff --git a/.gitignore b/.gitignore index 97fa82e..43cf15d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +*.beam +/config/*.secret.exs # The directory Mix will write compiled artifacts to. /_build/ diff --git a/Makefile b/Makefile index 73bb669..f880dcd 100644 --- a/Makefile +++ b/Makefile @@ -82,7 +82,7 @@ push-image-gcp: ## push image to gcp @echo "Removing previous image $(APP_VERSION) from your machine..."; \ docker rmi gcr.io/twinklymaha/sbom:$(APP_VERSION);\ fi - docker build . -t gcr.io/twinklymaha/sbom:$(APP_VERSION) #--no-cache + docker build . -t gcr.io/twinklymaha/sbom:$(APP_VERSION) --no-cache gcloud container images delete gcr.io/twinklymaha/sbom:$(APP_VERSION) --force-delete-tags || echo "no image to delete on the remote" docker push gcr.io/twinklymaha/sbom:$(APP_VERSION) diff --git a/config/prod.sample.exs b/config/prod.sample.exs new file mode 100644 index 0000000..da76605 --- /dev/null +++ b/config/prod.sample.exs @@ -0,0 +1,28 @@ +# In this file, we load production configuration and secrets +# from environment variables. You can also hardcode secrets, +# although such is generally not recommended and you have to +# remember to add this file to your .gitignore. +use Mix.Config + +database_url = "ecto://user:password@ipaddress/db_name" + +config :sbom_poc, SbomPoc.Repo, + # ssl: true, + url: database_url, + pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10") + +secret_key_base = "Secret Keybase " + +config :sbom_poc, SbomPocWeb.Endpoint, + http: [ + port: String.to_integer(System.get_env("PORT") || "4000"), + transport_options: [socket_opts: [:inet6]] + ], + secret_key_base: secret_key_base + +# ## Using releases (Elixir v1.9+) +# +# If you are doing OTP releases, you need to instruct Phoenix +# to start each relevant endpoint: +# +config :sbom_poc, SbomPocWeb.Endpoint, server: true From fcadbb418e35c244b187eb69ab328a8836a3aafe Mon Sep 17 00:00:00 2001 From: sigu Date: Mon, 19 Oct 2020 12:56:58 +0300 Subject: [PATCH 09/43] remove prod secrets --- config/prod.secret.exs | 41 ----------------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 config/prod.secret.exs diff --git a/config/prod.secret.exs b/config/prod.secret.exs deleted file mode 100644 index 0e9ef8e..0000000 --- a/config/prod.secret.exs +++ /dev/null @@ -1,41 +0,0 @@ -# In this file, we load production configuration and secrets -# from environment variables. You can also hardcode secrets, -# although such is generally not recommended and you have to -# remember to add this file to your .gitignore. -use Mix.Config - -database_url = - System.get_env("DATABASE_URL") || - raise """ - environment variable DATABASE_URL is missing. - For example: ecto://USER:PASS@HOST/DATABASE - """ - -config :sbom_poc, SbomPoc.Repo, - # ssl: true, - url: database_url, - pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10") - -secret_key_base = - System.get_env("SECRET_KEY_BASE") || - raise """ - environment variable SECRET_KEY_BASE is missing. - You can generate one by calling: mix phx.gen.secret - """ - -config :sbom_poc, SbomPocWeb.Endpoint, - http: [ - port: String.to_integer(System.get_env("PORT") || "4000"), - transport_options: [socket_opts: [:inet6]] - ], - secret_key_base: secret_key_base - -# ## Using releases (Elixir v1.9+) -# -# If you are doing OTP releases, you need to instruct Phoenix -# to start each relevant endpoint: -# -# config :sbom_poc, SbomPocWeb.Endpoint, server: true -# -# Then you can assemble a release by calling `mix release`. -# See `mix help release` for more information. From 417dedc81c7b89df6b01511571ae7c5393de3b54 Mon Sep 17 00:00:00 2001 From: sigu Date: Mon, 19 Oct 2020 16:03:03 +0300 Subject: [PATCH 10/43] add status page --- README.md | 73 ++++++------------- docs/deployment.md | 65 +++++++++++++++++ lib/sbomPoc/posts/posts.ex | 10 +++ lib/sbomPoc/posts/status.ex | 9 +++ .../controllers/m_d_pages_controller.ex | 8 ++ lib/sbomPoc_web/router.ex | 2 + .../templates/md_pages/status.html.eex | 3 + lib/sbomPoc_web/views/md_pages_view.ex | 3 + mix.exs | 3 +- mix.lock | 6 ++ status/sample.md | 8 ++ 11 files changed, 140 insertions(+), 50 deletions(-) create mode 100644 docs/deployment.md create mode 100644 lib/sbomPoc/posts/posts.ex create mode 100644 lib/sbomPoc/posts/status.ex create mode 100644 lib/sbomPoc_web/controllers/m_d_pages_controller.ex create mode 100644 lib/sbomPoc_web/templates/md_pages/status.html.eex create mode 100644 lib/sbomPoc_web/views/md_pages_view.ex create mode 100644 status/sample.md diff --git a/README.md b/README.md index e46fe0e..76525b0 100644 --- a/README.md +++ b/README.md @@ -37,67 +37,42 @@ test Run the test suite ``` ## Deployment to GCP -The deployment is done using docker images with the help of make tasks. We can create a docker image, push it to container registry on gcp and then launch -an instance using this docker image -The docker image is automatically tagged with the application version from your mix file +Instructions to deployment can be found on [deployment docs](./docs/deployment.md) -### Deployment from local machine -**Before you begin:** -- Make sure you have write access to the docker registry -- You will need the necessary permissions to create an instance -- Docker should be installed in your computer and running -- GCloud should be well set up, authenticated and initialised to use docker -- access to production secrets in the `prod.secrets.exs` file (look at `config/prod.sample.exs` to see an example) +## Adding status +You can add your project status as markdown content by adding a markdown file to the `/status` directory. -#### creating an image for use in your laptop -If you want to create a docker image for use in your laptop then you can use the command -```shell -make docker-image -``` +Your markdown file needs to have an author and the body. -#### Creating an image and pushing to GCP -You can optionally create an image on your laptop and push it up to GCP container registry using the following command -```shell -make push-image-gcp -``` -This will create the image and tag it with the current application version then push the created image to GCP +```markdown +%{ + author: "Your company name or your name" +} -#### creating an image and lauching an instance on GCP -You can also run a server on GCP using the docker image by running the following command -```shell -make push-and-serve-gcp instance-name= -``` +--- -If you had created an image before and would like to create a running server using the image run: -```shell -make deploy-existing-image instance-name= +The body of your content ``` -The instance name you provide above should be unique and should not be existing on GCP already otherwise you will get an error +### The author +This is at the top of the file and can look like this: -#### updating a running instance -If you want to update an already running instance with a different version of the application, you need -to ensure that the image is created and pushed to gcr.io using `make push-image-gcp` after which you can update an instance to use the image. +```markdown +%{ + author: "Your company name or your name" +} +``` -This is done by specifying the tag to the image you want to use (`image-tag`) and the running instance you want to update (`instance-name`) +### The body -```shell -make update-instance instance-name= image-tag= -``` +The body comes immediatly after the author declaration and is marked by three dashes `---` -An example would be: -```shell -make update-instance instance-name=testinstance image-tag=0.5.0 +```markdown +--- + +The body of your content ``` -### Accessing from GCP -The above procedures create an instance of this project -on GCP with the name you gave it. -Using console.cloud.google.compute, -go to your virtual machine instances, -and look up the external ip (a.b.c.d5) of the instance you just created (if you used one of the make commands then the ip address will be listed upon successful startup of the instance). -Note the phoenix webserver is running on port 4000 -Go to http://a.b.c.d:4000/ -Note it is http not https +A sample file can be found at [status/sample.md](status/sample.md) diff --git a/docs/deployment.md b/docs/deployment.md new file mode 100644 index 0000000..d092531 --- /dev/null +++ b/docs/deployment.md @@ -0,0 +1,65 @@ +## Deployment to GCP +The deployment is done using docker images with the help of make tasks. We can create a docker image, push it to container registry on gcp and then launch +an instance using this docker image + +The docker image is automatically tagged with the application version from your mix file + +### Deployment from local machine +**Before you begin:** +- Make sure you have write access to the docker registry +- You will need the necessary permissions to create an instance +- Docker should be installed in your computer and running +- GCloud should be well set up, authenticated and initialised to use docker +- access to production secrets in the `prod.secrets.exs` file (look at `config/prod.sample.exs` to see an example) + + +#### creating an image for use in your laptop +If you want to create a docker image for use in your laptop then you can use the command +```shell +make docker-image +``` + +#### Creating an image and pushing to GCP +You can optionally create an image on your laptop and push it up to GCP container registry using the following command +```shell +make push-image-gcp +``` +This will create the image and tag it with the current application version then push the created image to GCP + +#### creating an image and lauching an instance on GCP +You can also run a server on GCP using the docker image by running the following command +```shell +make push-and-serve-gcp instance-name= +``` + +If you had created an image before and would like to create a running server using the image run: +```shell +make deploy-existing-image instance-name= +``` + +The instance name you provide above should be unique and should not be existing on GCP already otherwise you will get an error + +#### updating a running instance +If you want to update an already running instance with a different version of the application, you need +to ensure that the image is created and pushed to gcr.io using `make push-image-gcp` after which you can update an instance to use the image. + +This is done by specifying the tag to the image you want to use (`image-tag`) and the running instance you want to update (`instance-name`) + +```shell +make update-instance instance-name= image-tag= +``` + +An example would be: +```shell +make update-instance instance-name=testinstance image-tag=0.5.0 +``` + +### Accessing from GCP +The above procedures create an instance of this project +on GCP with the name you gave it. +Using console.cloud.google.compute, +go to your virtual machine instances, +and look up the external ip (a.b.c.d5) of the instance you just created (if you used one of the make commands then the ip address will be listed upon successful startup of the instance). +Note the phoenix webserver is running on port 4000 +Go to http://a.b.c.d:4000/ +Note it is http not https diff --git a/lib/sbomPoc/posts/posts.ex b/lib/sbomPoc/posts/posts.ex new file mode 100644 index 0000000..bd6e25d --- /dev/null +++ b/lib/sbomPoc/posts/posts.ex @@ -0,0 +1,10 @@ +defmodule SbomPoc.Post do + alias SbomPoc.Post.Status + + use NimblePublisher, + build: Status, + from: "status/**/*.md", + as: :status + + def all_status, do: @status +end diff --git a/lib/sbomPoc/posts/status.ex b/lib/sbomPoc/posts/status.ex new file mode 100644 index 0000000..0079be8 --- /dev/null +++ b/lib/sbomPoc/posts/status.ex @@ -0,0 +1,9 @@ +defmodule SbomPoc.Post.Status do + @moduledoc false + @enforce_keys [:author, :body] + defstruct [:id, :author, :title, :body, :description, :tags] + + def build(filename, attrs, body) do + struct!(__MODULE__, [body: body] ++ Map.to_list(attrs)) + end +end diff --git a/lib/sbomPoc_web/controllers/m_d_pages_controller.ex b/lib/sbomPoc_web/controllers/m_d_pages_controller.ex new file mode 100644 index 0000000..6011065 --- /dev/null +++ b/lib/sbomPoc_web/controllers/m_d_pages_controller.ex @@ -0,0 +1,8 @@ +defmodule SbomPocWeb.MDPagesController do + use SbomPocWeb, :controller + + def status(conn, params) do + status = SbomPoc.Post.all_status() + render(conn, "status.html", status: status) + end +end diff --git a/lib/sbomPoc_web/router.ex b/lib/sbomPoc_web/router.ex index c41b9e8..baa9f0c 100644 --- a/lib/sbomPoc_web/router.ex +++ b/lib/sbomPoc_web/router.ex @@ -17,6 +17,8 @@ defmodule SbomPocWeb.Router do scope "/", SbomPocWeb do pipe_through :browser + get "/status", MDPagesController, :status + live "/", PageLive, :index end diff --git a/lib/sbomPoc_web/templates/md_pages/status.html.eex b/lib/sbomPoc_web/templates/md_pages/status.html.eex new file mode 100644 index 0000000..63bf712 --- /dev/null +++ b/lib/sbomPoc_web/templates/md_pages/status.html.eex @@ -0,0 +1,3 @@ +<%= for status <- @status do %> +<%= raw status.body %> +<% end %> diff --git a/lib/sbomPoc_web/views/md_pages_view.ex b/lib/sbomPoc_web/views/md_pages_view.ex new file mode 100644 index 0000000..b7dd847 --- /dev/null +++ b/lib/sbomPoc_web/views/md_pages_view.ex @@ -0,0 +1,3 @@ +defmodule SbomPocWeb.MDPagesView do + use SbomPocWeb, :view +end diff --git a/mix.exs b/mix.exs index 71cb4f6..bacd10f 100644 --- a/mix.exs +++ b/mix.exs @@ -54,7 +54,8 @@ defmodule SbomPoc.MixProject do {:gettext, "~> 0.11"}, {:jason, "~> 1.0"}, {:plug_cowboy, "~> 2.0"}, - {:credo, "~> 1.4", only: [:dev, :test], runtime: false} + {:credo, "~> 1.4", only: [:dev, :test], runtime: false}, + {:nimble_publisher, "~> 0.1.0"} ] end diff --git a/mix.lock b/mix.lock index de6a847..6248771 100644 --- a/mix.lock +++ b/mix.lock @@ -6,6 +6,8 @@ "credo": {:hex, :credo, "1.4.0", "92339d4cbadd1e88b5ee43d427b639b68a11071b6f73854e33638e30a0ea11f5", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1fd3b70dce216574ce3c18bdf510b57e7c4c85c2ec9cad4bff854abaf7e58658"}, "db_connection": {:hex, :db_connection, "2.2.2", "3bbca41b199e1598245b716248964926303b5d4609ff065125ce98bcd368939e", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "642af240d8a8affb93b4ba5a6fcd2bbcbdc327e1a524b825d383711536f8070c"}, "decimal": {:hex, :decimal, "1.8.1", "a4ef3f5f3428bdbc0d35374029ffcf4ede8533536fa79896dd450168d9acdf3c", [:mix], [], "hexpm", "3cb154b00225ac687f6cbd4acc4b7960027c757a5152b369923ead9ddbca7aec"}, + "earmark": {:hex, :earmark, "1.4.10", "bddce5e8ea37712a5bfb01541be8ba57d3b171d3fa4f80a0be9bcf1db417bcaf", [:mix], [{:earmark_parser, ">= 1.4.10", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "12dbfa80810478e521d3ffb941ad9fbfcbbd7debe94e1341b4c4a1b2411c1c27"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.10", "6603d7a603b9c18d3d20db69921527f82ef09990885ed7525003c7fe7dc86c56", [:mix], [], "hexpm", "8e2d5370b732385db2c9b22215c3f59c84ac7dda7ed7e544d7c459496ae519c0"}, "ecto": {:hex, :ecto, "3.4.4", "a2c881e80dc756d648197ae0d936216c0308370332c5e77a2325a10293eef845", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cc4bd3ad62abc3b21fb629f0f7a3dab23a192fca837d257dd08449fba7373561"}, "ecto_sql": {:hex, :ecto_sql, "3.4.4", "d28bac2d420f708993baed522054870086fd45016a9d09bb2cd521b9c48d32ea", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.4.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.0", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "edb49af715dd72f213b66adfd0f668a43c17ed510b5d9ac7528569b23af57fe8"}, "file_system": {:hex, :file_system, "0.2.8", "f632bd287927a1eed2b718f22af727c5aeaccc9a98d8c2bd7bff709e851dc986", [:mix], [], "hexpm", "97a3b6f8d63ef53bd0113070102db2ce05352ecf0d25390eb8d747c2bde98bca"}, @@ -13,7 +15,11 @@ "gettext": {:hex, :gettext, "0.18.0", "406d6b9e0e3278162c2ae1de0a60270452c553536772167e2d701f028116f870", [:mix], [], "hexpm", "c3f850be6367ebe1a08616c2158affe4a23231c70391050bf359d5f92f66a571"}, "html_entities": {:hex, :html_entities, "0.5.1", "1c9715058b42c35a2ab65edc5b36d0ea66dd083767bef6e3edb57870ef556549", [:mix], [], "hexpm", "30efab070904eb897ff05cd52fa61c1025d7f8ef3a9ca250bc4e6513d16c32de"}, "jason": {:hex, :jason, "1.2.1", "12b22825e22f468c02eb3e4b9985f3d0cb8dc40b9bd704730efa11abd2708c44", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b659b8571deedf60f79c5a608e15414085fa141344e2716fbd6988a084b5f993"}, + "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.15.0", "98312c9f0d3730fde4049985a1105da5155bfe5c11e47bdc7406d88e01e4219b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "75ffa34ab1056b7e24844c90bfc62aaf6f3a37a15faa76b07bc5eba27e4a8b4a"}, "mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm", "6cbe761d6a0ca5a31a0931bf4c63204bceb64538e664a8ecf784a9a6f3b875f1"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"}, + "nimble_publisher": {:hex, :nimble_publisher, "0.1.1", "1708947eb073702f69b256cf521be114154dd9115b7c40a75fb52357fa4f63ee", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:makeup_elixir, ">= 0.0.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "ccf0c552c9e409ffc5ca64377478e2832ea9a6a88c4282c6839bafac3f3c77f0"}, "phoenix": {:hex, :phoenix, "1.5.4", "0fca9ce7e960f9498d6315e41fcd0c80bfa6fbeb5fa3255b830c67fdfb7e703f", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4e516d131fde87b568abd62e1b14aa07ba7d5edfd230bab4e25cc9dedbb39135"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.1.0", "a044d0756d0464c5a541b4a0bf4bcaf89bffcaf92468862408290682c73ae50d", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "c5e666a341ff104d0399d8f0e4ff094559b2fde13a5985d4cb5023b2c2ac558b"}, "phoenix_html": {:hex, :phoenix_html, "2.14.2", "b8a3899a72050f3f48a36430da507dd99caf0ac2d06c77529b1646964f3d563e", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "58061c8dfd25da5df1ea0ca47c972f161beb6c875cd293917045b92ffe1bf617"}, diff --git a/status/sample.md b/status/sample.md new file mode 100644 index 0000000..e588d8b --- /dev/null +++ b/status/sample.md @@ -0,0 +1,8 @@ +%{ + author: "Sample Author" + } + +--- +# This is Heading one + +We are testing the status page From 4af95ddd53857f421122ecf86da692c785d29851 Mon Sep 17 00:00:00 2001 From: sigu Date: Tue, 20 Oct 2020 15:58:29 +0300 Subject: [PATCH 11/43] create sbom file --- Makefile | 5 +++++ README.md | 10 ++++++++++ mix.exs | 3 ++- mix.lock | 1 + 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f880dcd..acd5c4a 100644 --- a/Makefile +++ b/Makefile @@ -62,6 +62,11 @@ test: ## Run the test suite .PHONY: format format: mix format ## Run formatting tools on the code +.PHONY: sbom ## create sbom file for both hex and npm dependancies +sbom: + mix sbom.cyclonedx -o elixir_bom.xml + cd assets && cyclonedx-bom -o ../bom.xml -a ../elixir_bom.xml && cd .. + release: ## Build a release of the application with MIX_ENV=prod MIX_ENV=prod mix deps.get --only prod diff --git a/README.md b/README.md index e46fe0e..896f0eb 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,12 @@ First ensure you have the following set up in your computer You can use [the phoenix installation guide](https://hexdocs.pm/phoenix/installation.html#content) to ensure you have everything set up as expected +## Installing SBOM utilities +You will need to install the following dependancies to enable production of SBOM files from the command line + +```shell +npm install -g @cyclonedx/bom +``` To start your Phoenix server: @@ -34,8 +40,12 @@ lint-credo Use credo to ensure formatting styles lint-format Check if the project is well formated using elixir formatter lint Check if the project follows set conventions such as formatting test Run the test suite +sbom Create SBOM file for hex and npm deps ``` +## Generating SBOM file +To generate an sbom file, use the make task `make sbom` to generate an `sbom.xml` file on the project root + ## Deployment to GCP The deployment is done using docker images with the help of make tasks. We can create a docker image, push it to container registry on gcp and then launch an instance using this docker image diff --git a/mix.exs b/mix.exs index 71cb4f6..766dee2 100644 --- a/mix.exs +++ b/mix.exs @@ -54,7 +54,8 @@ defmodule SbomPoc.MixProject do {:gettext, "~> 0.11"}, {:jason, "~> 1.0"}, {:plug_cowboy, "~> 2.0"}, - {:credo, "~> 1.4", only: [:dev, :test], runtime: false} + {:credo, "~> 1.4", only: [:dev, :test], runtime: false}, + {:sbom, "~> 0.6.0", only: :dev, runtime: false} ] end diff --git a/mix.lock b/mix.lock index de6a847..d3db952 100644 --- a/mix.lock +++ b/mix.lock @@ -26,6 +26,7 @@ "plug_crypto": {:hex, :plug_crypto, "1.1.2", "bdd187572cc26dbd95b87136290425f2b580a116d3fb1f564216918c9730d227", [:mix], [], "hexpm", "6b8b608f895b6ffcfad49c37c7883e8df98ae19c6a28113b02aa1e9c5b22d6b5"}, "postgrex": {:hex, :postgrex, "0.15.5", "aec40306a622d459b01bff890fa42f1430dac61593b122754144ad9033a2152f", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "ed90c81e1525f65a2ba2279dbcebf030d6d13328daa2f8088b9661eb9143af7f"}, "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"}, + "sbom": {:hex, :sbom, "0.6.0", "65d489ef343e7978751ffc6a587aef31275e97276cba7336fbbc84daa410e565", [:mix], [], "hexpm", "bdb5f16b55985512d7081fc6c85dbfb2981259f15ba6fb50217360298bce842c"}, "telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"}, "telemetry_metrics": {:hex, :telemetry_metrics, "0.5.0", "1b796e74add83abf844e808564275dfb342bcc930b04c7577ab780e262b0d998", [:mix], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "31225e6ce7a37a421a0a96ec55244386aec1c190b22578bd245188a4a33298fd"}, "telemetry_poller": {:hex, :telemetry_poller, "0.5.1", "21071cc2e536810bac5628b935521ff3e28f0303e770951158c73eaaa01e962a", [:rebar3], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4cab72069210bc6e7a080cec9afffad1b33370149ed5d379b81c7c5f0c663fd4"}, From bab1c310b0871685d57eb736b96b8a42a95b20e4 Mon Sep 17 00:00:00 2001 From: sigu Date: Tue, 20 Oct 2020 21:45:57 +0300 Subject: [PATCH 12/43] move logger into sbom poc --- lib/sbomPoc/application.ex | 8 ++- lib/sbomPoc/mqtt.ex | 81 +++++++++++++++++++++++++ lib/sbomPoc/mqtt/handler.ex | 92 +++++++++++++++++++++++++++++ lib/sbomPoc_web/live/events_live.ex | 47 +++++++++++++++ lib/sbomPoc_web/router.ex | 2 + mix.exs | 3 +- mix.lock | 2 + 7 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 lib/sbomPoc/mqtt.ex create mode 100644 lib/sbomPoc/mqtt/handler.ex create mode 100644 lib/sbomPoc_web/live/events_live.ex diff --git a/lib/sbomPoc/application.ex b/lib/sbomPoc/application.ex index 38bc9dd..69f2c18 100644 --- a/lib/sbomPoc/application.ex +++ b/lib/sbomPoc/application.ex @@ -14,15 +14,21 @@ defmodule SbomPoc.Application do # Start the PubSub system {Phoenix.PubSub, name: SbomPoc.PubSub}, # Start the Endpoint (http/https) - SbomPocWeb.Endpoint + SbomPocWeb.Endpoint, # Start a worker by calling: SbomPoc.Worker.start_link(arg) # {SbomPoc.Worker, arg} + {Tortoise.Supervisor, + [ + name: Oc2Mqtt.Connection.Supervisor, + strategy: :one_for_one + ]} ] # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_one, name: SbomPoc.Supervisor] Supervisor.start_link(children, opts) + SbomPoc.Mqtt.start() end # Tell Phoenix to update the endpoint configuration diff --git a/lib/sbomPoc/mqtt.ex b/lib/sbomPoc/mqtt.ex new file mode 100644 index 0000000..389c5e7 --- /dev/null +++ b/lib/sbomPoc/mqtt.ex @@ -0,0 +1,81 @@ +defmodule SbomPoc.Mqtt do + @moduledoc """ + `Mqtt` is main module for handling mqtt + mqtt.start initializes the system + and starts the Tortoise mqtt client using mqtt.handler + """ + + require Logger + + @doc """ + Start initializes system variables + and starts supervisor of mqtt client + """ + def start do + client_id = + System.get_env("CLIENT_ID") || + raise """ + environment variable CLIENT_ID is missing. + For example: + export CLIENT_ID=:mqttlogger + """ + + Logger.info("client_id is #{client_id}") + + mqtt_host = + System.get_env("MQTT_HOST") || + raise """ + environment variable HOST is missing. + Examples: + export MQTT_HOST="34.86.117.113" + export MQTT_HOST="mqtt.sfractal.com" + """ + + Logger.info("mqtt_host is #{mqtt_host}") + + mqtt_port = + String.to_integer( + System.get_env("MQTT_PORT") || + raise(""" + environment variable MQTT_PORT is missing. + Example: + export MQTT_PORT=1883 + """) + ) + + Logger.info("mqtt_port is #{mqtt_port}") + + server = {Tortoise.Transport.Tcp, host: mqtt_host, port: mqtt_port} + + user_name = + System.get_env("USER_NAME") || + raise """ + environment variable USER_NAME is missing. + Examples: + export USER_NAME="plug" + """ + + Logger.info("user_name is #{user_name}") + + password = + System.get_env("PASSWORD") || + raise """ + environment variable PASSWORD is missing. + Example: + export PASSWORD="fest" + """ + + Logger.info("password set") + + {:ok, _} = + Tortoise.Supervisor.start_child( + Oc2Mqtt.Connection.Supervisor, + client_id: client_id, + handler: {SbomPoc.Mqtt.Handler, [name: client_id]}, + server: server, + user_name: user_name, + password: password, + subscriptions: [{"#", 0}] + ) + end +end diff --git a/lib/sbomPoc/mqtt/handler.ex b/lib/sbomPoc/mqtt/handler.ex new file mode 100644 index 0000000..b30346f --- /dev/null +++ b/lib/sbomPoc/mqtt/handler.ex @@ -0,0 +1,92 @@ +defmodule SbomPoc.Mqtt.Handler do + @moduledoc """ + Mqtt.Handler is a behaviour of Tortoise for handling mqtt + It allows for connections, subscriptons, and handles messages. + The mqtt-specific code is here; and this module calls oc2 for + OpenC2 parsing and execution + """ + + require Logger + + defstruct [:name, :events] + alias __MODULE__, as: State + + @behaviour Tortoise.Handler + + @impl true + def init(opts) do + name = Keyword.get(opts, :name) + create_events_table() + + {:ok, %State{name: name, events: []}} + end + + @impl true + def connection(:up, state) do + Logger.debug("Connection has been established") + {:ok, state} + end + + def connection(:down, state) do + Logger.warn("Connection has been dropped") + {:ok, state} + end + + def connection(:terminated, state) do + Logger.warn("Connection has been terminated") + {:ok, state} + end + + @impl true + def subscription(:up, topic, state) do + Logger.debug("Subscribed to #{topic}") + {:ok, state} + end + + def subscription({:warn, [requested: req, accepted: qos]}, topic, state) do + Logger.warn("Subscribed to #{topic}; requested #{req} but got accepted with QoS #{qos}") + {:ok, state} + end + + def subscription({:error, reason}, topic, state) do + Logger.error("Error subscribing to #{topic}; #{inspect(reason)}") + {:ok, state} + end + + def subscription(:down, topic, state) do + Logger.debug("Unsubscribed from #{topic}") + {:ok, state} + end + + def handle_message(topic, msg, state) do + Logger.debug("Found a message") + Logger.info("#{state.name}, #{Enum.join(topic, "/")} #{inspect(msg)}") + record_event(Enum.join(topic, "/"), inspect(msg), state.name) + + {:ok, state} + end + + @impl true + def terminate(reason, _state) do + Logger.warn("Client has been terminated with reason: #{inspect(reason)}") + :ok + end + + defp create_events_table do + :ets.new(:events_table, [:set, :public, :named_table]) + end + + defp record_event(topic, msg, name) do + data = {DateTime.utc_now(), %{name: name, topic: topic, message: msg}} + :ets.insert(:events_table, data) + _notify(data) + end + + def all_events do + :ets.tab2list(:events_table) + end + + defp _notify(event) do + Phoenix.PubSub.broadcast(SbomPoc.PubSub, "new_event", {"new_event", %{event: event}}) + end +end diff --git a/lib/sbomPoc_web/live/events_live.ex b/lib/sbomPoc_web/live/events_live.ex new file mode 100644 index 0000000..8ffcf26 --- /dev/null +++ b/lib/sbomPoc_web/live/events_live.ex @@ -0,0 +1,47 @@ +defmodule SbomPocWeb.EventsLive do + @moduledoc "Events page live view" + use SbomPocWeb, :live_view + + @topic "new_event" + + @impl true + def mount(_params, _session, socket) do + Phoenix.PubSub.subscribe(SbomPoc.PubSub, @topic) + + events = SbomPoc.Mqtt.Handler.all_events() + {:ok, assign(socket, events: events)} + end + + def render(assigns) do + ~L""" +

Events page view

+ <%= if Enum.empty? @events do %> +

No events yet

+ <% else %> + + + + + + + + + + <%= for {time, details} <- @events do %> + + + + + + <% end %> + +
TimeTopicMessage
<%= time %><%= details.topic %><%= details.message %>
+ <% end %> + """ + end + + def handle_info({"new_event", %{event: event}}, socket) do + events = [event | socket.assigns.events] + {:noreply, assign(socket, events: events)} + end +end diff --git a/lib/sbomPoc_web/router.ex b/lib/sbomPoc_web/router.ex index c41b9e8..ce07397 100644 --- a/lib/sbomPoc_web/router.ex +++ b/lib/sbomPoc_web/router.ex @@ -18,6 +18,8 @@ defmodule SbomPocWeb.Router do pipe_through :browser live "/", PageLive, :index + + live "/events", EventsLive, :index end # Other scopes may use custom stacks. diff --git a/mix.exs b/mix.exs index 71cb4f6..8e6ee42 100644 --- a/mix.exs +++ b/mix.exs @@ -54,7 +54,8 @@ defmodule SbomPoc.MixProject do {:gettext, "~> 0.11"}, {:jason, "~> 1.0"}, {:plug_cowboy, "~> 2.0"}, - {:credo, "~> 1.4", only: [:dev, :test], runtime: false} + {:credo, "~> 1.4", only: [:dev, :test], runtime: false}, + {:tortoise, "~> 0.9"} ] end diff --git a/mix.lock b/mix.lock index de6a847..52fc0d0 100644 --- a/mix.lock +++ b/mix.lock @@ -10,6 +10,7 @@ "ecto_sql": {:hex, :ecto_sql, "3.4.4", "d28bac2d420f708993baed522054870086fd45016a9d09bb2cd521b9c48d32ea", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.4.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.0", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "edb49af715dd72f213b66adfd0f668a43c17ed510b5d9ac7528569b23af57fe8"}, "file_system": {:hex, :file_system, "0.2.8", "f632bd287927a1eed2b718f22af727c5aeaccc9a98d8c2bd7bff709e851dc986", [:mix], [], "hexpm", "97a3b6f8d63ef53bd0113070102db2ce05352ecf0d25390eb8d747c2bde98bca"}, "floki": {:hex, :floki, "0.27.0", "6b29a14283f1e2e8fad824bc930eaa9477c462022075df6bea8f0ad811c13599", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "583b8c13697c37179f1f82443bcc7ad2f76fbc0bf4c186606eebd658f7f2631b"}, + "gen_state_machine": {:hex, :gen_state_machine, "2.1.0", "a38b0e53fad812d29ec149f0d354da5d1bc0d7222c3711f3a0bd5aa608b42992", [:mix], [], "hexpm", "ae367038808db25cee2f2c4b8d0531522ea587c4995eb6f96ee73410a60fa06b"}, "gettext": {:hex, :gettext, "0.18.0", "406d6b9e0e3278162c2ae1de0a60270452c553536772167e2d701f028116f870", [:mix], [], "hexpm", "c3f850be6367ebe1a08616c2158affe4a23231c70391050bf359d5f92f66a571"}, "html_entities": {:hex, :html_entities, "0.5.1", "1c9715058b42c35a2ab65edc5b36d0ea66dd083767bef6e3edb57870ef556549", [:mix], [], "hexpm", "30efab070904eb897ff05cd52fa61c1025d7f8ef3a9ca250bc4e6513d16c32de"}, "jason": {:hex, :jason, "1.2.1", "12b22825e22f468c02eb3e4b9985f3d0cb8dc40b9bd704730efa11abd2708c44", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b659b8571deedf60f79c5a608e15414085fa141344e2716fbd6988a084b5f993"}, @@ -29,4 +30,5 @@ "telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"}, "telemetry_metrics": {:hex, :telemetry_metrics, "0.5.0", "1b796e74add83abf844e808564275dfb342bcc930b04c7577ab780e262b0d998", [:mix], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "31225e6ce7a37a421a0a96ec55244386aec1c190b22578bd245188a4a33298fd"}, "telemetry_poller": {:hex, :telemetry_poller, "0.5.1", "21071cc2e536810bac5628b935521ff3e28f0303e770951158c73eaaa01e962a", [:rebar3], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4cab72069210bc6e7a080cec9afffad1b33370149ed5d379b81c7c5f0c663fd4"}, + "tortoise": {:hex, :tortoise, "0.9.4", "3bca5f4475f80a5bd45aab644ddb3364dd0956b67f4202dcef6ed20e045ea3a6", [:mix], [{:gen_state_machine, "~> 2.0", [hex: :gen_state_machine, repo: "hexpm", optional: false]}], "hexpm", "d5c00d7c2329016376181e19f18116a10fc65691bd96b08e5b726ca050d10094"}, } From 79b63439c0d2b31f75dc48d65c89709f740dc9e6 Mon Sep 17 00:00:00 2001 From: sigu Date: Wed, 21 Oct 2020 15:22:38 +0300 Subject: [PATCH 13/43] show single status --- lib/sbomPoc/posts/posts.ex | 9 +++++++++ lib/sbomPoc/posts/status.ex | 5 +++-- lib/sbomPoc_web/controllers/m_d_pages_controller.ex | 5 +++++ lib/sbomPoc_web/router.ex | 1 + lib/sbomPoc_web/templates/md_pages/show_status.html.eex | 2 ++ lib/sbomPoc_web/templates/md_pages/status.html.eex | 7 ++++++- 6 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 lib/sbomPoc_web/templates/md_pages/show_status.html.eex diff --git a/lib/sbomPoc/posts/posts.ex b/lib/sbomPoc/posts/posts.ex index bd6e25d..165490e 100644 --- a/lib/sbomPoc/posts/posts.ex +++ b/lib/sbomPoc/posts/posts.ex @@ -7,4 +7,13 @@ defmodule SbomPoc.Post do as: :status def all_status, do: @status + + def get_status_by_id!(id) do + Enum.find(all_status(), &(&1.id == id)) || + raise NotFoundError, "status with id=#{id} not found" + end +end + +defmodule NotFoundError do + defexception [:message, plug_status: 404] end diff --git a/lib/sbomPoc/posts/status.ex b/lib/sbomPoc/posts/status.ex index 0079be8..f7407a3 100644 --- a/lib/sbomPoc/posts/status.ex +++ b/lib/sbomPoc/posts/status.ex @@ -1,9 +1,10 @@ defmodule SbomPoc.Post.Status do @moduledoc false - @enforce_keys [:author, :body] + @enforce_keys [:id, :author, :body] defstruct [:id, :author, :title, :body, :description, :tags] def build(filename, attrs, body) do - struct!(__MODULE__, [body: body] ++ Map.to_list(attrs)) + [_, id] = filename |> Path.rootname() |> Path.split() |> Enum.take(-2) + struct!(__MODULE__, [body: body, id: id] ++ Map.to_list(attrs)) end end diff --git a/lib/sbomPoc_web/controllers/m_d_pages_controller.ex b/lib/sbomPoc_web/controllers/m_d_pages_controller.ex index 6011065..c96a39a 100644 --- a/lib/sbomPoc_web/controllers/m_d_pages_controller.ex +++ b/lib/sbomPoc_web/controllers/m_d_pages_controller.ex @@ -5,4 +5,9 @@ defmodule SbomPocWeb.MDPagesController do status = SbomPoc.Post.all_status() render(conn, "status.html", status: status) end + + def show_status(conn, %{"id" => id}) do + status = SbomPoc.Post.get_status_by_id!(id) + render(conn, "show_status.html", status: status) + end end diff --git a/lib/sbomPoc_web/router.ex b/lib/sbomPoc_web/router.ex index baa9f0c..98dda53 100644 --- a/lib/sbomPoc_web/router.ex +++ b/lib/sbomPoc_web/router.ex @@ -18,6 +18,7 @@ defmodule SbomPocWeb.Router do pipe_through :browser get "/status", MDPagesController, :status + get "/status/:id", MDPagesController, :show_status live "/", PageLive, :index end diff --git a/lib/sbomPoc_web/templates/md_pages/show_status.html.eex b/lib/sbomPoc_web/templates/md_pages/show_status.html.eex new file mode 100644 index 0000000..4424c3c --- /dev/null +++ b/lib/sbomPoc_web/templates/md_pages/show_status.html.eex @@ -0,0 +1,2 @@ +

<%= @status.author %>

+ <%= raw @status.body %> diff --git a/lib/sbomPoc_web/templates/md_pages/status.html.eex b/lib/sbomPoc_web/templates/md_pages/status.html.eex index 63bf712..60697e1 100644 --- a/lib/sbomPoc_web/templates/md_pages/status.html.eex +++ b/lib/sbomPoc_web/templates/md_pages/status.html.eex @@ -1,3 +1,8 @@ <%= for status <- @status do %> -<%= raw status.body %> +

+ <%= link status.author, to: Routes.md_pages_path(@conn, :show_status, status.id) %> +

+ <%= raw(status.body |> String.splitter("") |> Enum.take(100)) %> + + <%= link "read more", to: Routes.md_pages_path(@conn, :show_status, status.id) %> <% end %> From ac6c3890486e5efbf03f925aeda2804e3e81270f Mon Sep 17 00:00:00 2001 From: sigu Date: Wed, 21 Oct 2020 20:19:39 +0300 Subject: [PATCH 14/43] allow environment variables --- .github/workflows/elixir.yml | 6 ++++++ Dockerfile | 14 ++++++++++++++ Makefile | 17 ++++++++++++++--- README.md | 15 +++++++++++++++ lib/sbomPoc/mqtt/handler.ex | 6 ++++++ lib/sbomPoc_web/live/events_live.ex | 2 ++ 6 files changed, 57 insertions(+), 3 deletions(-) diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml index c01da1c..d602f83 100644 --- a/.github/workflows/elixir.yml +++ b/.github/workflows/elixir.yml @@ -47,5 +47,11 @@ jobs: run: mix deps.get - name: Run tests run: mix test + env: + CLIENT_ID: :sfractal2020 + MQTT_HOST: mqtt.sfractal.com + MQTT_PORT: 1883 + USER_NAME: plug + PASSWORD: fest - name: Check lints run: make lint diff --git a/Dockerfile b/Dockerfile index c533f7a..e721670 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,6 +36,20 @@ RUN mix phx.digest && mix release FROM debian:buster-slim AS app +ARG CLIENT_ID=:sfractal2020 +ARG MQTT_HOST=35.184.192.117 +ARG MQTT_PORT=1883 +ARG USER_NAME=plug +ARG PASSWORD=fest + + +ENV LANG=C.UTF-8 +ENV CLIENT_ID=$CLIENT_ID +ENV MQTT_HOST=$CLIENT_ID +ENV MQTT_PORT=$MQTT_PORT +ENV USER_NAME=$USER_NAME +ENV PASSWORD=$PASSWORD + RUN apt-get update && apt-get install -y openssl RUN useradd --create-home app diff --git a/Makefile b/Makefile index f880dcd..33b162e 100644 --- a/Makefile +++ b/Makefile @@ -74,7 +74,12 @@ release: ## Build a release of the application with MIX_ENV=prod .PHONY: docker-image docker-image: - docker build . -t sbom:$(APP_VERSION) --no-cache + docker build . -t sbom:$(APP_VERSION) --no-cache \ + --build-arg CLIENT_ID=$(CLIENT_ID) \ + --build-arg MQTT_HOST=$(MQTT_HOST) \ + --build-arg MQTT_PORT=$(MQTT_PORT) \ + --build-arg USER_NAME=$(USER_NAME) \ + --build-arg PASSWORD=$(PASSWORD) \ .PHONY: push-image-gcp push-and-serve deploy-existing-image push-image-gcp: ## push image to gcp @@ -82,7 +87,12 @@ push-image-gcp: ## push image to gcp @echo "Removing previous image $(APP_VERSION) from your machine..."; \ docker rmi gcr.io/twinklymaha/sbom:$(APP_VERSION);\ fi - docker build . -t gcr.io/twinklymaha/sbom:$(APP_VERSION) --no-cache + docker build . -t gcr.io/twinklymaha/sbom:$(APP_VERSION) --no-cache \ + --build-arg CLIENT_ID=$(CLIENT_ID) \ + --build-arg MQTT_HOST=$(MQTT_HOST) \ + --build-arg MQTT_PORT=$(MQTT_PORT) \ + --build-arg USER_NAME=$(USER_NAME) \ + --build-arg PASSWORD=$(PASSWORD) \ gcloud container images delete gcr.io/twinklymaha/sbom:$(APP_VERSION) --force-delete-tags || echo "no image to delete on the remote" docker push gcr.io/twinklymaha/sbom:$(APP_VERSION) @@ -97,7 +107,8 @@ deploy-existing-image: --network-tier=PREMIUM \ --metadata=google-logging-enabled=true \ --tags=http-server,https-server \ - --labels=project=sbom + --labels=project=sbom \ + --container-env=CLIENT_ID=$(CLIENT_ID),MQTT_HOST=$(MQTT_HOST),MQTT_PORT=$(MQTT_PORT),USER_NAME=$(USER_NAME),PASSWORD=$(PASSWORD) .PHONY: update-instance update-instance: diff --git a/README.md b/README.md index e46fe0e..f35bc79 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,21 @@ make deploy-existing-image instance-name= The instance name you provide above should be unique and should not be existing on GCP already otherwise you will get an error +#### Custom environment variables +You can set the following custom environment variables when building the image or launching a vm instance + +- CLIENT_ID +- MQTT_HOST +- MQTT_PORT +- USER_NAME +- PASSWORD + +When running the make commands above you can add any of the variables above that you want to customise for example: + +```shell +make deploy-existing-image instance-name= CLIENT_ID= USER_NAME= +``` + #### updating a running instance If you want to update an already running instance with a different version of the application, you need to ensure that the image is created and pushed to gcr.io using `make push-image-gcp` after which you can update an instance to use the image. diff --git a/lib/sbomPoc/mqtt/handler.ex b/lib/sbomPoc/mqtt/handler.ex index b30346f..6cbd14b 100644 --- a/lib/sbomPoc/mqtt/handler.ex +++ b/lib/sbomPoc/mqtt/handler.ex @@ -27,11 +27,13 @@ defmodule SbomPoc.Mqtt.Handler do {:ok, state} end + @impl true def connection(:down, state) do Logger.warn("Connection has been dropped") {:ok, state} end + @impl true def connection(:terminated, state) do Logger.warn("Connection has been terminated") {:ok, state} @@ -43,21 +45,25 @@ defmodule SbomPoc.Mqtt.Handler do {:ok, state} end + @impl true def subscription({:warn, [requested: req, accepted: qos]}, topic, state) do Logger.warn("Subscribed to #{topic}; requested #{req} but got accepted with QoS #{qos}") {:ok, state} end + @impl true def subscription({:error, reason}, topic, state) do Logger.error("Error subscribing to #{topic}; #{inspect(reason)}") {:ok, state} end + @impl true def subscription(:down, topic, state) do Logger.debug("Unsubscribed from #{topic}") {:ok, state} end + @impl true def handle_message(topic, msg, state) do Logger.debug("Found a message") Logger.info("#{state.name}, #{Enum.join(topic, "/")} #{inspect(msg)}") diff --git a/lib/sbomPoc_web/live/events_live.ex b/lib/sbomPoc_web/live/events_live.ex index 8ffcf26..c68f151 100644 --- a/lib/sbomPoc_web/live/events_live.ex +++ b/lib/sbomPoc_web/live/events_live.ex @@ -12,6 +12,7 @@ defmodule SbomPocWeb.EventsLive do {:ok, assign(socket, events: events)} end + @impl true def render(assigns) do ~L"""

Events page view

@@ -40,6 +41,7 @@ defmodule SbomPocWeb.EventsLive do """ end + @impl true def handle_info({"new_event", %{event: event}}, socket) do events = [event | socket.assigns.events] {:noreply, assign(socket, events: events)} From 1d0a8a089c30b8bc8484a632dd4ea1177e202efa Mon Sep 17 00:00:00 2001 From: Sigu Magwa Date: Wed, 21 Oct 2020 22:30:15 +0300 Subject: [PATCH 15/43] use sbompoc as client id --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e721670..c47a10f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,7 +36,7 @@ RUN mix phx.digest && mix release FROM debian:buster-slim AS app -ARG CLIENT_ID=:sfractal2020 +ARG CLIENT_ID=:sbompoc ARG MQTT_HOST=35.184.192.117 ARG MQTT_PORT=1883 ARG USER_NAME=plug From a5a0e90234b53f226a2dbae4e456eba8b8da0edd Mon Sep 17 00:00:00 2001 From: sigu Date: Thu, 22 Oct 2020 11:55:53 +0300 Subject: [PATCH 16/43] create table during start up --- Makefile | 7 ++++++- lib/sbomPoc/mqtt.ex | 3 +++ lib/sbomPoc/mqtt/handler.ex | 3 +-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 33b162e..1d6b253 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,11 @@ APP_NAME ?= `grep 'app:' mix.exs | sed -e 's/\[//g' -e 's/ //g' -e 's/app://' -e APP_VERSION := $(shell grep 'version:' mix.exs | cut -d '"' -f2) DOCKER_IMAGE_TAG ?= $(APP_VERSION) GIT_REVISION ?= `git rev-parse HEAD` +CLIENT_ID=:sbom_poc +MQTT_HOST=35.184.192.117 +MQTT_PORT=1883 +USER_NAME=plug +PASSWORD=fest # Introspection targets # --------------------- @@ -87,7 +92,7 @@ push-image-gcp: ## push image to gcp @echo "Removing previous image $(APP_VERSION) from your machine..."; \ docker rmi gcr.io/twinklymaha/sbom:$(APP_VERSION);\ fi - docker build . -t gcr.io/twinklymaha/sbom:$(APP_VERSION) --no-cache \ + docker build . -t gcr.io/twinklymaha/sbom:$(APP_VERSION) \ --build-arg CLIENT_ID=$(CLIENT_ID) \ --build-arg MQTT_HOST=$(MQTT_HOST) \ --build-arg MQTT_PORT=$(MQTT_PORT) \ diff --git a/lib/sbomPoc/mqtt.ex b/lib/sbomPoc/mqtt.ex index 389c5e7..ff80828 100644 --- a/lib/sbomPoc/mqtt.ex +++ b/lib/sbomPoc/mqtt.ex @@ -67,6 +67,9 @@ defmodule SbomPoc.Mqtt do Logger.info("password set") + Logger.info("Creating events table...") + :events_table = SbomPoc.Mqtt.Handler.create_events_table() + {:ok, _} = Tortoise.Supervisor.start_child( Oc2Mqtt.Connection.Supervisor, diff --git a/lib/sbomPoc/mqtt/handler.ex b/lib/sbomPoc/mqtt/handler.ex index 6cbd14b..c89055d 100644 --- a/lib/sbomPoc/mqtt/handler.ex +++ b/lib/sbomPoc/mqtt/handler.ex @@ -16,7 +16,6 @@ defmodule SbomPoc.Mqtt.Handler do @impl true def init(opts) do name = Keyword.get(opts, :name) - create_events_table() {:ok, %State{name: name, events: []}} end @@ -78,7 +77,7 @@ defmodule SbomPoc.Mqtt.Handler do :ok end - defp create_events_table do + def create_events_table do :ets.new(:events_table, [:set, :public, :named_table]) end From 7951de45e5e29f8996bfe8a56af5bd8bfc50e1e2 Mon Sep 17 00:00:00 2001 From: Sigu Magwa Date: Thu, 22 Oct 2020 12:01:26 +0300 Subject: [PATCH 17/43] use sbompoc as client id --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1d6b253..3d34a20 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ APP_NAME ?= `grep 'app:' mix.exs | sed -e 's/\[//g' -e 's/ //g' -e 's/app://' -e APP_VERSION := $(shell grep 'version:' mix.exs | cut -d '"' -f2) DOCKER_IMAGE_TAG ?= $(APP_VERSION) GIT_REVISION ?= `git rev-parse HEAD` -CLIENT_ID=:sbom_poc +CLIENT_ID=:sbompoc MQTT_HOST=35.184.192.117 MQTT_PORT=1883 USER_NAME=plug From 37f4243fa627a14395f38dffd05e4e016057ec7f Mon Sep 17 00:00:00 2001 From: sigu Date: Thu, 22 Oct 2020 12:55:18 +0300 Subject: [PATCH 18/43] basic auth --- config/test.exs | 3 + lib/sbomPoc.ex | 9 - lib/sbomPoc_web/router.ex | 43 -- lib/sbom_poc/accounts.ex | 349 +++++++++++++ lib/sbom_poc/accounts/user.ex | 116 +++++ lib/sbom_poc/accounts/user_notifier.ex | 73 +++ lib/sbom_poc/accounts/user_token.ex | 139 +++++ lib/{sbomPoc => sbom_poc}/application.ex | 0 lib/{sbomPoc => sbom_poc}/repo.ex | 0 lib/{sbomPoc_web.ex => sbom_poc_web.ex} | 2 +- .../channels/user_socket.ex | 0 lib/sbom_poc_web/controllers/user_auth.ex | 149 ++++++ .../user_confirmation_controller.ex | 43 ++ .../user_registration_controller.ex | 30 ++ .../user_reset_password_controller.ex | 59 +++ .../controllers/user_session_controller.ex | 26 + .../controllers/user_settings_controller.ex | 72 +++ lib/{sbomPoc_web => sbom_poc_web}/endpoint.ex | 0 lib/{sbomPoc_web => sbom_poc_web}/gettext.ex | 0 .../live/page_live.ex | 0 .../live/page_live.html.leex | 0 lib/sbom_poc_web/router.ex | 79 +++ .../telemetry.ex | 0 .../templates/layout/_user_menu.html.eex | 10 + .../templates/layout/app.html.eex | 0 .../templates/layout/live.html.leex | 0 .../templates/layout/root.html.leex | 1 + .../templates/user_confirmation/new.html.eex | 15 + .../templates/user_registration/new.html.eex | 26 + .../user_reset_password/edit.html.eex | 26 + .../user_reset_password/new.html.eex | 15 + .../templates/user_session/new.html.eex | 27 + .../templates/user_settings/edit.html.eex | 49 ++ .../views/error_helpers.ex | 0 .../views/error_view.ex | 0 .../views/layout_view.ex | 0 .../views/user_confirmation_view.ex | 3 + .../views/user_registration_view.ex | 3 + .../views/user_reset_password_view.ex | 3 + lib/sbom_poc_web/views/user_session_view.ex | 3 + lib/sbom_poc_web/views/user_settings_view.ex | 3 + mix.exs | 4 +- mix.lock | 4 + ...0201022092015_create_users_auth_tables.exs | 27 + test/sbom_poc/accounts_test.exs | 480 ++++++++++++++++++ .../controllers/user_auth_test.exs | 163 ++++++ .../user_confirmation_controller_test.exs | 84 +++ .../user_registration_controller_test.exs | 54 ++ .../user_reset_password_controller_test.exs | 113 +++++ .../user_session_controller_test.exs | 84 +++ .../user_settings_controller_test.exs | 125 +++++ test/support/conn_case.ex | 26 + test/support/fixtures/accounts_fixtures.ex | 27 + 53 files changed, 2513 insertions(+), 54 deletions(-) delete mode 100644 lib/sbomPoc.ex delete mode 100644 lib/sbomPoc_web/router.ex create mode 100644 lib/sbom_poc/accounts.ex create mode 100644 lib/sbom_poc/accounts/user.ex create mode 100644 lib/sbom_poc/accounts/user_notifier.ex create mode 100644 lib/sbom_poc/accounts/user_token.ex rename lib/{sbomPoc => sbom_poc}/application.ex (100%) rename lib/{sbomPoc => sbom_poc}/repo.ex (100%) rename lib/{sbomPoc_web.ex => sbom_poc_web.ex} (98%) rename lib/{sbomPoc_web => sbom_poc_web}/channels/user_socket.ex (100%) create mode 100644 lib/sbom_poc_web/controllers/user_auth.ex create mode 100644 lib/sbom_poc_web/controllers/user_confirmation_controller.ex create mode 100644 lib/sbom_poc_web/controllers/user_registration_controller.ex create mode 100644 lib/sbom_poc_web/controllers/user_reset_password_controller.ex create mode 100644 lib/sbom_poc_web/controllers/user_session_controller.ex create mode 100644 lib/sbom_poc_web/controllers/user_settings_controller.ex rename lib/{sbomPoc_web => sbom_poc_web}/endpoint.ex (100%) rename lib/{sbomPoc_web => sbom_poc_web}/gettext.ex (100%) rename lib/{sbomPoc_web => sbom_poc_web}/live/page_live.ex (100%) rename lib/{sbomPoc_web => sbom_poc_web}/live/page_live.html.leex (100%) create mode 100644 lib/sbom_poc_web/router.ex rename lib/{sbomPoc_web => sbom_poc_web}/telemetry.ex (100%) create mode 100644 lib/sbom_poc_web/templates/layout/_user_menu.html.eex rename lib/{sbomPoc_web => sbom_poc_web}/templates/layout/app.html.eex (100%) rename lib/{sbomPoc_web => sbom_poc_web}/templates/layout/live.html.leex (100%) rename lib/{sbomPoc_web => sbom_poc_web}/templates/layout/root.html.leex (96%) create mode 100644 lib/sbom_poc_web/templates/user_confirmation/new.html.eex create mode 100644 lib/sbom_poc_web/templates/user_registration/new.html.eex create mode 100644 lib/sbom_poc_web/templates/user_reset_password/edit.html.eex create mode 100644 lib/sbom_poc_web/templates/user_reset_password/new.html.eex create mode 100644 lib/sbom_poc_web/templates/user_session/new.html.eex create mode 100644 lib/sbom_poc_web/templates/user_settings/edit.html.eex rename lib/{sbomPoc_web => sbom_poc_web}/views/error_helpers.ex (100%) rename lib/{sbomPoc_web => sbom_poc_web}/views/error_view.ex (100%) rename lib/{sbomPoc_web => sbom_poc_web}/views/layout_view.ex (100%) create mode 100644 lib/sbom_poc_web/views/user_confirmation_view.ex create mode 100644 lib/sbom_poc_web/views/user_registration_view.ex create mode 100644 lib/sbom_poc_web/views/user_reset_password_view.ex create mode 100644 lib/sbom_poc_web/views/user_session_view.ex create mode 100644 lib/sbom_poc_web/views/user_settings_view.ex create mode 100644 priv/repo/migrations/20201022092015_create_users_auth_tables.exs create mode 100644 test/sbom_poc/accounts_test.exs create mode 100644 test/sbom_poc_web/controllers/user_auth_test.exs create mode 100644 test/sbom_poc_web/controllers/user_confirmation_controller_test.exs create mode 100644 test/sbom_poc_web/controllers/user_registration_controller_test.exs create mode 100644 test/sbom_poc_web/controllers/user_reset_password_controller_test.exs create mode 100644 test/sbom_poc_web/controllers/user_session_controller_test.exs create mode 100644 test/sbom_poc_web/controllers/user_settings_controller_test.exs create mode 100644 test/support/fixtures/accounts_fixtures.ex diff --git a/config/test.exs b/config/test.exs index 76ca340..e94bdc2 100644 --- a/config/test.exs +++ b/config/test.exs @@ -1,5 +1,8 @@ use Mix.Config +# Only in tests, remove the complexity from the password hashing algorithm +config :bcrypt_elixir, :log_rounds, 1 + # Configure your database # # The MIX_TEST_PARTITION environment variable can be used diff --git a/lib/sbomPoc.ex b/lib/sbomPoc.ex deleted file mode 100644 index 8a4dd0a..0000000 --- a/lib/sbomPoc.ex +++ /dev/null @@ -1,9 +0,0 @@ -defmodule SbomPoc do - @moduledoc """ - SbomPoc keeps the contexts that define your domain - and business logic. - - Contexts are also responsible for managing your data, regardless - if it comes from the database, an external API or others. - """ -end diff --git a/lib/sbomPoc_web/router.ex b/lib/sbomPoc_web/router.ex deleted file mode 100644 index c41b9e8..0000000 --- a/lib/sbomPoc_web/router.ex +++ /dev/null @@ -1,43 +0,0 @@ -defmodule SbomPocWeb.Router do - use SbomPocWeb, :router - - pipeline :browser do - plug :accepts, ["html"] - plug :fetch_session - plug :fetch_live_flash - plug :put_root_layout, {SbomPocWeb.LayoutView, :root} - plug :protect_from_forgery - plug :put_secure_browser_headers - end - - pipeline :api do - plug :accepts, ["json"] - end - - scope "/", SbomPocWeb do - pipe_through :browser - - live "/", PageLive, :index - end - - # Other scopes may use custom stacks. - # scope "/api", SbomPocWeb do - # pipe_through :api - # end - - # Enables LiveDashboard only for development - # - # If you want to use the LiveDashboard in production, you should put - # it behind authentication and allow only admins to access it. - # If your application does not have an admins-only section yet, - # you can use Plug.BasicAuth to set up some basic authentication - # as long as you are also using SSL (which you should anyway). - if Mix.env() in [:dev, :test] do - import Phoenix.LiveDashboard.Router - - scope "/" do - pipe_through :browser - live_dashboard "/dashboard", metrics: SbomPocWeb.Telemetry - end - end -end diff --git a/lib/sbom_poc/accounts.ex b/lib/sbom_poc/accounts.ex new file mode 100644 index 0000000..1cdfa56 --- /dev/null +++ b/lib/sbom_poc/accounts.ex @@ -0,0 +1,349 @@ +defmodule SbomPoc.Accounts do + @moduledoc """ + The Accounts context. + """ + + import Ecto.Query, warn: false + alias SbomPoc.Repo + alias SbomPoc.Accounts.{User, UserToken, UserNotifier} + + ## Database getters + + @doc """ + Gets a user by email. + + ## Examples + + iex> get_user_by_email("foo@example.com") + %User{} + + iex> get_user_by_email("unknown@example.com") + nil + + """ + def get_user_by_email(email) when is_binary(email) do + Repo.get_by(User, email: email) + end + + @doc """ + Gets a user by email and password. + + ## Examples + + iex> get_user_by_email_and_password("foo@example.com", "correct_password") + %User{} + + iex> get_user_by_email_and_password("foo@example.com", "invalid_password") + nil + + """ + def get_user_by_email_and_password(email, password) + when is_binary(email) and is_binary(password) do + user = Repo.get_by(User, email: email) + if User.valid_password?(user, password), do: user + end + + @doc """ + Gets a single user. + + Raises `Ecto.NoResultsError` if the User does not exist. + + ## Examples + + iex> get_user!(123) + %User{} + + iex> get_user!(456) + ** (Ecto.NoResultsError) + + """ + def get_user!(id), do: Repo.get!(User, id) + + ## User registration + + @doc """ + Registers a user. + + ## Examples + + iex> register_user(%{field: value}) + {:ok, %User{}} + + iex> register_user(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def register_user(attrs) do + %User{} + |> User.registration_changeset(attrs) + |> Repo.insert() + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking user changes. + + ## Examples + + iex> change_user_registration(user) + %Ecto.Changeset{data: %User{}} + + """ + def change_user_registration(%User{} = user, attrs \\ %{}) do + User.registration_changeset(user, attrs) + end + + ## Settings + + @doc """ + Returns an `%Ecto.Changeset{}` for changing the user e-mail. + + ## Examples + + iex> change_user_email(user) + %Ecto.Changeset{data: %User{}} + + """ + def change_user_email(user, attrs \\ %{}) do + User.email_changeset(user, attrs) + end + + @doc """ + Emulates that the e-mail will change without actually changing + it in the database. + + ## Examples + + iex> apply_user_email(user, "valid password", %{email: ...}) + {:ok, %User{}} + + iex> apply_user_email(user, "invalid password", %{email: ...}) + {:error, %Ecto.Changeset{}} + + """ + def apply_user_email(user, password, attrs) do + user + |> User.email_changeset(attrs) + |> User.validate_current_password(password) + |> Ecto.Changeset.apply_action(:update) + end + + @doc """ + Updates the user e-mail in token. + + If the token matches, the user email is updated and the token is deleted. + The confirmed_at date is also updated to the current time. + """ + def update_user_email(user, token) do + context = "change:#{user.email}" + + with {:ok, query} <- UserToken.verify_change_email_token_query(token, context), + %UserToken{sent_to: email} <- Repo.one(query), + {:ok, _} <- Repo.transaction(user_email_multi(user, email, context)) do + :ok + else + _ -> :error + end + end + + defp user_email_multi(user, email, context) do + changeset = user |> User.email_changeset(%{email: email}) |> User.confirm_changeset() + + Ecto.Multi.new() + |> Ecto.Multi.update(:user, changeset) + |> Ecto.Multi.delete_all(:tokens, UserToken.user_and_contexts_query(user, [context])) + end + + @doc """ + Delivers the update e-mail instructions to the given user. + + ## Examples + + iex> deliver_update_email_instructions(user, current_email, &Routes.user_update_email_url(conn, :edit, &1)) + {:ok, %{to: ..., body: ...}} + + """ + def deliver_update_email_instructions(%User{} = user, current_email, update_email_url_fun) + when is_function(update_email_url_fun, 1) do + {encoded_token, user_token} = UserToken.build_email_token(user, "change:#{current_email}") + + Repo.insert!(user_token) + UserNotifier.deliver_update_email_instructions(user, update_email_url_fun.(encoded_token)) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for changing the user password. + + ## Examples + + iex> change_user_password(user) + %Ecto.Changeset{data: %User{}} + + """ + def change_user_password(user, attrs \\ %{}) do + User.password_changeset(user, attrs) + end + + @doc """ + Updates the user password. + + ## Examples + + iex> update_user_password(user, "valid password", %{password: ...}) + {:ok, %User{}} + + iex> update_user_password(user, "invalid password", %{password: ...}) + {:error, %Ecto.Changeset{}} + + """ + def update_user_password(user, password, attrs) do + changeset = + user + |> User.password_changeset(attrs) + |> User.validate_current_password(password) + + Ecto.Multi.new() + |> Ecto.Multi.update(:user, changeset) + |> Ecto.Multi.delete_all(:tokens, UserToken.user_and_contexts_query(user, :all)) + |> Repo.transaction() + |> case do + {:ok, %{user: user}} -> {:ok, user} + {:error, :user, changeset, _} -> {:error, changeset} + end + end + + ## Session + + @doc """ + Generates a session token. + """ + def generate_user_session_token(user) do + {token, user_token} = UserToken.build_session_token(user) + Repo.insert!(user_token) + token + end + + @doc """ + Gets the user with the given signed token. + """ + def get_user_by_session_token(token) do + {:ok, query} = UserToken.verify_session_token_query(token) + Repo.one(query) + end + + @doc """ + Deletes the signed token with the given context. + """ + def delete_session_token(token) do + Repo.delete_all(UserToken.token_and_context_query(token, "session")) + :ok + end + + ## Confirmation + + @doc """ + Delivers the confirmation e-mail instructions to the given user. + + ## Examples + + iex> deliver_user_confirmation_instructions(user, &Routes.user_confirmation_url(conn, :confirm, &1)) + {:ok, %{to: ..., body: ...}} + + iex> deliver_user_confirmation_instructions(confirmed_user, &Routes.user_confirmation_url(conn, :confirm, &1)) + {:error, :already_confirmed} + + """ + def deliver_user_confirmation_instructions(%User{} = user, confirmation_url_fun) + when is_function(confirmation_url_fun, 1) do + if user.confirmed_at do + {:error, :already_confirmed} + else + {encoded_token, user_token} = UserToken.build_email_token(user, "confirm") + Repo.insert!(user_token) + UserNotifier.deliver_confirmation_instructions(user, confirmation_url_fun.(encoded_token)) + end + end + + @doc """ + Confirms a user by the given token. + + If the token matches, the user account is marked as confirmed + and the token is deleted. + """ + def confirm_user(token) do + with {:ok, query} <- UserToken.verify_email_token_query(token, "confirm"), + %User{} = user <- Repo.one(query), + {:ok, %{user: user}} <- Repo.transaction(confirm_user_multi(user)) do + {:ok, user} + else + _ -> :error + end + end + + defp confirm_user_multi(user) do + Ecto.Multi.new() + |> Ecto.Multi.update(:user, User.confirm_changeset(user)) + |> Ecto.Multi.delete_all(:tokens, UserToken.user_and_contexts_query(user, ["confirm"])) + end + + ## Reset password + + @doc """ + Delivers the reset password e-mail to the given user. + + ## Examples + + iex> deliver_user_reset_password_instructions(user, &Routes.user_reset_password_url(conn, :edit, &1)) + {:ok, %{to: ..., body: ...}} + + """ + def deliver_user_reset_password_instructions(%User{} = user, reset_password_url_fun) + when is_function(reset_password_url_fun, 1) do + {encoded_token, user_token} = UserToken.build_email_token(user, "reset_password") + Repo.insert!(user_token) + UserNotifier.deliver_reset_password_instructions(user, reset_password_url_fun.(encoded_token)) + end + + @doc """ + Gets the user by reset password token. + + ## Examples + + iex> get_user_by_reset_password_token("validtoken") + %User{} + + iex> get_user_by_reset_password_token("invalidtoken") + nil + + """ + def get_user_by_reset_password_token(token) do + with {:ok, query} <- UserToken.verify_email_token_query(token, "reset_password"), + %User{} = user <- Repo.one(query) do + user + else + _ -> nil + end + end + + @doc """ + Resets the user password. + + ## Examples + + iex> reset_user_password(user, %{password: "new long password", password_confirmation: "new long password"}) + {:ok, %User{}} + + iex> reset_user_password(user, %{password: "valid", password_confirmation: "not the same"}) + {:error, %Ecto.Changeset{}} + + """ + def reset_user_password(user, attrs) do + Ecto.Multi.new() + |> Ecto.Multi.update(:user, User.password_changeset(user, attrs)) + |> Ecto.Multi.delete_all(:tokens, UserToken.user_and_contexts_query(user, :all)) + |> Repo.transaction() + |> case do + {:ok, %{user: user}} -> {:ok, user} + {:error, :user, changeset, _} -> {:error, changeset} + end + end +end diff --git a/lib/sbom_poc/accounts/user.ex b/lib/sbom_poc/accounts/user.ex new file mode 100644 index 0000000..a39b973 --- /dev/null +++ b/lib/sbom_poc/accounts/user.ex @@ -0,0 +1,116 @@ +defmodule SbomPoc.Accounts.User do + use Ecto.Schema + import Ecto.Changeset + + @derive {Inspect, except: [:password]} + schema "users" do + field :email, :string + field :password, :string, virtual: true + field :hashed_password, :string + field :confirmed_at, :naive_datetime + + timestamps() + end + + @doc """ + A user changeset for registration. + + It is important to validate the length of both e-mail and password. + Otherwise databases may truncate the e-mail without warnings, which + could lead to unpredictable or insecure behaviour. Long passwords may + also be very expensive to hash for certain algorithms. + """ + def registration_changeset(user, attrs) do + user + |> cast(attrs, [:email, :password]) + |> validate_email() + |> validate_password() + end + + defp validate_email(changeset) do + changeset + |> validate_required([:email]) + |> validate_format(:email, ~r/^[^\s]+@[^\s]+$/, message: "must have the @ sign and no spaces") + |> validate_length(:email, max: 160) + |> unsafe_validate_unique(:email, SbomPoc.Repo) + |> unique_constraint(:email) + end + + defp validate_password(changeset) do + changeset + |> validate_required([:password]) + |> validate_length(:password, min: 12, max: 80) + # |> validate_format(:password, ~r/[a-z]/, message: "at least one lower case character") + # |> validate_format(:password, ~r/[A-Z]/, message: "at least one upper case character") + # |> validate_format(:password, ~r/[!?@#$%^&*_0-9]/, message: "at least one digit or punctuation character") + |> prepare_changes(&hash_password/1) + end + + defp hash_password(changeset) do + password = get_change(changeset, :password) + + changeset + |> put_change(:hashed_password, Bcrypt.hash_pwd_salt(password)) + |> delete_change(:password) + end + + @doc """ + A user changeset for changing the e-mail. + + It requires the e-mail to change otherwise an error is added. + """ + def email_changeset(user, attrs) do + user + |> cast(attrs, [:email]) + |> validate_email() + |> case do + %{changes: %{email: _}} = changeset -> changeset + %{} = changeset -> add_error(changeset, :email, "did not change") + end + end + + @doc """ + A user changeset for changing the password. + """ + def password_changeset(user, attrs) do + user + |> cast(attrs, [:password]) + |> validate_confirmation(:password, message: "does not match password") + |> validate_password() + end + + @doc """ + Confirms the account by setting `confirmed_at`. + """ + def confirm_changeset(user) do + now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + change(user, confirmed_at: now) + end + + @doc """ + Verifies the password. + + If there is no user or the user doesn't have a password, we call + `Bcrypt.no_user_verify/0` to avoid timing attacks. + """ + def valid_password?(%SbomPoc.Accounts.User{hashed_password: hashed_password}, password) + when is_binary(hashed_password) and byte_size(password) > 0 do + Bcrypt.verify_pass(password, hashed_password) + end + + def valid_password?(_, _) do + Bcrypt.no_user_verify() + false + end + + @doc """ + Validates the current password otherwise adds an error to the changeset. + """ + def validate_current_password(changeset, password) do + if valid_password?(changeset.data, password) do + changeset + else + add_error(changeset, :current_password, "is not valid") + end + end +end diff --git a/lib/sbom_poc/accounts/user_notifier.ex b/lib/sbom_poc/accounts/user_notifier.ex new file mode 100644 index 0000000..0c1f70f --- /dev/null +++ b/lib/sbom_poc/accounts/user_notifier.ex @@ -0,0 +1,73 @@ +defmodule SbomPoc.Accounts.UserNotifier do + # For simplicity, this module simply logs messages to the terminal. + # You should replace it by a proper e-mail or notification tool, such as: + # + # * Swoosh - https://hexdocs.pm/swoosh + # * Bamboo - https://hexdocs.pm/bamboo + # + defp deliver(to, body) do + require Logger + Logger.debug(body) + {:ok, %{to: to, body: body}} + end + + @doc """ + Deliver instructions to confirm account. + """ + def deliver_confirmation_instructions(user, url) do + deliver(user.email, """ + + ============================== + + Hi #{user.email}, + + You can confirm your account by visiting the url below: + + #{url} + + If you didn't create an account with us, please ignore this. + + ============================== + """) + end + + @doc """ + Deliver instructions to reset password account. + """ + def deliver_reset_password_instructions(user, url) do + deliver(user.email, """ + + ============================== + + Hi #{user.email}, + + You can reset your password by visiting the url below: + + #{url} + + If you didn't request this change, please ignore this. + + ============================== + """) + end + + @doc """ + Deliver instructions to update your e-mail. + """ + def deliver_update_email_instructions(user, url) do + deliver(user.email, """ + + ============================== + + Hi #{user.email}, + + You can change your e-mail by visiting the url below: + + #{url} + + If you didn't request this change, please ignore this. + + ============================== + """) + end +end diff --git a/lib/sbom_poc/accounts/user_token.ex b/lib/sbom_poc/accounts/user_token.ex new file mode 100644 index 0000000..687c1eb --- /dev/null +++ b/lib/sbom_poc/accounts/user_token.ex @@ -0,0 +1,139 @@ +defmodule SbomPoc.Accounts.UserToken do + use Ecto.Schema + import Ecto.Query + + @hash_algorithm :sha256 + @rand_size 32 + + # It is very important to keep the reset password token expiry short, + # since someone with access to the e-mail may take over the account. + @reset_password_validity_in_days 1 + @confirm_validity_in_days 7 + @change_email_validity_in_days 7 + @session_validity_in_days 60 + + schema "users_tokens" do + field :token, :binary + field :context, :string + field :sent_to, :string + belongs_to :user, SbomPoc.Accounts.User + + timestamps(updated_at: false) + end + + @doc """ + Generates a token that will be stored in a signed place, + such as session or cookie. As they are signed, those + tokens do not need to be hashed. + """ + def build_session_token(user) do + token = :crypto.strong_rand_bytes(@rand_size) + {token, %SbomPoc.Accounts.UserToken{token: token, context: "session", user_id: user.id}} + end + + @doc """ + Checks if the token is valid and returns its underlying lookup query. + + The query returns the user found by the token. + """ + def verify_session_token_query(token) do + query = + from token in token_and_context_query(token, "session"), + join: user in assoc(token, :user), + where: token.inserted_at > ago(@session_validity_in_days, "day"), + select: user + + {:ok, query} + end + + @doc """ + Builds a token with a hashed counter part. + + The non-hashed token is sent to the user e-mail while the + hashed part is stored in the database, to avoid reconstruction. + The token is valid for a week as long as users don't change + their email. + """ + def build_email_token(user, context) do + build_hashed_token(user, context, user.email) + end + + defp build_hashed_token(user, context, sent_to) do + token = :crypto.strong_rand_bytes(@rand_size) + hashed_token = :crypto.hash(@hash_algorithm, token) + + {Base.url_encode64(token, padding: false), + %SbomPoc.Accounts.UserToken{ + token: hashed_token, + context: context, + sent_to: sent_to, + user_id: user.id + }} + end + + @doc """ + Checks if the token is valid and returns its underlying lookup query. + + The query returns the user found by the token. + """ + def verify_email_token_query(token, context) do + case Base.url_decode64(token, padding: false) do + {:ok, decoded_token} -> + hashed_token = :crypto.hash(@hash_algorithm, decoded_token) + days = days_for_context(context) + + query = + from token in token_and_context_query(hashed_token, context), + join: user in assoc(token, :user), + where: token.inserted_at > ago(^days, "day") and token.sent_to == user.email, + select: user + + {:ok, query} + + :error -> + :error + end + end + + defp days_for_context("confirm"), do: @confirm_validity_in_days + defp days_for_context("reset_password"), do: @reset_password_validity_in_days + + @doc """ + Checks if the token is valid and returns its underlying lookup query. + + The query returns the user token record. + """ + def verify_change_email_token_query(token, context) do + case Base.url_decode64(token, padding: false) do + {:ok, decoded_token} -> + hashed_token = :crypto.hash(@hash_algorithm, decoded_token) + + query = + from token in token_and_context_query(hashed_token, context), + where: token.inserted_at > ago(@change_email_validity_in_days, "day") + + {:ok, query} + + :error -> + :error + end + end + + @doc """ + Returns the given token with the given context. + """ + def token_and_context_query(token, context) do + from SbomPoc.Accounts.UserToken, where: [token: ^token, context: ^context] + end + + @doc """ + Gets all tokens for the given user for the given contexts. + """ + def user_and_contexts_query(user, :all) do + from t in SbomPoc.Accounts.UserToken, where: t.user_id == ^user.id + end + + def user_and_contexts_query(user, [_ | _] = contexts) do + from t in SbomPoc.Accounts.UserToken, where: t.user_id == ^user.id and t.context in ^contexts + end +end diff --git a/lib/sbomPoc/application.ex b/lib/sbom_poc/application.ex similarity index 100% rename from lib/sbomPoc/application.ex rename to lib/sbom_poc/application.ex diff --git a/lib/sbomPoc/repo.ex b/lib/sbom_poc/repo.ex similarity index 100% rename from lib/sbomPoc/repo.ex rename to lib/sbom_poc/repo.ex diff --git a/lib/sbomPoc_web.ex b/lib/sbom_poc_web.ex similarity index 98% rename from lib/sbomPoc_web.ex rename to lib/sbom_poc_web.ex index 140ed6a..1d8c731 100644 --- a/lib/sbomPoc_web.ex +++ b/lib/sbom_poc_web.ex @@ -30,7 +30,7 @@ defmodule SbomPocWeb do def view do quote do use Phoenix.View, - root: "lib/sbomPoc_web/templates", + root: "lib/sbom_poc_web/templates", namespace: SbomPocWeb # Import convenience functions from controllers diff --git a/lib/sbomPoc_web/channels/user_socket.ex b/lib/sbom_poc_web/channels/user_socket.ex similarity index 100% rename from lib/sbomPoc_web/channels/user_socket.ex rename to lib/sbom_poc_web/channels/user_socket.ex diff --git a/lib/sbom_poc_web/controllers/user_auth.ex b/lib/sbom_poc_web/controllers/user_auth.ex new file mode 100644 index 0000000..a29409a --- /dev/null +++ b/lib/sbom_poc_web/controllers/user_auth.ex @@ -0,0 +1,149 @@ +defmodule SbomPocWeb.UserAuth do + import Plug.Conn + import Phoenix.Controller + + alias SbomPoc.Accounts + alias SbomPocWeb.Router.Helpers, as: Routes + + # Make the remember me cookie valid for 60 days. + # If you want bump or reduce this value, also change + # the token expiry itself in UserToken. + @max_age 60 * 60 * 24 * 60 + @remember_me_cookie "user_remember_me" + @remember_me_options [sign: true, max_age: @max_age] + + @doc """ + Logs the user in. + + It renews the session ID and clears the whole session + to avoid fixation attacks. See the renew_session + function to customize this behaviour. + + It also sets a `:live_socket_id` key in the session, + so LiveView sessions are identified and automatically + disconnected on log out. The line can be safely removed + if you are not using LiveView. + """ + def log_in_user(conn, user, params \\ %{}) do + token = Accounts.generate_user_session_token(user) + user_return_to = get_session(conn, :user_return_to) + + conn + |> renew_session() + |> put_session(:user_token, token) + |> put_session(:live_socket_id, "users_sessions:#{Base.url_encode64(token)}") + |> maybe_write_remember_me_cookie(token, params) + |> redirect(to: user_return_to || signed_in_path(conn)) + end + + defp maybe_write_remember_me_cookie(conn, token, %{"remember_me" => "true"}) do + put_resp_cookie(conn, @remember_me_cookie, token, @remember_me_options) + end + + defp maybe_write_remember_me_cookie(conn, _token, _params) do + conn + end + + # This function renews the session ID and erases the whole + # session to avoid fixation attacks. If there is any data + # in the session you may want to preserve after log in/log out, + # you must explicitly fetch the session data before clearing + # and then immediately set it after clearing, for example: + # + # defp renew_session(conn) do + # preferred_locale = get_session(conn, :preferred_locale) + # + # conn + # |> configure_session(renew: true) + # |> clear_session() + # |> put_session(:preferred_locale, preferred_locale) + # end + # + defp renew_session(conn) do + conn + |> configure_session(renew: true) + |> clear_session() + end + + @doc """ + Logs the user out. + + It clears all session data for safety. See renew_session. + """ + def log_out_user(conn) do + user_token = get_session(conn, :user_token) + user_token && Accounts.delete_session_token(user_token) + + if live_socket_id = get_session(conn, :live_socket_id) do + SbomPocWeb.Endpoint.broadcast(live_socket_id, "disconnect", %{}) + end + + conn + |> renew_session() + |> delete_resp_cookie(@remember_me_cookie) + |> redirect(to: "/") + end + + @doc """ + Authenticates the user by looking into the session + and remember me token. + """ + def fetch_current_user(conn, _opts) do + {user_token, conn} = ensure_user_token(conn) + user = user_token && Accounts.get_user_by_session_token(user_token) + assign(conn, :current_user, user) + end + + defp ensure_user_token(conn) do + if user_token = get_session(conn, :user_token) do + {user_token, conn} + else + conn = fetch_cookies(conn, signed: [@remember_me_cookie]) + + if user_token = conn.cookies[@remember_me_cookie] do + {user_token, put_session(conn, :user_token, user_token)} + else + {nil, conn} + end + end + end + + @doc """ + Used for routes that require the user to not be authenticated. + """ + def redirect_if_user_is_authenticated(conn, _opts) do + if conn.assigns[:current_user] do + conn + |> redirect(to: signed_in_path(conn)) + |> halt() + else + conn + end + end + + @doc """ + Used for routes that require the user to be authenticated. + + If you want to enforce the user e-mail is confirmed before + they use the application at all, here would be a good place. + """ + def require_authenticated_user(conn, _opts) do + if conn.assigns[:current_user] do + conn + else + conn + |> put_flash(:error, "You must log in to access this page.") + |> maybe_store_return_to() + |> redirect(to: Routes.user_session_path(conn, :new)) + |> halt() + end + end + + defp maybe_store_return_to(%{method: "GET", request_path: request_path} = conn) do + put_session(conn, :user_return_to, request_path) + end + + defp maybe_store_return_to(conn), do: conn + + defp signed_in_path(_conn), do: "/" +end diff --git a/lib/sbom_poc_web/controllers/user_confirmation_controller.ex b/lib/sbom_poc_web/controllers/user_confirmation_controller.ex new file mode 100644 index 0000000..b71fbc2 --- /dev/null +++ b/lib/sbom_poc_web/controllers/user_confirmation_controller.ex @@ -0,0 +1,43 @@ +defmodule SbomPocWeb.UserConfirmationController do + use SbomPocWeb, :controller + + alias SbomPoc.Accounts + + def new(conn, _params) do + render(conn, "new.html") + end + + def create(conn, %{"user" => %{"email" => email}}) do + if user = Accounts.get_user_by_email(email) do + Accounts.deliver_user_confirmation_instructions( + user, + &Routes.user_confirmation_url(conn, :confirm, &1) + ) + end + + # Regardless of the outcome, show an impartial success/error message. + conn + |> put_flash( + :info, + "If your e-mail is in our system and it has not been confirmed yet, " <> + "you will receive an e-mail with instructions shortly." + ) + |> redirect(to: "/") + end + + # Do not log in the user after confirmation to avoid a + # leaked token giving the user access to the account. + def confirm(conn, %{"token" => token}) do + case Accounts.confirm_user(token) do + {:ok, _} -> + conn + |> put_flash(:info, "Account confirmed successfully.") + |> redirect(to: "/") + + :error -> + conn + |> put_flash(:error, "Confirmation link is invalid or it has expired.") + |> redirect(to: "/") + end + end +end diff --git a/lib/sbom_poc_web/controllers/user_registration_controller.ex b/lib/sbom_poc_web/controllers/user_registration_controller.ex new file mode 100644 index 0000000..e5574e0 --- /dev/null +++ b/lib/sbom_poc_web/controllers/user_registration_controller.ex @@ -0,0 +1,30 @@ +defmodule SbomPocWeb.UserRegistrationController do + use SbomPocWeb, :controller + + alias SbomPoc.Accounts + alias SbomPoc.Accounts.User + alias SbomPocWeb.UserAuth + + def new(conn, _params) do + changeset = Accounts.change_user_registration(%User{}) + render(conn, "new.html", changeset: changeset) + end + + def create(conn, %{"user" => user_params}) do + case Accounts.register_user(user_params) do + {:ok, user} -> + {:ok, _} = + Accounts.deliver_user_confirmation_instructions( + user, + &Routes.user_confirmation_url(conn, :confirm, &1) + ) + + conn + |> put_flash(:info, "User created successfully.") + |> UserAuth.log_in_user(user) + + {:error, %Ecto.Changeset{} = changeset} -> + render(conn, "new.html", changeset: changeset) + end + end +end diff --git a/lib/sbom_poc_web/controllers/user_reset_password_controller.ex b/lib/sbom_poc_web/controllers/user_reset_password_controller.ex new file mode 100644 index 0000000..fab56ad --- /dev/null +++ b/lib/sbom_poc_web/controllers/user_reset_password_controller.ex @@ -0,0 +1,59 @@ +defmodule SbomPocWeb.UserResetPasswordController do + use SbomPocWeb, :controller + + alias SbomPoc.Accounts + + plug :get_user_by_reset_password_token when action in [:edit, :update] + + def new(conn, _params) do + render(conn, "new.html") + end + + def create(conn, %{"user" => %{"email" => email}}) do + if user = Accounts.get_user_by_email(email) do + Accounts.deliver_user_reset_password_instructions( + user, + &Routes.user_reset_password_url(conn, :edit, &1) + ) + end + + # Regardless of the outcome, show an impartial success/error message. + conn + |> put_flash( + :info, + "If your e-mail is in our system, you will receive instructions to reset your password shortly." + ) + |> redirect(to: "/") + end + + def edit(conn, _params) do + render(conn, "edit.html", changeset: Accounts.change_user_password(conn.assigns.user)) + end + + # Do not log in the user after reset password to avoid a + # leaked token giving the user access to the account. + def update(conn, %{"user" => user_params}) do + case Accounts.reset_user_password(conn.assigns.user, user_params) do + {:ok, _} -> + conn + |> put_flash(:info, "Password reset successfully.") + |> redirect(to: Routes.user_session_path(conn, :new)) + + {:error, changeset} -> + render(conn, "edit.html", changeset: changeset) + end + end + + defp get_user_by_reset_password_token(conn, _opts) do + %{"token" => token} = conn.params + + if user = Accounts.get_user_by_reset_password_token(token) do + conn |> assign(:user, user) |> assign(:token, token) + else + conn + |> put_flash(:error, "Reset password link is invalid or it has expired.") + |> redirect(to: "/") + |> halt() + end + end +end diff --git a/lib/sbom_poc_web/controllers/user_session_controller.ex b/lib/sbom_poc_web/controllers/user_session_controller.ex new file mode 100644 index 0000000..49be4f2 --- /dev/null +++ b/lib/sbom_poc_web/controllers/user_session_controller.ex @@ -0,0 +1,26 @@ +defmodule SbomPocWeb.UserSessionController do + use SbomPocWeb, :controller + + alias SbomPoc.Accounts + alias SbomPocWeb.UserAuth + + def new(conn, _params) do + render(conn, "new.html", error_message: nil) + end + + def create(conn, %{"user" => user_params}) do + %{"email" => email, "password" => password} = user_params + + if user = Accounts.get_user_by_email_and_password(email, password) do + UserAuth.log_in_user(conn, user, user_params) + else + render(conn, "new.html", error_message: "Invalid e-mail or password") + end + end + + def delete(conn, _params) do + conn + |> put_flash(:info, "Logged out successfully.") + |> UserAuth.log_out_user() + end +end diff --git a/lib/sbom_poc_web/controllers/user_settings_controller.ex b/lib/sbom_poc_web/controllers/user_settings_controller.ex new file mode 100644 index 0000000..330e5ae --- /dev/null +++ b/lib/sbom_poc_web/controllers/user_settings_controller.ex @@ -0,0 +1,72 @@ +defmodule SbomPocWeb.UserSettingsController do + use SbomPocWeb, :controller + + alias SbomPoc.Accounts + alias SbomPocWeb.UserAuth + + plug :assign_email_and_password_changesets + + def edit(conn, _params) do + render(conn, "edit.html") + end + + def update_email(conn, %{"current_password" => password, "user" => user_params}) do + user = conn.assigns.current_user + + case Accounts.apply_user_email(user, password, user_params) do + {:ok, applied_user} -> + Accounts.deliver_update_email_instructions( + applied_user, + user.email, + &Routes.user_settings_url(conn, :confirm_email, &1) + ) + + conn + |> put_flash( + :info, + "A link to confirm your e-mail change has been sent to the new address." + ) + |> redirect(to: Routes.user_settings_path(conn, :edit)) + + {:error, changeset} -> + render(conn, "edit.html", email_changeset: changeset) + end + end + + def confirm_email(conn, %{"token" => token}) do + case Accounts.update_user_email(conn.assigns.current_user, token) do + :ok -> + conn + |> put_flash(:info, "E-mail changed successfully.") + |> redirect(to: Routes.user_settings_path(conn, :edit)) + + :error -> + conn + |> put_flash(:error, "Email change link is invalid or it has expired.") + |> redirect(to: Routes.user_settings_path(conn, :edit)) + end + end + + def update_password(conn, %{"current_password" => password, "user" => user_params}) do + user = conn.assigns.current_user + + case Accounts.update_user_password(user, password, user_params) do + {:ok, user} -> + conn + |> put_flash(:info, "Password updated successfully.") + |> put_session(:user_return_to, Routes.user_settings_path(conn, :edit)) + |> UserAuth.log_in_user(user) + + {:error, changeset} -> + render(conn, "edit.html", password_changeset: changeset) + end + end + + defp assign_email_and_password_changesets(conn, _opts) do + user = conn.assigns.current_user + + conn + |> assign(:email_changeset, Accounts.change_user_email(user)) + |> assign(:password_changeset, Accounts.change_user_password(user)) + end +end diff --git a/lib/sbomPoc_web/endpoint.ex b/lib/sbom_poc_web/endpoint.ex similarity index 100% rename from lib/sbomPoc_web/endpoint.ex rename to lib/sbom_poc_web/endpoint.ex diff --git a/lib/sbomPoc_web/gettext.ex b/lib/sbom_poc_web/gettext.ex similarity index 100% rename from lib/sbomPoc_web/gettext.ex rename to lib/sbom_poc_web/gettext.ex diff --git a/lib/sbomPoc_web/live/page_live.ex b/lib/sbom_poc_web/live/page_live.ex similarity index 100% rename from lib/sbomPoc_web/live/page_live.ex rename to lib/sbom_poc_web/live/page_live.ex diff --git a/lib/sbomPoc_web/live/page_live.html.leex b/lib/sbom_poc_web/live/page_live.html.leex similarity index 100% rename from lib/sbomPoc_web/live/page_live.html.leex rename to lib/sbom_poc_web/live/page_live.html.leex diff --git a/lib/sbom_poc_web/router.ex b/lib/sbom_poc_web/router.ex new file mode 100644 index 0000000..481d00a --- /dev/null +++ b/lib/sbom_poc_web/router.ex @@ -0,0 +1,79 @@ +defmodule SbomPocWeb.Router do + use SbomPocWeb, :router + + import SbomPocWeb.UserAuth + + pipeline :browser do + plug :accepts, ["html"] + plug :fetch_session + plug :fetch_live_flash + plug :put_root_layout, {SbomPocWeb.LayoutView, :root} + plug :protect_from_forgery + plug :put_secure_browser_headers + plug :fetch_current_user + end + + pipeline :api do + plug :accepts, ["json"] + end + + scope "/", SbomPocWeb do + pipe_through :browser + + live "/", PageLive, :index + end + + # Other scopes may use custom stacks. + # scope "/api", SbomPocWeb do + # pipe_through :api + # end + + # Enables LiveDashboard only for development + # + # If you want to use the LiveDashboard in production, you should put + # it behind authentication and allow only admins to access it. + # If your application does not have an admins-only section yet, + # you can use Plug.BasicAuth to set up some basic authentication + # as long as you are also using SSL (which you should anyway). + if Mix.env() in [:dev, :test] do + import Phoenix.LiveDashboard.Router + + scope "/" do + pipe_through :browser + live_dashboard "/dashboard", metrics: SbomPocWeb.Telemetry + end + end + + ## Authentication routes + + scope "/", SbomPocWeb do + pipe_through [:browser, :redirect_if_user_is_authenticated] + + get "/users/register", UserRegistrationController, :new + post "/users/register", UserRegistrationController, :create + get "/users/log_in", UserSessionController, :new + post "/users/log_in", UserSessionController, :create + get "/users/reset_password", UserResetPasswordController, :new + post "/users/reset_password", UserResetPasswordController, :create + get "/users/reset_password/:token", UserResetPasswordController, :edit + put "/users/reset_password/:token", UserResetPasswordController, :update + end + + scope "/", SbomPocWeb do + pipe_through [:browser, :require_authenticated_user] + + get "/users/settings", UserSettingsController, :edit + put "/users/settings/update_password", UserSettingsController, :update_password + put "/users/settings/update_email", UserSettingsController, :update_email + get "/users/settings/confirm_email/:token", UserSettingsController, :confirm_email + end + + scope "/", SbomPocWeb do + pipe_through [:browser] + + delete "/users/log_out", UserSessionController, :delete + get "/users/confirm", UserConfirmationController, :new + post "/users/confirm", UserConfirmationController, :create + get "/users/confirm/:token", UserConfirmationController, :confirm + end +end diff --git a/lib/sbomPoc_web/telemetry.ex b/lib/sbom_poc_web/telemetry.ex similarity index 100% rename from lib/sbomPoc_web/telemetry.ex rename to lib/sbom_poc_web/telemetry.ex diff --git a/lib/sbom_poc_web/templates/layout/_user_menu.html.eex b/lib/sbom_poc_web/templates/layout/_user_menu.html.eex new file mode 100644 index 0000000..f281cfc --- /dev/null +++ b/lib/sbom_poc_web/templates/layout/_user_menu.html.eex @@ -0,0 +1,10 @@ +
    +<%= if @current_user do %> +
  • <%= @current_user.email %>
  • +
  • <%= link "Settings", to: Routes.user_settings_path(@conn, :edit) %>
  • +
  • <%= link "Log out", to: Routes.user_session_path(@conn, :delete), method: :delete %>
  • +<% else %> +
  • <%= link "Register", to: Routes.user_registration_path(@conn, :new) %>
  • +
  • <%= link "Log in", to: Routes.user_session_path(@conn, :new) %>
  • +<% end %> +
diff --git a/lib/sbomPoc_web/templates/layout/app.html.eex b/lib/sbom_poc_web/templates/layout/app.html.eex similarity index 100% rename from lib/sbomPoc_web/templates/layout/app.html.eex rename to lib/sbom_poc_web/templates/layout/app.html.eex diff --git a/lib/sbomPoc_web/templates/layout/live.html.leex b/lib/sbom_poc_web/templates/layout/live.html.leex similarity index 100% rename from lib/sbomPoc_web/templates/layout/live.html.leex rename to lib/sbom_poc_web/templates/layout/live.html.leex diff --git a/lib/sbomPoc_web/templates/layout/root.html.leex b/lib/sbom_poc_web/templates/layout/root.html.leex similarity index 96% rename from lib/sbomPoc_web/templates/layout/root.html.leex rename to lib/sbom_poc_web/templates/layout/root.html.leex index fe78478..08d9e36 100644 --- a/lib/sbomPoc_web/templates/layout/root.html.leex +++ b/lib/sbom_poc_web/templates/layout/root.html.leex @@ -19,6 +19,7 @@
  • <%= link "LiveDashboard", to: Routes.live_dashboard_path(@conn, :home) %>
  • <% end %> + <%= render "_user_menu.html", assigns %> " + assert response =~ "Register" + end + + test "redirects if already logged in", %{conn: conn} do + conn = conn |> log_in_user(user_fixture()) |> get(Routes.user_registration_path(conn, :new)) + assert redirected_to(conn) == "/" + end + end + + describe "POST /users/register" do + @tag :capture_log + test "creates account and logs the user in", %{conn: conn} do + email = unique_user_email() + + conn = + post(conn, Routes.user_registration_path(conn, :create), %{ + "user" => %{"email" => email, "password" => valid_user_password()} + }) + + assert get_session(conn, :user_token) + assert redirected_to(conn) =~ "/" + + # Now do a logged in request and assert on the menu + conn = get(conn, "/") + response = html_response(conn, 200) + assert response =~ email + assert response =~ "Settings" + assert response =~ "Log out" + end + + test "render errors for invalid data", %{conn: conn} do + conn = + post(conn, Routes.user_registration_path(conn, :create), %{ + "user" => %{"email" => "with spaces", "password" => "too short"} + }) + + response = html_response(conn, 200) + assert response =~ "

    Register

    " + assert response =~ "must have the @ sign and no spaces" + assert response =~ "should be at least 12 character" + end + end +end diff --git a/test/sbom_poc_web/controllers/user_reset_password_controller_test.exs b/test/sbom_poc_web/controllers/user_reset_password_controller_test.exs new file mode 100644 index 0000000..e121214 --- /dev/null +++ b/test/sbom_poc_web/controllers/user_reset_password_controller_test.exs @@ -0,0 +1,113 @@ +defmodule SbomPocWeb.UserResetPasswordControllerTest do + use SbomPocWeb.ConnCase, async: true + + alias SbomPoc.Accounts + alias SbomPoc.Repo + import SbomPoc.AccountsFixtures + + setup do + %{user: user_fixture()} + end + + describe "GET /users/reset_password" do + test "renders the reset password page", %{conn: conn} do + conn = get(conn, Routes.user_reset_password_path(conn, :new)) + response = html_response(conn, 200) + assert response =~ "

    Forgot your password?

    " + end + end + + describe "POST /users/reset_password" do + @tag :capture_log + test "sends a new reset password token", %{conn: conn, user: user} do + conn = + post(conn, Routes.user_reset_password_path(conn, :create), %{ + "user" => %{"email" => user.email} + }) + + assert redirected_to(conn) == "/" + assert get_flash(conn, :info) =~ "If your e-mail is in our system" + assert Repo.get_by!(Accounts.UserToken, user_id: user.id).context == "reset_password" + end + + test "does not send reset password token if email is invalid", %{conn: conn} do + conn = + post(conn, Routes.user_reset_password_path(conn, :create), %{ + "user" => %{"email" => "unknown@example.com"} + }) + + assert redirected_to(conn) == "/" + assert get_flash(conn, :info) =~ "If your e-mail is in our system" + assert Repo.all(Accounts.UserToken) == [] + end + end + + describe "GET /users/reset_password/:token" do + setup %{user: user} do + token = + extract_user_token(fn url -> + Accounts.deliver_user_reset_password_instructions(user, url) + end) + + %{token: token} + end + + test "renders reset password", %{conn: conn, token: token} do + conn = get(conn, Routes.user_reset_password_path(conn, :edit, token)) + assert html_response(conn, 200) =~ "

    Reset password

    " + end + + test "does not render reset password with invalid token", %{conn: conn} do + conn = get(conn, Routes.user_reset_password_path(conn, :edit, "oops")) + assert redirected_to(conn) == "/" + assert get_flash(conn, :error) =~ "Reset password link is invalid or it has expired" + end + end + + describe "PUT /users/reset_password/:token" do + setup %{user: user} do + token = + extract_user_token(fn url -> + Accounts.deliver_user_reset_password_instructions(user, url) + end) + + %{token: token} + end + + test "resets password once", %{conn: conn, user: user, token: token} do + conn = + put(conn, Routes.user_reset_password_path(conn, :update, token), %{ + "user" => %{ + "password" => "new valid password", + "password_confirmation" => "new valid password" + } + }) + + assert redirected_to(conn) == Routes.user_session_path(conn, :new) + refute get_session(conn, :user_token) + assert get_flash(conn, :info) =~ "Password reset successfully" + assert Accounts.get_user_by_email_and_password(user.email, "new valid password") + end + + test "does not reset password on invalid data", %{conn: conn, token: token} do + conn = + put(conn, Routes.user_reset_password_path(conn, :update, token), %{ + "user" => %{ + "password" => "too short", + "password_confirmation" => "does not match" + } + }) + + response = html_response(conn, 200) + assert response =~ "

    Reset password

    " + assert response =~ "should be at least 12 character(s)" + assert response =~ "does not match password" + end + + test "does not reset password with invalid token", %{conn: conn} do + conn = put(conn, Routes.user_reset_password_path(conn, :update, "oops")) + assert redirected_to(conn) == "/" + assert get_flash(conn, :error) =~ "Reset password link is invalid or it has expired" + end + end +end diff --git a/test/sbom_poc_web/controllers/user_session_controller_test.exs b/test/sbom_poc_web/controllers/user_session_controller_test.exs new file mode 100644 index 0000000..9bf8319 --- /dev/null +++ b/test/sbom_poc_web/controllers/user_session_controller_test.exs @@ -0,0 +1,84 @@ +defmodule SbomPocWeb.UserSessionControllerTest do + use SbomPocWeb.ConnCase, async: true + + import SbomPoc.AccountsFixtures + + setup do + %{user: user_fixture()} + end + + describe "GET /users/log_in" do + test "renders log in page", %{conn: conn} do + conn = get(conn, Routes.user_session_path(conn, :new)) + response = html_response(conn, 200) + assert response =~ "

    Log in

    " + assert response =~ "Log in" + assert response =~ "Register" + end + + test "redirects if already logged in", %{conn: conn, user: user} do + conn = conn |> log_in_user(user) |> get(Routes.user_session_path(conn, :new)) + assert redirected_to(conn) == "/" + end + end + + describe "POST /users/log_in" do + test "logs the user in", %{conn: conn, user: user} do + conn = + post(conn, Routes.user_session_path(conn, :create), %{ + "user" => %{"email" => user.email, "password" => valid_user_password()} + }) + + assert get_session(conn, :user_token) + assert redirected_to(conn) =~ "/" + + # Now do a logged in request and assert on the menu + conn = get(conn, "/") + response = html_response(conn, 200) + assert response =~ user.email + assert response =~ "Settings" + assert response =~ "Log out" + end + + test "logs the user in with remember me", %{conn: conn, user: user} do + conn = + post(conn, Routes.user_session_path(conn, :create), %{ + "user" => %{ + "email" => user.email, + "password" => valid_user_password(), + "remember_me" => "true" + } + }) + + assert conn.resp_cookies["user_remember_me"] + assert redirected_to(conn) =~ "/" + end + + test "emits error message with invalid credentials", %{conn: conn, user: user} do + conn = + post(conn, Routes.user_session_path(conn, :create), %{ + "user" => %{"email" => user.email, "password" => "invalid_password"} + }) + + response = html_response(conn, 200) + assert response =~ "

    Log in

    " + assert response =~ "Invalid e-mail or password" + end + end + + describe "DELETE /users/log_out" do + test "logs the user out", %{conn: conn, user: user} do + conn = conn |> log_in_user(user) |> delete(Routes.user_session_path(conn, :delete)) + assert redirected_to(conn) == "/" + refute get_session(conn, :user_token) + assert get_flash(conn, :info) =~ "Logged out successfully" + end + + test "succeeds even if the user is not logged in", %{conn: conn} do + conn = delete(conn, Routes.user_session_path(conn, :delete)) + assert redirected_to(conn) == "/" + refute get_session(conn, :user_token) + assert get_flash(conn, :info) =~ "Logged out successfully" + end + end +end diff --git a/test/sbom_poc_web/controllers/user_settings_controller_test.exs b/test/sbom_poc_web/controllers/user_settings_controller_test.exs new file mode 100644 index 0000000..c51d08a --- /dev/null +++ b/test/sbom_poc_web/controllers/user_settings_controller_test.exs @@ -0,0 +1,125 @@ +defmodule SbomPocWeb.UserSettingsControllerTest do + use SbomPocWeb.ConnCase, async: true + + alias SbomPoc.Accounts + import SbomPoc.AccountsFixtures + + setup :register_and_log_in_user + + describe "GET /users/settings" do + test "renders settings page", %{conn: conn} do + conn = get(conn, Routes.user_settings_path(conn, :edit)) + response = html_response(conn, 200) + assert response =~ "

    Settings

    " + end + + test "redirects if user is not logged in" do + conn = build_conn() + conn = get(conn, Routes.user_settings_path(conn, :edit)) + assert redirected_to(conn) == Routes.user_session_path(conn, :new) + end + end + + describe "PUT /users/settings/update_password" do + test "updates the user password and resets tokens", %{conn: conn, user: user} do + new_password_conn = + put(conn, Routes.user_settings_path(conn, :update_password), %{ + "current_password" => valid_user_password(), + "user" => %{ + "password" => "new valid password", + "password_confirmation" => "new valid password" + } + }) + + assert redirected_to(new_password_conn) == Routes.user_settings_path(conn, :edit) + assert get_session(new_password_conn, :user_token) != get_session(conn, :user_token) + assert get_flash(new_password_conn, :info) =~ "Password updated successfully" + assert Accounts.get_user_by_email_and_password(user.email, "new valid password") + end + + test "does not update password on invalid data", %{conn: conn} do + old_password_conn = + put(conn, Routes.user_settings_path(conn, :update_password), %{ + "current_password" => "invalid", + "user" => %{ + "password" => "too short", + "password_confirmation" => "does not match" + } + }) + + response = html_response(old_password_conn, 200) + assert response =~ "

    Settings

    " + assert response =~ "should be at least 12 character(s)" + assert response =~ "does not match password" + assert response =~ "is not valid" + + assert get_session(old_password_conn, :user_token) == get_session(conn, :user_token) + end + end + + describe "PUT /users/settings/update_email" do + @tag :capture_log + test "updates the user email", %{conn: conn, user: user} do + conn = + put(conn, Routes.user_settings_path(conn, :update_email), %{ + "current_password" => valid_user_password(), + "user" => %{"email" => unique_user_email()} + }) + + assert redirected_to(conn) == Routes.user_settings_path(conn, :edit) + assert get_flash(conn, :info) =~ "A link to confirm your e-mail" + assert Accounts.get_user_by_email(user.email) + end + + test "does not update email on invalid data", %{conn: conn} do + conn = + put(conn, Routes.user_settings_path(conn, :update_email), %{ + "current_password" => "invalid", + "user" => %{"email" => "with spaces"} + }) + + response = html_response(conn, 200) + assert response =~ "

    Settings

    " + assert response =~ "must have the @ sign and no spaces" + assert response =~ "is not valid" + end + end + + describe "GET /users/settings/confirm_email/:token" do + setup %{user: user} do + email = unique_user_email() + + token = + extract_user_token(fn url -> + Accounts.deliver_update_email_instructions(%{user | email: email}, user.email, url) + end) + + %{token: token, email: email} + end + + test "updates the user email once", %{conn: conn, user: user, token: token, email: email} do + conn = get(conn, Routes.user_settings_path(conn, :confirm_email, token)) + assert redirected_to(conn) == Routes.user_settings_path(conn, :edit) + assert get_flash(conn, :info) =~ "E-mail changed successfully" + refute Accounts.get_user_by_email(user.email) + assert Accounts.get_user_by_email(email) + + conn = get(conn, Routes.user_settings_path(conn, :confirm_email, token)) + assert redirected_to(conn) == Routes.user_settings_path(conn, :edit) + assert get_flash(conn, :error) =~ "Email change link is invalid or it has expired" + end + + test "does not update email with invalid token", %{conn: conn, user: user} do + conn = get(conn, Routes.user_settings_path(conn, :confirm_email, "oops")) + assert redirected_to(conn) == Routes.user_settings_path(conn, :edit) + assert get_flash(conn, :error) =~ "Email change link is invalid or it has expired" + assert Accounts.get_user_by_email(user.email) + end + + test "redirects if user is not logged in", %{token: token} do + conn = build_conn() + conn = get(conn, Routes.user_settings_path(conn, :confirm_email, token)) + assert redirected_to(conn) == Routes.user_session_path(conn, :new) + end + end +end diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index a8f333d..76c2904 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -40,4 +40,30 @@ defmodule SbomPocWeb.ConnCase do {:ok, conn: Phoenix.ConnTest.build_conn()} end + + @doc """ + Setup helper that registers and logs in users. + + setup :register_and_log_in_user + + It stores an updated connection and a registered user in the + test context. + """ + def register_and_log_in_user(%{conn: conn}) do + user = SbomPoc.AccountsFixtures.user_fixture() + %{conn: log_in_user(conn, user), user: user} + end + + @doc """ + Logs the given `user` into the `conn`. + + It returns an updated `conn`. + """ + def log_in_user(conn, user) do + token = SbomPoc.Accounts.generate_user_session_token(user) + + conn + |> Phoenix.ConnTest.init_test_session(%{}) + |> Plug.Conn.put_session(:user_token, token) + end end diff --git a/test/support/fixtures/accounts_fixtures.ex b/test/support/fixtures/accounts_fixtures.ex new file mode 100644 index 0000000..f609a6e --- /dev/null +++ b/test/support/fixtures/accounts_fixtures.ex @@ -0,0 +1,27 @@ +defmodule SbomPoc.AccountsFixtures do + @moduledoc """ + This module defines test helpers for creating + entities via the `SbomPoc.Accounts` context. + """ + + def unique_user_email, do: "user#{System.unique_integer()}@example.com" + def valid_user_password, do: "hello world!" + + def user_fixture(attrs \\ %{}) do + {:ok, user} = + attrs + |> Enum.into(%{ + email: unique_user_email(), + password: valid_user_password() + }) + |> SbomPoc.Accounts.register_user() + + user + end + + def extract_user_token(fun) do + {:ok, captured} = fun.(&"[TOKEN]#{&1}[TOKEN]") + [_, token, _] = String.split(captured.body, "[TOKEN]") + token + end +end From ee311f3977d8cbd6e7cf201f12a88513de521c31 Mon Sep 17 00:00:00 2001 From: Duncan Sparrell Date: Fri, 23 Oct 2020 15:17:47 -0400 Subject: [PATCH 19/43] log connect/messages at info level --- lib/sbomPoc/mqtt/handler.ex | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/sbomPoc/mqtt/handler.ex b/lib/sbomPoc/mqtt/handler.ex index c89055d..d9613a3 100644 --- a/lib/sbomPoc/mqtt/handler.ex +++ b/lib/sbomPoc/mqtt/handler.ex @@ -22,7 +22,7 @@ defmodule SbomPoc.Mqtt.Handler do @impl true def connection(:up, state) do - Logger.debug("Connection has been established") + Logger.info("Connection has been established") {:ok, state} end @@ -40,7 +40,7 @@ defmodule SbomPoc.Mqtt.Handler do @impl true def subscription(:up, topic, state) do - Logger.debug("Subscribed to #{topic}") + Logger.info("Subscribed to #{topic}") {:ok, state} end @@ -58,13 +58,13 @@ defmodule SbomPoc.Mqtt.Handler do @impl true def subscription(:down, topic, state) do - Logger.debug("Unsubscribed from #{topic}") + Logger.info("Unsubscribed from #{topic}") {:ok, state} end @impl true def handle_message(topic, msg, state) do - Logger.debug("Found a message") + Logger.info("Found a message") Logger.info("#{state.name}, #{Enum.join(topic, "/")} #{inspect(msg)}") record_event(Enum.join(topic, "/"), inspect(msg), state.name) From 1f0b268cbb43b65933ed8cb6b83b28f25cc51dcf Mon Sep 17 00:00:00 2001 From: Duncan Sparrell Date: Fri, 23 Oct 2020 22:58:12 -0400 Subject: [PATCH 20/43] url config --- config/prod.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/prod.exs b/config/prod.exs index 6f99b08..d60f3eb 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -10,7 +10,7 @@ use Mix.Config # which you should run after static files are built and # before starting your production server. config :sbom_poc, SbomPocWeb.Endpoint, - url: [host: "34.123.139.249", port: 4000], + url: [host: "sbompoc.sfractal.com", port: 4000], cache_static_manifest: "priv/static/cache_manifest.json" # Do not print debug messages in production From 7180593400eae75b881f4a8e5786b91e792d1147 Mon Sep 17 00:00:00 2001 From: Duncan Sparrell Date: Fri, 23 Oct 2020 23:22:41 -0400 Subject: [PATCH 21/43] check origin false --- config/prod.exs | 1 + 1 file changed, 1 insertion(+) diff --git a/config/prod.exs b/config/prod.exs index d60f3eb..1c73ff1 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -11,6 +11,7 @@ use Mix.Config # before starting your production server. config :sbom_poc, SbomPocWeb.Endpoint, url: [host: "sbompoc.sfractal.com", port: 4000], + check_origin: false, cache_static_manifest: "priv/static/cache_manifest.json" # Do not print debug messages in production From b39c64720f86ee5a3297f41878902d21d34ab88e Mon Sep 17 00:00:00 2001 From: Duncan Sparrell Date: Sat, 24 Oct 2020 11:49:27 -0400 Subject: [PATCH 22/43] alternate mqtt start --- lib/sbomPoc/application.ex | 78 +++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 5 deletions(-) diff --git a/lib/sbomPoc/application.ex b/lib/sbomPoc/application.ex index 69f2c18..29e29e9 100644 --- a/lib/sbomPoc/application.ex +++ b/lib/sbomPoc/application.ex @@ -5,7 +5,62 @@ defmodule SbomPoc.Application do use Application + require Logger + def start(_type, _args) do + client_id = + System.get_env("CLIENT_ID") || + raise """ + environment variable CLIENT_ID is missing. + For example: + export CLIENT_ID=:mqttlogger + """ + Logger.info("mqtt:application:client_id is #{client_id}") + + mqtt_host = + System.get_env("MQTT_HOST") || + raise """ + environment variable HOST is missing. + Examples: + export MQTT_HOST="34.86.117.113" + export MQTT_HOST="mqtt.sfractal.com" + """ + Logger.info("mqtt:application:mqtt_host is #{mqtt_host}") + + mqtt_port = + String.to_integer( + System.get_env("MQTT_PORT") || + raise(""" + environment variable MQTT_PORT is missing. + Example: + export MQTT_PORT=1883 + """) + ) + Logger.info("mqtt:application:mqtt_port is #{mqtt_port}") + + server = {Tortoise.Transport.Tcp, host: mqtt_host, port: mqtt_port} + + user_name = + System.get_env("USER_NAME") || + raise """ + environment variable USER_NAME is missing. + Examples: + export USER_NAME="plug" + """ + Logger.info("mqtt:application:user_name is #{user_name}") + + password = + System.get_env("PASSWORD") || + raise """ + environment variable PASSWORD is missing. + Example: + export PASSWORD="fest" + """ + Logger.info("mqtt:application:password set") + + Logger.info("mqtt:application:Creating events table...") + :events_table = SbomPoc.Mqtt.Handler.create_events_table() + children = [ # Start the Ecto repository SbomPoc.Repo, @@ -17,18 +72,31 @@ defmodule SbomPoc.Application do SbomPocWeb.Endpoint, # Start a worker by calling: SbomPoc.Worker.start_link(arg) # {SbomPoc.Worker, arg} - {Tortoise.Supervisor, + + ## orig way of starting mqtt which may be overkill + ##{Tortoise.Supervisor, + ## [ + ## name: Oc2Mqtt.Connection.Supervisor, + ## strategy: :one_for_one + ## ]} + # trying another way + {Tortoise.Connection, [ - name: Oc2Mqtt.Connection.Supervisor, - strategy: :one_for_one - ]} + client_id: client_id, + server: server, + handler: {SbomPoc.Mqtt.Handler, [name: client_id]}, + user_name: user_name, + password: password, + subscriptions: [{"#", 0}] + ] + } ] # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_one, name: SbomPoc.Supervisor] Supervisor.start_link(children, opts) - SbomPoc.Mqtt.start() + ##SbomPoc.Mqtt.start() end # Tell Phoenix to update the endpoint configuration From fdfc2ae782fac637a2fd2124b1ab2b84d2f08fd1 Mon Sep 17 00:00:00 2001 From: Duncan Sparrell Date: Sat, 24 Oct 2020 11:53:33 -0400 Subject: [PATCH 23/43] debug in production --- config/prod.exs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config/prod.exs b/config/prod.exs index 1c73ff1..3cb44ae 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -15,7 +15,9 @@ config :sbom_poc, SbomPocWeb.Endpoint, cache_static_manifest: "priv/static/cache_manifest.json" # Do not print debug messages in production -config :logger, level: :info +#config :logger, level: :info +config :logger, level: :debug + config :sbom_poc, SbomPocWeb.Endpoint, server: true From cb40067462c57e68bac2b17543707ea2bc219eb8 Mon Sep 17 00:00:00 2001 From: Duncan Sparrell Date: Sat, 24 Oct 2020 12:23:33 -0400 Subject: [PATCH 24/43] /phoenix --- lib/sbomPoc_web/router.ex | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/sbomPoc_web/router.ex b/lib/sbomPoc_web/router.ex index ce07397..b8c71ae 100644 --- a/lib/sbomPoc_web/router.ex +++ b/lib/sbomPoc_web/router.ex @@ -20,6 +20,8 @@ defmodule SbomPocWeb.Router do live "/", PageLive, :index live "/events", EventsLive, :index + + live "/phoenix", PageLive, :index end # Other scopes may use custom stacks. From fac084e54729a74709ad167e415f52b9e5a4b41b Mon Sep 17 00:00:00 2001 From: Duncan Sparrell Date: Sat, 24 Oct 2020 17:03:04 -0400 Subject: [PATCH 25/43] enable phoenix page application hexdocs search --- lib/sbomPoc_web/live/page_live.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/sbomPoc_web/live/page_live.ex b/lib/sbomPoc_web/live/page_live.ex index 98d6c9b..2b40519 100644 --- a/lib/sbomPoc_web/live/page_live.ex +++ b/lib/sbomPoc_web/live/page_live.ex @@ -27,9 +27,9 @@ defmodule SbomPocWeb.PageLive do end defp search(query) do - if not SbomPocWeb.Endpoint.config(:code_reloader) do - raise "action disabled when not in development" - end + #if not SbomPocWeb.Endpoint.config(:code_reloader) do + # raise "action disabled when not in development" + #end for {app, desc, vsn} <- Application.started_applications(), app = to_string(app), From dd35da798f57fc4d108b47487e6ad610a8225c42 Mon Sep 17 00:00:00 2001 From: Duncan Sparrell Date: Sat, 24 Oct 2020 20:03:42 -0400 Subject: [PATCH 26/43] add home page --- lib/sbomPoc_web/live/home_live.ex | 22 ++++++++++++++++++++++ lib/sbomPoc_web/router.ex | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 lib/sbomPoc_web/live/home_live.ex diff --git a/lib/sbomPoc_web/live/home_live.ex b/lib/sbomPoc_web/live/home_live.ex new file mode 100644 index 0000000..fcd508a --- /dev/null +++ b/lib/sbomPoc_web/live/home_live.ex @@ -0,0 +1,22 @@ +defmodule SbomPocWeb.HomeLive do + @moduledoc "Home page live view" + use SbomPocWeb, :live_view + + @impl true + def mount(_params, _session, socket) do + #Phoenix.PubSub.subscribe(SbomPoc.PubSub, @topic) + + #events = SbomPoc.Mqtt.Handler.all_events() + {:ok, assign(socket, home: "whatever")} + end + + @impl true + def render(assigns) do + ~L""" +

    Home page view

    + stuff + """ + end + + +end diff --git a/lib/sbomPoc_web/router.ex b/lib/sbomPoc_web/router.ex index b8c71ae..1a36730 100644 --- a/lib/sbomPoc_web/router.ex +++ b/lib/sbomPoc_web/router.ex @@ -17,7 +17,7 @@ defmodule SbomPocWeb.Router do scope "/", SbomPocWeb do pipe_through :browser - live "/", PageLive, :index + live "/", HomeLive, :index live "/events", EventsLive, :index From 3ea5b984faaf789e2392d20b149e90980ebcc00d Mon Sep 17 00:00:00 2001 From: Duncan Sparrell Date: Sat, 24 Oct 2020 22:11:55 -0400 Subject: [PATCH 27/43] add dashboard into production, add auth later --- lib/sbomPoc_web/router.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/sbomPoc_web/router.ex b/lib/sbomPoc_web/router.ex index 1a36730..9b528f4 100644 --- a/lib/sbomPoc_web/router.ex +++ b/lib/sbomPoc_web/router.ex @@ -36,7 +36,7 @@ defmodule SbomPocWeb.Router do # If your application does not have an admins-only section yet, # you can use Plug.BasicAuth to set up some basic authentication # as long as you are also using SSL (which you should anyway). - if Mix.env() in [:dev, :test] do + if Mix.env() in [:dev, :test, :prod] do import Phoenix.LiveDashboard.Router scope "/" do From 9f424c54ca96a2ee921b78a46f3347f33e49183a Mon Sep 17 00:00:00 2001 From: Duncan Sparrell Date: Sat, 24 Oct 2020 22:58:20 -0400 Subject: [PATCH 28/43] home page --- lib/sbomPoc_web/live/home_live.ex | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/sbomPoc_web/live/home_live.ex b/lib/sbomPoc_web/live/home_live.ex index fcd508a..5c29532 100644 --- a/lib/sbomPoc_web/live/home_live.ex +++ b/lib/sbomPoc_web/live/home_live.ex @@ -13,8 +13,33 @@ defmodule SbomPocWeb.HomeLive do @impl true def render(assigns) do ~L""" -

    Home page view

    - stuff + action item - replace phoenic logo + with plugfest logo +

    Home page

    + Info on sfractal machines: + +
  • sbompoc.sfractal.com
  • +
  • twinklymaha.sfractal.com
  • +
  • twinklyhaha.sfractal.com
  • +
  • blinkymaha.sfractal.com
  • +
  • blinkyhaha.sfractal.com
  • +
  • vulnerable.twinklymaha.sfractal.com
  • +
  • +
    +

    sbompoc.sfractal.com

    +

    This is running on GCP vm buddhabrot

    +

    / is this home page

    +

    /events is mqtt log

    +

    /phoenix is phoenix info page

    +

    /dashboard is beam under-the-hood info for debugging

    +

    +

    more stuff

    +

    x.sfractal.com

    +

    +

    x.sfractal.com

    +

    +

    x.sfractal.com

    +

    """ end From ec4b0ce1c422080b03e7fc885312d64152d9e72d Mon Sep 17 00:00:00 2001 From: Duncan Sparrell Date: Sun, 25 Oct 2020 08:03:16 -0400 Subject: [PATCH 29/43] plugest image --- docs/Plugfest.png | Bin 0 -> 136054 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/Plugfest.png diff --git a/docs/Plugfest.png b/docs/Plugfest.png new file mode 100644 index 0000000000000000000000000000000000000000..7b1fa70c8f6c271e53ccca02f0974ca30200be4c GIT binary patch literal 136054 zcmeEt^;cBU`Zt1tNGT#ArGRvIV-V7*fOOXk-6(d01H3st<92pFqEL z?E;_ho!{%bVPO%F{`W4=i zO4OI0`X>Zu(DChiq~xq>E@+TjQP}70ThpWk_i>T?q*|=OWN)2tL7}nWs;&>*HJRo1 zlVgAV4o)JLSrx6O?X~;uaD*k-1r}eZFs$r{m+XDMu>%g?oBK_e)6A}m;_b0 znW&l<<9~m>x(hjEWBAXD>VID`{BI2y{MTOqUekbZee{k$0ks1q)xZpMW~I-1$Am_4+<0 zKYbK-ciqei%*({^u>3WQ)zQ5r)c)%_Ikc*^wDb=42H9H;n1`$&EkksSXr#d+|c ziBr;v+^4DO%iEWdbR@(PeVvP64Y9(_+-ITErVI?n=fX2oP;iz|CAgsWhUi!dT*!&D z8?5#X_Id0|GW;IPv9@<3VrJ`(YRwhb)se~i+k2ww)wiD$!uNE51wX(UV&Rg8bdJ~xN)B+(~Y&SkRJ8}be zg0QXkxL$S&M>x7)OVC~Ai>_6|`SuUe7ct~|%#i(oXG_i@DA7J#n$Xh|uf`i%C&V7( zt^+!d3*_I0-B%T1_q0Fp*&{RkDVN2(Y*j-@%ROM>A(?iW_iwn539j^bU&?=w6K0#} zhIVa2v>NN7~#@-vz(uQ`X}oX3-9={C{sQWK~2QM0_tGHd75V5#oE5^P|wS+ z4Bp|gln};#+_Z6o)ixIVr*O%~6@=)6f;kZk92}7X&$^6s?s4C}=B1w5M0abbO zQABCW%8n`t|DhMM+o?+zfAtx)Vj8ja69=n*f=_&kcwx{Ty7*?|P5fU)85HqOFlwrm z{o&_~C|i4X+?kngG0QB$w5;OFHs!hZx(<>XP_pMOV@4Fm{R zvBK1!JP~uC!c8Za#k^b+>a=5ZZ_UX$+)Q|&-}IOj=lLZ5=nDicOxR`4B{BTKU4#W^ z^b5`#NHdYbEYgL}q!#SlJWrOEynN=%%XKo)kmN=7-z(0B)-HfL?`K1r-neE`E}dbK zi(eg*SA(5rvZ>5e7fIh4+e0S4!caZ@T%e&T#OrY#Yb5|dj0V1wm-t{Q5URtchiexe z9P`$s19*DJaX-A77+if>{i7ly2P7ipEo2vcqiFbFAKV8(h!5T$Z%E|8R`EaNVZ#-H z8kq56m6MfSMgQmTBO~AA+Ge&8{s)fOyc+sgEtfFS|5`f-*(A6kORVtUm41}V;3O4B z{6vg&ddu-M@IUL>-q`h=S^JCk4ZLpV^yYxE0XI7!0dqP1`cyHgL%J!;k8Y;>go8SgWq7z= zS?zaerHI=BeFJ|rds>!Lc6S6)B&FI)KLTX+T7fz_MurPa_9Wrnqdeg4zhg=wZwT}g z>bP9_m}$V6*^Uu5MN}0)lbmjCxp>;gd*b)?x|6r(Cl<=Q8oT&-V!uQUy!mtjtcL4n zFpT2P;TiIF*7pItfeI0RYa6xkamsB$fiB<7=>P@&8?r=L4L+TZ8hG;Wh9h~a`cCo{ zybci&Q1eXa)gLEqC{fE!%jKNc)Src?G7BS5eEKJzJ5VY8ciC`F5%1)i;z*ed5Czxg z`CxbVzPO#h>p+>{*QPUh{VQVC^7Kn5m(Jqx#-ba0J!`Hg&%F5)pj=!;;}$)tIkQ+& z4^V3!7`5$N+0|7_%978VFxwGGWaLAQ+LolWDM4CoA%h55*BAV!>7p*A(d1mq*>3Av zdU_9EzkA2X({@Vgcd@rNYm--0(3bPPAJ&nY`uNoM(!qhcR6;^w*KIhRw4!nO(eja~ zfX&E{f`Xj6xlg1=_v2-5XV`*TBUW6S4ll2WeWjdngF#kTKq8XGG~P@D zYw0W+DSM^Y)m*>xv$B#UMJbk2v7R$phdqT(vr64Hu4-tl@8BXKCkNK^ z^=Z>us)6ksqDRULsj8|y?VlqGgz-TSnv4@ z`kntB8ygFTZ&>WkxPayx6H-&jNxzDQo6($C8>EgzR|=9wXE1g{taWT6bM>BxJ^Ihv zT^cE;RWRJ3dU(HayQH-7<{XhB>cT)AfkPeHyPUq>rCnX9#ilh#1_dXjrNLxwCS+>F zWb)1>f@JF|;@YOVu)Mmu!#Isw(=}MXAokQu_MJr=*E35MPS?1G80g}YB3bm>e1#r7 zcwlK2Hq+ole|C1ZJ69jAw>twN!uU&%ifzzvx9swBx1I7At7a(~7)TTqy}FNmZ`8zD zIP$FT_wi>VR(RjQ#n<2`mhE=7{wiPG7r^f2d;{1oTo(eMA- z9=3wv&X#La2?0@tM>VzC+k-5Zg zHRd_e%T_Em5`Av6Uhhr%`Spu|pamB^wh4v|m73M%Ui8f^4B7<+Lmd%nOr*dUGf$Q2j~IC^^zKx41pXcSQ&Z!5yNA3@DXnY|FDX%)cN9srs3xwr$@hbxJEY6xr0&zLXy>Ee z=)ocCn`9Qug;$O1Bs)#`8yj5~lbfKs_|Z|d-vQFnd=*h;y%dSaslKx5#h!YIOV6Hm zc-QEbz|05DzQ6UAM|)G&xga|#s48dfk5U#j7qg{Ec-X)jVSEJ<{2&?|(O?0Z-nCc( zW||+YyS-}-gU7zChil8Ol-@LIN+Flt+1%M`c;rjYV)&v`g6B{iVg2yg*^uJgkGo%z+9MSwZUfEva5&aqQXMVDT^+Iz@MiB92%%#HuQ3XEeycD3I}mB% zAe{;E>*R5lmA<3AyUV;7Y7x(wwN$I4luG~0ZhthF9lPU~omZgSgLb`_hL@X{^+)Vm>lA=cSh!&y>VdU<=% z0dI7%z>|LqH|Yc}kS-G>eRoxP$G^?GGpsLAtr87A_w<+MnVp?2faXIQ(nhixcpauV z`*dUbH%{(-TXRmNeKfBBF%HiEum~hs(E3dg$2Xhqs)YIRVpT@zVypv@4xK!}rAdttJ@6aEAAV4niz#?goE;R^BN00CY#ntn@} z8}}zge9d_xnV#cw2xX&w;&Z6N*1^%YUHqlZizjuz)t1MivIGA!Diw~Z;{&p(1d8K- z&NbRkDgj0A<8$eL;qJC4G`)Os*?6&td>kv^w2=#pZx41iqlzbQ8XFoS;^K&Di1GX` z_AS<9G890e$O9H09+EVK>YF$B0s@{aE!hzg!T`*zrKQykZV1Q${+`ZnckBt{_laWF zl~IWU%f(hV1)aE?eXow8zF6vsyT$eZ>NI0tw!GWZyRI#ohrfbfe^w9JrjP8mn7^v8 z99x(a0?{Ke`(BrQB91oQXeE1ldtlIX@)8p+Gay~YRbuG zXED~j?h{jUxAzY*@4f4W!g2;kR5vh`vr|B#yr({{+U<`XJwgvCNK4wI@p0c7x(*i2 zquZ$?kOY(wpy0mCpxUEHEVvo_YYI&Hp$luM_2bxbJ1s zJMT8ywR5KRL0?f(aWE3gq``)SL$^YbSIL1FJjF@we-vHUP;Z71_BcDUw6Td751E@9 z?+yxBp$0AJN88zd(Uwnh_I%1^%cA$h%-$#RLCS~hJP+x$QGa$(H;CoN^2_Ogg1M~z zFpCoOW_nm1X%XLIS4o?JPm?E0EN0u*vHIwg{At~gx>u3{KNd)I)ZEJTTnkMGVDFG3 z<$NB{($fCjpM_m{IQX#TE;T2MEuUX3 z`tcY*L2Cpi=(o+E_H7dfnSh;s(RBDDTCd|)$T+}*NF?Bp89Vre2k>|)D2NPr>?v`9 z>sxn!!3T+I7?Cd>$Q<5tY&{A$>x~V6zUS^=EL5`)ZuTuNuir)nqo3=y@8h{Y&$sJ4 zR8z$n9n$@lSv3=A{Z;@d(b3h7f0(CTtg;Rdx+DOGE*3yNnN`v|>+B}5W@@Ym!sO)0 z$jM@C6^x8%gG~<`LpK!3@ls(`6L)S`8K+MN_n2EsvfTRc^!0>te7e}JH4dTs*W@V3 zfWfHPhc*A=ZCB59aGAqGFGq_=bzuLexvY1Vazidu`jD1i5gKn^Q5|~TUVn{@w44ul zun{k=^pMwUpXSFH>j)PYuu$(95}3%N$N$W{_c*&hDz!l~RTdbwo@$->NXd4HBG5WwDG`lBA zN$83SqbP>i7#q_y1l&Lw!{=AbC~+qs>Kg_0H=B_jmHmt|GI=NK@Qq(Ac}xlK>27dY zMqcE){>1&Q&%U+US2ho?(|6>qpc(2F)8&sHo2Knp5c@nh`j$D3%vF2vvQ@0%>jzZ> z@BHF$k#kwzi};ra$>V12goez2`)=TgN;>at-xc0l47ua+bewWo4YL()2esH^8<;o%!OUZ+4MLMc_S1wY4#p ztXv1Gc^zN*Ak+A<^MBH-gjA&75Lag8XtVcSO6_zf3H= zee(JrS6GdtA>OD8LO@lWoOr7BVnRZ&v(;FhvZxg{Hm2w18hh@~_1@mleu1TUx6vgI zlC@Z9e%jd?bOb{xDlZ~aJV+pw4QV?3ay~u}Hby1VY=e^DGre_mBo-E)MIA;W>gXOe zcbR^3sBByB$^Bfw%FVrAQd+S*4Ls5>7kpl$ppudjGU>HOxi&D`+Qa$s6uY9_pF)}H zVwC2uFyTK652`tIw)1`zJxUMHWNY!U#BgvTkFf(VN&|e%9agF}@MN(WS9#6e{# zOZE8c<{VdCR1|h~DQufRTh}g|xfZ;Q6Z6iIgS0dq6BkVa zOxu;bR$cTl(I=qDssh|SJhU}6yF8|ihcYJ}W?HQX+S=NHA8MK)U$dwD0O*P`kJ0Z} z%BhD%JON)zO4u1vm5>Vp7t-u}Vp}bmklJ z?3hnAspDo(b9-k8D_z4#%DyXC+iHC{V|8^k_i&Gv7;h+*i;;#{TVG#{Hzes+B8(`d z_O0$4q9R?9lX4R7^@?929Nu*1hkxZADXnhU|45SjFz>Bu`g{;JoU&lp)1eEVMJmrm5# z&a@kb*6Z*x2qQUWO9mN|lcb|}B_0V@s@<9H=!*}!W(0avxS7T$t+%|ClHPf#y^C#r zb|BF6k0{|M>M^Vpf5+#$ODijSS6nO*OU{)49)8G6GvUV%H8eHf*lgTB4a{Xx&+U1p zYuE+QxY=efwSdjA=;O^DHgOjK6trJIlZ_ls(dW*P0MdVjgFfh#&U-&SIHK2S>p4ROioQb?4zchXaM?L zd%N-6+}t6?AG83CO`ZBkZtUFkb24q0Ea~WwhWi*HUAX z30zZrZqK;dXq~-p{ad0(g4zGP*G!cQWFK;K^XF+8->gOk$jt@jhuE~ozf!25K z32SxHNOki?1hQw4mz9P}(N_W@@1+ zhVYv1rSs!jCwKiN#p!30Hb?(C<%KpXChPRyf0K9pj zLVJMeI-v8G`4WJGCug17Ri}k>ppRArYU9>L>UxjJc2DXWDyLrsiW|XfbjeK$cj%cN zrgS`aS3pfUfZBcQ17_fmfnOThwK)b(Z7C9t9XZt&{iKh=(j|RJlUUTv`{Q!TjBCR) zGig`X*7$tJnf}XN3VoOF(*^9ha5o>mJwA5*RZ_CLl7|*GX*v4{^giCl#6++c*(tpb zD6-Y}zttz*jIm-Q#CZurkB=XXN;m~x1uQNusu>5;5l3`Y7)dnU-C}ri1x zFg;rCRmqUdP)uT`MG`PWrr8M3F>YS2y_3?8rR@pW?sZ3&MC1x5-jaeMBHFT_@6u0< z16P9L`lqDi<8~g=M9_UE6$=~f=HC0^k1Tdtl$Bg6Fi!N%dkr-h==x0e}hsd7A*PG~4PU5HEejda>Xo z0|-i3ruxiB-kfdf@%_<^WDG4lZ;{6v_!k#Xcg4EL@^Fs5rnEYIg)DZcBP9q`I%L{L z$-*~c^(03}b0jWz7~{Vs<%FVm0iwe(ivocV*2s42^F2hw#8!_pCDSr~RCF{O8`V1t z3&zUU)+k%S-|>N`jK%7C;Ruf@Pu)>=VTdOb?6uEb(Iy`4^bz^_K=i^;7a3+XtMeh( z`(;^e2J!$>SokFXbBTM^9~5p6moy=kD&_9tNiR_>~xZ$thNhlv8OORvDn;} zxq=q>*cQY?p!(Na+W4tz630KS9N=RY7fAIM?~A|h#aZdN`~z>s#zHonWA`)}o)DxB zg~3pil+UC_w#q72{_gW+3VNH;N>&k*t9_;qGBwRaBND(cTJ_HIc$%AfscdLFs;j1! z9#|QLj~~hD;x}T%9=^261J(nFWFFq^v4ftQZtrVZJmYqCtr>(5t!Q~p! z9|}p>dwcB7o&K!qU(r1DM~F8emn%ByQd0{V-O<<{9FO`&(SXo(Lu&~(lbOkre z`B}pjN^#{!)a%o{x-OA*O*;qTK5#>d;MXq}E+r;1$o@9-C#nBpc6{T@o?aiHm=32i3MTLxb@cZ?P&SW-i z@9U%f;NaKKABC~9QTa4Sn(_`r$Xvf{ZfGfPP=l&y1^NIo0jpvsOcwGwb82eJ43ibK z=ws-PlH0-@VQ&1F+lJBw{5*ZLWEr{^+f=uL3{vF)c^>8bm@v#)lu$*WH|iOOD6oUr z*tojtI4c^j`9GHXW@KjO08$XjwaMG;l7Qvbd{F=8{-)`&&w{_hI3$k4yYDIUP}=m0 zyZA$!CKtbKLE&@Mk?60V4|C2#Cv1KMo0}B@t=w0 zA4I{lZ_L%Q^F(Dh9(TjUdT5e;x*aE^0}^X#lbDO+ppqT_hD~ERFy+K8MDl43^kF!Kr~IUaCRwI`kEM?oCUBda#6MvC6#gVhyB&1R&(Z4i@u|4Jn^ zej#lLw&+=ry&_huxjHcdMLoSBR?(#Yy;r68u_;BYZ-VKERJxJ%)qG&s>zBM-SQyDQ z$*G2zRLi5tfUMN6sd9s_z2*Q0L!DfbNn1rG8ThYzid`NYyQEJP|5=zHz7TdSlqP@0 z!V-Zw=!hT55~*HIRQ{Q(F#^EifsqlQXm|m_1vHq(x=p<1F5Yyxo^=VM-?tdaoD>um9-p3$Mjj}ebl9Ta zl5-h~?s@{Y6FTy+$@|EBA29x4~6iHWg`y35z>k@fW$`J=k22UcdJS+MHsp9q5;Svbg+j)#8# znym%~id-Sm+zb4rrsi?PmTT+ErN1c>Ut>d-XAZJX!J&mTk%hR*%59 zZ(sz}Js_E4yW(g@z0?%xZmEHt5UMpt!vIIm3#zhBX>Y%H#y4MUi5n0(+#XWb=K-C@ zDsE3PKT5r;)|8%;uEFMd;zo_ZN@J zr-up{d>ZuPVv`$Qk(CwT^4i&hmYw3SV*xQHc}t*Jz;Rcv8^z0=#v!$EuFd&!)U3MnxY4n}NBK*ta41{SqruU0UPsW&gh)lTxX|5QAX#Oq@7%a@ zp$S^n`{Hu!Y0x-^Bq_$v|MPV^j50kyvwL(vEh_uvqKE_CMe8xC&*Dye;EEqk+CZU{J@v&8MPvCYz}@_Tgy1p+!aG*kd=nIAtGqN1W6hQ0M}GX@AbAgcoYsC3?R zr)qpWiy5uI{f|_71Qd|kWEq0(G7E4!OnKki*|CY$!`^k8J{#={VSR_QsWE7o=*&MT zgQi<)X_4Ut^^{igL{lI^EF2uk+%p27sN2yjGoJ6ex?dG}aC+W+T@Pr}OO<0KV~~)@ z0&V~p*aN?Rcki4Pzw`F;61mfwd42tir&OFcu1EOn!R3|q%YE;QMfak*d_Y?7GJULW z>fK`fK)9N@2J3U2jx<67JGrj@2_ddR4s%Pb$C5iQ799mAr``I|T&S6(6-lcwV4RJQ zYyBP?q7tws1S;1?1^p#-58!omdYv!vj)`EMC|&@v0Bw-SkB)PQAw?-cg;@+f-J^$e zLR+1TxEB)B1()p+A4jA}`7eds&)3-e0)v3xG4W}DN=oT#Zg4)tzgyJSp0~AN^xwZl zrG-i1--4GJnKBzDo<^JLf4n*oLsJpqhI&i>yL`g?KeMxgy4?oo)mk|{STioJu>6%k zrV_2|s@&p{+Ij#8OYAF?h|H;oCv_px2ar;KK%wLi*q~LK5x};Vp-%JiW^Z0jPCmUn zh1`*xY{02KK8Dz30)!<;!*8n0c%^P{*LkhOmYlT!A;F&J_hyM}$NX@a)S=p9 z{t*#Z=tzdSiCc*7H1u$|mZ+|dunhCarm1nWo1a@>OGRIw{9U|)zHnWA?@W7JXiiJ> z=ANC!RGELV3R^*=t!bY;U{G9MUJ42c*L?q;`N4hr5~eccE%$}KF3zwP@8K+>X(uVOGDs(myN$WH>z?cX*~RvrXqBn|P(neRkbzo076 z$p=P9*Gs#IrO|1D;>&oD7^#lROc95?R}y|aVPRog1(?wIu`PFViE#Ci%;z&*;kUCr zd%;`AmHU;}@)&YgH#gv9z&iygid3%^8}DcGC!IUMK4D{H%de{9rEMQAd@B&xArtVe zU=r7uF0c)T>RfY8OiNSn@DS=+>fAhBs+;J#cqd6`qa>;J9i`gde7mqeSLj>+Vw3vJNtCQ%~@7DMF{{PKo>HE)}}x%X!x(}^291zvI7V^!JkBP zZ~;UGi(Z}so}3^zOuhXFNK!r9g!j$oK_k-+R}h%K28(Zb42*Y4O+RrNRm_QuJH1b`f( z%4x=~zad**fYUtPal4id1v}bVpYP88{rmS@WPf9OMR40ld0n1Fnx5H90t)UQMMYvp z&hHoX8S=%Yc`Y7^(O`Z_UtKY@-d;Jny0+fGQJj;Q`&Fu}rMKC?Rpqnik)=0W_=6$Z zQu0kuURE-~Qnx0>M5ujW&Q>Z6n#Ue=&lm>3y$z%T8TZo1rd@)1*El(Hqo+k{n};ep z7W+u{{ZnWqT7H%g3OItWAh7R6^=Wr)4n!nUyDJlU(h;SLA5!SH0<6xA1CJ*>c4sG4 zU)WA8OuohBNQl{-Q??(5by!@TDur}m$;rvNySx8EF7)?Kx}lLNPT4wWGO@oIXLjQF zL^%b9Ge+;mRsL0imDQ_f&z@~1{OtP1f2trVAwfM<)40-R#Ci87@%%RUoA$ar7IB<> zMzPp-GFu)z0)RjwUT6}`(tr&s*^jca7@+ai)YdA*po#Vc65cPdsU5+HU>8Voml_*5 zoxe2wt5>hkH?Zl;>(#Jew>aXnidKrPE!%FO`fF?1I5-MQN}>Sc?NqTpBA0#)3II5}15--{+qNfVPt)_}88HI-V#X^4So z^DjV?Et)Vtk6K&8Lz09R_^k9d91nqS1W)NCDXUsU@&Yg)6Y}x^uCAv3N+x^650#}( zEZMIhe!xW|I`U^dxP#{wf6ni81)kK}S-#41SiEOYLLMFa1@1=Drur9$6pB!bb<}R+JYN7TzBc zoWQFJk76O+I!FX04|V_BlRQ8%T5UYQICBmy|1+8Z^{c<`rXUDIEwXU>l5~(Mby~qp zQcl#aX3iM^x?O;saa?M06J^QobDA@#&mz(hzw>*;j77y+A`YEJ7p?zycV3-$$$CBJ zZEirIh`MAG0OMFUMmQLsQ=|6?@8`%C;J4DTuyrK0>qVu?vLK!OvsI;3TN}LTrsFb( zcFRJoR&~7&)>%B@hkH`-V`)*Y?*=7ZbAn;ewem!zSwK5ZJMcevCVp{o(rduIv~ZC5 z86kC;WrxF|E9~4aVzRy=6Z9+sW_{cA3fKlC7ws4P0SQbE0ecMVqijDKMEdCW{ZjL8 zu6eF68iL?CGU$%`p~0tEveUO}%n?JZCzTLL2a);`I{tOu(l)l(P>vAn!I)-A^Es0w zkTv0@ECi&o>uZ02dO9{xLnbn$U%{6000nQ)Q~T57B{==TszvQK+PPQ2FuB%o=J^OL zXE>18pVsjdY+5*!LX01A>(gcoSXclu3CT{#dB`Ee`wCiF=_HG#rhj-s5#e;;#hkG_ z_l=Hi1P-?W;)OtIkd%!`R!zBWp75eu0Xyz({$u*qPUSc!Zx&NIjE?8D$i&>765tt* zq2g&1S&WFIGj2m^>vMG?_oU=b&(5BFm5uCQ+3K(H;Q`G_ROP^}_-1u+rVc5*oagqI z+{Dpd%n#H>(SelyBML2xytt!&zJ-90`_FIH()b3?K1L}}Tn%FZaZe~z7|H>*x10uAZ;_L(YHu4%VMdA7<72QG6r z&*p%9pNXBW32P6GKkyOWV@*2FXI*1VP@*{(SrFtBm%#W0UeX2Lo=kh&$w_5F>$E;( zC@U*}X}!i8;R@(6XKOX4xR)1Q_6-kKh3~ykCw}hcb>b>~A$*j}w{bX&pGHEEi&YDI z)>`T;tPhRo*f&tHXiW;_c%#7H-EJw8fOC^LY1D!q-Dg3&o%nvzYU|lUb#w`T>-ixz zHgb?gV5Az6Fk!mC>5^0X`aF0suM0o|$S3ymp;9)G1A1M;>Wq+K$cX$&LpeOnd&g z%C|u^(31d|^+0tJ6RcLhBi57Pr8;n67@Aafvj6UO>I)|$ms>2Xtc(X}BeC5($UOJ2 z?V`%k2e9XXbt8hr9}%>iiSEMGgw+7}O1wr*zXI`$*(Og-ef$TS_H;7I{dYwU5t9W6 zGOKF*LXa@d0)n(jg`nT6HVp5XjX)`8#Gn7oMM=Kh0d|63Xr8w`ydahTj>PALrQMLAjg{`oV?c6De}x{8;^LlDt+} zy2d^a@-Q1g>v+h!z~=FD4M6$T(*sgSU!J5L%v6W^1^MxO?RmX1x#RrU&Jh)7;7G-n zWyK1d_7N6&`kwi6Y_FmAuv<o-tR_4;O zrL^SfwU48CNy*tD9y4DXekBj~iJTwz6_cm7+3@p}&A?*pVQ~EZWi_3prkA%U}E&v zvbl%ZI>uF*SqKzay-DTDdMoOX{D}lQQnLf$vl*p~ih6thS}hyUFlbbAK1KR0ZPtR{ zsX2ZdPsGkW*ez~q%F(aI_2kntYGE1cZFGJqU+1xULsNQsM0X=S^cf%+YV6^k`-^2< z4i%2W2CQ`ayow+qbQSO6`M3&3K#^tenqdRMD8Nt$`0vB}*iM6ryFvBa-+r~s#CS{> zPiGT_VO*xBG{JL%O`=H~Xc zQe`hSA#p*NdW4yPjFSkwVH9g=WPt3-qHbBy-ie|vBa@s%8xKF;j37Rs^-#9oy7c%DTZgC-|*!o z$TLzSUSrE&cx)Y`hqv5DG3^%^NqE4?FOwLz3y-IbhNDytstr&I8G^G^Pn{2gNn3z7 z1FWWXnVIxd06N|we{cd`u^xzhO!xO^GMv+!<*VArGA)*-?@+JR{WnW)cc<#Ij88JN z4AMoyEaT#0_=Sak1F3`V?y%_NArB)65VPV5Jc_1~);eH&h;33{zG7~IKb0z6^3KBP zTO1Sbld_l33BUP(=?xIXZil-m*-iEz#xgUDtIc4zKm@WWWNphm(`o*gsP)2I?B;Y$ zExyzPVRw) zg~j#OQGYe}r_NY~DI{P;25n}kEC^8&0sS{_b7&e@-(vNbkv2>vd{vHd-bF>g8>$MgzYslE#&ir0B+!xYE zdS6pPQ!txYAd=kx?-P}_h2g4EPedz6I;A>e6B!8FEj_>*IrB`jj z2wjj%y68Gb z_cw5YljP*&>}0(4-&f0V9UR*47+fNOLno8=TvdiFNPjG(FWdPulbt^!RJMe+gu%{?<}9~SWr;xuAp#? z?WaAC!Y(3Ce(h=>nJXW;a1`!eTWUCJ^&DK#iyRHVdAu|($2(0~P&@J3X`J`0g(c+w zvH;4`Hb>BxX35?^s_(fmh3KZAF1DgpMEHfpe*-#as!2mrQ&@0tAbV+vvuMrQ(~^>! z01UBX`=zxo$eXRh@hhzB!y+lM;rTs754WmCACWF+_bb%NKqNLT2i$b^`edN>lvG(5 z%;^7ubbVrz2wTle3YAHC)}jhX!erz<}I@dm%9`fB;8 zVW{_V!$jlIc(7&|heWcoq2mU8brpqI1aK(-vr?0y=H_sq6AZ7HQO^I6BbaS+V+jbj znRn^mn{EHV&u=gAl!$0!BGibRBJcVytrX3)Gm)aVe8u>i^Ms>#)O0-`Yz2=CKA@ z?9mYuo`J&8@}tL(dXE}8V_s>;Fh4ESq*7<5OepZ?ByMhDOiulDgkhQ30z|(*+kH;1 zq`F$CMSThP?-3DYS*{}2jk?&?amdFaL*kIjt1Nr)lj}q2b%{_y2&3emmXy!4BecMs3YEIj)a#F_mP*bkpA+@>jOcbr;d=MNNq5@23z*57fjI z27`Uehd8Z|n4OiRRFTbZSE{Gobpnn@qDzPar~Ji9?p~WsN@kp_D`$%-n5%t#-9%kz zp(3!cO~*w}P{X<5AcRy}{C*3QPjH(+b7Ie$C-9e;h9{F#)@Qt9{BBS{VNRh9wB_lJSmOZe8UQY8-L2kW;W#SVoP-=I-yZs2uVXk6>zdgOXIwps@Ora7M zS-7;W5S4c40o&nRq56?(J-*MMLD+G1R{8H3 zjXDMedw>ysUbE+-LiU8q+I?+?K?0jM|EG?K@OZVKNMc2j82^@Fy~$k5g@blgVQJIEyGrMGVX=3wLC0+PY^^f5qSfqdlZ~b& zf56K?J6S147FA=RD?yRl@dY?yIg~c}XI3n(Vz910!bNQ4J~nZ4bGQ42ifKazFQqKV zlhJLvRc{1WvN=U*FqCfU>n0!W#EN$;F-RC6oXPwBO>&hoIn#YIoy5$TlCAe4vN=V` zzJ8CR(*v9c9~v$>EobCU+eVYPT%a~62W2A%6sM9!%pWrezLtYAJZ~!76$~6d!hW}f zk8Mp-Q(~${U?}XwR?Mi_V$BqjDBCm%d(Zq<@4dO2P3S%Og2*xV3M6h-9U|sc+#7Z0o&h%-R!mLy^71p40!|`Oo6U#!^m5xsFp|~ z@8Qf2E}dV1YlddXbNXSf;G#)qd7@UQm*{wv+tnXYiA-yX8-s+2c;i;{LdRBxF8C`u zeUf%Mb)cN}>K>Dl96sp}wZwMj*bAne_VwiGFYDrG)plpO%$o9~HHADPGw>q9JXS(n z{5+%YPElM&N)1Vamg(u~FP_Jee}k_Qt_tk9*{{MNMNKpdHpER(x13S+?aTk>r2InS`U?Bxmk7qYS` z>))p*Imxt%2@CQiHNrfd@{T&J&g3_;xrOeXUYu7oI(_5%DDaG%rL8T%lHU$EXX%4R zMKm4UVibp8c#jMiVn+76a5XC1foEzW6S`z}>?=<~JNlV*X!hZh>qbSR)q4Ub* z33;^qlh0#gnm~Z>$UDZ8U(=oD!=!UlwzrhyuBQYzA`aQUPIkb5`{VKbmwut@&T4wP za`FXc<5Ps;mZS|Wyjr>+)>aIVXx^=uDC9w5%@4BL-r>bI9RI^(T;O1n=|r(3IS;qR zS44NNROrvlaJUWQ^Z!TGTZcs*to_4EgQ#?Omo!K#(nyzpbeD9ebazRYba!`mcXvsy zbiLy_&v}1;c;U6MyYsD?`~K8Ov(=AINsLU-BaQspw?Y zkDnAlG$vvA(*6_vubV?C;Z zA{o13nxZ0920IjlC9qnCl~kI~lQ^x_`X?mFl(k+H2wVk2)G9LTblgPb#d8(F)5RJq zy1hf?0Q)(k^eVNNJyl^x5ko|vQIZ<-aQApT4kbR+STg^MO7&W1pirzMN(=%vhuMld zt;T|?iI8p81WIs$jGQ-mDxdoHdZgwlrN|soUQ0{rXA(IKZ^D#0rWAksbcTHlMOjWw zRTLOLPNV^2g=!LdIsiD0V9V?l~ah%Ww13`Lv0R?s)%GV&bhvTB!#QmYo50qR$dTu&X$_=fIG-ywVRXY6VN4!oA}Mm`ASJiwPf92eh`9Y z$iV4$CX3DvmY-@8&F_{uUwfgnnb!=9jGSIw_2_bltYUx+kVjTnuJYjF#*)nu%thDU58qu)O^LD?bozH$^*Qke43yZV zjSbj4dxVqk!Uds3;nQq`PPR4Ke?iCHhW3X#4u+MO3i~6A3VxpHq!B+j5ciQ&$|%hy zN6Ivz6ATTlDf4;f=o>#Nh5Y)pZ`A4#jU)p*EMoFXPpy614~5#Uo3CPG^BneqJ==8~ z7s*i+CTBQ8F-Debthm4zVAJL~{3b4b>Gt;RFwL6<9Aa6>w42lAUpB%SrR9dFx?<;b z%5b)bH;RQApylHxNB>G4eTB}nnB2<{5uh02zDM@iJW(iqQ~7j#bEon7uBSGMw<9Uj z>|CRIz;4uf)HY4q9ZI8rufmGnbGb1l|F@{XfmihKS4E(yQP9$gSkw?7Fv7UwMhhMi zQC}bV?B&|j9`RXpu!yh?^)3$PgV$r;&mkYyq=Zcip*r5CpI^7XJ6p~hz}pS3Fi!@v z7;qm?CUatrHSCgQoH=eS##r=};03*f!(F!O+58z6b2a}5H?Xz!+})1T!;y!sM3>P< zz&BX|a=58dTuZWhwIR33ncv7;X>c#^KNNaYFmbn3J{e@v%6ov`Pp$1&hck>y!+%!3T4-7J5A;S9Z@ zGEm-?bIvw#(bgvR@bIuQTlWa&@(9)!qm2x?V0riVZ%g6!ev}l|B0zwFTBFm1{qnp! zGLr@=Cx@K+Ph%ks5}^Bf@XM%+&mUE7MuYMS0cWSB<>hgPNa%!hW{J=gzIk!|r{Rkt z=&eL1Wq&5)5zlLTQSmy3UuMzoLzdQF6M6ncu}lmW36(TGL#Vbjq%1Af_xpnQ=!uVx zPAmDy38UE`!zoXC=lo%Al=DV#@9yc~K%{7__0UFLuN6l*8qOFN@q=%WxP}Z{6p}v5 z8+cI%l}{|({@przhgq!!2Mr?hUsq-|w5sC#$B?9ayu-?vv+}r54h&{(ampBt85bIK3G1o9 z_}eK_o(d_36St=V-w9+aXkSPlzA^9M*E&^iOq}(X4SV9iXmLNE?74NVs9wX@2*XIn zSo5R->aRu1s?E~;0XZ4pF1(Z`#Anv5_xK78lu@S%iUCl`Yuqd@zR3x$C9`*pxQtGEd5>&+!01A84SaJudhiE zpn!QTzp^q~jL7Aey(?>uk?V3w^Cv6+zycD4RHx^=8X^lroy_(P-kiySsoY@`GqWwH z_mA&($F04LFZR6!D=OWr!?Ij-`Ec<8e#Ewf01L&)*j5nzh7pAs7xs@MwCpE4oW$-R zieMO@ckTl8mi58n>~EVQx^=sbYf+FFf|wgL>zxi1@k9-KEa)z#RpYoWuS|1BzPJ*Sr+9Z5=+3`YVt*FjjPx**0@4d7&4Ka zjgkx1?(^^!ecp5;YkyXvBNpVFd|j;>Vi(}x#)(#l7tM;6&C0DhF*zB|gCkgN-m@aA zm8RM?eDP-BAQp8jgHUy->JD1tjH%3q!3HB{yv9frrH4#6JGR&U(iF4$jgs;QJPWBv zcRXQ!uXTIP{rhT|wg-!A-nY@~_9X@k@oA0pb~GckSCFRc4G<^u@I(>!W&5wj4*D9e zp3p0SuK~3jZmJf}{sTSET2e#*TC>bLQ2FDup0ZR1Z-RSXfm=YeRAt17jWR;-%deRq;%HX1cmK{2tfm)a@_e><-g;65 z8zg>-bwA$y0~;4>Ocf_xvuSJ}0H;&0_fPxn_=_qYAPez>Fka;2TbX8aC# zvnarvuDeWMem>#*-ge3KD>Gg=AS`_W9~~`cg5%pcu>a}B#nsg{LQ=qvOTQOs&ePN8X?bz^GYT+2i*eZ(gr`_NBQ=%jSE}EQmV1pZEO7k;gG|loub+#GhL$+4uG=aN zeJ4$JN~*`8G?~aUd`RTJeH(UaccYKwyJW6ZySy9o_3T-=fJt!@j6$Gpt&#a_7f>7# z9gPZTR?xER@XKRVsD}?!jXgi*lz0`!-n(dFjW7Y&?46TeurMp~JIbJbHukX_atSh_ zZWc1sB-pnCjDJ7sI*LC!?N>jRdEwhoj*@+&6z%L#r5YoK)7Ev$4xF}#*ZA&&1^Mxs zwJ0ngV${S)HT*IoFr7lf>9s=w+EOg(>8X1}998ucZ=_+FI+>&ocp#`=|2?#RXtfi`qeS=IqwNEw!h0EfMSrihr>Bs&GUhD)zIT%aD`<$*3J zC|t{Kb)c1%85yvGuOpb-J#>iCH<9PHrU#OhISzRKxcrE+SMMeXE?J)lra7WOXThNK zVaP{-ThXxYv?X|lFC-)cgksTQ)S$lqn+v0HjUMSP^Wd<)b6w39Z!H-!o|>P(ekL}5 z)#4z`jz^g!MK;V@#phiVkwqgp_favh%z#@q%Y)ylU?hWafsr|;ygRJXB zYH@oi-d$=)sz-?C^lfHwQg7vJ&lxx9%Q(FL7mc&6u11f8CQ!8w&wD0tAw}kr#!L`$ z`B^Al8zHEZDKeNCV4}gAmMh+5q$K{K>YwT7-OPB37*ATC3Hubt z+hf4e2j;PYqM=S-cu1_Ludi>*4NBDZreO|t5OTuL>7k??LZcw-j z1y=c;=O)fU3S~X24)6fx2A)RJB&n&TrI1Anqm!lDu&}Umpw*z${(67em&gqn!CZ0P z4u2efdGrGrBx9dm+`~lCH-njf{0KyW@%9hJ(q+XnwX_tSW-n_#EuU}*2g2`+%1Rc{ ztk%}n);QUtgbNoG7wcQNr(Wtr0c|1MaXPo&HW>;s9C$gWzC3a*od`q(36e#ZYJU9A zz&@4{NrHg<_B|UH^ZB&^a<%h!(!+2Iz82rU-q&FvQoziQ6$%@g>pV5BgJPn7KuJ)z zxtrLGgV_n5P*#qYarbJU>8tyI*tM zxI45cK!-(dKHR;=0(M@xiCDue1>DCONRNX$>CnN_hrmxTwgp`Pq^zx1=dV7(oaox zMLl~x6yXscR6&@G@e$)sc08UL@$1i)#6XFIg+b|PfFB$p$(!+bt5DWjhnOS3k^5FN zER3RJS(@)@g!K9Ejv%XTfW29&Qg&<@pWu)1#J)Z{sMkzDZjJo*ZB`*2JRGmw>hSuE z60w1CG119m43`m8=TNypW$6PNjn~*292_oimx&xuvEdiGOZl3gCxVOo#K92cMfxJ zW!i2D(H)6a__}KM%>aTCp5>$-guQ9b1mXU7vkfhkd;2io&*w(3hKsI1SHvaPM15IYLM zl6;Yf@sm(u4#ge$g4Z1PdA@2#olqG!&T#6G9RRP1!yuZ0+rhyBRAzr1-30yIsJ=2@ zA()Owy9RdKC>$1XUw*=bBYjxu(_;ZrWx%p!V|ns_NNbQS6rF~H94-Out@*XDkgxmQ zu(pxAdul(i7vI-1EXJL3flJi%+v$wk%l0SyaRCT&NVbmCf?C_7J%D^c<^zZMoKEfH z?F{v&!S|l$LO|~~3SZvfL!IFqQ|`XI9wbbLBTZFjx!9FtoZhQO|Lqd2bQe!&UKuMp zqfB0RUhE?o;aGn^s0*Wd#NSFso{}=3=qlmKG2IN8kt#6n6xcR`8nCX_A#*FP?Rlt3yk* z#CsqlNayZy7g)|Yh_mj2_skD4ThuA{4-5K{Q_StJb2$e%|he|Hir^H>v&QA!VUrlk#5=Ue^A6|LF2HrYAR1 z3xsbioN&%Lx2{0o=99ZErh1p51>Ni(yD08W37sbRCi~IcFuR3>K!p!%7@>U{KCg^o zdvJ$+8O$!H=ZOuiX+&k6e$DQ4POPAjp-GU0Fe;cPRbG^A$hr6v`ciCk^aMf~pL@qp zS`hLJOUdYAz2%bTJhI4TUx4d;$(qu-+y zGEX$vWaGfLmKY>U$6pw>w)Lr&JZ}7L&!R%h8+{yWv7%a=T-%8WBOS|8hBY~`)N$C- zZouO6Dz{I<@Oybbfb&|z?8ZvJx=#qr zS0@u@)8rJfislHL7A6AG(>o$Qan^K-Jc`30Z{xL)j~Ah1dRV=HNZdCeAXvV?enAh00Y90NW2LAhsA3;~ED~9|w5I=J#kFzc-^pu# zApxp(iI_{@Cv@*ci#*`o1kzt9<;lYxwvXsUAZ#j({TS}eO?A1fp`q;iY#P04Lv#6Y z^PexSb=IwIQcWhuN zsTi9I<@JdA&0wHxnI;2n|2osQ^eWCq=?K+!{OOOy;hI4vI55yuqkfs#F@JZWm+0g% zAY}YRk?@Jb@sZ9dDk@v{JfYbahHM4p)b?U+p3`Qvdmof#FoY(z+)hxcwaOcvB&OLJ zEf^x)>x_@&XTDvcGgvw58DLf4+HGh*-(~zKD@@k&5?x(gz2T7f*_&SARxqHc*>tTs z<9g$fe|#=A4>x*@a56*iIdRx6&w{6h7QH~P>X?iYLImm^IMHH2n4 zS90`$`FF8q$$f-QE1lokUD<#%U+X>M}9@W-BD4`=c?9L5P31!^2HaHILM zRhp2Yt=_K-?OvavPPX^Qtw=ENHZS^#hx4zA-czs?OYwv{5ea+HjuW^hh4@<%R3)9B zT1ru&cj{R82@D^yZ`vm>oZG%BZ=I7i%uTHN`8K80$C=DO?~now5M^&8`%_<5MFcw- ze^rE1l_3*}*~?DLf02)yWa+EX4WqQyHATlx;3RZFM|>^8T+yL5=5wE<_$}N=I6PPN zQA{{PYQUK3iOYE0tV0Q4%5NhFA-Cr%J8q}Zq;L4m@V4~D*kbdODqeVjx@Biox8TW%s9VJb5cw1Fd*&A%^a6N3KH`x zZD2st+_I6z=-44#RKLw}(Wn|^H(GNM0IeKYz1F@My9R2=GoXmKs|&Tx08{qh9F!He zM#~5w^mFanieG)D6B$bNr|sA-%1980?Id4>JL_Bjfpzu)Fp)C6C+q?@jpLIG3jWn+sux z_;hZ_*SoD#zENwT8L0d5aCkF@f_Y zgonvv>cN#-P+1v7&iqpZfRZcosHPYGFy`p|Ze3%jG(sT7j5m}l6|D`1yi#Hd@f;#u z@gxVrP1RAZhNDHBS0k2B`t~6p1VWMoB@-|RAg~Cme*e1QuSIWor7)pET?Pu}?8yTO z+Iw7NH~@aNd3FN6?s3tA6A(M^0?C=`w&@WuPN;JVKuk*4rnP|UPIWgWd03X>$f&=iJJc_N~7NOG=lt**k+uGS)PKn0Cl3p1TO^-&=i; zhqSv42ku>W$$A7b-senm<&1_p?o5tGk2{gu%8TbuO8^BwsHtGR?Dj@<$5OdPhC$Ru zK|w*s@zvfB>Acth2wqiNx}ptp?az9>iK_+k-r+rU9^(dq+Z4NydCgCCKEh-vr_Yv8 zCq@@*-o1Jt{I$({`2^_Sl0afntYogq+0mEt#0kTW{8_Jmua-dlkVt;!@O@d=UOESu>ZsG5 zv&Cs>K6cWD=sA9&`xp%yWW_8|bj$;th2k?TU7g3KQ^Oo1g&Nu~NMp$&WyA(V9|Kh* zATlwyS05z$S?~&TR_}^^x@XDB$zlIkzhkcPT9{>7g@c&uGf&zUkaz8XwB6J{*m-sO zP~zDGpr-rxY=Be%eBgdlGMjQ6GOE_CUcS3Id*THq==bLHWgn7f(t5Q~tbFWMdqnHr zFD?qKMdTfY`F#O7XP|NOnz0F6{$beZBZ-HtRN(?KAF#!19~WdkFkGB!v}(FR7x8XP zCwcS4G1DMfnG!)L?f&tzJjTEKu+4+Fw6wGUH%XUr$b6GMz2o6|D*t1sB1XP2eOfA& zWB#G_KAXhz`a@S-V&cBP>Ke^Z>{s&IMGNt1cI8wB_6($yV$%n^Ov4K2BryWYc*$LJ zfOml!T)@kF#18(Ath>;kFLMKKmxsNL7-QSL^~M!uy!~yk(kXuvYZfgOj}S=sbK{t> z?@|xfzL%%6NvCrdA}KMZw{t>%v7?a;YiFQcjyhtPOWgB+w1PF?ZwO!BK_r}M|VF@a9_suuj8*6T7lthsb z(Df!apEiZQ#n;k%x=(c8OL71XbWY2afn&ED5SbX#ZMpw_{hrF>33_I3)&@XecAc=; zdaNnjH!I3O5t{^xe!N!UqIg%a+aIRaLJ*&Z%~0 zYik-XPKW~U#n3aDtpE&$B7$1KEac$G ziCRm&jbxPUKJr<=Vkwb8+lI~>x?K_40e+_eYh_`MwOTMsaaf9EE|}B2I4@n+=e7(D z^@u~VrRc7RBzRjZAH8G>0R7) zDiqu23D|k2NW1ljFWh^9@Ju=`FQQn&IiPt*m(hPuy#ar`k)Bv}wJQ6FUXtvzk}|G` z)gM041M_k1_M$}=($fPIl8pk=CGY3k0zjgT*v*PB!|+bWx8@2P-UW8k%dR)$*s1+bH|zc6k$lK_m_3gWL&E9{m>!YlLVNXA zT#rlt{evA&NqK*MkQ2H0;x!uhDQy1OP)`pEtTiC6Zz4wBT9<657S=!@>|Bw zTm=7;5uYAzrq|aasfxqQ5bMGsgbvlE^0x41{^?4(Xuk?{o3g!BR;GS0ZFOmm-zHoU zsCnb)h{^cf!2CnSHE2@yQ$lCI_~xM&g{#449;#qc#YPi*DQ)`jzNJ~BzFQ082ex!j?I`!z6A<{+exlWS-kfsCG{VhWv;buSs2-^X_iJcsC<^Xqv?>)eIj1xf z6nq8^$YKZc-hMBgYe6d}K@j1{h?4ddm@QRVV<_Vl+DU)Qy4*}nP2Q*c>1EZONID#v ziy&f~%Hx9ladsSOdik}_o;+5HW2QL|RV)w#cmsuLkbx)UlAVc&b&8E8DLZaz#NDpn z#rf;I3-8@U#Gq}DPsD3)Uv9tSq;46yKG;?7*nyUHi}N;tBuyq(27AugkTpr))sPA; zxP@|{GAeZMRX>HCqQw5PH%M%+H~5sCw|m1OAds#taAijo%U!m8*ra8>x@p~Dk|u5d zr@yV1iiTnzY;S}qdvl^6-<~+lfa%xY#~me(@-DEjv@{oxz159euqv!UsSW85g+L$F z3ubem8>*?PK_PnYn>Wc6=wir+)K$r1Mz z(Ov>Cfg0_LhNixZFzvn|cg_!lJ|~Z*ljXNLlO6oT@|Ac<$FV8YLyZ@kaCLQ5mqRuE zU2UFRH=lG?pG_YU?FDwU1Ivb71ep?tm4Cx%9&tjdkNa3c{QD(nsGhF}{oQw2*q(CK zURHCSB1|cHQSGkZZzR9aQl!7yjWB279GEuCLqrgl$QX;>JE5| z4?IvG(e-uh?bXqIEg~d?D2daRj8G6AFAuCd*1Y^o~F z_F(52VU$Dt$+d7{`tm+`R2&gkVkiVAX>`xWqi6cOKh4?%N6&O&Rk6WC)ux)!6}C(U z`#AfV9F-bTa3qg4qOVGYMc?KC&v!&#QiTzrrfQ)ETWxF(X-|Q`4*E%h;sUa7>|E>d zE75KEa=8!VjkcEy%kjguyOBdOePT+b8kLu)nm@Ms#!FoXu_FetTcy>n&@?8LxAZ`K z1@r=*Uf1eTBP;dFpx;K8N~wvYdH2kI{d&X(og+E+_qVMfwvd}ogx{Ap8=;xge~ut8 z$uNmBX5#vD`i9G5nX^8LM8|9z<5!OhMSPW}zI-L?&(v!Ywa_r%Pu|TrviIjF&4y28 z$ z#USHx;A-h}wBW1TFID}^-~)e^Lkivh8-~<`Of}(XbvfN zO<3dIZTV&f(G<5+nM^$P5IcG9u+U_jUdH?M`og8lr=?Q@3?n^uN4xa*7hxmz!cC?Ac&h@M|NgnSw zdB^L$FTU}_6P+(R^r1mLZGOqhEaa-UjXQ36kDh`fHq8#&JK*I6l70(Le5cZn=T~CJ zYn)~3E|hgpdL1;6_pkUKT;fAhjAVLY7uFDqpY@HpV!PXB(5`bg8g&ua#=O3nQ~#iZ zsBDXY;1eSE?W?-}NSu$ducpny&Rhla_aEq}glu|loukp|n%sjsJ_cy-2bQx(E4+cl zOXt(s8-!jQ$0B$BvFJK+s+ zkk=r)(a`%9nDa~2sslFVf-Wjqu$Z*M7WFzwByhs1C?qK2B^AGaAAWv%0E$1*Q#~76 z4lMiG#s<@`5+y91tg!KoEE>_vNbmaxBd|dKo@UKoBn*4QlTU7)G(1X4^@jNPXooM* zH%0PmqoGOEnmYXc5G!g*upE_;C<;;#^=Frkh-sFu0mCt<0}Xhc!1FBKE7%*mMF-k0iY9*t9=G_E(k65>+he$z*L?;l!~aJj;H$3 zj+5Vb%H+{h?Hsuo=R(h4_fgB3jQ0GmXSCZ#ME8Bf+qG#m!L+2He2J-s!Z!%^Vw*eUZo^g=VJiX$Qq03;=4WqAb!)|`@-QKOtH zzK-{d_*+7=Zp=ZwrtwvD6WmC=&9FS8MpWt9nbnS3@Lq}+T!X3!&UoRXz)lakd{P`_ zJ=UZH9PUc274dp9g-=m*3}QlTDf^B|Jx z?${2b-*2kWjdqJ^GEo|n&-at1bCkiX^PSKp|NeHVLJL|RumOaEygYybXwedeI!_$! zPPmDl?XIxQN};Je_+MSE;jF7ydP7QOr`MOIDbNPRQr3!n!_^4z``NtgPD7BS`nKpQ z@9*I-MDnt;V@w$OHa18?v6%EWyQucYtp@0==H_N~SyRrP`M3xi$3C68ySlplyQB0f zajqaohX)5Fs#;^9qnUIdR7+^w^8L2cnlaA3uc4&8>GOt>Bwbuid;OeqCA^(s@7E|h z&gcQiwrMFF{+n}Q8ko|n;HW1F-^3;{lHH-<8y!}X4UJ2<67$-ZWFkgf?<1ZGa}us3 zh8rUiRBA0lkPFr3Pqh|v(jm^NK}?Ha&I(4>5nT@gHD!rjv>IYdV*nffV{HBvn_$A? zBYOFoahUVU<4+lr*Y^~K|sU{f6gR8981^T|^93+or;sKbjZ*PXfsznQ+ zZvss^&@+%+x}4yiAEa;Dug3b%W-6QoTPNqI7$&3@1f%2x!!)I1I)FS)5M26iZ-AVc z22hk*aH4}=q8SsOYuGL5;r)jkN|#69U)9CiE6i5#mlKu&a8;g#fQtoj7(l5P9}jZW zwSfA`Jh7Xp{--Sgj}%ep2 z*%`2)@w-v)*>L9)ZWq~EyhT{ISd+YASSJ#OnEU_i>GBUM#Kxng_|p|9eM7ThZ3-wF zU^kv3kjyPak(RQu{a^&0sI3v0`!mWRnijF&^{1~ z)_-UZBy0aNU21CBKZ$b1M**jdXbva<0|EkYh=_~~4E#(ee9Ddvp!_5%nfQbgRYE$S zUzc=cG_O6*n6?{T>_uDoUpcvqUw?Vi@-ij?<=pxbIf8nfNj{Z7y8YRR*2DI#kSWtr z&Cl{-is}wxU2mr_<=hk1SzWSdg#Xy&K=4@>$mswJIoRzrboy{4baRK9`E~R6z{8^> zGQ98@Frr>P;T$zDxfAgv%dt}f*KK1AWeUwcy4*@6L<|us(2GdsMu?BlH)t?|`y2Fm zBWb+Y<@2GlX8d%t!1x1Jo2k`RX*V}s!fxEUNTulnwa>ygsPcb)E0JSKbXtwd=}B0N zE~4bS@!GITQlOE7y#mP7!II2vwF%aY-&phG4e9Qt)yx^?DLeN^t3#%GnIuhb->-3WVi?|89Bv~{G*fdHeKiUu%XjvN- zNjHYjQou1|F{qwLkYwuHIPZ2aYpyO9Xq=|nIr4LVPfC3&cbbF-OBhHRzE03@Rtu;z z5NWKp*5a~Y(T}>8@j5v#tB8)AoE*e6OioV=f$%GSUFgyay8Bv}9*2(-tD=%@x@EaNJJksNR z%jdeo-Q$2QKP#h9trO466~?N3jkw4Cg}u=g5ijr(DZ7z}7s$`SqYfZL5O4!r6gJK4 ztIy`uTrM;rF;?_Mu3NBwFA`NX1jdF8F&9?Ie);7@_+p4`UuT@`E!Y1bkLIgf%o!Rg za%Zn@eF6fKAF%68noVJKbwX!JG$WN8%yve}4iPY*0BWX*ZNvG(Y(Eb;Q(-DFs8oFCv^hlo-b zqo}b$_DLR_Xu}s*1cT=!S|_E#C&3TzB`jxvD+n(#fvZGT)7OWKN*@&-${cE?AhpGnb<6|j8}0HI zQprs~urlw{?1rx0x@iwG3c*SS(4N?IrHtNY{Cue$$QJDR%6g!);|*7yFmK+4@9*hF zjFv_{?5jE=c4?tW7=uY~OY5zgkcJO5VL{!SmJ z+RT-#yhR^l3DAEC4hSGk>nkc!h1D@@l-L?rXCL@UhVa{)8Dr)SC@uh_TvHR5oQwy& zXOVOt1TX=A2FMJW5P+$`WD(~#WY{V4LddX+7rRrOU|L_*0rlP37LxX(}+iTF?O z6NVWToyY0h?BXX^8EIwN{-pFEh`@VhwpC?nCBAlu$Ns~?`8EIhd@bL~##bERv8)~| zN+%}A_}OU^!g4HPTTLw?E2Ebn`RgY;#fXEZkuEzm4n978bL+{1AZwDw)l~++&B828 zukf|nRBTSvuK}Pjx~`|L?8wm546;OjZ*Hp1=NW-1`w-Bvzq-U~ zbL#68!7e-?>MmnkA7>jm!0U72--2Vkl2bui!$ni-x4mH-vyGeuj>0+e;BB~Ix;8NZ zYrS`#0;1^{1I1|LCA=@(nfo$P+sy*P&Ex)?4~;JwTo-uMGA$~Q2kH#>?7J>buEUt# z=&6UQvuX9>9||o59qg~ajTKXQ974pozEqJ*I62iH7Xs<4AOjXT4ssdy zaKVq|I7uMXMy{@|9vK<2zW-|~lOZrVGJ<@_?F(=p+1%Sdj^R4h-j3uo9ZOoR0sdu~%Lca~lV8yrZK0hxoKN60g6DnsnmLtQ2k!+=>- zaOwN{*3q{!^SEt(dV0Ib44mEOMrw1^$bMWrJTeTVI|jB(rr zN<(IikXoN)a}_uq%7uMx@yjUDawch@p`pu~ZL;JFj$HF1l)(&p;p{#-qD75{2)1baW{hnR|wnAq8Z}{x?`gg?Yno-x8M-hT=Zq zjp{A3{@P&rWKG!E(mPM=Zpb)PYQ#Uej=il<+!XxXYGHClU0WJo&5%5MKrBk5gI0)D zFD%Adh6N?rAQU~bKL~X&foAV=L`K%`vPS}}-_a&L9)T3G563D(HiSaXt_pI@3MEl-I-FPA?^6}b%GT4hlexhLEY|4wm%Z#F=MaLl7D<}@>*tIn+BO{}gT2gRD z%8DD&GKZjwsNTda9G{&TgNM|auZ`x$Xf{GRh4bH*9pKgg3%TWY@RlK_`NjvuT2i#& zh7&pTFF?jwc08uewVxc`8Br?H_BYaM>xtOiPuAlZ;ZVwyvHaYuUP|!|DG3I0g_jjE zG1x?uphaie?4v|=2!hyW%P4l=-((_MSk#Ea=zkYuk&{qezu52)pu6RXGp6b4x%+(X zu%_nj2K9_^*AWw9KyGl%bZu4u)R;w^nO*MDqRPgauUCcGnU5ikfm+F13oUm2) z2|jXy_Am5G#^Xo#LvX(Eop<0DxFeQQH>%q7*UDgae9t^{5j2xUbzynGR z9Fp$f$WbyiiB`{n+Z}{3n6M`oF?2B#aYDD8-k+@4U#V#ECm9*=3Gpa))yKNU+Rrc{T_?JrB6tyQQX$HDqNm1p zz@11aqzb>DL3RsCs3Wy^I@&Pw_c0;WFGxZZiOsegSHw1wUBBaAJt~Pmi4KA!-0xBX z+UC!qSifossziUq1<4`2jsEx!g}n&@jtquDbvjh~Z;pZ@><0l3fEnZz3Nf2h*tx;; z)*o+h;7LPDe(aJmcvmz<+q1nP(ODVTiPcal(FjFhXfTUtWcvpjMESM~PNPO#Jsef??Sik$YQU_|n8kV|bHAy%W#- zB0@m@M#fvG?UhQzXBsi_g`gOJQ(tE2g+{)FG%?{H$kd+~g5)qb-@zrY|0H3>>536# z815PDkLnVJBZmp2i9kT5@yk-0t2Fvq^~O>cGcr_k+NkDs#)KVjG(h;(my#dHp`z8% zD7DiEW#9cikYM-y`l_-O2VJ?Xy36kJ3insNDBcWqC{eMYAwoaL$(Q2En&7K=wQv8q z?jjWdTNx%Qn1q;aYLhofqB*8Nu`>Rh+{KBw51GZQNTW+Sj0>R*Zfs`k$-6>LFQ)7e zlZ!%d%l!MJe|L_dSg7oO{|jE3R{0%gGM%4?_J5aX(!!eJ?{yY@7rmdO-Mk4q$NxJ| z|K2L!OjB|>jLiMZi| z0r>y_zd;sseV%8){_+M4ND=zKA5q;It^VWRsR|*FHoZS0>64d`)2~oFI zvpv-G7Y@8pTXH{7IP*uCZ_Tg&^QIC6JsDdiy7&C7Md5L~UVS_%#nq`+iRiNc%o;yLsbUPja{i+GEz%U2oHlWd6547kMGx+#d;ND{Irarvtcj% z-Ex1W7EvWLA0q5S0uPu3&@xbBHX;tlI1~^sXeWPb9}&7cst7~w*t3sBmc(0T&@)EIh&bvsTa$+qV<|8qJ~M0N zq+gTz39@79I@)50NoF{k?;$9^rS+?1gO>d_|ZMviQ-- z*5uhvZGWNQ$xro`LSbKthqIq3CEGw#W&+v#snBNfzjFpYnl6GA+rZ8tZd-=TgMa9^ zbC(-b9p^ckSv23Z6GC_kv3q38S&hGYtth$X7NrcbuK4?RLv;)UxEm|gAK50_$)>8q z^wANVCTzwU30iOPrNYDY{rI42hBB2sNNI_`ZsPt?i7;-3)^L!55_Re7VB*^CvSTqW zut}xMp7Aw@i6_axH6AZ~9p%P?T&Y(Uhfhd4=^L2eFsSE$$oDkgn2p{#-)Mf0SK}Us(CaV%mLbeB-p{27Bk8gmKXf}A z5&7?&VnO4F0y-GmMuHc|_2J(#8LyzO;7#NDrF7A=^9uA#XhJgEvV?N-nEp=bPZ>2IFAr~aRO)(KmE!{ue8W#YYqATXW_+loM zxG;TN7u%e8Tvr&onupXs@Iv~(VCs#lea-cA7DnO3Msg%2(T>{*9mVze9S75kC~O>% z;nFVy>O3MCCR9+u!$1Kc%AdayRZPzay5HZ*h&vQ7eMzHbhMEm1vb*uty!<{Z692<2 z{uEuRK}G#gJWMC*c7hwG0HbC&G7fFI?r_DGD7t%{{NYclpO9cGx08)7%;%Y365kJy zHeO1$;5eX+;+clH=Dy7Tysw+^?;m_+v8?-;OKg2@_zf+z9}&*i^}_+~|7KEV1X2W; zAr&9|vZf%&_)@?&SB;g8L2IqaiEx8T=a;O3`ZfspmuO?vR(n{i&huBR&6fM^YgH)# zsH}5DoUFRhhA1__)s;#GqxfWHk@|FIE@O{w$;I+}c(guVSiLZ)91<3<{ubHhdKaL3 zJ`;_7_t&?aS&hcWUd6LbERG)@ZMFMx&Z;HR_hGyj1xgp^SfPPCLWlw_3+!QO&Gknh zhr^gk-MtLT?DOP6hE_9G3FByLes5}y=6+exb?c(UoWNR_(LP#Lsi-j1#JEZ zg2f#jL1KAj+1W?qv3u_LA#!ekvzR7@A3AIPjenXL7utT%1CKQ+22!cp*Vecg9p;A9 zhb%QbFg_B6p`w>}(nQ<5icHq*9!NhEtG6)-Q}_o-Upe-EwAs#U)tIgqTQ8yiTnhQy zT}TYcNlN5S5a=z5cN*_)92~WXu(vTCS4*9*%ssT7{d)R*LGJE!YU0(vn=Jn~m%<7jIyoj_*C8SBynF&I4k!?#%U{ZQ~Gf__B|NxMfSS6{CIa$NliO+#4_W_b)|o^zpwp3G^i8D>!{I9 z$XiB=8&+n3J%&(}mTytmk+1FM=O*gabEuGazxSHA)f&x*D~4uwNrA~H zf7A2NWZOE3+b^v+M2tCPcJgjF>~7A-%Zav#-?asPn6zBK18y#YWWGM)*1xrR<6c8U z7tz?KyPd)0?prb1wj!mV;2af2!9IGDw|vl0l2sA%MY?&h6<&AoZYP@0FlC>Wo3~eU zccm^-xnE@QDmQ1xM}3-8rHVTTvB(OA!U7r8X)=(DM4|#(zA>ch3hIX7kD_C{O9L`v zZ14x~sjw^(t85?ZsXvYKmp|!HHdSR^s8h7=9|EiC&ztsJ|DrBCnu*TFEKl&~3j}{k z)K9-Av8;LB+Lh&2%h3SnJSi=0mr1L!{^)L<=)iXP|D)+EqoVA-w~-JKL_|tjM7q0E z5b1^?rKP*OrKP1q=>~`HRBGrNIwgi0hM{@y=l5UlT6~_h*!!Gw@3^9RC}n2&=4k)P z&4zOREALTq!@m@k*88!r?Ix*LWd9X&1?ic#=jBT+U*C*yZxH1TnkD&*tMX^>YL?=i z*Ulu~G`%!Eqj%xQeEX{(J41qXt40PpLMCp=?OySbDS=RK<>5ubAT?EMHV{1aqt(vj zRj3-{If#{*iSUI*Bj|)$qAx!&z`VCfH@4c4!;@1I^&LheCssJ>50@0JKYMFi>L;p{ zfaCQryzzwZ`?%HT(is3KI8^o9V9#-?U)z3@CTt`4yQQuakK=_5SKoev>UH=bklG&x zcSx54zu^mN3ZPaiah_?Zx^DSxA3b$NI-dDas1joPi~pkTk%FH$EArpxG0PqnQMXnK zfRsTU*I6g&Er)$>yiFtU+;f^T?ll&=Aqo9xgCUEdwf@;?h++#}hli9=koS(`#Z{l7 zQq~Y-Y-tt^u-feq^@-_z`_$yr&iL*zyCo-||BCx7-D*IZEKkZ`{J+BYIj#AsC)Ym4 z>wY2awaaqR5O-na+HVaJblvpqn+x%Zt@607HR8n@e><(%$GqTv=XP8X5_C7Zst?XL zuM*^bf;36Tb_w}(?072%OZUcPs$y>6)F3p!;*?pT6|vs!{rm8dObSO3%Eg;0KDW8O-V$^ zs~tGI} zxoOp6!COoSJo!3-i~DXwlfAO|Nk?!T=uwI0IRD;^ z>iaJ>uc{S<9o<6S6UVmtWT)zBY=PAnTS75uvd7Ip#7p++cC^qIXy6dr=|{&H>YTu& zQC}~PKOeBqeja38Z@Mq(``RGc*-w@aMtOWr|E2hw-`8h z9(g$|8G?PJ7Om-9%b)xmsaoo6cjj#a)P(q-UC{}+nXmgehA)SjpChJ9Tb%A~ygGLu zCt$~)@#<^cFb&MbUP3gP)3%OUe|Ev7N$*#Bb}#AtIF;Q(b~QoFX($+2QT>jzU-=3F zqAW1yI_UzIQ)-Mmilo(sj{Tc;EOKn4eN7H+iY2v17{k-)s_}bqG8;RcPu~_y$d*yYCLVSHBIIEHW?9{nTX%Wbn#yZqO6}T|NX?#@dnx?#Oo6$adW;< zA?L2$DqDL1?f-<=(Qf6NIMM+)A;9&oc%Sy+COeszf3t><)}|PiF8Vs}Z!jeGaq_m6 zReu`l7pMB)?7X^Zo?<{*q&V2B*kPv_-n4t42v5@Os;AK{8A*D}A9{bjmcP|h7}h16 zy33t0ngl47{Vnk^Ot>ELmRZ0!{`b}$lA`bn_L8yK@Rzm$FaQ=QEC`ijl6s4mfu`UC z_wX70%^E97vw;(=#Yo7wD0{|wH!Eb!m&KEvmg{xlI~#0_C>LtfGo50ZePF}KqD1I4 zzMI-=jQ2Kjgx`p^8YYlbea?60lnoYe>RJT*>L`*{Rhb*JWV@cT62ADT5UN;YaGijt zXot9!r-;Yq0prTa{18{D0+RrWJ?xw~Lzh z2)lJ#=BVB16~fbpsp0GK)!Kcd{)N`v3jRuPqQW=dqX`S{`=!yRi2%({hx6*rtbtDl zPlNTBSWmEH0aoYuiCtIV%{OLD(B$45>|jFeup6E8fTU~-IyQJfn~dy!>FS|6Huxb3 z)QhyRRp%Hi&*OlkV}SKoxtZL$eEr5F4!nRS{kgUFOOD+Uwom^)e9hu{E+jD3P}H1< zKAhS9H(c)^lRn-`c5on5}=ns|wrc@qaO3dq{WF|Wa4?-@4n4K~2M zs%PNZ5m7l5?W8LWfKhRZEKN`8B1Ox=ISP8rF6H9L8VLlw88YyMDBpIvaGKe7;K$jV z-{%E@2DLXPO|$PB5JS`?Hc{(^L#iP{Z974ub8B1sr zh8>1;wuse5u`DUn(Q(>`Ekt+{9JeN`?ow~7T@9ZEs;W@$-=%O|8~Ooy*uxs7H!C~H zRhSHEhgeI7-2i``)XwO9cdivf^MF^QL_=Coj^NIV0o9HRhd|pSqHxX?zFKB{HA`wa zMJC{{Ij zRud_%nHc_CjTfa09wlq~aEaYJylZ>712AamA=GvD<$}OmeBw7&z%84wYmh(E@Cxuz|&}i6BUKlCeXFZ+E%8 z${EEdq4i7to7QrS8-_IRN;-va>$paL<3n;NHp_qm`_vDu7orZ)o&p|uv#lEYiXfIs z(C2I>MP-^YaLp&w($8G$$U@46TOe1W& zQcm?j2b*LUuX07FGo14pah+!PeMOo(6RGln1 z-S;m5mX2P+ref{*=h!SZIS4kg1}w>B0Z1CKH*vg4*ls~RpWkp);_9ZkI(f5>L`Z>> z+*)(UMgKyh)>RFMfd-0>02{!~C&{DtbFP&2?5DSp;*Ec5V-qCiC>bLDraJ86kNWBh zVpF{vx$7t1xQNl`^W3qN z-1xVOsbnC)vK*6s>Sn`a)8Z$(H|9n?axr z3r^WBLpTkM9faKbCqzFz!d$S+CbB&_!v%zN6gd6m>ZV<8IxGBVO)^e7L~z?vh|ICK z-rHh}(dl3N5*^)Vsaps zo^H8`PJFf5cR~piB;ojuJIh+kyCubc_u)AXR~Ou+s}J-sOgU#IH?I4vacL>&21V8R zrGpwwqBs$#K>c1TH0-|s0VOGSn8S-%m}7uhTiJ))F{GFUxTB#p+V8D~BwYj1X{rZzEwAO*bvO zC?s6JQLLZx0a%E&9>}C#YuSjWVlflP8sbxJJo5{L?R%Tflb|qVjB;&VhcUxoYjWI~ zm(i*p2s&@Lfd8tK$VSF^B#w*l-x=kMt@mBQKxxAY^SKj<_`KkW0JuobTM4J4pP2%- z-WL43W~&~J5dJh`WI(xKeNpP2defs?f_2sn^EaO>YX|1IFb!7Xn-!AB+|on}^8%5C z_%Ll|38z%HnP>K;6r@I^Bb#_JAL=MEE466(0zzR1u~qk^E^9C7a%dq`B18F)gTq*v zua#zK2+NQJa4Lzn>JGRIFlfyb(sLJ=5NnI5TMeg?Zsan%(iNY?~vTo59VG?{;II4OofarUB{ZrO2DebB1RyOJz5@{ra3j zY;(b#sLuUI^8)5aD=?^5^wX3YfI3Eh>?3NiEzzu&Wg~n6_|5d4zjCCHWm@;q*k@Mw zV{Iv_efFu_h@CmY8t60U#_00vsE`g`x=-3U>#g7ek1`-d9_RX^$kWwvl9QVkQ`fRrzut4ngnnmKV@7w$Y5m&Fa*lP@Laktf-!yas zHqa2H4Y!nGWaLC6Fqo)T$v*nj(?dy!85XK0slh6AKb$C?LwdB=fb3iixblG;>NZg5 z)cf+n4IN69VZP$EM0Tmt3axv0R#1Lx7{%WF(bf4U>IdfD5ThTf23Q{n;IwXdyJN=2 zW1<2?7NlQ-apiNqByjqCXW@G*mTxr3i5qhO*s{`?Z^B6hPv#&hb{l;qXm>3^{)np$h`97+H~!TY$=0&dVT;r8MIXHwTmp7Z9z!7DcCoKKp*2f}r%!$*| zQiiS7wyKp5WHWcj3zQUpaVchoy$h6@Nw=OKDG$%@*jVAH?87htk`iH+3X{Wj{gc0QdLusixO3tATE6MsnStR8 zJO0ZVZhhI_PYD7oDH!_xw!BAZwF{9B&|`|VpA85rSr7$Fg;9D_j?D8X_!lTqeg2kwVhA~?Q zntvAZwqC6Ti0K-+U<04{ZDGA2WJ-~Cti!JFnpKnC$6}X{je`Fj@40Ck`_hztrIsL7 zVuMEizP?Lxl%LPKH=rq`71^=VcU2YXcmw3K^3ejpahKWjnB#a}V#T+*Z_&45(E-{& z8-0+PQ+CQT0AAvCyqwTtW6F3^4Tg<&1)}gmPgl`P<0YS)-pzwmau?j4xf>`Iv(A)C zXE21fp8bC;z&&h0M$|lUyqRh7Z~n12PHufT$8+-Q92$OdCr4{Pyue`YFG^p}qE7=YfR=&%*YEiac zxu3LzEOpIFwSN7`EE41k^@lO7J=Ku6Y%W&DnZVP_2_}=kDb>FpfQAO#RsQlv=Dc%S5qL0|0QWr9Z z%v}IH6M!e9r%L4bs#`5Sdsnq4Q*a?#9(7*u2ANx$a&wSAq1mYQCJz|SCB}*MAQfxd zpbjqvZm12`21-5(054sbi&!}p-qEEmDG4q z*@1ar+T>+z9g(kt3XNKoW3ILF4umMqTn>5@ZtudK!$3j_{iwT}l9@{sYu z0sfG8l;7xjvFf=Sh2oPm*qw{3qqk`&$!*g1BK9j);eK9*!!H+%WC04mX|ui#1bn+< zh>Mu_)XA1CXP`15`h^Iuv3jTP-}I~&QO(T^Q;R5jcHI|!dLBh-KxUk?CSPV8yP0A( z#&CsFb12k)5Zk#n4r(3ZWxG#@oP6=`jb(f%({=TWF`1LNW>?)zwUbb~@VgzNijSpP zj|^Mw)CYCZih($%H1Y8|+kdC09ZL44mqnB(6Bh_@H`xtwBB8Nob1ZhsE61)}BcrgI z2uU2(@yrolYKroGWdQ0&m55g7bV_yNkEFbxu@;y4castF8b6H2%$){*Dy^}B_t(;J z0zqCT>UPT86CbUM4W7>Xkz6NJZ|`;%(f3JzidLVNEk78I{>twT8LZImY8c3|6h{9ln;-=&w!5ub-0{Al;U`?H*a7v`A*Ft{$S>s ztt!lF7`46=ME`?k-!X-sGP&Mjj(p*Wws@r$P{at`kQ$8^R$T)Zx-k3^pMq$*uE7w% zHb*o=_^%J8LAs$eTkO6`-t8Xh=FO+D=K4yzNiW08e#J(0kX`7P)@8t3%n*mMrweCd z*XZ=#NBjYjFFT?e{Q4J#MP)diDZgj0kzxxmgm(MQ+b(bUi;c$4`@>u(>$|IJVBeEJ z*qA(sRcNI*Zf92?2Jv+qNaJlUsm{FBf2abzTUHtMs4R1l1CAS8frf(k#Zs*w`afr( z!|F^u0aPtvylEHbD%8O--obKBL593d_3bPiw9Y<@fdHevw$Fe&IS-bo-BW#KtOJiQc4#_E8K&N9SXSS)2emQ}cM_}Fsd%C@O+WAS+ z+5Eu^XYlVmuR+mj*S0<@vC-yD{ZteQ7UYTR>^b}K5`gi9%hHL@P-|r&#uZ+EozMDS z{jqhU!t-R^i|Ul;bn6Z9gy;O^*c2>v&Ux09Qt)%s(13VS|G&Whd}Gt)E`I@gzxv-< zHitH`4Q#s*M2FjjgzT*d5{-UP%FrJ&3rpoSP~oBdO;ot7&`uUT?5p$JO4f!sP5-P* zwUlINz}Z}pl>qEH?Lq-;t1~DB6TKi~7k_I57l;b#yC`>2?yU$=rREz@5I7K~n9@(q zDx&?T_s2wreu!O1ikG#6GtEJR>zPVcz31arjoQOzBPb1o;rIZ=uws4CtR4VE)DC|u z0+B2zsCHRJ*Z@g#da_#9tbK)8?tcAW`{ljx+E*4(WFKg9@HEJ^=MnLl%XC5B{J}xG zI=b>?AWn?cjEnVvMsf%4)Ad7QOaN8l%E8aZ^+z^;t_cr~BsgQB@UQv(W>Wjj##+9y zTK+;O@|nv@^E%MFHwsP5E-Ty>jT_tB?^SkinmiuI<`5pV%`e*8aYW#cvWq{{y{!1t z1rWqW8y3w51sSG?x%|Y>Cja}zy*Ez-m>kzO!qQwOLdGt&kJ#_Lg+wMW69XektrLLj z`ZOTcWE{I+`l-8r!R^y(gEXms!4tx8u@NwxK6#TzHtuUCgudY#JCa6NZTyV6c&7t! zCG0}3{v8&7bQyrxhLXzAF81bN@RI4Zo0~#Il4ZCIzSz@_izW7jsd`OH9c7>~WxG^$q2T% zRU=I&r?~PNx-Rn0VDGRP9&@f6+iGfZ5gWG^@u-?}tPpFWymk zGy~I+?)z(o>tdtkv$aif|J^c4aRqM`YmNJd+4rJ{*MkL2sP`vlO~F9824!@ z5@to;w`!5yvG|dvy@t$b*Q)y%dA#>JJxKe`3D{3ve|l_ZPQiigc_uHYgy5~u3A8VZ|2Hs&y%o5!gT4k{6t{FE+4Shd6kXsYWSvh$Pn;nt$k(LS&JpRQl8 z-8^*f*CHQ8MYaLIfHg)S5N_NOl>&1<~wp3&4os&==rsK|HYyC7rmr@d|x7#1? zve3=aRi1NR#wxjxj-jOx?QTy|spkpKrRw)V*aSZAtsXD(4*)jKMz7GE$l8kMTXSZ) zvu6A33bm0n_aC*Z0V2$F!uWmR^*+^L;uz&$yPo6DSU_ zJ=7}@7y$TJo=&<@t*3#NpQyis&sQ8tnAmbhND-UZ;mncmeFI%-IS`$Qe&wp-KS{(o zY^8F3dF%oh*lfI!Q6tWKTDZ!$@GGhe)y! zV(;i*!8^wkMMHv&4)}80SHX#C?3D@IXIC4>3Ck%KmOgSv7J*q_5?AVh0SiZq>#eys zBF*M8!7SfqJo7%ON{S$sy}j>+ z^3Tu(S!RbvU9(a&C1_LgUa@OA$gSiectShuu7&#|yCV2lhRrbFkG?}+(0rIvL*-49 zrzy682w9(ZwV!Nl=ij4?J~2Nt$L%Nm5*t3@_~x~N4C*X%sV0+UY!2zTGqOMVQ=h+cytC#75*fLfIvDCHYcz#38+R{IkQ?)i>pJu7f@UF&!Kpnu4zipcMxNfI1!aCrt zq>92s452sUF&O?g-?1|nt+V~GWJ68hOYwC_wH?QLj!#0-?@ZQ`o1gpLhRt2oRs!Ai z+a4#e>f>~>w6B5J3K%3>F!gW@v2UL?tQRuwTT4Fe4I^8-Uqy&K6V(1uNXCMwyNrS8 zvF^DM0iM(F3!{7eOILB7`(D(kAmEMz-|57>z%Emoqd8%v4p zk%l&L`z1pascQKEaKMpVc<~~TOu3PDFVGM>q$L@qf7pdkgA@T!@YH0tiM2t$(~j80 zpu-gBOKtR@Jt!!-W7ukXtLJBiR1mYKKjl+|Cf<4%x#mXqTRx{FW;I4YFWO@P!iMM? z-E{@XMMzOzf~@NKX0nr}Ieh6BAIaj>6>o$T`dI|#tCVNqruau_Xqcv+RkvhnmglKD zA<|ZnTbF_t*QRSO2px7I?~r!->FlmDB1o`Kw+TDhs#ol5S8zf^+v)VdZ@=~OT@zbF z(!^na9N5*?nXY;Y@$~>NL#*!RZ9#J*2FhF&gVyBgJlP8V^aR+zY9DB&X<_vB@oq(( zD@MMNx>e=rM=gUZjjfgW03Bo^L8pkSYHr2x75ASswEp|u0W>AhQX7KuoBbx5 zb!TR;5DrVKNwDn@V?Lz42v((m`Q&#&|HytvIaC$FF|A+p=8M~}*h)W$%hQ$q4RK>r zNghr_7Ngn&;JaJ{bzslvZ(#M@F}tTuI=XrB$*0P_;o$aJjl#)R0Mu#Yexh3ZJX4|g z4>24^qm4B^wDXz`_g3?sUe>{)#!3TxXKxAV5d5_r5)&Oqkt$5r?~h@8w|)5u*wEj z<;v{`I&Xf)qaT_LY-p@FlE66I&u_l$5O;B?Uc`wF{Tg$w;_NDTiPB$4 zbw$tbrhQ6fEbtq!7v7<&90~r2M!R_;KzQLn}v?b_S#)!)wKBjmk1U?zCBQ)p)iwiBKHrNR%@a_M(Xx+ zj8+iv)4i1Z8{UhhZ8zdcsqo+(+v;cF{fPa)^}P8(SX6;cu_kTXo`9_ImdZ|MNwg&h zxU2x73xL&-xLdWda=;oU*&+v(zWah~$>-{|)3<>2$^347Ppu(N+J^nEZ|y$2QEeR9 z-UjD+SdC=&Nz8-%fivN8G=Bt8sHCK#)>1I36&R5j78`<70^1A)gb?42j_9Ny-* z@M5uLZRHnv^sxT3z$}o!Y7D1#WSYM?1kkzyl$gCmRREc=bMKV^Y8`zkJ8-LdkUrSG z$<=saSx_CQ-?qVl%(~2suh?gou`RL1pz;mF|8}Z}gz&>jc5J-n6%;;)(?H`?7CPyZ z)<8vL zUH!7(*;*BV31FgSx6pCwIhtU}f<$IZZk$(pVg+G7x2TaWht1=VR5EKAUIUY-o zDk-#ej#Q2`bY@40ZIpPMvM9FhwfpGjp_G%+9ub`Kk##!rl{7I3NedGo=dc0VXL@+h zuHQQQDCh&Rr|=N`niCH!o-@`So_+I%71Ng z@#SS@50*4;L#8&Cw8dW`T_`HUr`KPhJm(vBW})3W?Xz@@W3kgZ=%zf#IgOLfISN9Ssgh+s z*zTPR#Wm0_WX#lINomRB3cNTO!J5SAbGw*bA%mE*Uty^_38xk3py?TG{YpD(oO;kX zZC5yL8*ycUnu3S{OclV;1K=^A=~Dm~ls5Bv1(Fp{su`WCl31Vlxi`n7ApkC@Wcs#T zTysi0?XG%())vYyjpaF|y|z}?7064K_$FR%RlY6lwYnX+SbvQUt>5SsS!$>oYJfOb zIv~_WM}Wgx66=q-u>NEXZB02p z_B%r)eeG^z5>Av{BL%Cc+{ztoEj`|{*cS&24;$HkT5>`Nl_4hEUEZ z^Ed~nVbE?MO4sFvsYY<>#0r@j_9mTKCPrB*-gJ|T0!GY|4bWQuS713T*zXph?YFVt z+QwV^X`{K(2O14xhnce{oUQ@1&RrI+M>3NM1|}OV$EU=k&+ew-vTRC_;zgR zjBhY0ngHs3SRt068b76C{2EphP&BZG^U%YvEc=b>m*`RaZyZP&x?wGfHo}{&QNbTz z#x2RuIYOHNub&!0U4$Q0<5XW`ST{F_O@~jha4tl?8dBNn<0DbYSAghZ?F;;b;XpIm< zaJ?kZ*L_*X90ZIdMUC^6G;5kBb3Qc8dnw*@Ooyu5K?lFh*zU4>X6r1^+24%6m>m55 zbH2WYA%C|P*lR>d^WQUoU=d$o)hd?|b~^Ri3ear}gTu zT%YEqc!B7`7w*ho4AVUMkr>2S#@e+6wR4U%wO=*2{;gihYf1T#>zYj zY$bIRas8mL0jvW$>S7b@%^c!NGoJ+@pL|^T6PvcB>97xrMdk}f0aaR{nEk7voh^OKD&EH`U>)p?Vrp&)P_)}Z1mYiU`KRgCw0ep+&z zMUryZ)celL*lT7S@at^Gha}JrFwuqeaLe@~K7uLVD!L*2&*B+qI}Y|@ml`Z5jeHBA z_sw0rXz~r1y&Y2oOYNGC+VA&NfQ~H04x^*3P9cMr#Y;^BZdC?ML2T~^{5Lq5J}ejq zzC$tbJ+t9XKxc|ZLW)hfQXCRPS#}MnR1?qK6C}o=H7g^sm=HKNM89>FJgxin*SVtq zf*fFnJv4G!3F4j$Z~>Up4NI&B&5nrNp9+e0jW9dRajXfe@UQK%Wk3qP=`MN?=DMD$ zZ7Dryk~A$FV^e%UvD*!*(hcG}2kgTSj{jYD%6Eh+L|6DC$|18a_lO)6)cgiZn@#3! z_o_d=>_~Oi+ES+Mx9w}6jsf(DS5c(b+Q<-tetD^uE&3+RXeiow@8@1Q`OVgc%v1kJ zOCbPPb(1Oc=@aEvV@>F<^O^rm)oAl^?tHDrQk_=G_s3}bS+*A^Zk^pQzJyDE{L0g0 z7%3#4Ce9U~w*QA)Z#rOk}F18Z|!es@MZlOTtfC8t|pZd`txdp^8&*G$B6Y1RZ{Df0ryymUbn z`z1|p=0zoZ&lF)lSN_>`Js8~n9ck)_*eIw?+WH#*01@U8rM*c!%><6IqCc_fZoLM~x6Jx;B|}`6kKBB_BUA{#7U}O0HCUdx z?*$IXew{v!hd+nz@YAiC@Vs^HOvN{Yt>CUF$qn^)hjIrsZeb`sn{se^#D2~o(2KkH z5+0=u`y6RQTP>b$a4vvoF5Jmklt0vXjO%8{l_NU6I`mo-eQUAb`HxCny%2Ex$~;dKScW8F?lVy3&YrX zzS6O#n-$wek?Ps|jK<^l5fz~HL!Yn|Hg}n+U{UrQz@rvFvW}pMZy?z{tPD1up z6}b1wPuIrZppG3s#eIau^Xf3S+9|o+3xw;%&S%|%iqG9Z_y4@DYN1q4 zy21D^>vdsl0I}_PYhP7(@K*~;989JBh{jxmZ%|WZN7{0&&Raz`)mXW4h3S|cyP=q+ zI8p!}GBz>6{>^(;0b1eENErK1u3^3mTLw(!uyAJO*m^G4<@1C_!yp;=9{u=xv@2Qq zAeLG?g<;uuCQk0GEu5&0kkaIi^Aen;j@BS4U(7Ob#&Q8J_0J*@b?}iD*FpiAn)Xqc z7pD$@NqZDJWeXBodkOpTPblTwmlDO$?MB@G(?wcTVnIX0a4N=ZTr;a=Cox3BGje*2 zbYfKXY@Vgrc`C$JnCOG39oyS!);u}62;ZSZeOmCvlKPFI-bg?xdPPG;2{0-Uv1ED~ zAr0Kbt@9R0ZZoLR$RS%F6?zAt{9+NbB`dxQVC1PjqRH&TnPa0Cixpch6n9*Yo45KWtFl7yi+6jW_}E>y z@}OXaXD&V8@n~22$kcSb_n7vqn3NMuyDv#4e0Htah3j;2Ale1#i&d7est+G4#YmV( zZFZOz4&5X%h5_`fBfE*yQ2hV;qS9Kt+K>u;s4ez^z8P4X1^7siWAQPbJ?H1f4V!TO zvHDk~O}HH>aw}Jr01~mBemx$$j=i+d_t2QV{qd9~C4;Q`kJ{wH0$I6^mkoAJRbV>q z%1ug?vS3CHg-9=4SNKbTi*YB3Z@uUm3233FNd+nRwEW1J+J#OGA5n~`gdv}P4@|(| z!5L2C_cM9n4OXCs>;K0BIFEkdwws$f=37+~Va7C_Vo*sc)=L6KL zJJ<5dF)o)!IZ!q#Us1mcL&2_B7QvF#MAaI30TeR~qP3)3(_tjnh7O%v z96DKPzVtPNcJ&uN>ae$Jir;j^sk6Z}I`a#ED)c|^dL?YD0c08CSl}XXb8~NXi2(Bh zAO_lEbVncsa_mW+$t^du!hzBlVLK>4unT`^H%Ak$r zA9ezF`H*i5(V>-w4l@`kaldZH&_YkCptsKoDVB!c;o#R({B#DAYik&hKt1 z4#hz>6?lWB)Hvk$I9({BzHokXfC83GfR6MyMJ50(GoSv`cJQ!z2M|jv0S9d9!VN`- zsXwkDhjuG;1#pI*<=g7E5A2p|jp>*UYoCX_Me%xSD6?H^TJxg1;hdbPakS{TDU9tK zLzOKX`fxi@)r69pV<2YYB>PR|cz{~VXQ0VWl5e5nt-CO5G^UKNkwy4@sgpm+ko(>{ z^n>?#h|BZtx!$`#E0WyYy->Sp5mJLg-x|3GTTiI|{E{#5vA)we1f7<3 z`C$B;%P^5=B;0_n`^MnnX$aFjhg2|0R?33GCO&b{+QkM*?|B8L{dDc&TaS{)l?BUc zq;BV3)6`wH{!+Z5M`h=mBOe>BEkQhhY647=fMEr&SO5e<0HE^tBN(pNrddRN-GeDU z*`&c&8R^w&%}D6F>Xf!SldTIVLsW^wsCopl_^JuB*GNnOj>yj6l>ceG7p`eu5`&9oIYsYt_Jb#=d5$cwxE^%)DU$l;YMbv8fHXepEWRsV$~!0Bd@m# z7W`qf&y96lLW0rzGLy7<)jN1%0uOjToyM1Jr{d141fsb+#3s>N$z=TyeM=sJm6yfM60kadF>mAUeP|30dtz5%NF{Le^=o~m2ORjFZ;)8 zy~eDY6D8T|PnyJ&xlqhtJMVv+PVaXGLjk-6u4Y20-2iG=SySoIwExL7L3hC+2LZ~0 z%E}p|?bhYKMq&gjENuZG%!K!skmnLgQgCr~y*1D~`;OL$>f?!LZBP%$;fWRtym&l* zpLoXb^dKCg^R4^(k0PPlqa7Dvh{QFl@!%iUe5Xpc@A_w|t{|)4{e`vJzp9S|-%lGq z1#$Lfbo17Kftq-q5__Ir88BShpgAY`wjgA1+4Rl z02rX*LPU*gPaA1%SbWUFkz{d8%hpyW)<*2QxRRALZOFg|`vNMnYyqoitfek=`jT;i zMb-I^NXF22Dp1$^(4Bd-UqLUrQY==VtvfHR@uE>7V|@eyK;1hnXWQ~4823L=l9O*= z9?blo=A0&Yt=L-&P^%!vLpWD?oZD`ePqA{au<>T!bh*yYlIMB??fle~dOm42*aUn^ zG&kSEDyMW9qH9-HOdJD*d}I0O=1S((yIs<6ufL<=ru^dhLL2_;J39^}C=efy^0PBk z`R?G5x%RvY5cf-F-SsWM@6t!N0*vp&%S(ggdq~d%94TPE4Y&jWcbsd4QpO+^+|!&~ z2F9j~R>%X6lOGiF?q&8?Z31o72s!q2P~6u1Op>(1 zpyRDg8Avjgr^|M{KwJJk9Iv<0)#8+tqaAl2cdQ$>`;+>PBIxX~8Q}kgr6%`7imwj? z%q=Dq)LT4=tqqc-WjjCRCtmcq{rrI(u2+c?3<^p`cDd5h*EY&%b|V?|XkIs~+Ke4}6`*gW;-a^=hv7Fv;z4g?^(! z@w_jVLuTsvvr8H4;N4z9JtH~Qpb+n_HikGmfhyi_3{yR0v*&m`LdH3~@GH_mShI-( zg@ok$G_$imvD~hwDXO^(g|dx{%|ZC}KY~X&Vm70Z^aWk2;^!5wJ|V^9nuIi#T%V>s z8Pp?AlTlvmq`ciOq}-i^A`EsG)~)nWZhK_Gi@$xanKJG z^$)9D_l{ly$@!GQR63OKIbzE~wh`$e!Iq5v#Rq?mlXfQ@$4-RK`#1(3t>-My#DZY1 z!KUYvCAoi4zL3()j>(V+?M$1i4LvWQUQI}>b{ag?j@Z`v7V!)MH@<_Qrp}0~=q{)A zeNF+fS9yrLH+a{*FQId!PwCz4kKzh?^iTN^XQXGhR=hm^4i9!3^jtlh<@yj1;-BT*r*(LBx=Tyu7>{&brULp=)8$st7XV z4?@hnC7K`oqSsT5?s5_O`KUT}lk+9d)X^H5f;&a1dcYY^tv|7IwViW57v8%^dQ9zy zf=5w|`eisyq{)P7&}nAtz7Jy-P%lL$8Z9TJhA9Di&=-dXo>#5XB)j?I9jx75UoWGmt*<-G&+J516g%WQBnKKrQb7V z$s|eSu<1-WeruV4m5v<;?5}?Boo|YPNR4iAeoMdQ>hKYa%<#gwo{UTza$)}6m{NYM zo#m({k{~YuUJdMP_$FW+V)A5)8Yr&mE|EFU>7x0x6Tyl@KPaU+Oo{!gq&zYaqm*+u zT(S8J>GQ0T%_N4~?;S4F{uxW#Xm?Mv|0J$h1+7q$oT-xJDVAgc|6pd}ds|{G;((Om zPWo3`U$z`Kj8crlMO)BpSbSf7l|mcY46$C1+&PUbxhwEG9U5kL7>;ox_8Wi$I5Oj4 zCQB&`>qt8!Uh`UGSS}Mg%8skhp9cF5ld6No%#C!~GOC+PAS6))j0~hY6=^x;zmLa^ z4+5M%(k$@4?Cm06JlCAk z(xMfFu5y5d4x_mPMeBPps?NFcR|d~74Ur67t$db;sKnKj#lOGV4SlFzhUPa z+1NO-yh1fB@%+=Oi-z*3x#YX|Hg&Za?_i{;KaU5M1s-1MhL&iOr^5%o_~q3oYXHdi z^+Mih9F3G+f2MC;G8|w2Cgb_T>`eL#Wo+)Z7R2pOA1E~4eFCvtN%X4f^ZQ4u;JgbbDM?+z7qQPe!?i$+*j)Yx( zDDSzk+p~u26icRGJZo`%o%e?d4Jk=ls78iE@|!TNakh(H^}X$@N)p3#%lg1oR}>7p za7h{zbwbFW^S$1A38b@}W za+n`$OmDC58N?*uEppW>zw{dM4Ro+Sx|*J`fo3hW+6 zp8!u=K(*x{OLHmr57Xy-L-_wvHQ}2|>sP#z(?0dFEqXuQU;osa`z>&TU*wNl6*8vy z&GRbrT-ixh32i;z( z8i9zZ56@SEhJugpLM`zpov5QGjwXkn{Xx6#BkB5*ux-OvieV8Fb;-m%-_e9n!z*6P zn3)S2$y}OV0PO3M|Kb1e*ZCfgv;UcVDKX_B+Z^`=#?)@FA z>#=R#2+hdINZihjRd9sHFLdEon44Zo74zvNp|7C$)k7{YAZAU+jie%K`SFeKnm}%u zvOKSltkcNB5EO(i1*Z085W;%&_A1EDmSEfGsMhC6B+Ks~5cegT_aUDhZH`wWff;`r z&b0w^^TH+u)pKxV+#3jsy)YHTH?8j=AbMt4!kp}0m5r1150KPnrl%pXyEe@S(+|AK zg=(93|1BUjV#6mPLYSTvjT}{2E~@I{aILb<;(ydhG9z`-Hk?RWDL~RXLbL6I-`+&X z$(W*$vvu0xtePjm)JjnOSMOA4vVB#Fj~ztzwm-?Si0Rr=W$2cl$6%_vyKr!`a0fdy zFgAPyw|p+k{8(YPy9jH{r??B0F^~&I#tuDv*6_T?O?Nw#&7y87sX61gJZhqf=wgv|Y zM}+b=T^as#5GSwW3!_+FQ$eHD>Y^moGDEr%ViM-Cbbp#cC@;Lbar&Vh5cxS&74LX;q3K+IAcT^ zY~1k^Sp5+8l6(J)dxEUH+Ck?iKF?3N_oZ71+CT&53^VV6qv&(Am`*xpqM`l)3+p`& zFYhS?;(fZ$>3#Rh@wd=t=FNr7t52_Pct7k@YkW!(82c%lCQ&>ZmBg$Ll`TG-`1_lE z<7qo1kWQ466!75QFwCx}O`ftSklt64NsJ%g16c&J2s#j7{iLe;Mg+Yi#9u=}Fq`TR zo5aVPEkj;m7_Wi_6?JS7^<%c*Ec1FUBe=`04XRS*x|v~|MU#Y$AZg;*R<-fl%?hY~ ziu6c%R2UvNs|RQiP^So$bZ$c^QGLj&UP(~2eqT~ZM9iN>zs%E7!$$JPUso|?Q1-n% z-d0FU;U_iO(Eof3WMIFaq-cl1xJZ8(pXfvvQ=5h1{o-K=ckB*9$t9upN_72TsS|6hlWTa$-x`}kPnZ( z&X#wV!?X9t~@rYSHm6TxdrL#_o)$Veq|Cpr}-Ost8uyj$HACYd`$9+Pbmgw&){5Nni zkbk_Dp4W{i9Hv5s8e@QibMiPWc4W4ObzmA;mx#=q!dh^B@4iuszWKau_B*E{sEZ%X z$Fvvbv-KD*f>Gp~P>&ihqU$Q6M>HY$?`J!YM?bjUUv^n2zp?8S8JhB|hksW6IX$JC z@BSO2AEZ%=75h!b=}V}`pJA7pFbQO|u25Yky8Vf=!N;3aH8npFpR@F982M9?jLkVD zrfOStQ6IdCffg;W`U6_ORKvE5E?Ec`gTIpy3d@0)p6#yQ{bay!4D*o{PL`A5yqyI2 zCzBAh$J565{@YxmCV3y%J`yYidItVt4mn`ylkGAb&0=Ff~+4w~dCmrxqlslQq?<%g9+6N?l%#Abw9 z2(;sM)9fhLp9dU|&!KGE{iG6bSI&G7Y@fkH;gX$NeH1>(ZPURY97gPkn)uBfn+fYo zxX3I*nK9ImG!psrUnbhtu+TqyA`dd8+n<9Fm-|+#kJ4hwNh69xBAhF65w*>=MuX70 zz7M6fhW()hp7eVB@b0g+45yuUhD09XA?VrgaM0em6i!wom#vN_lCffAw-m&LBE||R zoWHJzmun2)Jp1|qeeLtD?Flg+tqEC`s#pZX5m$vdpkg$$umIb=8MnW029QTp?sjh( zPwWIG?X<~*t9VMp$O54IvKq>_f|;J}-^jHR^o`t5-H7WwZXAC_Z@}q8`PpQ#{03+POpU2XAW$YX4 z&J`E=-G?oTrkB#CVQknMCxYX37S>2xDMDHS6++7<&cUM`)xWW{KVnKik+d|Ro;Y*1 zF{TzknCwmmd$aj^n3vMVo>Kk3(m}oeeO&Oorb3Q;+t0d?06Pn)H_tCL?qoSv_g(Id z$9T9ssfp#IpSB&Tf<3X^Y)?Y$_v~0hkK`waRx2sKR?b4?9&wx$fI?+x60@89fz z;0#Tz@G;<~jZ%i&={Ew{!@x&depq!SVY)n4n=B*VhBL~A7X_SqiN|-iS@P&f!mIq} zB)9)?l+ZffK+fy=bGok2N`96_!K2v;heKwF2}-KvYiSnMEU6 zQkRTzur|JmY$z%oQe>jeW3uld%%p*B|LIup{@Y6-?!VzCw zJMiXxgKH=$fddW>u|BQuW{Zz_VMKZoKb$hOyXXyH?nODCESy-_+BSZO%g)aJbA0UL zI#jAk3<1ZHMwNDmdW8o5O&#wWva6`1R0BGio2}md^Z?n0+~jwkLJdI=#_`WI89N6D z8BWwnDD@_`wcx1XULqwvw57HTZU|p`hLW}%#W*XLL;wIW;;FdK4%lJAh;HO0I9*`L zj7;o{>Bpz<53g9IGl$iY^>>3{DK&Uz23P@8-XkvZp(p6!}7ySOANAwWO-3VGyk z5$S0*dKHiDQt8EJ@;h(25QixaC@r}nqo80T<`jpQHtNY)%F&W#?VT!M6K`KLuYHOc z*7@S(n?5P1ko2j&wc?%8A>15?5crg`{8iloNjl&VUJh_$7sshRt`zz6)!oAbud%Ul z>uc9X8+EYyYv0Rh*(KSsz4oxCs#&iEsM%6fo^mbbgm=V&JFbW_mX3l14MVWrS2@J} zz1bSMsgoBcy2L$psyX!`r>XB5-p7|&F(>>Rrp~I2d~-EU4`4UO?rz;Zo7c0*gHTcb zEI zeRSVh>2+txmrnB17QJaHam1edp=U8iD0{#|xcZRN6g7ikRb#t(di?PhF<)Twa9o}g z0o&NV`Pa(mMvA_u7RO0mkYSWVk=a2=%UJb^R*l!Xa?_m2QY3U@JWQrBQ9e9WSrXiu zJzd;R^KEgXvKXNI%{O(e6C@xu?ANQc{r6gLWUgXIy#42v;u9lC$ga+*&_#xFXbj51 z7t5l-+N^7GtWVyj=Zy*#(HE*He~*qp`YXr#hDM5C4&zhY{nzs?WG=Jslvx}1&V=3C z69a-j(}P`+B+8iWet7*C#X_@Fk|cRP#A37g?n70jQ}#U<3g}#DzM?{eqwt0$5*|Q6 z_WQFIOG4y>L$lBk<^q-i0;`m6z;}Sz(q!qHFr=DD*&*nL(EanYfR!tCZ)xMlN{XXp z5iCd`Ak2JW%IetEtQ7a9Z_o_g%ZF=Ym2S?&k9tebtFXC@U5%>CPVN473$6!5XZ3$Z z6Ab)W_!RXwXAaBT_JP`F&6z&6Zwc*R*TVzU$Zg^c67u>oAx(d@qLdztcul^D7Za$K^-XDtE znLc^SPUa#MPyID6hCn`E=V4<)orC8+9Nta88o7{gTW3l^+Naa%f*Y1mL&fVpw(Ag} z8Mlz&*1_HZFC_S!<@gd3uyKF#*j*PR_K5NI7Nnv1zpCyhw@01B!mecgt88?a*4_fs z#kMwHkSVp{e34U_tw*eHwISyJCPvd|x!^q+jC1W0gn4l-T?~(A4qw8$xS^S(d0>z` zWlm@}1ae`4L{t1$-Rdp%q}lU$heH>F%|D(*Q_-h1>1K+m=X-kHLtQ3JT`gNyNw|}M zIO|gFIV{Bvm1K$!azYSlgU)h2h%FgDbNafwVYzp_klfGqStBdZ%G9g9a47VH4&uMl zk$w+8pNU$V#mmvU=w?aOZEGo#{_ly7>cjcE?+kw3SaEmmVLAOiZ+@iyJV?&>xxcsG9JXJ2O?GrEZB#f6f#E%q z6&}-O)O)0#E{pC5DFs%NXz4TzNk4uHnpcv*GK=SY!R^S@-|O6gv+slxBQ6|-L9>F{T3d5j9T|@l zQw6E&X`}!)J2yEJ3xJ`Zh$INlv3s9vot=w1sbH!P!_}%;2&0hnk-5UaJG}`deG9pB z=?tekniL89fdf);utK9I?`$8?_m3RKt`??D$ykzL004wULWh?@1Yoi)A5APPc6qpn z(#bH-=AGf7OobaQx`r=^263nc4BW9|T#3tcXj=;=B6KNW*Lb}eL;RI~cFw!LymlV7 zl8esc+YBbGGpm%F6p2}X{jZeXJoC%{{uB3{BW-GdeBuGAuP$dOGo4ZONno`T8$-~a ziK*+CnxvB*9hm`)mR8^ATcPMwRrnZd7L5Vzd{{@uaEjHBZqgeiPB!=ecH4AA`}g$B zl=k>W;hnh-Uq!iPq2$<- z0ymiJu;E;(RQ{bdpZ5B~`zzbKtoynX8cPhvh8(F9To8{Ynd)GOstlnu}OM^QjKUI2bApgtqNrD;2l_ z(i9Lx_^&%OFfj0KmNy+{nj({U5=LI#`73AK8@h{1$)m#r6*OW+68T||s)40Q4*Gs( z3p+cvXlIoXbH-FLsw7~PirG$n&dEL(&e@uVI`U(A}Ft*6O{0Qw2I(BJ|Yq-H3` zB;!vLRy^t0t$*8GF&@yG>jSw#a%r5xuy|!PxYhl*{mJ61;lia1KrPNQqLoJ za77_HYOlJC=H;*76MN58&In$G`j`f#`smPOBmrf0y1xkhE(`!6F)nS?q33e}pXF@@ z!XkF2(i+46`U*qgC4$=eF+i(Vr{sL=w(EA%|xU?~)hRc?2?5eAP0w8Mf8T zlVSa9LfZ>NJH$m}RF8D1in{l{ET=JPEj(x5Q@#{bWv>dTsp;HwPn? z%Oj7Ir!RlPmTW7wp(1rtmuM4KLHn{_so z%Kf*Rw^1)QCEVS-w~@-Yym2ejlk6DB=L-cXh{B1KK-Upm>)S$T23H0FYrzW^+r~pP zQYEI#!(Clr47AE5oqz!H16kpnT)TOWV(EqF z>35nRM}!*f<>qBhtI3(BTEIxm5ctr6N({(sa6X2<|JwMJ^Y<4LHKrZNu+t2=6#u;J z*a=Q`uZF=BpESvAfLxW>3{K-~S(Z0P_Jel!I71PeyvX6guV1m^LEr#9@FeqC+DNi>ozCeH zAk!9P7+!#oI|U!Ri>&hPr&)qL)rqIr?s7~Gn zbS0K{l&bZh4f`D>?WN4D{P^>?Kd{~_)Fj425fV|x$+xuIzHskUclwHg%@F23KjZ@3-*R0qyeUcn!Yolu*9)D2) zEv4yjt+nlxX{+^Yuf_0YQx74yVnoXOyo+aWP|pp=#|I2L5>28t1et2h@uX|i8~%qL z(^{qHmHAO6(^LIM7OmWL+{kUD}?H@qjM=I*`W~B&hkx; zyy!yWiG-u;u`{Bm((Q@1>adO;3EUH9tc|#S;bjZI6w?@oqHgPq&?q10ide68P&!`s!{AEODQ z!<_S@b#K}eIf__Q8jKOMCfheIM}BSm2@Yqf?d(N3i~_7L(3<@L`hqH<>*B0|8c;CRUQz<@izm_SC+sEdB1ix6bhOK1l&zOiXRU7aP%;M|xK`Bi{J ziOjJV3dnG0cqjf7T@A2svF66mQ}a8Tj5SiOnNbsb%p5w|cI9q1^If^M-4zXYhKerJ zD)ebaJ{wk#*ej`(ywy>}USzRJWgK=ymzZfeH6t1day;j^ClahYYMWU!filhhfgcw{ zp6kPRk!(uB)^Ms3_^-{a&t%M7Z$mbTs)@(~&32Kqh9bLYYWnrXw|jdd=6VohqViP6 z@iR^)OJK*&#d%AHv^gS-4H+q&*u}rudL3@{xEREB+)MsUuq4Mrn#nNm4Ts=x^LI|> z!wf|=F+bL>3khcNt)C7<>mTcDYCPnEva-=nzcuIT>&Y`6e^TpNP?K5fH$Z_AJ#j(A z3-Vta*b*Y)T)6JyikUD11!QA;PN9}WJ`-ZxM3R(PEJWGp1(FRuD>gVj84vP(&hKo2 zN->p+_?QeI6nN?P#;gkuN&$Z}Myv8>J;Gku> z?aU2oMNA5{;%sDlfcw(WPKp3|TNLSy5J5H&xyv2&j84r@Zho38v*Me)VORGzoTJTd zljEP6>J#c-l4SOHOrzB&M!kXu$~!vzu;A&VHoH3McvF0i$nX$R2GlWF+yCl-zMgha z%c>`EYNVJRo53mUwRJf*p1jQ>w54vfgKxk7)08**aq4QQ%P6A<_`r$D(T~@eiyrm% zv-dor=Dqq|mhjx~qa~>)DYbi#F%WA-9G>MIO0bV@Um{fqxu<>MFWX9>_H@{FWeAs` z+7u{8_yK?|g2~-{>Ndxt;Z=+n9Fm}|1bH;#NXL@s2$jpIo9+!GY_de6VPHS@AFM=4 zk;;lv;+KncDPwMfP>2Q0F8j7?Mt>(BS5OqmsH+Ea^kUhID+cUxizUghQxE7S8{#ER z%S}8>1D6`)8RY$|uh&O3s>EM4`m5!+xU2I-DMalxev*e^smQ-gWDH2wl4j;JI-HCx z;2~nLdSm^vn;!_QG5Dn)M$(guP)xLjAQMcJu^wzdW65$*M16t$N?m1%cfkfu)*2P4 zcM6jN6>Jl9QH42V25hqP;NS&BGbiqEavAdK=5l;Gcdzf5MtuG9V~+c#y#!x;g@$ zc}QcgAn?l|SgO~;UIXOhpYGJto2JB1F;_5I-Qt`Ct3e>Hzg(9w|IG^Z$FNrV?zG@#7fLo-{ttEmqnm@{s6SOm?u zNjiQk6>C^jOEHB}zlv%Cpv;TAr{uMunrN)_1Mn?;_U(3*k5b|o{_xwmsnJ>a@+|2i z-#eC%3R`F|YZsvE|I-$Gg89vuF!5UyL&`Oa5PNv58OI4<78mA&YJk-cnZW3bmxGUB z?lz4(3c)$Vb^jn``vq^RbX!$xZlz)ET0d#t)pUbL0@dH*+njF-YiFb4h{g%r`&4?X zX~W7xfR1{+yKMkGt1NzIC76WM%~;_)eyBZYy1YUMlX(vn$thvD*0@;cjwhB1YAlCW zzR=B=Q^z20V(!Ggm$+-PW+S49in;04iOGM8M0a3d2a@xw45NS|*uW7|<7SG5%wFSc zY9h!TNKtqy!6T6G??WD}$8)8`7&laty7Unih?L?+*Vyw+V8Z3gkjWH`@gF*(=|UVF#08;b`B@FC9-a1w#lIO zt}b^JJfDQauRKW_P>V9mKxiTZ=}jnE9*nGRGX-ig)KO}?lr^HfB2iWWPuPofY zOaE!|l5BXO`BZsAJ|LrvMd{*9EcQ@j$jPg-x)Q4!-%{lFF*4AnO#k_E0Eb_w&Rl!! zuNg8Vx%tdSxOg`nRqU@Uf(2)$gkWwM=^N`{jgADStf`DSEdG@{RKahWhEB3gVeeTR z4^U#Pb!|PHQ^sXkPj)a_WvnMo*z+lo--mrMGJ*!3y~u)z@UjK~rVtztNwrqt^!ygB zpOf#Y^}1MD6H@1VtsL0N-xP!nH9ilxX#~CUk42vNp1L%Iss4c5ca*fcA||EkaeiYb z?_EpS_9kLs^>TXk@{=HYEQORfk)L2_zaG5fzrTTO90Jv9YH*OyXbIm`ZJVpDZTVrF zv!lJS&$5e7ZDvxOqg=HRAd3z}m7D6`ztEUES(o0Jq$M>R%xODTY}tMm)~?`DeII0j zXBh}TjuW2QM`ufI#!Eb-0!|EIlLQ)0m1TzjvEzDww=K?JNo!pZglpt$?b8}NVyP2G z`&)?YOx$aN8F^Ow*KcVHyF8DDxl{a=Ju!rLozf79IaZ_u-{T(s<2GRq)kWlYj2w&$6u~8^l7d&OGM``4utSC?LZ9(2gaAU*kO#Ssg6}n%sv#dBlI?eHitq{Df|O_c4Pzr zOz}hRo`z^?>cKj&9n0Ir9A&_@Cjj9I90qMQm(FIcxZxbap5Y(%qPDi%A&s63sWDH1 zU-Z{aUisddwKSx6cX=dIT4jV92u#QQHn_zJH&20mQbU-~7rJ*rfaFOgP4Cd2_YyUr zB6{keYR849Hofv0^-e*3hrdhW7N(QyN1mUGg@)jTKwVwor6H@sDZ}^Urp{4h5l?bX zl-yZe!--e5tRWt$(L0OlL>j5Fw~d@QZ`nTk?FL)e;uEggT=`MKoL@jv)n7oA8lr-@Y4{7H(cT9ZctgDF2bo^zAKqb(Jxyxtlh#+38n|@F#_JP96 z5yEa5#ifgMZwttQMC_8uBm(Pb9Bag+uuahW<<21vjiXGL!2D+YFxt*A@jxkN zykKVKxLRY@0nDS`Ch>p|1d{Mg`Bhb@BrP^5x0`(77uyGU`%f|6)_?5-BB39|Bj0$b z^*Bt~M?Z;vVI<#{%Nt2P)4BoMt6zQ`VJ_XBrgf&ggS^`kT`O@!3y73~HpoSlc;Y|3 zQv%z_BXQnCYihkKEfh1APxaN`LS1{sBNIm`CL$#+Dsz-!MVK2L2l8XEi$~mBFB2RZ z<$H?s2q#O?u_l=K+EGQB$I?biv-jsvixF}fuS)Ui%@}*bBH{XNEX^}KW~DOu1zX;{ z8T+k2wxEmoZ`LnggfsjTo1VUGHr#i;r&yN#mpTqnkFkeb*=eK?0~4B9gMH~eXVwKw z7gPPlD|gY{Qz&Oc*lF+*$~D=SzmAQ$bvIgO#TUo-Y@3(ntRh7VzgaSp8Ggx;&qNk>l{`-50?^RU{nM%gSY=W;3e9^Cm z4Uq<~O=yIiLp6pzWdGuPuPGWD=tVdS{bN+j`m=fF?{xiB7SW7OW<@n~V70ZO&mSnC zcV18W21+E6@A$)*d=9VD__zZ7?hW|=U68apEN!lbv^pOI8sa_gZiFeA&f=rUrBI&l zG5M{enWGVL`{zDW1_}2ZcYwxbJ(TJ;mK`?yT!LMzmzxtTqFnAG;JQRh`0xc>-odBu|*UM7_X)YV0HAT}OLuA9mykc(x@?Png{^mr{oCC5*a_9izgsY;mlsLsg zI1!@WqNF@fmOASEsVk_PF)iXdFdRDmGE)9fiRD&7-~Qz`Z|!%~E z7yt-tdz~4|{?GhIbe{s2X%j6tu*VOpF0x7zFg0^Y9)3j`sPVwkjMKPa&&&k zsb0#*k26g4?#kj1mwRFOqfRYPoW~TwB>Cz5bJ0x$g|k~x1J+?fln@IGFvf;bT|Xp` zA%+6Po&EfyLH*xZL)jfRSkKEJ?)RdoCzhs^cFW9B^Qh*dfwaf^R}jtt2`7wI`X|}Z z2MZ*1m$=bCJo?MSQ)BerQ;+@_B&*uI(<<#G(d)5MjBNgFtU3Z;zriEvq%9e=2 z+4kCe$}tbv-mVnk@Y#6mVoH_#@bw##j-3!+LKqaD6a!q42;kfblYXi2u4VkDGj3Gc zLQ{OxFvM_U`{E;+qy#mn|9MR`1Y4pF>af%GDh=;f{>Yr!146ZQC4D+tf7;#WcQLwU z{iPfJj3i$zV&q4#_U}5^9M(FY_Lm zt)FQXj_kLPDRLJ>f0#~CeGr&MSp1T6ksD98I`^m52FW)rNHUE9GYlZPHI(bRoCZhA zn5tyC8Y=ROG1O^<(HJYZv;UP0{vc zR-&BDI<}oQbkBnBkhFNHVf2X!(J;OjQ~$QZj0dB{4lS9t;_vxbwUqWVK+&ch#upQ` zRG=!efHuo_pWE_kss0*6gUWJ4QS=cS)%xDd=Cfyv!>je?oBN?lB_s8YjTW;L2g=Qk z>Yc#=cSpyQ9ddZyFOgR(JgNA$ z{A;V}i>Px_z2D0tCCMx<^B%4C5d_}};X;tl`imHYeZg8_UOCZ zCaKYlUP^9(j(~>>U-%MUJR(-4Z9^i z{iz?`QZ=hy#OuXAYjLExJRCj^92a9K1 zmZ$^#;lON-{e;ny00EGWW-*^6YF+?iKGB0N9hLq7pWosh$ZSdG7hV; zJQo1ewyutQ&u5vVN1BBww;s{SQb7Fv{Drv5X(RM*3eXRKxcz(A+@KeYouEOF)(Ft^ zt&JID5BJ}A`f|j5s8L^cP+Ti);|fVLgcar>nS=8T{ZEcR={5(loqvd%*I?Ty_OkV# z?ZjMT9Q*Uc$r&Nl(yzXSP^qr0%uhDp)0Z_@AEiZcw=v5Ic5mJw2MP*Rm!GkZC8=L} zNUp|7r3p~QIJG`ko)8+ngnr(@g}eK5P_fy6u*x*tntz*k(#|~XPnfZo<#cKJ0h~*Q zM*%R^cDfP82{<+co@hT}j)%?n?LhIs#Cw%wA+$o|5c?_ay?k#kx&lAcmKch4iNqUW zYnDUn;tBhzi?2CS^f>*?%bLm=i<^t~fh&rqv?uQMor1)Z`rL>abQ+aC&D}4yyF#^f zwT;2k+(q!d#;jGa+|krJ4(9_`5J4D;85Z6YDIYx%()akIyJ13yLm{}j{&7r67h6GS zMh*_>V+jOBb6U(c2osqY!Oc|xZssMz!fQ_FEL9%&+hG@jOun@{yq?-BXr**!qKh;V zLoRwiwFI;U7|4zH8ob<=vc}FN>n(AI87}Bbu^Ez62>TA3)~_4cBE8=!V5RHgmN_;! zvJfp%$qe|tUyFX_ZCb&4?OSZMxPd2?2{C3PXAKiV%8By>u6G^P1lztI_xQV9j`MSw z_3oeT%-ghOd@QP{SwtxJt_}h+-&CACTV{%^`}cK;aA}g9_82tSHweTA{-TymnmXD! z*lNA#966#5y`p&@50H}EXBkfI!9CD7O~XfL641Mh1zek=_nmscZimlTNac}eG(ULqtANv-eMwStXW$9@lm8 z)}?w~)5YhaK;j(s-Tk1wr^B-*vAb^DKf?V6m>y81 zWTU;je7(Mn-A?CXl`dNe6l%wUPaZXLacTH|Y$yM^zMhG4hKXj*WY+e|gF)+QnAQ;# zfnS*vl%uj&73$5qr);?_%l1glsTmHE7zsm zIh$En1f?dxl+eFGhng#>tJez0?vRiZUYw;b$xGRxb0?7HZTVd9tPYm2YN+}>^5=jo zD9h`6xjn1v(Eqpqv?;%h@3sHPu9qGUpq90J8-3*VZDnbCo15#!)A!GR^dAv(X1=z8 zk@a-&P0ZE#D~fI3_e2qzN*tYw1y~Xh)s{(d!IQs^v}@^9IT}}HxnnzQJKE2sk4^c8 zaBqPItUaT-Chqy@^ScHZtMj+VqoBcsVP9=v*#Rd+@JmQ-B9@>@8rSQ>K>cuKsExY&qjG;(UrZ8jW{!&IH&=(vC~7d4^I!v5vy?A zrjF#RD#DVGQcO|IZRxWPVEGCxxim(}i?ef~_S%$%wf(6Z3J3A$p@eZX%loMxE*9Fm zgGipYNNSwj;VyGOd7~j2WI}V4lU|i6@A7}z7a*Y;y31p% zY^TbxW5?dx!caj|9V|N*vug-k{3?tk0S5e5of1@5`(!VfuqUgd_xku2suC|-IuG{S z<~k!sOVw2e>gWkDB;OOVH;6}xDU={b^|2+HdHno`_xBlNxbK|;Tm-JMc(nDqXZpCW zy}T6kE1#udGzw@eQ~U3wUW+}jo-Rss<&o`dbfeTGzK)dE5BYZMGJZa&v?J%D?egu;u3?Y@TJ|^)-6oh~J80;;GCZP;6 z922cj$QIMURn3Rx;O1|bcq*!RYI72n9HhaD`G_P+mA&g3Q~-5k-EH)0(g3EV6HB}I z&3_hJgzDe?kdum%S0GGh7DU(eU(;riWJl*fK!EHb!~i)0Z$TmJReb-^2~{kKkve1$ zY0F_QZhDfJqm4c2uk-w|DgB%_l6$q?eI);QjwPxrqC_)HIQ7}PORFywN&5G&Cl(jyw@Q`#mlecRKTbN+#P_RNqz|Lk-dFBY>P#ENZm=f5BUzv z&?w*0tj5cABOtH<#&Fbw=QH=MG7O9e@f01Y0z5$J>}{_Qg?*&4Sn7f?=4Nx(3gy?>3ci7~$57*n62=`vnTV;3`ycm{A?144t_cTWn{d590l zA)@sq*;OV$Yms2mmQse+BQyDOnY3X$a*Mx)KFUWn01H%uA@T|V-y>zWqd(+^=TiM! z9*JuiE*amyddRaRs9wO`^|VW`Z4u3S57mRB=^wLBM5HU+(dt8J z@n8GTIfn>G;C+poW*u9q4aoq84ij4M!}#05#AuRmNn*}fm)L43>&wsRPULKak~wjO z*OH&tK==_DLjh5INhv8nOH>e_x19Y^V#BUT9Z-VBFY4(Q#P8QkAZXoU@X|#1uqRU^ zMRkB?R`%9+IN3B#h4hS$H6{0}Bf9J-IJU7Md{-t(jFS(La6`D8EdRp05%gfmKjZb& zpT{9T#O%jK4qTaypG}CBqDErfckjLKzHGEL-k*mF*=T&&3jSBO0NbB!wiI6Q11PP zP2xN(ydo2|=Ozj*FNbR-GX;4g#{JB1IZ}e~j9@ojhMWU1Qh^*;dK6+ThhT+|;VKV7 z9#11WLj02vOLIfAF=zezm( z52O7Vr3+o}Kc@Yx`+`E=dxVVR>?&zM`Zc)UurSAE!-9bk-=jW1TSj+w3IU&VzqtXE z9CYS+lm1EZ@3A5qTO3wCXmKoyM@fyef{*&Z9-c8|h@pd&l1ooWwsEalQSy%s+l_X2 zdKLFDgc>jo>C+sD!rUdUX5g0=eh8L%8H{5HRzPeRQa8`IZiCF~wW8zVz~~Ji+O>zJ z4>XU@$xvv^eBCI~qM4}(l~;mY^yWA6Gz++WchaC@-~2fven_3Jz{AiP?OUovR3g#r zuGIOR-z!4bMT~vgP;Pdf^e>(hTXMJ4QHq;-ewUUrb7+G%8XxJ88PW&`q<&oQUJT!n zrW!l!prEeCK0q|XZRqf_gZfHHD=6Yw1@QQ9u?Pqyblo==?kCIzjVGGfQy7uK#`OJO z;TKQ>n><;K z9H{+J;;1S+rfDu9zm!306>p)0W@piAz|=?NF~oz5Ebu@0suL(0gis4;3~kl@XLn!? z0ZhNkwLx|~g5o3ph73(SoT`tWhRODqT(G$jjx2lZ;^oYK26%4NsKLtcSCk1^+C$)a z3;oRNwRXcXMKz^|Ypi0VSHd62E%~TzQGKdEih$!LI10~;K)8Ior{3ofj(~!>kARQQccRwn&?t>g=O~5A?TbK@`r+?(y?vrQI8%TYIZHhp|o#1W;1=~(}Xl-jx@qAH#O*H{3|v(@q9`5 z7bIaNNWkkh6EpWsrS8{GjIe)AZ~B@4=n{yL>jp`YY#ieaY5PLrlRtWT2B`gI1~f+? z1OQOWDZ*_yIJoos-8hQWwV;3hd~3>4h5EnrK1H)niFQ+ zwfQPR(6t_KO!^|@H@Y9C8{7iIQ*lLp3GPtoT$NLa(JT-ur&`BdNt@-G-j>sODGMj5 zvzsE^o(X}?LKD4S8`gLV16`!p zPBM8;sVA|3*0k#ew^-(>>Y{slm?{z%<=i2$0{6*KB4AcDAg>oINYHPM@MSnq zke_L2qjBApQoL_(txx3nLVG1Kn4ts-6_%N_hM|HrtzecVW+fwB^vQDzT9<7BQysV3 z=t)vXvTe!h=ul}?>@ICZl?~H!vqgx+WH{_J*-+Tam4JKRKtXLmfc#P?QEPV9iOpw5a1Nr2tmdQX;T-*zYz|ZRl19K; zF_srXsw=nuu(^03edpCanBjEuqo}IfcIgl=45sMBvad0l3)F@L8tvMj(rGJ`8rEbo z5qeGj)lpT?*75Y6Oj``0RwA>UVTqa;T*Pf$_8=2mf%2|0OLNcIWTT#gihIZN~MnqsWo10K^FX@&tG@M(fYRYYKuRh zBY41EQ}!|>xH!iVlU#E#NWBg8_u!9p;I<)XcPpA}>rpC|@J({hDfkG;CY_y~BPMkg zmX@K_N1?8t8+|O>5dOFfXUDb{lndmtV-y%-Ls#{2v9wd(Ridpil4y&mF%m0~hdWp| zlgp&ewPi>nJ&Riu?XD?2x@5TUl&JW%-_|VttoB~Ktzajy_JuLo%)c45wjFkQ(A=F! zaciQ(CDYNEHB|Vq?(^lcRjdCUw}2eiRBguNl$vH6KY+Jpam05;f~N#lNhOzMUgO9X z|1k{ql)q-pF}zSwq33hP^e;~Gr#W95(n78sMHOomN8;IPXM%S36@ z07heHa2&BffPug>xk*jSgBb1?J1;s2-u~LPw_(_d_IKbzNcdx$Eb2Kimee;s5f zyr|m&12_ffs>|}ZFx1^|TnhZ%mnW}17F03qXV2_7j9K=-O_Lqh7juK16A9^h)rKzQ zC!o~5+F?I6>_~4GzVazN+l}~FA2rcs+U-CUe@4&db!)x1o2!$XvK1KH+bi+j8`F^S z(8d&4@RnX)S)MEoFJ8N*#ec&-R;BrQ_N;!lpHBUwHxpGsonl77@YKg*`0x!3`vppxCpe*fOKsFtAv510=-DPHH zkA~0j#*9j>5_T#gMB}f8^>f+ykhb;qL#M^3yKSLJ zb64Z4S}^-lxqh(6JL`n^_Gbf3`a%K!7E%jedpN&bp{~~$RwYO>qB3Th;-ZO?V%9Sig^WpmTdgt`)8To7=DLw@1 z`6}+Tcf+9NO%x6Tq@S6}fOMfjwb51+MR9Tc6ZQj4Ikh5Nb{xmAvdFV%_x!suYUKV$k(sdrnn)BxB6c@QtU2@|ap6sX-DKmk2766jLHz7lhZF zttibJ5By0z9uoLpNgz`{KWF=~>+I+BUOS^ORLc4hu*4jP5K9TkZaxvT3AU0jWh?H^ zlJg^^v?6(Uqd@Rstq}iZ4_|p1&S>VnruN-^Tmy9?54u;;@WcWibSX0Oi zy3diA6C|UXm!2=^3TdTHK9Al)JMnK!p0uCWr?yQuZx@bC8KCA)q5V5Y9SL(2=J&<= z%n{z=+fN$|a)UqI00>NW()d4`zA-wl{^>eugT}ViIBgo+P8!>`Z99#9#kOtRN#n-0 z{hs^(u4iRkpR$7UJLk;o*)y~EysJt5!MqGG7J4W=E8qq7r!!#yf0dzQ!?xIR$(l%3 zc%jOM<@)U6Vu;W8(DZLIHl#0z=p&u!?gKvFGls;MC2-IK@1pBguGVc9VmH&Xd@**d zDFZR{#9pRf9?$E(T=)ItJ6&j~A{6Nv8k*P+HaSfQ6XR-Fj2qf&-hGU$J}_utgG?nf zKmx`5#rjT+nQhMR`Pzg<)Dm8?J>eX?PvXi^<9nkg&gus3J!+xu$i9l@IqzK;8mCTa zC*wfk=rOK4ENw(Ue`xGK&Cd@oPE7jV=W;AEP>B#Rc0kX!tLJw=8j_4rz1!3FS~r1j zsMpxQA}HWMZed{o^rYeGS<@2ER+nY)TGeM=G`1h?PI6A$^pF3H8ePpKRFnAH(b_~^ z4rcy|s5uJkalC?sz}Egs8~yJbGVl-NFEh)sUr?H-vocHe#|OLUo9PGA580AK&aF3G zg}S5n$NYuoe9C`Orag6eA~wf)BfN%D?PfJ!%!kkK^QbniREGY9G`d2mt_R@7ux?o1(Fry@FkOvilt&J72<*+-zM@8l z!}*jm?l!_c^sXtKu-hn-8Lt1yM^o%wJO6hE!m;(Lke>xKfaj#T%l6;&so7Rs$sv-5Y9MA3rIgu zFs}!)E#E6PHdqRX&AlV+ex#%{Z#~r|9jRh}&0o7J^G$MDE8*Y5fJFVQ zdW;LOGFhrL_LMzp6t#6XYf;cq{O#xqGK64{IbiJ$#x#}HT%?~;wb4BPtBr1nX@AZE z57TcH+`!hB@#5oRx~AR)|4oC)D;(x22S!w{H^>VaHy;KPtgW{Dl)dZ4*C(Rd=lWKy z!^}U9kh!-Ky?7p*?n|r}XfP+(Yo`r#=w4C=7qbg+0_FAMJa3<8S+1$%V&0E@i{>{| z6BnDu4(siToZ9kW6ig6-uqrj;jI4T)KD|RuLEWnK4DGSU`?a?-WEaTKLrYp)V8M8m8 zKMf{d5?0zu1C3500=8j7Y;r6)J(z+Li75(wp|oGyTd$Xh>;`qaCukZjtOH45*~~ zS!+?R7lQdA4MGCpEoKNIe#~@-hF-kjfH88tDpj9ZfM)d_V*G~cv9cx{v*Ev6HLRDC z);VJM?4(T}YKI?QBF=elX2#$S>ZF+0QBUGQk7$D~pz8S(0B`F^5iK zYr_mHyDj4eHJ*n^%XYPiPT2~>lco>da}U2%y)IjG<6aK_H85yO4lB+jVF4F_gwY#A zfoLngMPBya#{AfV{!Dj1U2@xhQMNmL4@B3@R*LjGRqePXBV8pl#H!ApIvdz1eU;x49GEd?2qut=1D&5 z^U3SX%%8)n5h9i@l?=S3H`&2CH*SV%#p{dj=7J0wvYF(u-+kdPS>!~LnUe_&|w8okK_^o+zES&$& zr@iOGkeBJkJ6MT?pL6&YIa;k23R3ff2|{iIm$aaQ`pfE3Mr3#eBP&N0JjI86;ssh} zjJ<6dXE1n|6{ ziPEQm^js;O4~o>#1=`fD4~}fNMs-Bq^%6OiUpmRJog@mXC(|I{52y)oj9ThL*Dugd z2jHrFKik#2edqzNAaU{^RETq?kTRo(u!!BOL7d^g(S!>Lz0hPPpcelAl$lTPd-2V- zG<4uDmE=)K@VNXfWxxg^x1}Km`QS}=dOqG9`+j1UFWLN?__-7(-jqZR^1whE2#}}F zgM(NP3?gWMytQT98cn+NMmt@uq{x^|9t6LaiZA2v`0d-=(4b_!b#+zK46E!6-O(Ra zD{uKz5lNyl*{3RMu~d}Ix>C9vF%=+ekDbzq-rfWpruha6!?Wn3*@Yo7i&)cv-9*87 zCIV#KJo=!jLX=L=md~ne2s_}W0Man9!GgaIBSk@@!W6}Zg<0Xu_S{nJmW$dPznwZ) zc?TyS&kqN`NtHFxTjz&UwcN%R8H%C8@TcfO;E;c=wI<9kHr=M!O1RiwYmO%qEN;MjS90Ydh}XW#uV>9 zJ|SFkwP<(M%^m$(skj@E_|ST6t*)~;_n2C30J+sg%Txc5#Fa+`7q3fWfrRYD=Xry8 zZF8x$d<0kE2=#qgYp(Oz(3l=t?#6x{7NCdFP~WOut?oiXKp-i+8!5G3``fhf=X_Dg zhVu{&*Zs4sv)`w>36MivzpjTKxpey@wL4wUvV#n(p_bk=BZ?+hjjsi3<}0wPhWT)B z>{f*YqO00n=kuXw^c*$US?`u)Y*{?{^;^0jGc8_z(shBhHpyYY(>GWCU-)qL!GUMH z+jT61v$D0O#%u*Lwh6~I9V13TH1Ao8AFoV_C0n)bQs3*AGtT)pOgH_~GIs`RsA#iR z=_W0{B7-Ovhg3zzTC0LLi-LLu2+c^Z7^>1Q+}1r_yq81Q9os5|5_bkRzr?J#5eRZ) zDM3CXR^VUj&|~457w#dRH~K4R>2_aypH9&<{{LySNSL5GBHh|c$B58T7mm%f7L#A6HakGc!j=RBXg%6zfw@emTYZca?GO0>6hA*?s-8n# zYpM*RslY1})fR=g!KeMj_UlW?i?7`}OtMQRB{;JHZyVyEtM$`zPxMF;#%W>eYMRj* ztJudePH7c5vY@L4o%c|5H5y2EA&w=qLfhuwm=R)M$*n(|-_d|NS&zQlYyXr`$ zk!!ivt2;nOoBa7(T8T@K6!r1ir#v(&M#OBGtk5UXz482FyA97~H%^#whzOs3ZevV6n=LiUG*jC#Csx^ER~1}UxdtsV2y1OaJM?J)%jPhhc60P4<`)bJ zH-yG<=BVzc#oScw$h_Lzti^It@sP&8a=Qv0=BUw+P1~_FS&BChLwOQk^2Ui%Z}rVt z=qma%us>LgT8#_?Wx+`g-s~;8qfUqUTurnw=^uKrBU8z69koz%U7=2hj69=2n)3sv zFWLNPs~58S4-6Ee@3FbD4tr8(OZOz2vSxP7;ZI#Q5E=yynoPNmD(<%kH{R!``E?Ip zstqh1QJ;H{JGIV%dZ_OL%eDRXs$Z~b3dn>16~8_Z+qMSMZa%62Om4?>sm}Bm8V6K` z&fsx27A`?(0!1boNrB>Z#%KCxO`|;ZjCV=KsZC3gSi&$qFECRcE&ZwE#P5kmVx`JK<4NDGlgtJY{TEVBbFhDCBMw1v57wa*RKYsD68 zgN@l;!TaT$Zlg;G186q*a{Y8!3rivxV{xMeIJjqrgP_2()78<7Dj}o#_;S80EFF0p z3>DJ~8BO{Ge-9;xQ;OV1d8rppLKBUBN6v+_6Pe2EIE-1$GP0Bo;<-P{6{n7QL@o2!HNB){GyQ8k-|AR{SAy*sy z@y-A0LsqBx#}trJXwT2jfo>AuOe@4(e7KvM2Ga^Ux?HSUR!9NX**;i&c1o43`Cihh zuhjC0Zmrm2iq(tDtm#Lj!9(iMb+8RuZjqm>;0c0_3Bdtt0%Lo_SW}1-0##k#_xt5( z1D=TNpsv} zj27#RQB!EuS8ZEWkgCR@3oA zmkby{r#B@vX4Mci#%%v4`%i_I;&)0E@x+b|@iyco*18m7c%DPv?jUL^eo7UyZdetXfjTzuYKW3XM)= zR^>Ci*Q~5nwB<2JI}|(~3XAnC%B}FBKKU@up9N*i?8a3Q!jt%rA}b z;7uyp5`Ev{;O3r~)cqvUMp_@lOPH?Zwn9TlOWkG1D#H>D_rs0w8zVKTjr9bv2QAJ? z4xbqNm2YB3i~e`UsIWjKK57)tPyAnNJAhFO~GCc)WNwfu5DRw*HIG4qTgRm8_s4sr-c|9=z%4jXtz% z-l%%|ST_shzEWu@2Jpoh1V}PH{YZSVuQAs%-dya?g9?~*W?UpNW{T%c{|nAB`m9BU z-Sde1iw~=EHioki${kLpA$9Dad(OYuSb~0uI`}hK9*A|_j#%w&i1DKwTDM4-dwU3{ zCn~*_Z~todv#xkg9Gv!8@)TCYRgp+SZh%uCssfW>HuX@?w^vvfyBhk`9xyMz@S@{#5bF z`R?_ZLNOj1LCS~6OJRqkN2xh3(Do!*m$&WJvs2>rRUiA=Scm6x<-c`3yLP!9{EdO6 z`2qb-ZEZl=+L8?dAJ4Fa$oq+Us#hDm4Mft=oe-%?@ig4+j%RIc4T7^N)V8O`XI#4w zMZzj7KMOB-^lUumU6^#vZVeXO^~OF-%={)20HZA=y_l{VP#%zxZ|CNxWQx>U#q!NV z^LZh3bNE1}s`z48{Y$e1Z^nOd;sB+{uuKJ24r9KezCQAlw>f%ne93Mq`JOz!5~`nK zM?KUrS2Tz9V?{bWHy2#zjAP)Vvwfw}l&`d+f0*}9RRzy5x}U^D_FclPvk9 zaP=fcRP#2@X`6#eVPEO`-91sw?dIqH&443aEPB}2Vvw81eP1Iu0nLiv#rb$mx!jF# zZQ%Ikhib>iA{i75GEAcN#Sm$3vO$V8{T z$CXXl;EI$|6>}@+`-;`j*yx_?Z8526sLwkA3#TX$La8{Uw7x|oI6(nwzA<}KOB+zc zR+Qt$Fj}I>8SEE=cXdfP#V@*7qs@LD?$)2Tm;FEFu){8tkJ>WE4kCJ=U`?*n7+=X) zLXm4ifp41%E=qTc;RlPiV(p*NBNEd&)7M>QaB(HnV^`eESM3^i6jX}zV|paN^JBO_`9ZM#q}yOKK+Ua5$`XOj{j&?^<~&xsx_& z0@%%;Kl1e4Z>>)GJL(>yPMbNrgdK_pb3<4l687>oguZQ>!dz}lQk0`=-2=7>OFBg0 zS+~GIzaMge!VJR1s09l+S;D3hP(U98c#Vq zZ#j3uSp%F0uQNG~>diyGzHq!5AiX|b7(9X?;Z3z6JZ?gq)smH!zqoS$U_(P4Yb}!G z$||AARj{z~*=apo=G&=T0;*t#urI~gz{8fi_ocbSk?z~8NB!B6BR7P{b#_MwCAf0Q zaK?>Vx14YrujLmR;dF;+wYFY|WwmTJ|Z{IELb4uYu+mBIo+1Iyx%(dZtXazF) zDcF#T2sh+>o`q(;torh|Dq8S!k~NNrovvW7w}{6Y_uFd#g(8L?5HA=M8~l^_{%rr4 z@8xnR_w@UbY~67WXG*q;!fGL=cnL^0EXC%+hGuf8mjkfW(r$w-*B_1H%?1=4X2L{GFm0aT_ z*d^@4RCO|3x-%vh_dZqY_?LT?_mJhT+HQeLn@0EZurgqJ-DFL;{(-!_>B9)k(9$Bz zouFvD%Rvb6dYU=r*eX5u0g*C?n}jjvo4sjxY;K{3G+&Q|J6=@`>Yj_s-@+$|=6^3= zk5y4#zX6xJecj{}>vob0)|Z;8x)!o#V3uQU7UFM{E`9@V^y>c945Wfy@msYsFWNyB!CC2m4yHuZg z$q1lPY0SmUZ`zM50N7vbRnJ)VwC8r-;LjG=Db-6=3HQ@D3JE8%`U(yGyyzV}Uu(g9 zZe6JiYt|?u-ienRZUv&0`d5?}b^OM%Gm9x&pa>8E8C@<^o<8?N3{t$)@nPhccGleY z<~7&&NJX)J=|#Z;DCK|0H@Yv$|ETq>E{=CzD~*>s82c`GxFo>-W=ozV=5hfL zPR_&CIa##lB z@R8;@c$6_CKmQ!>_IhUT-u6htkzW)_>--Q3}i-ujhGU4I8j2NEQkisF*{4kkFOV1kX}1OYtH~9 zJ$3L?7IM7?2ha>NQ!GF%JkcJ&li?$L+n>NtmNM(`_7P($Rf@>y@_+`;+?zq>LQg^s z6(O}=l)INe2%MzXj<^7vggEl-bdRff6QYNrx;;#qa@YDysRUz@cabVVx%@t5Q68_z z-b>nr`}KBNs%EIYJKJrwX;KJ@cVbbuJM`ikLvBqSBu}!FvUTzNkRzQqY?}Zxsu-N> zPiqLA@6Xp=vJH$MSgM_$)17;bN_K~2{;6Znwv-2*lFDnK3qoF({z~rTGk|I_q)^r* z$b~gYc1tGa50WkbQyd5fi^pPLcTS95w?oTryXmyr^y2KX&ka~3&qnBDOj9bDvB%%M zK1w;JFF0W^RW$fwt965_(`@t&d=gu^NkLPxcpe1RprL(m+GB~n_`;(&ar;5ly(HiL zT5DL6fydVE7-7lzlRXaPjiwknJ5V1P>vO=GT&>Z+6iv`T9$!^fX_F}HYg!EwgbB!n z5j49{;fGMDD?cU9e(7UtIf!tz8yZsVe9XZFf@jlg=^;T`;V-y1rx+CuD4m5wgND{gVo+5X~J@) z(kgh6h6KVadFDS;5D891$PAr3T$+XcAK+lw!g+-V$Vf$K;?KSdU=OYr! z*4Vt|J}7OV?EW>O^A-2Pm2b5IJB5MA63&vNvqXs`S>a~=A4!`+s5w%TUYL3&dq(PQ zi70pV`$A=f+D5OsX$2X`iUJ)ce3zqLsW-SMiT^mnUta?|Bs_PeV6Ok|hAp;Ue-d?d zP17E~m~P}%sl?pfIrZzW#!?zrR;4qgja~x92scC^0qj?A_JVXj|45;6siQW9f2F7M zeh4on3IP)mm##EYjfzgY+)n|b54LVkTO+M#snc?~54R4Vtm(_~6U*F%hf>mM>sPm1 zrCK$k*LS3wY2XEbJnZs+8*|2{mjKFuSK#K#2;pKLg_H+aCMwxI67C#TZCGuzOmX3t zHz@J};Mj3osZWmEu@&F5{o%S6&t^Zo$tQ|F`EXGs0{}D8{HeIuxNXLIYE^I-@+N<_ zHg55Yt8|9?zMO;Ls&Ex=5oAV9A?5Kt4Qh|vZ}12S4~}MP>zwrUYx~6A7?*#0rjofh zAFt<16Zw8zrL@@3uW__HTd(k-&yF450vlg;_g>ueS=0+q3IOY3QV%4>1j$0td(V7! zu2z#xapa`k@7-u+mZ0tgU3?!nKu!KC@*AI^Co${zFKYvaJeupbJ$gD_;GO_*F1FbN zRnA+M-splG3qAx)6-UzSV#s*-qSNaJh)#z{ZK(2%xr!&^i!&qbyh)B{Ua5w-!P#yA z>(J%2mUZ@4Xt~?Ueuj*Y&Tx(H80r?ll}CqQP!x^M89@9exJ$On{Z=LimZ9{IA8T7H z-l@Bsk=EpZ2VWYqhON$Lu1F(yl0q4D6W@SX*N5dp=idFEYL%F+#1ulfDMbO4_Aufw z__iefudFCPBG>bP&yFml&v!0!Yv*^T684hYIF<=4rLt8QXTS=JZGFfwGDMOURA@&t zv`z{F6GsL|TY>l*P%^`RceQh2=ykVcySq!|=9&h_5JeE`%8)0)i|3aO^?h`&rw2^v zIJeG8D(uE*N?4wAoB4}I509~TCf1YpHgUJqmzgrxE7N zv6D=uD>MfY-tv3TP_uo=7moZJ%R;mZd1_(6@{cgqv+Dj3a-l`Bsb|mtB z?nh$csc@(+F1Jp1?BmU3@rRP3m`uU{{0mRxX2%+2Shk1Fc2-7*dF!M1X_pLeK5k+@C>J1-tc&{(F_R^6)zGSe14oaPrQD@RT_zuQ*_)too z#oZfa3KiZCn=WflFNo~icQ`P`yrzN=sITw((c@E({bv4*BL5M%yEx!lvnf1c@7Ry$ zdl-@@M#dK5H~ofI*{`(hU3QX-c%S5$d;Z8b!nfgt^*ZGX8N7JPY#>o13H&Pl&*dOF z2pYTdRq5}e;!pO=Hczo@tuL2bza>uy69t@qYz_?kO99b_9}e5JL?2=z7=YC4uHnBN za9=AS3!sH_CFd#l9UTN~Gu}*RcL&SqJTHTw&{I|aD@5>ubYDsVdH8t1IV@Z>Uq>TJ zR-zIv7@``XI+u&R=dvEU!%O%0B}t5z*7{Y}X<_ZM*34?*xBV_3HApZ5dkV3T1woY z4H6t74xVI$|5Eni?Sz%(-(*S`uH7=K2>*NPh?iz8xg&!?+Y)AX+4;jO(OyJ`uk53{ z?@5SacoQiE$;@HNKs~AgV0Hwb((zBS2H7acjw0vNolEs|g9|W+6M_+--m`FGfj!#$ zU23rgP+0#Rs3{hLekKkz2bO}4^`V?EErbOab1l@-!PNzs*8OwF^H~y*I!#m|PWYU% zPG5T{pRJI6%nKA^E4@ZS^xfLteby!c+vXKJ$?qJr4MAH!1$iB1<1VcDDxs*9swJh1 zai@gC?0+Q{dTghF#VlT02tEp}oMDFu5F?kA2`alYettHtGRLv9C{%S%`jlP*UAIHy z*19**4mwu*x4!D!+_1xYAfAmap8j?4fW9{3@{d0pY&8a|j6|&UE9&!qS?!NE;lAxz zmQ`+4rkOr)OoIISC)`dk>h11=q?7>wDEsWV_jKBP*JhA9GqMNJVtT594~kr{A03?D*-8bS1auGnxAz zJaixsm7+D^73UV~rN|lkx&S3j4j{wXF4=(;VD;XY3pJ#$G=R%pi30TLfj7;7JFt%0 zBRQb8!+~YZed>4mWf^Fq?4kbIxQodD?~tE>LpGeJe4KIa3eq=^pN8%04pWlF{+}p5 z_?VKDvo_-zdeuyS{@A%BLD8?eyj)Ht4}lFID=J@X&M@SFRFu7QTE>cW)k0PBBCfUR z&yFkXe+=Zdy6)i2WJ7{}B)wuJU7RLr~34wc!pr!31=1tDiBs@Odt0I$|PvX^BiUEF9cz_FFD;-DU=_wnS^0P{`TFd$wOinTgFn0-M&0cG zKGgMU#w=uf9)TmUS$krPcD7A&|$P|j?1Z$g*wea@jJy2 z87fepdS#Jo4kP&DVtsm;@AFqx>kfg{svE9?BxzjOwGs~ z2-+^X0;N#7)LFoHIEshRD5!)XG~n@27VP5%$kiJ*wY@%@s{Q=fbl-+I*EM7yG>{Gy zGEDJ4I^`Ksc2!-s`uTi!oAEnx&}9n?$*&hq65J#?@?e>NUL}57>IM0=(X^mSaT0lhX=YTyPNoF6#?R0E=6tdL;@cT*ngVZN1*b=8c$E9nUpf+RF{uUY zfGFExfzQy!T*vvghs$X{^Ri|!=iUEYR<_I7bBsq8jH*kRV~Mt7KeLIDEFPrMYgE9S zG^xjSmx#pClRxO_5OWk7xq2!-1X>9Ox-{WuO`VT7e|vNo&w)E*YEI2T(@n}sbNT7Q zH(}E2 zoKI=lNkZVU4sX-xEBDWJZ9v1;_gW(P;)5fbT`wMV5y)diDaf`?@17d!07pxBQd)UZoW}JNMNe*-UbWL&X;sU(-MXwIA82 zex8vWLxJ=RqDeo=LO$O|fizf@IkSfu0y`u)n3#4u)bl~U<=PV9+qwbMxj`9>b=W*y zfcrpbzB!90iJBCE7>yrLT;?yYOLlt|FNK35Muz*Hn)^%cFJcTOzvAK*lAijix=JS+brX_rY+CO|(Mi z3*WkBO5t*I!eouxES}#^7@DkqX3D5`iWw6&)^^%F#voJ-pa7z%|65m&EEM2?JF`is!Tr~E0o5&`F^DOq&J+MD1q}{pqTXfy2;~JavRgO z`n1pk?z4K!oJMXsZ^SJ@A`)<6+`334;Nh`C4}m<~M)&nd>8}^aOx_cAtqC9@ySLMU4ba|ijQK49U9c1Z-=d*E_uB`-3#!3^ zmzq;epf^5=(t8*xEh_WDT@s?#E5d+RgaH|E#jw=kn1ia3{UvvHhHHI_wKS$*gB0PwKgx9<=GJeve^>k!DKkSeQdda@c9+eXJ3qFY2 z#Zj)Ro^CRopNl@3Hp}ZgZ}R?E!`GpBn!Y?Qk`T8pyHx0q^@sgT((H|AG_d~?MLvuVP=uS6Wlx`ds;jq}YDhij_h<-)aIwM_ z{fj&E@!5FAcQ;R%YJX4`5)z`D7E>cb0|mW`@Cd0yai1dABS<-pHm~9b!$%_24kFxJ zqTOPh)L4G{2Wq_@ucnUy%1?Pj9|jcL8q3(FE@#5kX-)q8+v zX}?Ep-pfEj!N`#P;vV?$))qFjXW8I~nJlj>H#t?ZV)_D86M(`gyCEo*msOnY9wWE; zgz&L{@(A!M^EK9*xje2}&9&TjSwz+e$A9dD=NV z2DM&`4o19}HeXG_AZmh#E=UsiNu)-=zDL!aK0SDn#Z-`||EaKIHmilYHq?H*YRagQ z4*a|wTJ{W$bhI~QOUYdlC4uVhyaca$JK^bgx*4aY(+M|`GWwj23nlJkgvm`}At~Sz z1D|V(YwMLTWh}DJ&3PP|FxzO`6+-6iNHO4);$7l(KqlGPMfjaAHeReL@OvJ4l%nRD zR3SX!>DV#0H@f-ux_oOqPozq;M@t1eptj}zW&u(%rLJNNK_Eijm+I!Li5r#!91@oP z0(PYw_JW7MNvA2c7c@L%YYa189^c1REB9t{0}ELUUZ9gGXX;oVy2$nnDf?JvBzHF| zv$5T=gxxiTdr0kWel!RNkxk#(?|1tIGitvIu-bBF8Pu|yE_VRWFC{fZ0lDW%;)1Wi zOM^=T-SiHBW*BCUylIDM_lYD;(hdHsl81lg#4c4OjgC1(3YjW4{r+u2y)>l|;Msm9 zkm7Ovqyh~JZtM*;f&VlTtP-;)I$?W_s)GY|&Le$Woa2u_hkqS2&6$Z*=@j=X* z@C`8+5$XO$cbJgDa&3ReT#Gn45P|g6V@lh4&|SG8P^Q<|imNTF!|C;{$-8@da(sGF z81LT7$KehZ5i7K_j*(gR;Fkt8Ag){(LqXT4lIpmodJ7W4x;gJhn%8ggEMQMxei~mG z1%#ae?9?5fb@o&AjQ3Mvt1n(JK%86^QZe_KTTkh9x>*EY|+K*ycb@ z1DSJueENb{0r&JmkP=F*$iL{+$kE+uO<#t1-%dAb5NiS|1t42ye3*4+NrV5Y!hct+L+2_K==4ArI zsX|+km5S{*UzhXn=S|?}=9D>jU^W6s5QPA`(G@NAui9VqnGu5=ve}OE_=*K}RO+j) z1VsIG+?9$zN|qB|^DJ^F@cu8Oj>qJojTrDo1ky4)#D8G$p@?DPhDFI@w;N@}^2m_E zLsh_aS04<4j`40CTND73_iAq4g!3;G%+tAVj?lDjpDz{I%?ZM_-S&-BE5QpU;a5F(Py(*HsLWkiGW$E(+qQ2Y7ZHaA zG$>HwkUt##~!J`Y$Q4t=6~q!r`@-k55l`ce6jgPTwKs zLtC{B4>isId)j0x->alTLNBD%znh9C-}|y^Zr^uEDYYsweUF{iW5{sQ>Hox&=d(yUYzo^c5qE z&%Nw-3ZcE{XuwD8ed(zzq#yi=BL3LPLz=O~hp{XPk-Tn&?#pjk4-AgmwO7C#wN)11} zjn}&D?_A;8$xbRS>!yq%Yg;P#5?Ad39MCbMfH)|(+x?mip_Q?5dEx8VOwTnf6Y7>T$%#PBBD$Y{Az#u57vwuz?PVw9t(ajIA;HlLG@uT5B z3;L_kEqO6gg6%i|+ds74H$JqXml(vuLl#*p^3_YN_SrpzIhFnMQ;3~5*H96Lfwb;= z+HKr&Dvttput7_6+anj&|NO67kuvKR>nwXRz4io~Z3kTc3|?|TdE;w4pU)pnk+8J5 zT-8!BV1r%TFXi}u4UwFQu<;HevOu4O`WPSvH zpU`CWZTpyk_w_A7kA-(w1_K{KBT{0s?w%sE)11fOZ{OXr`di_3DkHj?dAQ2G?GM!% z^6Yu2Zq68mU}byW*9h~jLcVciGN`J>sHxd%1?~YxhCs^#0uAV!e^+XF{0f*i7xc2=-=*Ku87?|?L_T` zCTSmADIxJ%%^!6?jxTe2^Vc)hb_>;Wsalw7t0vSFZzhTh3Kb-E(2oBd?%>G1xDV%s zx{vRqxETZD*1*mH&qI!C(|35lk`Bg9H0@BoFu9WZM)Er>AYx^2kknr+>0Av2B^Lbq zoiv*7uUc7N>8XSb&CRo$o2;cj=F+(3@VVLZJoqp$GQga)P5W1kf%2`)^xLoB6NB?x zt%xMRcJQBhSsr(V{k!}7S=6>-!2qWEe93>3{8)`*f9tN%4Qf-_n&qI-aO5Vh*#xmw zD%7STUhrR4MQYXdnvpIcx`!`TQcGAMHvl`m#Ctm3+Dv|8rqZ4CTcurb@*Q&2Yl)=a zbnGKMzIqQT?eY0^+J^fPBANCf?FTZVmA(wIh5zB_vN+=IAjQ&(3*4iFe?2IKM{9$O zH(bZ}-zC^?=9;@b*FP>#4U*ep>=u z++ubCOv*D?AWMaHN^g9Ogz-YP|I~lmp*efm@6t3eeyQeGfVA0sh5_}h&-oxh@)~#@ z<#@3F?F`@m6H~T<25U`NyEblaf0dP|_F+yrPa(d!Q=Z}$U&;_&BjP8H0kGWkJM+U2 zFn)~#cNMNNT1~loa*%@Lw0ZnZ!O`OjApaHNrxKIk#x2W@|9CSUswO8RO;7n+vFIgF zjn3>`DM-Tt$(nt_s*neZK!P73@~BON842oq6Q1!xG9k3sq`|aiiBQWMnK%(m77DBj z)H8XtQ8I^D<&E@36y(GyOJWqYQSCfjX#u&H!-+o15m zm!YxUl(GW{jz{Ah(ioG!@mfpIpoe@?mVh4sSV@{oaW(~iKuI7nJ+52@_rS7 z^$bbE=v9CsA=_=k-c8-S{aRCJI6u8lneHmhPOeKK;=BgD8(Nt48r=e!vH8dS45Nhb zZbyf6psQN0QfuOZ0*XT6T;`<7=)MCPVx`wRE-+LjVgQOfA9XXd%7dN13XV%9Ib>nrhVxWB%*3;aDPY+7W4;1)6LTX zh=>x$Al1!TXE&!Hr_9K=Djaq@5vP`6v0E{c84rUSA}|4i+HXM2_D_ORH?iM%fB#o# z@qB295V**|PnQt=5FE^YBV)|UoVdy>jrFYa;zf3IVM$tw!@4NwMw{5ZgTl$hY2TEe zXywo47>v8?M#I$YvPsJn%s8e?!O*6l+L%hV_ja^g{XSSw)$(+5I!_Zo}Cc1%Z?!RPbHlF5SO;K z#TzYLI6#l-s5D`+5&Tk>M8#Q?a%|Demg5Rfr%jK?kE&Mj6U*)?d|f%&N5%-8i6aTD z+mR$V2;SkhzPoxWO_Od9JTiiaxw-j&;`ipbY0^WAS@f8ZcNY8hEPO4uYrCq#)-$yD z=tSd4WD_FBb7GVJuAxmggMIyXYdDPO`S04?t6PHra^lnV;RSkik*S0?LxBq21k-7M zbY)Z3?I?+!P`;hrt}{bvx1~7 z%6XN09lQL)gLA(BJ;1Jv*y%&dpr_0eD0F?ef>b#y@30p?l0JcBKVe1u)D`u=-d zfi!k+tAF>hS^jiTT&{LsE=#!uEmmVMZq^p0$=HH`^&=}!73yN>aA6vC(C4y~u~Efs5AEN7 zR08nHBWw6W{1w`v)0jjG3{#!nt7Z2-Vb$pgR>e3QCq#gokci@0k)}CUeuV6046pjI zB}Waa{7olCY`O#&G?*<$K%ty(KeRf6xlD{Ih5er!0bim|F>8Yd&6`X#Gr4c*c(( zK{F!ZMUm&1|HB#KHN{c@C5FwC)@T3q)BhcwSHqw5o2<~bM|$dbDn(_~T;5?@6({qM z!hbLNqWGVp|902p-j%%R#&1SUnXt*R;SJJF(#rO<0(~2?8<_w(oJ0t>=w6F zHLbmj?oZ8``xWO@02lS|TgZ4J0-Bm@C5q17lf^e+r;nl)yaMKbFhm%)#s}g0@-pKj z$zu-Wk-xy9+X1dR*us4%@uTFx*e8(ScrJl!ALPXl1YEHJt_7%U>h!J<9m#BEGpB^6 z1bjd~pe}>e_T_~4*XOgTY`cw@amo!{U_6^TQ^D_IB|YsR4^td1q1UR~e)8H$%OLp> zw)ZUdjPiiv?IK+cnPv14iWvkY8+;@`Fe&GwgbnY!aj9iOdS4=3$hMl_N|G!_iTPNa zzIR(}5PO(eto`lwA-R49bh@)W@$vh4+1$E=(&b0Bc0-yQ_XWy%DQS)m^{DCoWs%;EMFmOTN99YP#c)mN9Q_5p zp)rwu@idVSq##(}z(rc2rdVV&G&RT1;AsnUKxpaT<(n(X9qIG9N3P|W71IhQOd8`} z!Oj+5I<|DaFV&C`9in^FUdCAI>(<6@8zhsH08cJ3>%DXBhQpje<0&Vjl)}DT2VHsJ z?13m{l$alNw^*}}{B5|bY_rTq(WOYTbIG=wHmIkLuG(v!1yDr-cKI2NBzd!m!Vi_G zuaZZO;X`kY%Ua|R@b%p5fFaIQ^{3@toFqY--vP*zoqP6B{=&CBvuT@#=2SC77eN8O zL`;FPstT)OFbKmSOyvsycvTl%47Oh||A~{xL6{smcJnNhULqF~fX7)Fgv>c;Fx&p9U|^<#5B#fN z1BFRZ@@7kl4Y-x?)xt#cz)DW|cU3290i;;mi_ z+kK8(NV5S--ilR3;-}20s)#`n=YHM5ac!oO z!X*J(*csT+je;65B*1c=F?or?9P8r!Rr!UeackC&?<2R$0f+JmJB?tPgTuNBw+!RT zSYGE}Amf6sHK7RV?S#mKKjp3qgf{*W(Wscu{L_i|Vh%&%g}zq>0*DMot@&8!&E9b6m4rabg>bqyEGdedg0(spbm!sY4StH228 ztgd@LA!*HY`Iivh&53_Mo_cWXugbpiO$LnvrD@$OXUr}S(y+Z-j+zZu`>(FDGu|@q zQ8?H~9x>3ab7XU3gf;`e*>G0aVR}z%hBQ!A zf`uD;QZK2jK5XBz&K^zhz&!T@sil@}>-n$D+k3id{r9eb=xYo$!N&#H&~rMZyNjLN z4<4Yi#t{;MQ>F3wb+hTLqmGx0$ty^g$UXVL4*;-Qy{^@@61fW}z!&{={)O&vxNr=2 zv@swKsN-0OIf|ZClCMh{HB@MKv%jHBxl*`KN|@R?SiwHxd&fX~y53YNSL>OVL~Poi z$t?I$exDz(hmsM`7S=ytJvE;D4lZ+icn$qsswm~>82BQry5fU7w}50g zKXH)CkF%_}_Lq>EaQi>NV|0t1L@wz*?TjCqGFHgl;}fd}vA*)|d2#mPy;z62qQ6;` zHFY@HuY8#w*09UofR3<<_IIo}>lLrecIx}ha&9-TIJ}tOiQPGNg#YnzUfy)k{`w1A=U?;`|IVXqjA25NK|pdJ``~(Q=8FZE zJfn`KHu7^NzG0E=Qcdu19&b}xp6&aXLE0^ipR-HAzDFkHlsJ#g+9MwD$*6njFxkcd z;@RXC*It?}iQpTkiHGZ|4ywKbe{8nt-WfXPW-TA6koJkL zd^@CSmXuMF9PKh7Y7Q&zY_O*v(S>S8UZi{Y+xb_}!~GHK)s57%Bx(c!<7dZZt+m%_ zW_Jb#Y{}M#f_o{@;sZrouL^!!9$?ssJcj1b!Y54X#yo~nLzTXo8_i7^Qzlnl zFFdM-az@tl!c6_8qd_dJ7zvhV0ApNt^8eBF&C!*7!PXPowrx#p+qONiJ+bXfjES90 z>||mm6Wg|vuYd1-uUG!Kcde||eNR`_sZ&*ZZ=lU)9+$Y_f-GXR_B|a3?~gj)jv1P&o!i*zM&*{&VUVj_|!yDctP@F?C zQMM5ZRG%A%EE}0u4yAc9Zkp)F;g$i4E^XxqXZvjt|3L*pMtp4b&Fr+?f#K&UGGX0P1aI6zJ>!NdW%aLlz}B7Ym7u-4MDwQ!jex?*+U3o|XgC#>U1bFSB7mXFi>! zscG|2i#?F}0zk%e&6!-Dsdp zXM%m$x$zGMq(CVGsMruA_p;lzirY89g@OVjM1TxKI+xshe%7gqdZpMXcOIZp*Yy#x zzdx`jk4<4Oy_SeC;EP=Vvm7%b`LDE+sT3?O1z12JGdM!7$9+*=)d#wzeSLkblQl1( zUs+Tk+o8Dw2Z?kRJe^uFS*5dEoV{>Noy=Fud;`pY=ImzoqF~ygL!||Z|7fPUc9ZeV z%JCU6twNS52gn3cs<&*}R#|6B(Rlf7n|<=#r~t`Y?8hP~Raq)+$LAy_#ikocVBGJ0?g6EdiX;lR@knjEO;En)$Od0&C}lq6MY z=k`s=#OiaJ$0QFurhZ{~jbj+V;20Pf$VpkI(Q0nPDsx?^(Qk8W0q(=wpFPZqd-^*J zX7bW`nN)<^&nyM>c?AId5u*-kB2jwvk9y_R!*5afK-R-K^9?ZQYW*R<+syy3{%MFgmcT1PsdI$81xptNJ!~^zeAn!fv%J*!|Y<`59LzE-9zGY1$CEV{i zz@s>yxKdDwq_^t&FB|Pa#@oBhh)=$)(OQygA7%N8mF0mEtcflsJc!7=G}7bETb^(F z*5~~ib{dPyk+MSb@IOxtXrFhQXceV#Ih}858oAmUzUdsfvF+8RpB}JcSk(ttpNF+v zws+Q>t6XU*V$uihmzTSziW_6S^)+*izaRN3Qk6?F)s@>sUU;c}4MTQHHJ9l`=3}{g zJP`=nYD?Qbaj4C>(;EJEev$5azhQ^UVTG&(C?s0u21Fs*eZfflrN6=p$cv#Or^kaY z85H@mWnS;i^KJ55LA)MzNwA)e1?|@g33i;zjjh2@p5Y^HU`4^%dlvP7uj_JrYxfiC za;Ux$T3$KIDTV^#VEM!Q8S!#o=MZ1l8boEOM;wotZhiq3Px$okz>}%_CHbh*qOA`VQ+1>PWbcn(atzuF+a5d@2e{r6B!Bylr!J+(!~FA`C9Tp+T=Q@`ao#e9pd zB4;Q_1Ph`($uaoNk_3zu;85MHj&JsT>c^82M9$nNq5sV*g1u3dwX>d8wY4eO_Rf5i zGP6daDhVz)vuf`+!S)(Hcyuo!@_XrLpx{yn1vh}^!N+4*9;hLhZm`?=SO23DXpET& zh%HGQYwwjkiKd-yOG!0_{A)LNc{ywbuU=@~?qT5!{M=P^v<{LDX z7Oo1;Ylq#M8WrI#W}LW`3N?JckUgPo z6XZ0gCCM3KjJ&D>_35jGc8gzrAq7ubL~lF>iccEZ@0-7@!Y-G7pp#%n^QB0nW~JS} zIQQ>wF8E2pyA+!)mUh!qTc*B6M0s-|ay|ZjyqmIf8T^`Dpy7THfg&#bQMNNA)MGo_CMdbikwgup>KVftvL_94Cb zVPf!9`^-b}-cZH*H@TeR=Kgfp6mtodRkHPf=vH#oF*sMrd>zDSP!}q2>|?$EETt(cF_jCB4o8WMblx zPBoW9b>3OR|IGq?K5XTm3-r@1GaeobxPHq-MURHKQnIE0eX}nmEve@``vSMJ$t^^i zD!kmRl6A}XS%WQm$t*J$*D+mP4EDgsvh|mc^A`h$claD%M@M#CvW|tF0&0KitGHQM ztUanIbUxRQZg1u4E%2i7qT*NPN5M*+4{nt-F#v5VGeAfcYYMQWKCEs6;B)<^dN2~5 zO;3~|exKv3Qy1|C1AB>$F4uDB0Y*vM?=o51q%jR5%^p0(n=AB80^WhwFSawTE~n$Q z5Z1}V#I4R`*cK;J`MIqH3eS1vq!;bqUr}E2qVJ`1^LN`8JX=87H;CDvN%7Al(8&73 z>MM^3i_iX%PwNjzGwJpQNxB=YA@&Q7#<=OIR!jJ+>~qL^gD<2zqI*?z9jfcq&SEqe zxtJaKBQohm{fIL_D@9OAV8Wznfr4SsyL>dP7QpQy_^n)e)ow^Izzc<1L`kE)GSYl` z(Ia_qmDSrIjE^rdZG{d;W}6$ZVG9KM9V%)O==e!G=@Qa#G+_!Hkms-SE{_~NO~0ov zful`czm66w3hj*syO@qxmVbdPkt`Xx$Wnw-CHo|UH2bN1qw&|l2~@@WB;*AlP;x9r z!S;50Kh{~&7}k=^-KsU{?62mJ(p+){FDK5=FDGm~nv>Ko-yU?VJq|Zr-uRDPx+fc| zoO^#rv!}@|r~dMg21L^0#Yh_mRY%R6S=oM!+NiEdNax7VIO(_Ik88;MotMZlQ27Sm zWx<0`VhWwdnb5LzdFiX*`c(;iasQ zjVcrA^rH_LZ^AA$g-g67;M>xkX+$Jy74+wY~5sLQSs5G2=n>AyPKkB_ws z7$w=U(yW!FD4#z)BuCBO&51f??>3RN2M=*#^HWICqw0KzD%#$bv`=LxY<T0bG}S8qe(o2GQ?LY-Ol3Y@3;ETWlQDN9Qh- zv;xbLU6>qYtiL;_K!rtU&AhQY%cV14x+~dnYq#rO3tgZkcU`YGTaQ_o@%2?-I{et_ z)?;#omY*wRI>y{qdTconevK!DiRA@4o630oOB>b!pn`EC>bylS58mc*&eo%QC{Yye zN*K1CLaXvBx1<&BL=d|!AZqPxVFNqX!SzYzr&dl_cPkRoR%wGu=3#?2g~d$@B^fkB zwi*`X*_nL5%?jukR8cu7ly$UOi^&JSXEEGYsCljBZN7nhI`74HmOSVg(Kf1f% zKSr=zaz3&Rs`VGyW^p?Ce~f8asD!24y<=`k#Cd?!J0+~}O2-2erHpl<+NQQ(* zM<5B}8Vch*a8V`Xwbip$zK;8Tol7(ZHXag|ieM(oSZxlXEpNr7<~#NN`K)hSPEv-> z>SyANXGNk^-+lsP6E_}Knm1yKkyjE~G^U7fV7yQD@%&`^Pw|2#Yc-vPkLTwem#hzg zgQDSK&Zjog9EwOlXw=C~3S>U6Qg3BRiKJewoh?ZJF>a{$6US*x(@du71Q zdw%rC1iQoxvzZeUF%zCB((z4^@~@di2fGDZRQQ!k+oweIV-b1DqrOr6*Ei?GA{M5i z36U9D)uqBtzXQ!Nb}@|Q6;->Rqs$8HpE6pmTaGHkrT$K7f2^yogQY`R&M+%3P@L}F z$A`Oa!!R2?;Dok2j`F^}xmX9Qj=II2S=i)`XiL;WeCK`WXeB3*_L=~&QO20^9Gshb z5$p>2;|wJ}PvFdrds?S1+K+?Oahc*52;jReC~8rGI$H#`ZxlBT36FHkbTGL(>uWc2#GWZ)zXe+H<@!|Xj!3VWq_DrtfYGJ&gCbk^d*aHBaS(RefDaCy zo?G_?Nt8kpfo7!{(id!Ld(>oDs=|_l`Qialh@o2XstOZ(LHvb5=q(!{`Rfz>=*$W~ zoXvGL?;g!HaKw#GmP6uqga<$2o6qW&ELBAEF(2fvOJYt$&_})2ZJhbXTzhJLM9H&A z3A(&OL_n0`w5&-&*@b9l2CwtNqk(1BKG*}6(_=#_`yd|XFN|lg+^3S&r5ohnpk8<` zoQM#S^DXO}8BsJdw(i!DBaD9?M{Dp14@#P?@smg0(OOktGyfnaO_8`e`g@4K&|iGJ-@j}pFd3Uxl@sZX zoh4^=T>cVJ71@!l=BrXMH<_7QX}5()(PL((VSGnc1OX`{1ceU&?^ztLriY#I1JG^P zlFv6>*n)#Mw3eJ%GhrStKXJ0ZZ%L8Q#ULl?Y24kt5$FLYXxl*;w?00%*&r3@43X!S zQt>iw*w>A~z(CDJAz#Re!nv+yasgSGNV$1>T_ITxkx=BSQpDb`o?`{gC_#qBS~+r5 z_3V|J}Uhxk)EF_k`zsa7h0y`iEnIEVcx!n!R1p^)C1QJb*oCm@|L%|; z1H!{*txSWXP>yI(?r#n>X7Le;To@Mqd)V-#p}Qf5>*HxE&J_(_{r=oalU$d5^{IpyNP7n<)G*qW@g3tO)FZQe=Oh8I~l>C$t`Da3CC@L+@5hhe7$1+Q#XooDz-OT}t)v*BZ9Gslek6L78)GX1K_;|TS4sSZg~%=(@Rx|#{&=Kt#V+`rp(rlqCHL+?T7W=bOnAbV$|w z!y_JbE+dn`y~0pxUSniwtZbv}okUd^TSAekOIBL1P~z}EA!@QEZ9_Gpy2%icKB|N$ z3E&gJKr2x0D?q3yg2E6osDhs1xh!b)?ZN7CkhfiE1z|*>i?R0N)+krn*kYIRn=Cx7 z;MNRYVdHc)n>-a}*U=fjerPvjnEfqZ^;cE>LoHO$@s@u7@R2ljd#L|LaM?adnF=ex z1_IIyof{WOv7^OPxlIYL1rFQ?8n~!Ur6R{9+xA+dy%CQ%W;>EV)SlTl!Iz=Gb>qPv zSQ*%G^!dHz{MjhTz~yMc9N$d~I4E$*j?(a<*-1&0VC*dE4xjL3h}#-^J`#8(Y;^cX z%rQW-bPVV=Ywfa2nkSyh*L35$_gX#3h!kD8r3Z^#C42XAg(+~a%WAG96( zn*-L-V=LFvYI^}IzwFxnzdJg*f`dD>2fiRj0Iw-9@SB{qQJLxbW04aiB%D?C4PSP5 z_sGeqH@bCBXiDQ*z7<4$#^|#aA^V>iiwA84F;dl+b3Mh`1?++}P5)8Q)vX?2MB!?v zMb)ZWNrvtF?(H_e7o>tZ2rZ@{wko)2+kf{6R7EPV%@zu_YyIz6T5_dXGtXh|POXJ! zWL)pD^G}x^&HTE5{2}_cCF^D#*O2eWznQ-?N|@i~Q^-{z=v{35RdGwe%@z;TMnQSl zn~0`ew0m|mnJ1yYnHDiVZDk&0wTf#sER3%)VMA7@mVt{~TZ;hO_b&imK0*oU`XkzH!51>GcKtk!QZQ5FlYx1BFq zj1Zus$5xy*Z)o4`e4z@I2z1~mhcS@8=tpY1$;K+0E!~$NW;+-?n>|Rj!S62cS{d|B zgSh$g0dR^M2*^lq@5OgwV&ZLh3RKwHF3sy|hleD&)xdry75sl+{N9KT;jLCd9S z`ok|hNWk55xZ*y40M0HXB-D%QLJJR9w1W(`f$6cyB1d_V-`szPkLdo9QBWY7VS%TD zE9vn2XWRkI>Kf|2z*=1a&UnS*q8!ZMSiEd2n<(@zT9_GO_lwS0Uw`-#zLZ-jDgwf8 z!J%&b9}kpZpi|#m?bUJrvmX_-|Fs;pm!kGjsxbGpV1Pkf8!f1mpQR>v}DD7qQqx0yM!qzW91M%yOwR@$}VWH zPeT6EIl0OIlsF2H-njkK)RwSKa7cFg;HEQq4U`r+DBZL-3FYr(U@}S&^yOrr*Z)07 zM7vf9fiA|=2JcV(Ya!dF+kYKTyfLw5EHN4(85u)XAA#E}S6e+do>5TEV#=&xHncJ5Y#-{3OWu0{K@ih;9Ai(%j zQno9P(Y3?S<@&P^G38C{{tNPB0nEurIK?1aHbMA325ta}3%2>H9LO#Hi~AJ)S0Rhi zODLR_yL>NFX_7>EeRu3Sw)j*--TYf5zgU?H%G1WmfJVEKAd{eu|KceEK0J%DERb(-H=c%*RuBz22~& zqBB6~py{Jv;KiH+t_AFP&WCI<(En$Ltf>X)pz!_g=W$NCo+i*EG?bUp9*uhk0aWS9 zQYX6Dl_%N5!_0{hL1(mbF0VnUAw~8+&?L<8!i+~MhD4CP%x3Zr+FQt^*>2GnR;Op8 z)Fr_DwFbxq|s5hkVcx4K5z3t2^cI zTBLeA?U)2};t=9IkBp4p1S2#dy?1(uZi17?f8CoNzs0H$G6|&b9wCv}!v!h9aq(+| z9!Z60m?Om|dnt%&zE8aS)J$Xb^qIg7p%vZmi~WA*eyq+3izs}OaWnuul>A?7ivz2D z6stoA-3j?~zzfz{=LSD=bIq4N8rgO3eb7_?iz^I;p`#NK!TkNa5yL`v9vQH2KR+5C z-ZN@+J&l@-U!K3k{QSV@GYoQvS}+O{23bEYOWU}|wv{la=VRiJPEMprL-GQtv)%rh z*`zC>6yERY3UzeknOYs2r#LIi6r`9O#lb&q@hkAS@n{Qyfzr-ekziezC^tC&x>uX` z9ZG;yznQH%z-)=c5yTCZ*eS4poxYu(BiNN5sNY0h#X5z9*?{J9f%#uMu?{1lFvdBU z%7X`3hrvIUd(B5^L6gHqZgLk zJ=5AchiN1w10dJQDA*$uhr2p?1q|D4GgXVV&45rrVa?5{fZXKG@F~&AgSnld8 zfFI}GC0G4kpAjjPFx^3K8%qK%Mv8gTB+tr0p;M%s+}i2oCQg@y@yj1CGp0xHZ<3zN zgH6-Y{lkTs(KZC%w6JZgN>uQh%lrM3@!Y893MlQnalHV)t7GrUptL}qGOBOxH>_*w zC?yb;H$juqs|%ABRVPyL_IFhjC;j)!VnOq0k-QM7l6joYK9coILf{Yh;L6(k+qQ}T z%E1%7^$7a1Pt-Gb;J54R{v)^G=J75!A$I=-_s?a{z^sfaTn!gKX2ri6{}U48cuPr~ z<}d|ccTl|FSP$aN%$~UspZJ2L{pA@SZ0?_4D@-A72s; zRyr$-)NV@v{CO|<(cRFqbRJOzT7*Q}#U+I*moG*TpB)?jU+~$!_NEt27>a}~*Ie?! zBN5`wqep996~kcVC=TBQjFz*4NV6k8GHgs?eBBkIE@~dGwwj!boVIdE9!P9x4iN&^ z&=vw;2xFw;OseR<%9@U93B0qAau!jtyE5!s>c$^^C}p(Kis-+d_@)msBDLIDD6tbO zIctJ}9j2U@y+Vukcci#|t96KH=LivEoff=PQ~X@|P)BaivuCxU6Y%_AC+6#9T^!3O zr7)$D5g{zNc!>n|*bEFKM=YASKFfsbU2n>x3+GqzXfBJeBDE_qc0aN{K2TBqcSD~4 zCMx5cjA{5W?N=P7AqJ$}5{BDG%YIq~2q6QQE&Q!83eduodxa^6wv7SAV9PtOQE3<X3tm*764Lz6N(Jwjkz}ULJ%NT_Km&6M@c( zrLH{9*4mg6=|a&F>&J_w)5B-Lk+sB;w;c6>MGE+)A4jv;-OND<(^%geROj>xJ=1W; zTB|awQ}XxgeY6O6TBhkDA>b6p#0|zw)@29__>A>uBmAhxZ<*}tpQ>05pxT+SSbpD` ztujjP9QLdSZ(|m74u*u*adQ!Ijp}(}Ma}ma-4<$ju&bl$c`43}P}Rsu`1WWC9Bxzz zCyQUPwLka;m!tzVbNW=F>77XE4hEnP-4&s=uzkWf4F4#y|T`wtQ`#O<4d+JANE9X$d5_WPj#4bzpjgz6B3`{OCb_uPWR9p%C@7&yZ z$0}~A5RE*aMFF39KtP4BGpjb#coI1(5bg(hg~EUrRG$&Llywsc>IM@nH|)`j0SbsX zSbhaLnTX5UmRwhvnRF5@dnGN})(kVhdu$y$<`Qkqjf4kSVq6f^*1-J`>a84=J_0qE zcv5BVRf28I0RR0B|HjVW*9fomv8T7@967GcSDCsjj;t6$o^>L0oYQ%}g6>b%1^sE0 z1ho7pjV4LLssyoPXy{A=ST6p=^)G?}K0oRqBjG}5jL9lSPt*d0CMDiv zf>#-9&OUFBK5rEP+#@-`AM3K%l^P`RySsW_v#a2{cj%HQ0?wyv#44Ox7|1fG~wN3NNns);Y$Coa+Ssq;q;-XA|x1iR!#pwq_-?_ z`F$+%YL>hoWM`3PlqzEeh5eV*em|T0cRZp=c%FN$|D(jnj6Hm*+l?*V1!Zn}$tDYR z?GYPiQdtwL->u960IP5%iF)yvk^mf1Kq+ZCPT(HC8Z zqu^7bpC!n7Q0*1|KWdK2-w!$ShpGN5<>S-{u~ciQNRP>T5vn9Xb16qTO4rAGirSW2Y-OFmLyFwHcvU1!9;AmMhNWU<^~E+Rk*o)Lm}g%#MCCw=0;-J&fNcT&uMv zv7n%eNd=s*jIXwOsXgbEPAvr2k>WtOppgakT)<0)&uh*NO~oN^DV7Bx{| z7r_#w*Vf&9h^|;P8;n&i$kEEsaODe0`c8xODWLyv7673VdT0V77LCK`NDtBDAqiKv zUHc=@^Z?tCnJV%4=A%gnX0*UJi^$dCAUwRKp^`a_3PQ_&m*gZUt$Q)qq*NEg3Z@34 z<^=CDSBAiNxy87~pd~Hd?$1xomS5s}Qg#UOgwnUo>0zFyb(6)Gg>qoR6Uz-E82o=j z3?-YFK5dX!!Hl$Y&X{Iy zt!oTrpKoRB4APHQ%5YS~7JozNLRBMMB`@!k9aeZ_kcvO%?{Mn=RYltMD*GO}^)58ZcW6UO%=^X!7AAtj*ni!7tyJ0%t?h|t7~j4VK!#u_^y>t|9)d+DW@NOy z13R1VuV+J^)%H@#= zc@*0lf3x1kFhJmePo92fX|B&Xo;dKt#?2CD%>V^1*mcLG-BwuAdC4H?nG*1N)RB=v zJ+p*q?#L`J>w>OmO)rZY8Pawa*OTAoHAYJfZnx2%HyyBJ0SRTVqiY({4;c)Gla zzxbvN@K4XQ?V9xOQ1%qdY1|ZD5$;}Goo@e>%^Gu)k4Ngp8e{2k$6N_yr{H{lb$fqE z|AZcKbNm&Wp34FcHqZJ}HtiqF>(Grg?Uy>f43yNV2B61gyT6n?EK+*>4nQt(S45|r z#tq=5dM3u2x)|DFVP%GKzrX}N5{%?{*ZDisv8a4r8Yh>pKbzC9i|j?;*V2sR_Q_l5 zbyR3Lwu5HGJq%z(R4N6M9B>fc7&Ci6^n>xGYz^x)8YOHUn?{4fhhMha7zU#XAIMz; z{nckeSDFhzLd;1D{bRbN1`D#D@A_KyN1vU?e&ZR8^kGJo8I`?W8wLyiv)Hrt&g zwd(XGBqi(VqYn=)aPjaIwJwSS=kw|?cGDGOZhOJ_&7;fC4!IT{L>st+tlcp6?Kmnm znj75Zb-gyiUdeMgV^YTdOS@KaElpSzDfa;L-9r+*acAr_+NgrbihHE&eqH<`O^;^b z$to%$i%UR`4zH8zJJyO5=__iZnIiH#{k85mfHAl?+t#>|Nr}fA$^uz3?l=Q+=z z`|`fEAtPrir^?EgGt?kbrL(Bf7@L{n_Xukca9|;Do5bx#8W;$0l^z? zS*3p&t16)oZC-7AOoSM6X=n@FVhK*7yVDL75uhfsPf9n zA{JZ{8=d^4Wg0?0)(}S5+0|7UQ&X}qW1}32%n?jk(nO<|+XJzp`P$&6EMT5{kIOUH zV-=31Lkmgn&Di3ce<3(sW)2AN^q2$8F%k^R{qse^s-mLX8e|jhEfV z-H^c)0>(VjmSlPA8Nfqgkacr$cQ$>HjMqNj=31z@=Uk97@iQ#$a-Ld-#m|zW8Q~Gk ztsLU#|6v!@vrN5heGONfg^OTve%wgDJX7^Z*xKTi7ssZcjwhY3umRsvfC}T4?-8Eo z)>}=k#mPP2P;YPGRZ!wMN~GBFu~k`7QPFwV+)TnY|CJwDn{RHd|ApngGa;7#zc_0J zB1g|$NuFQ1pNMEb9jV2*@EKdNfFS(d(Aah%nYZId^bGZQelk#R@9mRU)_8|XI-6Dq zv2YmVsv&(Kr%jcWJJ(-s&pIp(aU_w`5ZdYm!# z`;Mi+SXZln$X7v-_?4!R5XD~2q@`hJIxnQhu1ru;x4IIwl1e_ESOX-Va2t8V@YR`Y z05k(NM1NrKBBURgHDr5kNa^?uD#Fl#sCerJsLl(_#QXGzndGN!-Ede`8V;*1;RoS^7F}Tn2mcyuK0~O-c3bDL219zcxY>x*3pC& ziPefCUSG@(_j_f-yuO10;b95qddh%a6?hAzP=#DO8>*iw zWd+SlB8DriNFHX`BTib~zAsI}r}auUMa|94ddE6&!qoV~a~uYxARy6$Ntj5RYa^

    At{V2dc)!}n18wVGEsA*Ryq@_hd;Jv`( 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

    X-H9<>de^T*wPi7?_g> zk{`OB@t<9Gf6swU5b`7F8GJ{ZtaPE@ zHzyL=$gw#6#yvj*H?D}+XsNL1WK|bTrZ16WgfNDruisg)a?xL4KPAAP9 zHwO$Raaw@eny(81H_9!}o*a~|xZwdGSJLQ9Dw|3_yDmdlr`4^_n60WcIx71srVO`- zx+nkhUjGfjd0a8Uy#Kj2VkDJ*qwsJ1TKWI3B%gryi#`pI`xyUsOJSYSGRCfWE z1Js}L?7xu^otCli^}naQ?fPdl{*C{;`oB5&zjg5czrEl)RVn@6k3si;w)_9Sub16F Ydg?aKz`n%WKLN(OH|h!%a;72w4=KpNNB{r; literal 0 HcmV?d00001 From ea30ea6003cf4e7da91df89197e36e655573006e Mon Sep 17 00:00:00 2001 From: sigu Date: Mon, 26 Oct 2020 16:22:38 +0300 Subject: [PATCH 30/43] use correct broker ip --- Dockerfile | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index c47a10f..f22d53f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,7 @@ RUN mix phx.digest && mix release FROM debian:buster-slim AS app ARG CLIENT_ID=:sbompoc -ARG MQTT_HOST=35.184.192.117 +ARG MQTT_HOST=34.86.117.113 ARG MQTT_PORT=1883 ARG USER_NAME=plug ARG PASSWORD=fest diff --git a/Makefile b/Makefile index 3d34a20..40e44eb 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ APP_VERSION := $(shell grep 'version:' mix.exs | cut -d '"' -f2) DOCKER_IMAGE_TAG ?= $(APP_VERSION) GIT_REVISION ?= `git rev-parse HEAD` CLIENT_ID=:sbompoc -MQTT_HOST=35.184.192.117 +MQTT_HOST=34.86.117.113 MQTT_PORT=1883 USER_NAME=plug PASSWORD=fest From 7bd27b3222ca92ed65c09098124870c40d85a160 Mon Sep 17 00:00:00 2001 From: Duncan Sparrell Date: Mon, 26 Oct 2020 09:31:47 -0400 Subject: [PATCH 31/43] ds_store --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 43cf15d..1bd8185 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.beam /config/*.secret.exs +.DS_Store # The directory Mix will write compiled artifacts to. /_build/ From 868c881c3f84554be18cccee8f4f03e5e2f01a2b Mon Sep 17 00:00:00 2001 From: Duncan Sparrell Date: Mon, 26 Oct 2020 21:10:33 -0400 Subject: [PATCH 32/43] plugfest image --- assets/static/images/Plugfest.png | Bin 0 -> 136054 bytes .../templates/layout/root.html.leex | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 assets/static/images/Plugfest.png diff --git a/assets/static/images/Plugfest.png b/assets/static/images/Plugfest.png new file mode 100644 index 0000000000000000000000000000000000000000..7b1fa70c8f6c271e53ccca02f0974ca30200be4c GIT binary patch literal 136054 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

    At{V2dc)!}n18wVGEsA*Ryq@_hd;Jv`( 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

    X-H9<>de^T*wPi7?_g> zk{`OB@t<9Gf6swU5b`7F8GJ{ZtaPE@ zHzyL=$gw#6#yvj*H?D}+XsNL1WK|bTrZ16WgfNDruisg)a?xL4KPAAP9 zHwO$Raaw@eny(81H_9!}o*a~|xZwdGSJLQ9Dw|3_yDmdlr`4^_n60WcIx71srVO`- zx+nkhUjGfjd0a8Uy#Kj2VkDJ*qwsJ1TKWI3B%gryi#`pI`xyUsOJSYSGRCfWE z1Js}L?7xu^otCli^}naQ?fPdl{*C{;`oB5&zjg5czrEl)RVn@6k3si;w)_9Sub16F Ydg?aKz`n%WKLN(OH|h!%a;72w4=KpNNB{r; literal 0 HcmV?d00001 diff --git a/lib/sbomPoc_web/templates/layout/root.html.leex b/lib/sbomPoc_web/templates/layout/root.html.leex index fe78478..435b0d5 100644 --- a/lib/sbomPoc_web/templates/layout/root.html.leex +++ b/lib/sbomPoc_web/templates/layout/root.html.leex @@ -20,8 +20,8 @@ <% end %> - From 74cdde94edc39956abb68553f5550943971f0a57 Mon Sep 17 00:00:00 2001 From: Duncan Sparrell Date: Mon, 26 Oct 2020 21:21:38 -0400 Subject: [PATCH 33/43] home page --- lib/sbomPoc_web/live/home_live.ex | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/lib/sbomPoc_web/live/home_live.ex b/lib/sbomPoc_web/live/home_live.ex index 5c29532..b7a7963 100644 --- a/lib/sbomPoc_web/live/home_live.ex +++ b/lib/sbomPoc_web/live/home_live.ex @@ -24,22 +24,29 @@ defmodule SbomPocWeb.HomeLive do

  • blinkymaha.sfractal.com
  • blinkyhaha.sfractal.com
  • vulnerable.twinklymaha.sfractal.com
  • -
  • sbompoc.sfractal.com

    This is running on GCP vm buddhabrot

    -

    / is this home page

    -

    /events is mqtt log

    -

    /phoenix is phoenix info page

    -

    /dashboard is beam under-the-hood info for debugging

    -

    -

    more stuff

    -

    x.sfractal.com

    -

    -

    x.sfractal.com

    -

    -

    x.sfractal.com

    +

    home page http://sbompoc.sfractal.com:4000/

    +

    events is mqtt log http://sbompoc.sfractal.com:4000/events

    +

    ??? is sbom and dependency tracker add-link-here

    +

    phoenix is phoenix info page http://sbompoc.sfractal.com:4000/phoenix

    +

    dashboard is beam under-the-hood info for debugging http://sbompoc.sfractal.com:4000/dashboard/sbom_poc%40buddhabrot/home

    + +

    twinklymaha.sfractal.com

    +

    Twinkly (ie digital twin of blinky ie web leds) + MaHa (ie Mqtt Api Helloworld Actuator) + http://twinklymaha.sbompoc.sfractal.com:4000/

    +

    twinklyhaha.sfractal.com

    +

    Twinkly (ie digital twin of blinky ie web leds) + HaHa (ie Http Api Helloworld Actuator)

    +

    blinkymaha.sfractal.com

    +

    Raspberry Pi with LEDs (ie Blinky) + MaHa (ie Mqtt Api Helloworld Actuator)

    +

    blinkyhaha.sfractal.com

    +

    Raspberry Pi with LEDs (ie Blinky) + HaHa (ie Http Api Helloworld Actuator)

    """ end From 9d5f5b1f2de00b1ae7e7da3d00af0dc43725ab4f Mon Sep 17 00:00:00 2001 From: sigu Date: Tue, 27 Oct 2020 11:23:17 +0300 Subject: [PATCH 34/43] pretty print json output --- assets/css/app.scss | 7 ++ assets/js/app.js | 105 +++++++++++++++++++++++++--- lib/sbomPoc_web/live/events_live.ex | 6 +- 3 files changed, 105 insertions(+), 13 deletions(-) diff --git a/assets/css/app.scss b/assets/css/app.scss index bccd4fa..226ed48 100644 --- a/assets/css/app.scss +++ b/assets/css/app.scss @@ -2,6 +2,13 @@ @import "./phoenix.css"; @import "../node_modules/nprogress/nprogress.css"; +pre {outline: 1px solid #ccc; padding: 5px; margin: 5px; } +.string { color: green; } +.number { color: darkorange; } +.boolean { color: blue; } +.null { color: magenta; } +.key { color: red; } + /* LiveView specific classes for your customizations */ .invalid-feedback { color: #a94442; diff --git a/assets/js/app.js b/assets/js/app.js index dc8033b..eb2939e 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -1,7 +1,7 @@ // We need to import the CSS so that webpack will load it. // The MiniCssExtractPlugin is used to separate it out into // its own CSS file. -import "../css/app.scss" +import "../css/app.scss"; // webpack automatically bundles all modules in your // entry points. Those entry points can be configured @@ -12,22 +12,105 @@ import "../css/app.scss" // import {Socket} from "phoenix" // import socket from "./socket" // -import "phoenix_html" -import {Socket} from "phoenix" -import NProgress from "nprogress" -import {LiveSocket} from "phoenix_live_view" +import "phoenix_html"; +import { Socket } from "phoenix"; +import NProgress from "nprogress"; +import { LiveSocket } from "phoenix_live_view"; -let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") -let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}}) +let csrfToken = document + .querySelector("meta[name='csrf-token']") + .getAttribute("content"); // Show progress bar on live navigation and form submits -window.addEventListener("phx:page-loading-start", info => NProgress.start()) -window.addEventListener("phx:page-loading-stop", info => NProgress.done()) +window.addEventListener("phx:page-loading-start", info => NProgress.start()); +window.addEventListener("phx:page-loading-stop", info => NProgress.done()); + +function syntaxHighlight(json) { + if (typeof json != "string") { + json = JSON.stringify(json, undefined, 2); + } + json = json + .replace(/&/g, "&") + .replace(//g, ">"); + return json.replace( + /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, + function(match) { + var cls = "number"; + if (/^"/.test(match)) { + if (/:$/.test(match)) { + cls = "key"; + } else { + cls = "string"; + } + } else if (/true|false/.test(match)) { + cls = "boolean"; + } else if (/null/.test(match)) { + cls = "null"; + } + return '' + match + ""; + } + ); +} + +function isJsonString(jsonString) { + // This function below ('printError') can be used to print details about the error, if any. + // Please, refer to the original article (see the end of this post) + // for more details. I suppressed details to keep the code clean. + // + let printError = function(error, explicit) { + console.log( + `[${explicit ? "EXPLICIT" : "INEXPLICIT"}] ${error.name}: ${ + error.message + }` + ); + }; + + try { + JSON.parse(jsonString); + return true; // It's a valid JSON format + } catch (e) { + return false; // It's not a valid JSON format + } +} + +function prettyPrinting() { + var instances = document.getElementsByClassName("json"); + for (let instance of instances) { + let content = instance.innerHTML; + if (isJsonString(content)) { + try { + let obj = JSON.parse(content); + content = JSON.stringify(JSON.parse(obj), undefined, 4); + instance.innerHTML = syntaxHighlight(content); + instance.style.whiteSpace = "pre"; + } catch (e) { + return false; // It's not a valid JSON format + } + } + } +} + +let Hooks = {}; + +Hooks.PrettyPrint = { + mounted() { + prettyPrinting(); + }, + updated() { + prettyPrinting(); + } +}; // connect if there are any LiveViews on the page -liveSocket.connect() + +let liveSocket = new LiveSocket("/live", Socket, { + params: { _csrf_token: csrfToken }, + hooks: Hooks +}); +liveSocket.connect(); // expose liveSocket on window for web console debug logs and latency simulation: // >> liveSocket.enableDebug() // >> liveSocket.enableLatencySim(1000) -window.liveSocket = liveSocket +window.liveSocket = liveSocket; diff --git a/lib/sbomPoc_web/live/events_live.ex b/lib/sbomPoc_web/live/events_live.ex index c68f151..e672eae 100644 --- a/lib/sbomPoc_web/live/events_live.ex +++ b/lib/sbomPoc_web/live/events_live.ex @@ -19,7 +19,7 @@ defmodule SbomPocWeb.EventsLive do <%= if Enum.empty? @events do %>

    No events yet

    <% else %> - +
    @@ -32,7 +32,9 @@ defmodule SbomPocWeb.EventsLive do - + <% end %> From a0d9dc52fcd67072f2485b9f6ab4ff2c82076cc4 Mon Sep 17 00:00:00 2001 From: sigu Date: Tue, 27 Oct 2020 12:18:48 +0300 Subject: [PATCH 35/43] linting and removing unused tests --- config/prod.exs | 3 +-- lib/sbom_poc/accounts.ex | 2 +- lib/sbom_poc/accounts/user.ex | 1 + lib/sbom_poc/accounts/user_notifier.ex | 1 + lib/sbom_poc/accounts/user_token.ex | 1 + lib/sbom_poc/application.ex | 24 ++++++++++++--------- lib/sbom_poc_web/controllers/user_auth.ex | 1 + lib/sbom_poc_web/live/home_live.ex | 6 ++---- lib/sbom_poc_web/live/page_live.ex | 4 ++-- test/sbomPoc_web/live/page_live_test.exs | 11 ---------- test/sbomPoc_web/views/error_view_test.exs | 14 ------------ test/sbomPoc_web/views/layout_view_test.exs | 8 ------- 12 files changed, 24 insertions(+), 52 deletions(-) delete mode 100644 test/sbomPoc_web/live/page_live_test.exs delete mode 100644 test/sbomPoc_web/views/error_view_test.exs delete mode 100644 test/sbomPoc_web/views/layout_view_test.exs diff --git a/config/prod.exs b/config/prod.exs index 3cb44ae..5150727 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -15,10 +15,9 @@ config :sbom_poc, SbomPocWeb.Endpoint, cache_static_manifest: "priv/static/cache_manifest.json" # Do not print debug messages in production -#config :logger, level: :info +# config :logger, level: :info config :logger, level: :debug - config :sbom_poc, SbomPocWeb.Endpoint, server: true # ## SSL Support diff --git a/lib/sbom_poc/accounts.ex b/lib/sbom_poc/accounts.ex index 1cdfa56..62dcffa 100644 --- a/lib/sbom_poc/accounts.ex +++ b/lib/sbom_poc/accounts.ex @@ -4,8 +4,8 @@ defmodule SbomPoc.Accounts do """ import Ecto.Query, warn: false + alias SbomPoc.Accounts.{User, UserNotifier, UserToken} alias SbomPoc.Repo - alias SbomPoc.Accounts.{User, UserToken, UserNotifier} ## Database getters diff --git a/lib/sbom_poc/accounts/user.ex b/lib/sbom_poc/accounts/user.ex index a39b973..b3e52b3 100644 --- a/lib/sbom_poc/accounts/user.ex +++ b/lib/sbom_poc/accounts/user.ex @@ -1,4 +1,5 @@ defmodule SbomPoc.Accounts.User do + @moduledoc false use Ecto.Schema import Ecto.Changeset diff --git a/lib/sbom_poc/accounts/user_notifier.ex b/lib/sbom_poc/accounts/user_notifier.ex index 0c1f70f..d1ba277 100644 --- a/lib/sbom_poc/accounts/user_notifier.ex +++ b/lib/sbom_poc/accounts/user_notifier.ex @@ -1,4 +1,5 @@ defmodule SbomPoc.Accounts.UserNotifier do + @moduledoc false # For simplicity, this module simply logs messages to the terminal. # You should replace it by a proper e-mail or notification tool, such as: # diff --git a/lib/sbom_poc/accounts/user_token.ex b/lib/sbom_poc/accounts/user_token.ex index 687c1eb..d1bf805 100644 --- a/lib/sbom_poc/accounts/user_token.ex +++ b/lib/sbom_poc/accounts/user_token.ex @@ -1,4 +1,5 @@ defmodule SbomPoc.Accounts.UserToken do + @moduledoc false use Ecto.Schema import Ecto.Query diff --git a/lib/sbom_poc/application.ex b/lib/sbom_poc/application.ex index 29e29e9..23f6e95 100644 --- a/lib/sbom_poc/application.ex +++ b/lib/sbom_poc/application.ex @@ -15,6 +15,7 @@ defmodule SbomPoc.Application do For example: export CLIENT_ID=:mqttlogger """ + Logger.info("mqtt:application:client_id is #{client_id}") mqtt_host = @@ -25,6 +26,7 @@ defmodule SbomPoc.Application do export MQTT_HOST="34.86.117.113" export MQTT_HOST="mqtt.sfractal.com" """ + Logger.info("mqtt:application:mqtt_host is #{mqtt_host}") mqtt_port = @@ -36,6 +38,7 @@ defmodule SbomPoc.Application do export MQTT_PORT=1883 """) ) + Logger.info("mqtt:application:mqtt_port is #{mqtt_port}") server = {Tortoise.Transport.Tcp, host: mqtt_host, port: mqtt_port} @@ -47,6 +50,7 @@ defmodule SbomPoc.Application do Examples: export USER_NAME="plug" """ + Logger.info("mqtt:application:user_name is #{user_name}") password = @@ -56,6 +60,7 @@ defmodule SbomPoc.Application do Example: export PASSWORD="fest" """ + Logger.info("mqtt:application:password set") Logger.info("mqtt:application:Creating events table...") @@ -74,7 +79,7 @@ defmodule SbomPoc.Application do # {SbomPoc.Worker, arg} ## orig way of starting mqtt which may be overkill - ##{Tortoise.Supervisor, + ## {Tortoise.Supervisor, ## [ ## name: Oc2Mqtt.Connection.Supervisor, ## strategy: :one_for_one @@ -82,21 +87,20 @@ defmodule SbomPoc.Application do # trying another way {Tortoise.Connection, [ - client_id: client_id, - server: server, - handler: {SbomPoc.Mqtt.Handler, [name: client_id]}, - user_name: user_name, - password: password, - subscriptions: [{"#", 0}] - ] - } + client_id: client_id, + server: server, + handler: {SbomPoc.Mqtt.Handler, [name: client_id]}, + user_name: user_name, + password: password, + subscriptions: [{"#", 0}] + ]} ] # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_one, name: SbomPoc.Supervisor] Supervisor.start_link(children, opts) - ##SbomPoc.Mqtt.start() + ## SbomPoc.Mqtt.start() end # Tell Phoenix to update the endpoint configuration diff --git a/lib/sbom_poc_web/controllers/user_auth.ex b/lib/sbom_poc_web/controllers/user_auth.ex index a29409a..2f77c70 100644 --- a/lib/sbom_poc_web/controllers/user_auth.ex +++ b/lib/sbom_poc_web/controllers/user_auth.ex @@ -1,4 +1,5 @@ defmodule SbomPocWeb.UserAuth do + @moduledoc false import Plug.Conn import Phoenix.Controller diff --git a/lib/sbom_poc_web/live/home_live.ex b/lib/sbom_poc_web/live/home_live.ex index b7a7963..91dd07b 100644 --- a/lib/sbom_poc_web/live/home_live.ex +++ b/lib/sbom_poc_web/live/home_live.ex @@ -4,9 +4,9 @@ defmodule SbomPocWeb.HomeLive do @impl true def mount(_params, _session, socket) do - #Phoenix.PubSub.subscribe(SbomPoc.PubSub, @topic) + # Phoenix.PubSub.subscribe(SbomPoc.PubSub, @topic) - #events = SbomPoc.Mqtt.Handler.all_events() + # events = SbomPoc.Mqtt.Handler.all_events() {:ok, assign(socket, home: "whatever")} end @@ -49,6 +49,4 @@ defmodule SbomPocWeb.HomeLive do HaHa (ie Http Api Helloworld Actuator)

    """ end - - end diff --git a/lib/sbom_poc_web/live/page_live.ex b/lib/sbom_poc_web/live/page_live.ex index 2b40519..79f7c9a 100644 --- a/lib/sbom_poc_web/live/page_live.ex +++ b/lib/sbom_poc_web/live/page_live.ex @@ -27,9 +27,9 @@ defmodule SbomPocWeb.PageLive do end defp search(query) do - #if not SbomPocWeb.Endpoint.config(:code_reloader) do + # if not SbomPocWeb.Endpoint.config(:code_reloader) do # raise "action disabled when not in development" - #end + # end for {app, desc, vsn} <- Application.started_applications(), app = to_string(app), diff --git a/test/sbomPoc_web/live/page_live_test.exs b/test/sbomPoc_web/live/page_live_test.exs deleted file mode 100644 index c81e653..0000000 --- a/test/sbomPoc_web/live/page_live_test.exs +++ /dev/null @@ -1,11 +0,0 @@ -defmodule SbomPocWeb.PageLiveTest do - use SbomPocWeb.ConnCase - - import Phoenix.LiveViewTest - - test "disconnected and connected render", %{conn: conn} do - {:ok, page_live, disconnected_html} = live(conn, "/") - assert disconnected_html =~ "Welcome to Phoenix!" - assert render(page_live) =~ "Welcome to Phoenix!" - end -end diff --git a/test/sbomPoc_web/views/error_view_test.exs b/test/sbomPoc_web/views/error_view_test.exs deleted file mode 100644 index 4d0a10c..0000000 --- a/test/sbomPoc_web/views/error_view_test.exs +++ /dev/null @@ -1,14 +0,0 @@ -defmodule SbomPocWeb.ErrorViewTest do - use SbomPocWeb.ConnCase, async: true - - # Bring render/3 and render_to_string/3 for testing custom views - import Phoenix.View - - test "renders 404.html" do - assert render_to_string(SbomPocWeb.ErrorView, "404.html", []) == "Not Found" - end - - test "renders 500.html" do - assert render_to_string(SbomPocWeb.ErrorView, "500.html", []) == "Internal Server Error" - end -end diff --git a/test/sbomPoc_web/views/layout_view_test.exs b/test/sbomPoc_web/views/layout_view_test.exs deleted file mode 100644 index 7738832..0000000 --- a/test/sbomPoc_web/views/layout_view_test.exs +++ /dev/null @@ -1,8 +0,0 @@ -defmodule SbomPocWeb.LayoutViewTest do - use SbomPocWeb.ConnCase, async: true - - # When testing helpers, you may want to import Phoenix.HTML and - # use functions such as safe_to_string() to convert the helper - # result into an HTML string. - # import Phoenix.HTML -end From ed7615883a048295a39a080f0799254e998cf9c7 Mon Sep 17 00:00:00 2001 From: sigu Date: Tue, 27 Oct 2020 12:34:26 +0300 Subject: [PATCH 36/43] lint code --- lib/sbom_poc/posts/posts.ex | 1 + lib/sbom_poc_web/controllers/m_d_pages_controller.ex | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/sbom_poc/posts/posts.ex b/lib/sbom_poc/posts/posts.ex index 165490e..920b1e9 100644 --- a/lib/sbom_poc/posts/posts.ex +++ b/lib/sbom_poc/posts/posts.ex @@ -1,4 +1,5 @@ defmodule SbomPoc.Post do + @moduledoc false alias SbomPoc.Post.Status use NimblePublisher, diff --git a/lib/sbom_poc_web/controllers/m_d_pages_controller.ex b/lib/sbom_poc_web/controllers/m_d_pages_controller.ex index c96a39a..b69c338 100644 --- a/lib/sbom_poc_web/controllers/m_d_pages_controller.ex +++ b/lib/sbom_poc_web/controllers/m_d_pages_controller.ex @@ -1,7 +1,7 @@ defmodule SbomPocWeb.MDPagesController do use SbomPocWeb, :controller - def status(conn, params) do + def status(conn, _params) do status = SbomPoc.Post.all_status() render(conn, "status.html", status: status) end From cef94914a2c097d8d5d7a41e8ef2a8b7d1ae48b7 Mon Sep 17 00:00:00 2001 From: sigu Date: Tue, 27 Oct 2020 14:44:59 +0300 Subject: [PATCH 37/43] show sbom dashboard --- README.md | 6 ++++++ lib/sbom_poc_web/templates/layout/root.html.leex | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1aa0a18..035c759 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,12 @@ You will need to install the following dependancies to enable production of SBOM npm install -g @cyclonedx/bom ``` +### Password for accessing the sbom dashboard +```shell +username: sbom +password: sbom +``` + To start your Phoenix server: * Install dependencies with `mix deps.get` diff --git a/lib/sbom_poc_web/templates/layout/root.html.leex b/lib/sbom_poc_web/templates/layout/root.html.leex index 944811e..e1e5c22 100644 --- a/lib/sbom_poc_web/templates/layout/root.html.leex +++ b/lib/sbom_poc_web/templates/layout/root.html.leex @@ -14,7 +14,8 @@
    Time
    <%= time %> <%= details.topic %><%= details.message %> + <%= raw details.message %> +
    +
    @@ -32,7 +32,7 @@ defmodule SbomPocWeb.EventsLive do -
    Time
    <%= time %> <%= details.topic %> + <%= raw details.message %>