diff --git a/.drone.yml b/.drone.yml index eb08521..adca04a 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,14 +1,84 @@ kind: pipeline type: docker name: default + +workspace: + path: /drone/workdir + steps: + - name: mongo + image: mongo + pull: if-not-exists + detach: true + + - name: maildev + image: maildev/maildev + pull: if-not-exists + commands: + - node bin/maildev --web 80 --smtp 25 -v --hide-extensions=STARTTLS + detach: true + - name: load dependencies image: node + pull: if-not-exists + environment: + FORCE_COLOR: "true" + volumes: + - name: cache + path: /cache commands: - - yarn install + - mkdir -p /cache/node_modules + - mkdir -p /cache/user-cache + - ln -s /cache/node_modules ./node_modules + - ln -s /cache/user-cache ~/.cache + - echo cache=/cache/npm-cache >> .npmrc + - "echo 'enableGlobalCache: false' >> .yarnrc" + - 'echo ''cacheFolder: "/cache/yarn-cache"'' >> .yarnrc' + - 'echo ''yarn-offline-mirror "/cache/npm-packages-offline-cache"'' >> .yarnrc' + - "echo 'yarn-offline-mirror-pruning: true' >> .yarnrc" + - cat .yarnrc + - yarn install --verbose --frozen-lockfile + + - name: liveserver + image: node + pull: if-not-exists + volumes: + - name: cache + path: /cache + commands: + - yarn run -- live-server --no-browser --port=80 --ignore='*' --entry-file=spa.html --no-css-inject --proxy=/api:http://wmbasic-api:8080/api/v1/_/__NAMESPACE__ dist + detach: true + + - name: wmbasic-api + image: registry.webmakers.de/wmbasic/wmbasic-api + pull: never + environment: + DB_DIAL: mongodb://mongo + API_PORT: 8080 + MAIL_HOST: maildev:25 + detach: true + + - name: cypress run + image: cypress/base + pull: if-not-exists + volumes: + - name: cache + path: /cache + environment: + FORCE_COLOR: "true" + CYPRESS_BASE_URL: http://liveserver + CYPRESS_CI: "true" + CYPRESS_mongodbUri: mongodb://mongo + CYPRESS_wmbasicApiUrl: http://wmbasic-api:8080/api/v1 + CYPRESS_projectApiConfig: /drone/workdir/api/config.yml + commands: + - ln -s /cache/user-cache ~/.cache + - yarn build:instanbul + - yarn cy:run - name: modify master config image: bash + pull: if-not-exists commands: - bash scripts/modify-config.sh master __MASTER_URL__ when: @@ -16,6 +86,7 @@ steps: - name: modify dev config image: bash + pull: if-not-exists commands: - bash scripts/modify-config.sh dev __DEV_URL__ when: @@ -23,21 +94,34 @@ steps: - name: build image: node + pull: if-not-exists + volumes: + - name: cache + path: /cache commands: - yarn build - name: build ssr image: node + pull: if-not-exists + volumes: + - name: cache + path: /cache commands: - yarn build:server - name: build legacy image: node + pull: if-not-exists + volumes: + - name: cache + path: /cache commands: - yarn build:legacy - name: modify html image: bash + pull: if-not-exists commands: - bash scripts/preload-meta.sh public/spa.html - bash scripts/preload-meta.sh public/spa.html > dist/spa.html @@ -51,26 +135,53 @@ steps: - name: deploy master image: instrumentisto/rsync-ssh + pull: if-not-exists environment: RSYNC_USER: USER_PROJECT_master RSYNC_PASS: from_secret: rsync_master commands: - - apk add --no-cache sshpass - - scripts/deploy.sh ftp1.webmakers.de $${RSYNC_USER} $${RSYNC_PASS} + - apk add --no-cache sshpass + - scripts/deploy.sh ftp1.webmakers.de $${RSYNC_USER} $${RSYNC_PASS} when: branch: [master] event: [push] - name: deploy dev image: instrumentisto/rsync-ssh + pull: if-not-exists environment: RSYNC_USER: USER_PROJECT_dev RSYNC_PASS: from_secret: rsync_dev commands: - - apk add --no-cache sshpass - - scripts/deploy.sh ftp1.webmakers.de $${RSYNC_USER} $${RSYNC_PASS} + - apk add --no-cache sshpass + - scripts/deploy.sh ftp1.webmakers.de $${RSYNC_USER} $${RSYNC_PASS} when: branch: [dev] event: [push] + + - name: prepare notify + image: cypress/base + pull: if-not-exists + commands: + - find cypress -type f -wholename "cypress/videos/*" -or -wholename "cypress/screenshots/*" | tar -cvf cypress-media.tar -T - + when: + status: + - failure + + - name: notify + image: drillster/drone-email + pull: if-not-exists + settings: + from: noreply@ci.gitbase.de + host: smtp.basehosts.de + attachment: cypress-media.tar + when: + status: + - failure + +volumes: + - name: cache + host: + path: /tmp/cache/drone/${DRONE_REPO} diff --git a/.gitignore b/.gitignore index bf4d182..9780e8f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,10 @@ yarn-error.log /media/ /test.js /api/templates/spa.html -/api/hooks/lib/app.server* \ No newline at end of file +/api/hooks/lib/app.server* +cypress/_old +cypress/videos +cypress/screenshots +.~lock.* +coverage/ +.nyc_output/ diff --git a/README.md b/README.md index b9dd29c..554c7cb 100644 --- a/README.md +++ b/README.md @@ -16,12 +16,31 @@ Um die SSR-Last so gering wie möglich zu halten, wurde ein Caching in der "ssr" yarn install ``` -### Entwickeln +### Entwickeln mit dev-Webserver + +```sh +yarn start +``` + +oder mit abweichender API für "/api"-Proxy + +```sh +API_BASE=https://login.wmbasic.de/api/v1_/__NAMESPACE__ yarn start +``` + +### Entwickeln mit externem Webserver (z.B. vscode live server) ```sh yarn dev ``` +### Testen + +```sh +yarn build:istanbul # instrumentiert Code für coverage-Report +yarn cy:docker:run # oder mit Xserver und UI cy:docker:open +``` + ### Bauen ```sh diff --git a/cypress.json b/cypress.json new file mode 100644 index 0000000..0ea3c1a --- /dev/null +++ b/cypress.json @@ -0,0 +1,12 @@ +{ + "baseUrl": "http://localhost:3000", + "env": { + "mongodbUri": "mongodb://localhost", + "wmbasicApiUrl": "http://localhost:8080/api/v1", + "wmbasicDbPrefix": "wmbasic", + "wmbasicUsername": "admin", + "wmbasicPassword": "admin", + "projectApiConfig": "./api/config.yml", + "projectApiNamespace": "cypress_test" + } +} diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json new file mode 100644 index 0000000..02e4254 --- /dev/null +++ b/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/cypress/integration/0-renz-einfo/demo.spec.js b/cypress/integration/0-renz-einfo/demo.spec.js new file mode 100644 index 0000000..4f8d37c --- /dev/null +++ b/cypress/integration/0-renz-einfo/demo.spec.js @@ -0,0 +1,22 @@ +/// + +const { before } = require("../../support") + +// @ts-check + +describe("renz einfo auth", () => { + beforeEach(() => { + before() + }) + + afterEach(function () { + if (this.currentTest.state === "failed") { + cy.setCookie("shouldSkip", "true") + Cypress.runner.stop() + } + }) + + it("can visit homepage", () => { + cy.visit("/") + }) +}) diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js new file mode 100644 index 0000000..6cdba11 --- /dev/null +++ b/cypress/plugins/index.js @@ -0,0 +1,124 @@ +/// +// @ts-check + +const { default: axios } = require("axios") +const { MongoClient } = require("mongodb") +const fs = require("fs") +const util = require("util") + +// *********************************************************** +// This example plugins/index.js can be used to load plugins +// +// You can change the location of this file or turn off loading +// the plugins file with the 'pluginsFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/plugins-guide +// *********************************************************** + +// This function is called when a project is opened or re-opened (e.g. due to +// the project's config changing) + +function logObj(o) { + console.log(util.inspect(o, false, null, true /* enable colors */)) +} + +/** + * @type {Cypress.PluginConfig} + */ +// eslint-disable-next-line no-unused-vars +module.exports = (on, config) => { + require("cypress-terminal-report/src/installLogsPrinter")(on, { + printLogsToConsole: "always", + includeSuccessfulHookLogs: true, + }) + + const registerCodeCoverageTask = require("@cypress/code-coverage/task") + + // `on` is used to hook into various events Cypress emits + // `config` is the resolved Cypress config + on("before:run", async (details) => { + /* + if (details.specs && details.browser) { + // details.specs and details.browser will be undefined in interactive mode + console.log( + "Running", + details.specs.length, + "specs in", + details.browser.name + ) + }*/ + + if (config.env.CI) { + // is continous integration test run, so initialize database + console.log("CI RUN: init database") + + const wmbasicDbPrefix = config.env.wmbasicDbPrefix + const projectNamespace = config.env.projectApiNamespace + + // drop database from tests before + console.log(" - connecting to mongodb: " + config.env.mongodbUri) + const dbClient = new MongoClient(config.env.mongodbUri) + await dbClient.connect() + console.log(" - removing project from wmbasic db") + let db = dbClient.db(wmbasicDbPrefix) + db.collection("project").deleteMany({ namespace: projectNamespace }) + + const dbName = wmbasicDbPrefix + "_" + projectNamespace + console.log(" - dropping database: " + dbName) + db = dbClient.db(dbName) + await db.dropDatabase() + + // login + const apiUrl = config.env.wmbasicApiUrl + const l = await axios.post(apiUrl + "/login", { + username: config.env.wmbasicUsername, + password: config.env.wmbasicPassword, + }) + const wmbasicToken = l.data.token + + // create project + console.log(" - creating wmbasic project: " + projectNamespace) + let project + try { + const p = await axios.post( + apiUrl + "/project", + { + configFile: config.env.projectApiConfig, + name: projectNamespace, + namespace: projectNamespace, + description: projectNamespace, + }, + { + headers: { + "X-Auth-Token": wmbasicToken, + }, + } + ) + project = p.data + } catch (e) { + logObj(e) + throw e + } + + console.log(" - checking project status: " + project.id) + try { + const p = await axios.get(apiUrl + "/project/" + project.id, { + headers: { + "X-Auth-Token": wmbasicToken, + }, + }) + if (!p.data.api.isOnline) { + throw p.data + } + } catch (e) { + logObj(e) + throw e + } + + // TODO fill wmbasic database with test data + } + }) + + return registerCodeCoverageTask(on, config) +} diff --git a/cypress/support/commands.js b/cypress/support/commands.js new file mode 100644 index 0000000..119ab03 --- /dev/null +++ b/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) diff --git a/cypress/support/index.js b/cypress/support/index.js new file mode 100644 index 0000000..8421c0f --- /dev/null +++ b/cypress/support/index.js @@ -0,0 +1,41 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import "./commands" + +import installLogsCollector from "cypress-terminal-report/src/installLogsCollector" +installLogsCollector() + +import "@cypress/code-coverage/support" + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +export const before = () => { + if (Cypress.browser.isHeaded) { + cy.clearCookie("shouldSkip") + } else { + cy.getCookie("shouldSkip").then((cookie) => { + if ( + cookie && + typeof cookie === "object" && + cookie.value === "true" + ) { + Cypress.runner.stop() + } + }) + } +} diff --git a/docker-compose.cypress.yml b/docker-compose.cypress.yml new file mode 100644 index 0000000..5f341be --- /dev/null +++ b/docker-compose.cypress.yml @@ -0,0 +1,62 @@ +version: "3.9" + +services: + maildev: + image: maildev/maildev + command: + [ + node, + bin/maildev, + --web, + "80", + --smtp, + "25", + -v, + --hide-extensions=STARTTLS, + ] + + mongo: + image: mongo + + wmbasic-api: + image: registry.webmakers.de/wmbasic/wmbasic-api + environment: + DB_DIAL: mongodb://mongo + API_PORT: 8080 + MAIL_HOST: maildev:25 + depends_on: + - maildev + - mongo + volumes: + - ./:/workdir + + liveserver: + image: node + command: yarn run -- live-server --no-browser --port=80 --ignore='*' --entry-file=spa.html --no-css-inject --proxy=/api:http://wmbasic-api:8080/api/v1/_/einfo_test dist + depends_on: + - wmbasic-api + volumes: + - ./:/workdir + working_dir: /workdir + + cypress: + #image: cypress/base + image: cypress/browsers:node14.17.0-chrome91-ff89 + environment: + FORCE_COLOR: "true" + CYPRESS_BASE_URL: http://liveserver + CYPRESS_CI: "true" + CYPRESS_mongodbUri: mongodb://mongo + CYPRESS_wmbasicApiUrl: http://wmbasic-api:8080/api/v1 + CYPRESS_projectApiConfig: /workdir/api/config.yml + DISPLAY: host.docker.internal:0.0 + LIBGL_ALWAYS_INDIRECT: 1 + command: sh ./scripts/cy-command.docker.sh $CY_COMMAND + #command: yarn cy:$CY_COMMAND + depends_on: + - liveserver + volumes: + - ./:/workdir + - ~/.cache:/home/node/.cache + working_dir: /workdir + user: $CURRENT_UID diff --git a/package.json b/package.json index 95503e8..56c7eeb 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "babel-plugin-istanbul": "^6.0.0", "cypress": "^8.3.1", "cypress-terminal-report": "^3.3.2", + "live-server": "^1.2.1", "mongodb": "^4.1.1" } } diff --git a/scripts/cy-command.docker.sh b/scripts/cy-command.docker.sh index 033b343..bfac7c2 100755 --- a/scripts/cy-command.docker.sh +++ b/scripts/cy-command.docker.sh @@ -1,7 +1,10 @@ #!/bin/sh -export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2; exit;}'):0.0 -export DISPLAY=host.docker.internal:0.0 +#export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2; exit;}'):0.0 +#export DISPLAY=host.docker.internal:0.0 +rm -r coverage +rm -r .nyc_output +yarn build:instanbul echo DISPLAY: $DISPLAY yarn cy:$1 diff --git a/scripts/modify-config.sh b/scripts/modify-config.sh index da51e64..adb7a99 100755 --- a/scripts/modify-config.sh +++ b/scripts/modify-config.sh @@ -2,7 +2,6 @@ branch=$1 url=$2 -paypal=sandbox if [ "$branch" == "" ]; then echo missing branch name @@ -24,12 +23,15 @@ sed -i 's#\(pppReturnURL:\).*#pppReturnURL:"'$url'/checkout/overview\?type=paypa sed -i 's#\(pppCancelURL:\).*#pppCancelURL:"'$url'/checkout/payment\?type=paypal",#g' api/hooks/config.js sed -i 's#\(var paypalMode *=\).*#var paypalMode = "'$paypal'"#g' api/hooks/config.js cat api/hooks/config.js -sed -i 's#\(apiBaseURL.*\)"http.*"#\1"'$url'/api/"#g' src/config.ts sed -i 's#\(sentryEnvironment.*\)".*"#\1"'$branch'"#g' src/config.ts -if [ "$branch" == "master" || "$branch" == "dev" ]; then +if [[ "$branch" == "master" || "$branch" == "dev" ]]; then sed -i 's#//\( sentry\\.init.*\)#\1#g' src/config.ts fi - cat src/config.ts + +if [ "$branch" != "master" ]; then + sed -i 's#\(namespace:.*\)#\1_'$branch'#g' api/config.yml + cat api/config.yml +fi diff --git a/tsconfig.json b/tsconfig.json index 71061af..786c546 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,10 +1,10 @@ { "extends": "@tsconfig/svelte/tsconfig.json", - "include": ["src/**/*", "types/**/*"], + "include": ["src/**/*", "types/**/*", "wmbasic-api-types", "api/**/*"], "compilerOptions": { "module": "esnext", - "typeRoots": ["./node_modules/@types", "./types", "wmbasic-api-types"], + "typeRoots": ["./node_modules/@types", "./types"], "target": "esnext", "moduleResolution": "node", @@ -15,6 +15,9 @@ "resolveJsonModule": true, "useDefineForClassFields": true, "allowSyntheticDefaultImports": true, - "importsNotUsedAsValues": "error" + "importsNotUsedAsValues": "error", + + "allowJs": true, + "checkJs": true } } diff --git a/yarn.lock b/yarn.lock index 6363779..4e656f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1644,6 +1644,18 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +apache-crypt@^1.1.2: + version "1.2.5" + resolved "https://registry.yarnpkg.com/apache-crypt/-/apache-crypt-1.2.5.tgz#4eb6b6dbaed2041ce5bc2d802f4421f5fdadc25e" + integrity sha512-ICnYQH+DFVmw+S4Q0QY2XRXD8Ne8ewh8HgbuFH4K7022zCxgHM0Hz1xkRnUlEfAXNbwp1Cnhbedu60USIfDxvg== + dependencies: + unix-crypt-td-js "^1.1.4" + +apache-md5@^1.0.6: + version "1.1.7" + resolved "https://registry.yarnpkg.com/apache-md5/-/apache-md5-1.1.7.tgz#dcef1802700cc231d60c5e08fd088f2f9b36375a" + integrity sha512-JtHjzZmJxtzfTSjsCyHgPR155HBe5WGyUyHTaEkfy46qhwCFKx1Epm6nAxgUG3WfUZP1dWhGqj9Z2NOBeZ+uBw== + append-transform@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" @@ -1930,6 +1942,11 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +bcryptjs@^2.3.0: + version "2.4.3" + resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" + integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms= + binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -2659,7 +2676,7 @@ colorette@^1.3.0: resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== -colors@^1.1.2: +colors@^1.1.2, colors@latest: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== @@ -2756,6 +2773,16 @@ connect@3.6.6: parseurl "~1.3.2" utils-merge "1.0.1" +connect@^3.6.6: + version "3.7.0" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" + integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + console-browserify@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" @@ -2847,6 +2874,14 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +cors@latest: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + create-ecdh@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" @@ -3205,6 +3240,11 @@ duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: dependencies: readable-stream "^2.0.2" +duplexer@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + easy-extender@^2.3.4: version "2.3.4" resolved "https://registry.yarnpkg.com/easy-extender/-/easy-extender-2.3.4.tgz#298789b64f9aaba62169c77a2b3b64b4c9589b8f" @@ -3407,6 +3447,19 @@ etag@1.8.1, etag@^1.8.1, etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= +event-stream@3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" + integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= + dependencies: + duplexer "~0.1.1" + from "~0" + map-stream "~0.1.0" + pause-stream "0.0.11" + split "0.3" + stream-combiner "~0.0.4" + through "~2.3.1" + eventemitter2@^6.4.3: version "6.4.4" resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.4.tgz#aa96e8275c4dbeb017a5d0e03780c65612a1202b" @@ -3604,6 +3657,13 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +faye-websocket@0.11.x: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + fd-slicer@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" @@ -3653,7 +3713,7 @@ finalhandler@1.1.0: statuses "~1.3.1" unpipe "~1.0.0" -finalhandler@~1.1.2: +finalhandler@1.1.2, finalhandler@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== @@ -3737,6 +3797,11 @@ fresh@0.5.2, fresh@^0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= +from@~0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" + integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= + fromentries@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.3.2.tgz#e4bca6808816bf8f93b52750f1127f5a6fd86e3a" @@ -4063,6 +4128,16 @@ htmlescape@^1.1.0: resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" integrity sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E= +http-auth@3.1.x: + version "3.1.3" + resolved "https://registry.yarnpkg.com/http-auth/-/http-auth-3.1.3.tgz#945cfadd66521eaf8f7c84913d377d7b15f24e31" + integrity sha1-lFz63WZSHq+PfISRPTd9exXyTjE= + dependencies: + apache-crypt "^1.1.2" + apache-md5 "^1.0.6" + bcryptjs "^2.3.0" + uuid "^3.0.0" + http-errors@1.7.2: version "1.7.2" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" @@ -4095,6 +4170,11 @@ http-errors@~1.6.2: setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" +http-parser-js@>=0.5.1: + version "0.5.3" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" + integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== + http-proxy-middleware@^0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz#0987e6bb5a5606e5a69168d8f967a87f15dd8aab" @@ -4762,6 +4842,25 @@ listr2@^3.8.3: through "^2.3.8" wrap-ansi "^7.0.0" +live-server@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/live-server/-/live-server-1.2.1.tgz#670630dd409d22fe9c513ab1c1894686c757153e" + integrity sha512-Yn2XCVjErTkqnM3FfTmM7/kWy3zP7+cEtC7x6u+wUzlQ+1UW3zEYbbyJrc0jNDwiMDZI0m4a0i3dxlGHVyXczw== + dependencies: + chokidar "^2.0.4" + colors latest + connect "^3.6.6" + cors latest + event-stream "3.3.4" + faye-websocket "0.11.x" + http-auth "3.1.x" + morgan "^1.9.1" + object-assign latest + opn latest + proxy-middleware latest + send latest + serve-index "^1.9.1" + localtunnel@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/localtunnel/-/localtunnel-2.0.1.tgz#8f7c593f3005647f7675e6e69af9bf746571a631" @@ -4885,6 +4984,11 @@ map-cache@^0.2.2: resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= +map-stream@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" + integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= + map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" @@ -5102,7 +5206,7 @@ mongodb@^4.1.1: optionalDependencies: saslprep "^1.0.0" -morgan@^1.10.0: +morgan@^1.10.0, morgan@^1.9.1: version "1.10.0" resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== @@ -5266,7 +5370,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1, object-assign@latest: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -5347,6 +5451,13 @@ opn@5.3.0: dependencies: is-wsl "^1.1.0" +opn@latest: + version "6.0.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-6.0.0.tgz#3c5b0db676d5f97da1233d1ed42d182bc5a27d2d" + integrity sha512-I9PKfIZC+e4RXZ/qr1RhgyCnGgYX0UEIlXgWnCOVACIvFgaC9rz6Won7xbdhoHrd8IIhV7YEpHjreNUNkqCGkQ== + dependencies: + is-wsl "^1.1.0" + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -5532,6 +5643,13 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pause-stream@0.0.11: + version "0.0.11" + resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" + integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= + dependencies: + through "~2.3" + pbkdf2@^3.0.3: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" @@ -5676,6 +5794,11 @@ proxy-from-env@^1.0.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== +proxy-middleware@latest: + version "0.15.0" + resolved "https://registry.yarnpkg.com/proxy-middleware/-/proxy-middleware-0.15.0.tgz#a3fdf1befb730f951965872ac2f6074c61477a56" + integrity sha1-o/3xvvtzD5UZZYcqwvYHTGFHelY= + prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" @@ -6123,7 +6246,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -6210,7 +6333,7 @@ send@0.16.2: range-parser "~1.2.0" statuses "~1.4.0" -send@0.17.1: +send@0.17.1, send@latest: version "0.17.1" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== @@ -6229,7 +6352,7 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" -serve-index@1.9.1: +serve-index@1.9.1, serve-index@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= @@ -6529,6 +6652,13 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" +split@0.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" + integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= + dependencies: + through "2" + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -6593,6 +6723,13 @@ stream-combiner2@^1.1.1: duplexer2 "~0.1.0" readable-stream "^2.0.2" +stream-combiner@~0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" + integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= + dependencies: + duplexer "~0.1.1" + stream-http@^2.0.0: version "2.8.3" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" @@ -6838,7 +6975,7 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -"through@>=2.2.7 <3", through@^2.3.8: +through@2, "through@>=2.2.7 <3", through@^2.3.8, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -7084,6 +7221,11 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== +unix-crypt-td-js@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/unix-crypt-td-js/-/unix-crypt-td-js-1.1.4.tgz#4912dfad1c8aeb7d20fa0a39e4c31918c1d5d5dd" + integrity sha512-8rMeVYWSIyccIJscb9NdCfZKSRBKYTeVnwmiRYT2ulE3qd1RaDQ0xQDP+rI3ccIWbhu/zuo5cgN8z73belNZgw== + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -7156,7 +7298,7 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= -uuid@^3.3.2, uuid@^3.3.3: +uuid@^3.0.0, uuid@^3.3.2, uuid@^3.3.3: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== @@ -7166,7 +7308,7 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -vary@~1.1.2: +vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= @@ -7215,6 +7357,20 @@ webidl-conversions@^6.1.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== +websocket-driver@>=0.5.1: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: version "1.0.5" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"