diff --git a/.gitignore b/.gitignore index 0900fafd..f5cca07b 100644 --- a/.gitignore +++ b/.gitignore @@ -53,7 +53,6 @@ typings/ # dotenv environment variable files .env* -./docker/kratos/config/kratos.yml # Mac files .DS_Store @@ -86,13 +85,3 @@ docker/nginx/conf.d/server-override/* __pycache__ /.idea/ /venv* - -# CockroachDB certificates -docker/cockroach/certs/*.crt -docker/cockroach/certs/*.key -docker/kratos/cr_certs/*.crt -docker/kratos/cr_certs/*.key - -# Oathkeeper JWKS signing token -docker/kratos/oathkeeper/id_token.jwks.json -/docker/kratos/config/kratos.yml diff --git a/docker-compose.accounts.yml b/docker-compose.accounts.yml index 0ce21695..ac6e72cc 100644 --- a/docker-compose.accounts.yml +++ b/docker-compose.accounts.yml @@ -29,18 +29,22 @@ services: env_file: - .env environment: - - SKYNET_DB_HOST=${SKYNET_DB_HOST} - - SKYNET_DB_PORT=${SKYNET_DB_PORT} - - SKYNET_DB_USER=${SKYNET_DB_USER} - - SKYNET_DB_PASS=${SKYNET_DB_PASS} + - ACCOUNTS_EMAIL_URI=${ACCOUNTS_EMAIL_URI} + - ACCOUNTS_JWKS_FILE=/data/jwks.json - COOKIE_DOMAIN=${COOKIE_DOMAIN} - COOKIE_HASH_KEY=${COOKIE_HASH_KEY} - COOKIE_ENC_KEY=${COOKIE_ENC_KEY} + - PORTAL_DOMAIN=${PORTAL_DOMAIN} + - SERVER_DOMAIN=${SERVER_DOMAIN} + - SKYNET_DB_HOST=${SKYNET_DB_HOST:-mongo} + - SKYNET_DB_PORT=${SKYNET_DB_PORT:-27017} + - SKYNET_DB_USER=${SKYNET_DB_USER} + - SKYNET_DB_PASS=${SKYNET_DB_PASS} - STRIPE_API_KEY=${STRIPE_API_KEY} - STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET} - - SKYNET_ACCOUNTS_LOG_LEVEL=${SKYNET_ACCOUNTS_LOG_LEVEL} - - KRATOS_ADDR=${KRATOS_ADDR} - - OATHKEEPER_ADDR=${OATHKEEPER_ADDR} + - SKYNET_ACCOUNTS_LOG_LEVEL=${SKYNET_ACCOUNTS_LOG_LEVEL:-info} + volumes: + - ./docker/data/accounts:/data expose: - 3000 networks: @@ -48,50 +52,6 @@ services: ipv4_address: 10.10.10.70 depends_on: - mongo - - oathkeeper - - kratos-migrate: - image: oryd/kratos:v0.5.5-alpha.1 - container_name: kratos-migrate - restart: "no" - logging: *default-logging - environment: - - DSN=cockroach://root@cockroach:26257/defaultdb?max_conns=20&max_idle_conns=4&sslmode=verify-full&sslcert=/certs/node.crt&sslkey=/certs/node.key&sslrootcert=/certs/ca.crt - - SQA_OPT_OUT=true - volumes: - - ./docker/kratos/config:/etc/config/kratos - - ./docker/data/cockroach/sqlite:/var/lib/sqlite - - ./docker/kratos/cr_certs:/certs - command: -c /etc/config/kratos/kratos.yml migrate sql -e --yes - networks: - shared: - ipv4_address: 10.10.10.80 - depends_on: - - cockroach - - kratos: - image: oryd/kratos:v0.5.5-alpha.1 - container_name: kratos - restart: unless-stopped - logging: *default-logging - expose: - - 4433 # public - - 4434 # admin - environment: - - DSN=cockroach://root@cockroach:26257/defaultdb?max_conns=20&max_idle_conns=4&sslmode=verify-full&sslcert=/certs/node.crt&sslkey=/certs/node.key&sslrootcert=/certs/ca.crt - - LOG_LEVEL=trace - - SERVE_PUBLIC_BASE_URL=${SKYNET_DASHBOARD_URL}/.ory/kratos/public/ - - SQA_OPT_OUT=true - command: serve -c /etc/config/kratos/kratos.yml - volumes: - - ./docker/kratos/config:/etc/config/kratos - - ./docker/data/cockroach/sqlite:/var/lib/sqlite - - ./docker/kratos/cr_certs:/certs - networks: - shared: - ipv4_address: 10.10.10.81 - depends_on: - - kratos-migrate dashboard: build: @@ -105,50 +65,13 @@ services: environment: - NEXT_PUBLIC_SKYNET_PORTAL_API=${SKYNET_PORTAL_API} - NEXT_PUBLIC_SKYNET_DASHBOARD_URL=${SKYNET_DASHBOARD_URL} - - NEXT_PUBLIC_KRATOS_BROWSER_URL=${SKYNET_DASHBOARD_URL}/.ory/kratos/public - - NEXT_PUBLIC_KRATOS_PUBLIC_URL=http://oathkeeper:4455/.ory/kratos/public - NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=${STRIPE_PUBLISHABLE_KEY} + volumes: + - ./docker/data/dashboard/.next:/usr/app/.next networks: shared: ipv4_address: 10.10.10.85 expose: - 3000 depends_on: - - oathkeeper - - oathkeeper: - image: oryd/oathkeeper:v0.38 - container_name: oathkeeper - expose: - - 4455 - - 4456 - command: serve proxy -c "/etc/config/oathkeeper/oathkeeper.yml" - environment: - - LOG_LEVEL=debug - volumes: - - ./docker/kratos/oathkeeper:/etc/config/oathkeeper - restart: on-failure - logging: *default-logging - networks: - shared: - ipv4_address: 10.10.10.83 - depends_on: - - kratos - - cockroach: - image: cockroachdb/cockroach:v20.2.3 - container_name: cockroach - restart: unless-stopped - logging: *default-logging - env_file: - - .env - command: start --advertise-addr=${CR_IP} --join=${CR_CLUSTER_NODES} --certs-dir=/certs --listen-addr=0.0.0.0:26257 --http-addr=0.0.0.0:8080 - volumes: - - ./docker/data/cockroach/sqlite:/cockroach/cockroach-data - - ./docker/cockroach/certs:/certs - ports: - - "4080:8080" - - "26257:26257" - networks: - shared: - ipv4_address: 10.10.10.84 + - mongo diff --git a/docker/accounts/Dockerfile b/docker/accounts/Dockerfile index f1670bf4..4ec4a69e 100644 --- a/docker/accounts/Dockerfile +++ b/docker/accounts/Dockerfile @@ -1,5 +1,5 @@ FROM golang:1.16.7 -LABEL maintainer="NebulousLabs " +LABEL maintainer="NebulousLabs " ENV GOOS linux ENV GOARCH amd64 diff --git a/docker/cockroach/certs/README.md b/docker/cockroach/certs/README.md deleted file mode 100644 index fd957133..00000000 --- a/docker/cockroach/certs/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This directory needs to contain all certificates needed by this cockroachdb node. Those can be generated by the steps -outlined in the README in the root directory, under "Setting up CockroachDB". diff --git a/docker/kratos/config/identity.schema.json b/docker/kratos/config/identity.schema.json deleted file mode 100644 index 781fc761..00000000 --- a/docker/kratos/config/identity.schema.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$id": "https://schemas.ory.sh/presets/kratos/quickstart/email-password/identity.schema.json", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Person", - "type": "object", - "properties": { - "traits": { - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "title": "E-Mail", - "minLength": 3, - "ory.sh/kratos": { - "credentials": { - "password": { - "identifier": true - } - }, - "recovery": { - "via": "email" - } - } - } - }, - "required": ["email"], - "additionalProperties": true - } - } -} diff --git a/docker/kratos/config/kratos.yml.sample b/docker/kratos/config/kratos.yml.sample deleted file mode 100644 index 15442f0f..00000000 --- a/docker/kratos/config/kratos.yml.sample +++ /dev/null @@ -1,86 +0,0 @@ -version: v0.5.5-alpha.1 - -dsn: memory - -serve: - public: - base_url: http://127.0.0.1/ - cors: - enabled: true - admin: - base_url: http://127.0.0.1/admin/ - -selfservice: - default_browser_return_url: http://127.0.0.1/ - whitelisted_return_urls: - - http://127.0.0.1/ - - methods: - password: - enabled: true - - flows: - error: - ui_url: http://127.0.0.1/error - - settings: - ui_url: http://127.0.0.1/settings - privileged_session_max_age: 15m - - recovery: - enabled: true - ui_url: http://127.0.0.1/recovery - - verification: - enabled: true - ui_url: http://127.0.0.1/verify - after: - default_browser_return_url: http://127.0.0.1/ - - logout: - after: - default_browser_return_url: http://127.0.0.1/auth/login - - login: - ui_url: http://127.0.0.1/auth/login - lifespan: 10m - - registration: - lifespan: 10m - ui_url: http://127.0.0.1/auth/registration - after: - password: - hooks: - - hook: session - -log: - level: debug - format: text - leak_sensitive_values: true - -password: - max_breaches: 100 - -secrets: - cookie: - - PLEASE-CHANGE-ME-I-AM-VERY-INSECURE - -session: - cookie: - domain: account.siasky.net - lifespan: "720h" - -hashers: - argon2: - parallelism: 1 - memory: 131072 - iterations: 2 - salt_length: 16 - key_length: 16 - -identity: - default_schema_url: file:///etc/config/kratos/identity.schema.json - -courier: - smtp: - connection_uri: smtps://test:test@mailslurper:1025/?skip_ssl_verify=true diff --git a/docker/kratos/config/oidc/identity.traits.schema.json b/docker/kratos/config/oidc/identity.traits.schema.json deleted file mode 100644 index 62de3d1b..00000000 --- a/docker/kratos/config/oidc/identity.traits.schema.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$id": "https://schemas.ory.sh/presets/kratos/quickstart/email-password/identity.schema.json", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Person", - "type": "object", - "properties": { - "traits": { - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "email", - "title": "E-Mail", - "minLength": 3, - "ory.sh/kratos": { - "credentials": { - "password": { - "identifier": true - } - }, - "verification": { - "via": "email" - }, - "recovery": { - "via": "email" - } - } - }, - "website": { - "type": "object" - } - }, - "required": ["website", "email"], - "additionalProperties": false - } - } -} diff --git a/docker/kratos/config/oidc/oidc.github.jsonnet b/docker/kratos/config/oidc/oidc.github.jsonnet deleted file mode 100644 index 06b92bf9..00000000 --- a/docker/kratos/config/oidc/oidc.github.jsonnet +++ /dev/null @@ -1,17 +0,0 @@ -local claims = { - email_verified: false -} + std.extVar('claims'); - -{ - identity: { - traits: { - // Allowing unverified email addresses enables account - // enumeration attacks, especially if the value is used for - // e.g. verification or as a password login identifier. - // - // Therefore we only return the email if it (a) exists and (b) is marked verified - // by GitHub. - [if "email" in claims && claims.email_verified then "email" else null]: claims.email, - }, - }, -} diff --git a/docker/kratos/cr_certs/README.md b/docker/kratos/cr_certs/README.md deleted file mode 100644 index 72e8dda8..00000000 --- a/docker/kratos/cr_certs/README.md +++ /dev/null @@ -1,7 +0,0 @@ -This directory needs to contain all certificates needed by this cockroachdb node. Those can be generated by the steps -outlined in the README in the root directory, under "Setting up CockroachDB". - -The only difference between the files here and those under -`docker/cockroach/certs` is that the files here need to be readable by anyone, while the files under `cockroach` need to -have their original access rights -(all \*.key files should be 600 instead of 644 there). diff --git a/docker/kratos/oathkeeper/access-rules.yml b/docker/kratos/oathkeeper/access-rules.yml deleted file mode 100644 index 75bdee65..00000000 --- a/docker/kratos/oathkeeper/access-rules.yml +++ /dev/null @@ -1,116 +0,0 @@ -- id: "ory:kratos:public" - upstream: - preserve_host: true - url: "http://kratos:4433" - strip_path: /.ory/kratos/public - match: - url: "http://oathkeeper:4455/.ory/kratos/public/<**>" - methods: - - GET - - POST - - PUT - - DELETE - - PATCH - authenticators: - - handler: noop - authorizer: - handler: allow - mutators: - - handler: noop - -- id: "dashboard:anonymous" - upstream: - preserve_host: true - url: "http://dashboard:3000" - match: - url: "http://oathkeeper:4455/<{_next/**,auth/**,recovery,verify,error,favicon.ico}{/,}>" - methods: - - GET - authenticators: - - handler: anonymous - authorizer: - handler: allow - mutators: - - handler: noop - -- id: "dashboard:protected" - upstream: - preserve_host: true - url: "http://dashboard:3000" - match: - url: "http://oathkeeper:4455/<{,api/**,settings,uploads,downloads,payments}>" - methods: - - GET - - POST - - PUT - - DELETE - - PATCH - authenticators: - - handler: cookie_session - authorizer: - handler: allow - mutators: - - handler: id_token - - handler: header - config: - headers: - X-User: "{{ print .Subject }}" - errors: - - handler: redirect - config: - to: http://127.0.0.1/auth/login - -- id: "accounts:anonymous" - upstream: - preserve_host: true - url: "http://accounts:3000" - match: - url: "http://oathkeeper<{,:4455}>/<{health,stripe/prices,stripe/webhook}>" - methods: - - GET - - POST - authenticators: - - handler: anonymous - authorizer: - handler: allow - mutators: - - handler: noop - -- id: "accounts:public" - upstream: - preserve_host: true - url: "http://accounts:3000" - match: - url: "http://oathkeeper<{,:4455}>/<{user/limits}>" - methods: - - GET - authenticators: - - handler: cookie_session - - handler: noop - authorizer: - handler: allow - mutators: - - handler: id_token - -- id: "accounts:protected" - upstream: - preserve_host: true - url: "http://accounts:3000" - match: - url: "http://oathkeeper<{,:4455}>/<{login,logout,user,user/uploads,user/uploads/*,user/downloads,user/stats}>" - methods: - - GET - - POST - - PUT - - DELETE - - PATCH - authenticators: - - handler: cookie_session - authorizer: - handler: allow - mutators: - - handler: id_token - errors: - - handler: redirect - config: - to: http://127.0.0.1/auth/login diff --git a/docker/kratos/oathkeeper/oathkeeper.yml b/docker/kratos/oathkeeper/oathkeeper.yml deleted file mode 100644 index 6436c2ee..00000000 --- a/docker/kratos/oathkeeper/oathkeeper.yml +++ /dev/null @@ -1,94 +0,0 @@ -log: - level: debug - format: json - -serve: - proxy: - cors: - enabled: true - allowed_origins: - - "*" - allowed_methods: - - POST - - GET - - PUT - - PATCH - - DELETE - allowed_headers: - - Authorization - - Content-Type - exposed_headers: - - Content-Type - allow_credentials: true - debug: true - -errors: - fallback: - - json - - handlers: - redirect: - enabled: true - config: - to: http://127.0.0.1/auth/login - when: - - error: - - unauthorized - - forbidden - request: - header: - accept: - - text/html - json: - enabled: true - config: - verbose: true - -access_rules: - matching_strategy: glob - repositories: - - file:///etc/config/oathkeeper/access-rules.yml - -authenticators: - anonymous: - enabled: true - config: - subject: guest - - cookie_session: - enabled: true - config: - check_session_url: http://kratos:4433/sessions/whoami - preserve_path: true - extra_from: "@this" - subject_from: "identity.id" - only: - - ory_kratos_session - - noop: - enabled: true - -authorizers: - allow: - enabled: true - -mutators: - noop: - enabled: true - - header: - enabled: true - config: - headers: - X-User: "{{ print .Subject }}" - - id_token: - enabled: true - config: - issuer_url: http://oathkeeper:4455/ - jwks_url: file:///etc/config/oathkeeper/id_token.jwks.json - ttl: 720h - claims: | - { - "session": {{ .Extra | toJson }} - } diff --git a/docker/nginx/conf.d/server/server.account b/docker/nginx/conf.d/server/server.account index 5c524a52..47ac31cd 100644 --- a/docker/nginx/conf.d/server/server.account +++ b/docker/nginx/conf.d/server/server.account @@ -5,6 +5,18 @@ include /etc/nginx/conf.d/include/ssl-settings; include /etc/nginx/conf.d/include/init-optional-variables; location / { - proxy_redirect http://127.0.0.1/ https://$host/; - proxy_pass http://oathkeeper:4455; + proxy_pass http://dashboard:3000; +} + +location /api/stripe/billing { + proxy_pass http://dashboard:3000; +} + +location /api/stripe/checkout { + proxy_pass http://dashboard:3000; +} + +location /api { + rewrite /api/(.*) /$1 break; + proxy_pass http://accounts:3000; } diff --git a/packages/dashboard/.env b/packages/dashboard/.env deleted file mode 100644 index bb640cd8..00000000 --- a/packages/dashboard/.env +++ /dev/null @@ -1,4 +0,0 @@ -NEXT_PUBLIC_SKYNET_PORTAL_API=https://siasky.net -NEXT_PUBLIC_SKYNET_DASHBOARD_URL=https://account.siasky.net -NEXT_PUBLIC_KRATOS_BROWSER_URL=https://account.siasky.net/.ory/kratos/public -NEXT_PUBLIC_KRATOS_PUBLIC_URL=https://account.siasky.net/.ory/kratos/public diff --git a/packages/dashboard/.eslintrc.json b/packages/dashboard/.eslintrc.json new file mode 100644 index 00000000..130d98c1 --- /dev/null +++ b/packages/dashboard/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "extends": "next/core-web-vitals", + "rules": { + "@next/next/no-html-link-for-pages": "off" + } +} diff --git a/packages/dashboard/Dockerfile b/packages/dashboard/Dockerfile index 1eb955d7..57a3d7ab 100644 --- a/packages/dashboard/Dockerfile +++ b/packages/dashboard/Dockerfile @@ -10,6 +10,6 @@ RUN yarn --frozen-lockfile COPY public ./public COPY src ./src COPY styles ./styles -COPY postcss.config.js tailwind.config.js ./ +COPY .eslintrc.json postcss.config.js tailwind.config.js ./ -CMD ["sh", "-c", "env | grep -E 'NEXT_PUBLIC|KRATOS|STRIPE' > .env.local && yarn build && yarn start"] +CMD ["sh", "-c", "env | grep -E 'NEXT_PUBLIC|STRIPE' > .env.local && yarn build && yarn start"] diff --git a/packages/dashboard/package.json b/packages/dashboard/package.json index 80c0a2b6..14dcd063 100644 --- a/packages/dashboard/package.json +++ b/packages/dashboard/package.json @@ -8,11 +8,10 @@ "start": "next start" }, "dependencies": { - "@fontsource/metropolis": "4.5.0", - "@ory/kratos-client": "0.5.4-alpha.1", + "@fontsource/sora": "4.5.0", + "@fontsource/source-sans-pro": "4.5.0", "@stripe/react-stripe-js": "1.6.0", "@stripe/stripe-js": "1.21.1", - "@tailwindcss/forms": "0.3.4", "autoprefixer": "10.4.0", "classnames": "2.3.1", "copy-text-to-clipboard": "^3.0.1", @@ -21,7 +20,7 @@ "fast-levenshtein": "3.0.0", "formik": "2.2.9", "http-status-codes": "2.1.4", - "ky": "0.25.1", + "ky": "0.28.7", "next": "12.0.3", "normalize.css": "8.0.1", "postcss": "8.3.11", @@ -31,13 +30,16 @@ "react-dom": "17.0.2", "react-toastify": "8.1.0", "skynet-js": "3.0.2", - "stripe": "8.186.1", + "stripe": "8.188.0", "superagent": "6.1.0", "swr": "1.0.1", - "tailwindcss": "2.2.19", "yup": "0.32.11" }, - "resolutions": { - "axios": "0.21.4" + "devDependencies": { + "@tailwindcss/forms": "0.3.4", + "@tailwindcss/typography": "0.4.1", + "eslint": "<8.0.0", + "eslint-config-next": "12.0.3", + "tailwindcss": "2.2.19" } } diff --git a/packages/dashboard/src/components/Form/SelfServiceForm.js b/packages/dashboard/src/components/Form/SelfServiceForm.js index 67e4f717..b4d086ad 100644 --- a/packages/dashboard/src/components/Form/SelfServiceForm.js +++ b/packages/dashboard/src/components/Form/SelfServiceForm.js @@ -1,25 +1,44 @@ +import * as React from "react"; import { useFormik, getIn, setIn } from "formik"; import classnames from "classnames"; import SelfServiceMessages from "./SelfServiceMessages"; -export default function SelfServiceForm({ flow, config, fieldsConfig, title, button = "Submit" }) { - const fields = config.fields - .filter((field) => !field.name.startsWith("traits.name")) // drop name fields - .map((field) => ({ ...field, ...fieldsConfig[field.name] })) - .sort((a, b) => (a.position < b.position ? -1 : 1)); +export default function SelfServiceForm({ fieldsConfig, onSubmit, title, validationSchema = null, button = "Submit" }) { + const [messages, setMessages] = React.useState([]); + const fields = fieldsConfig.sort((a, b) => (a.position < b.position ? -1 : 1)); const formik = useFormik({ initialValues: fields.reduce((acc, field) => setIn(acc, field.name, field.value ?? ""), {}), + validationSchema, + onSubmit: async (values) => { + if (!formik.isValid) return; + + setMessages([]); + + try { + await onSubmit(values); + } catch (error) { + if (error.response) { + const data = await error.response.json(); + + if (data.message) { + setMessages((messages) => [...messages, { type: "error", text: data.message }]); + } + } else { + setMessages((messages) => [...messages, { type: "error", text: error.toString() }]); + } + } + }, }); return (
{title &&

{title}

}
-
+ {fields.map((field) => (
- - - {field.checks && ( -
-
    - {field.checks.map((check, index) => ( -
  • -
    - - - - - -
    -
    -

    {check.label}

    -
    -
    -
    -
  • - ))} -
-
+ {formik.errors[field.name] && formik.touched[field.name] && ( +

{formik.errors[field.name]}

)}
@@ -94,9 +75,7 @@ export default function SelfServiceForm({ flow, config, fieldsConfig, title, but {button} - - - {flow && } + {messages.length > 0 && }
diff --git a/packages/dashboard/src/components/Form/SelfServiceMessages.js b/packages/dashboard/src/components/Form/SelfServiceMessages.js index 9395e227..ccaadb32 100644 --- a/packages/dashboard/src/components/Form/SelfServiceMessages.js +++ b/packages/dashboard/src/components/Form/SelfServiceMessages.js @@ -32,8 +32,9 @@ import classnames from "classnames"; export default function SelfServiceMessages({ messages = [] }) { if (!messages) return null; // make sure we don't throw on invalid data - return messages.map(({ text, type }) => ( + return messages.map(({ text, type }, index) => (

- - - + Skynet + @@ -152,7 +142,7 @@ export default function Layout({ title, children }) { aria-orientation="vertical" aria-labelledby="user-menu" > - + Settings @@ -281,7 +271,7 @@ export default function Layout({ title, children }) { */}

- + Settings diff --git a/packages/dashboard/src/components/Table.js b/packages/dashboard/src/components/Table.js index 1c01b1fa..697b7d2c 100644 --- a/packages/dashboard/src/components/Table.js +++ b/packages/dashboard/src/components/Table.js @@ -44,7 +44,7 @@ export default function Table({ items, count, headers, mutate, actions, offset, if (offset < 0) setOffset(0); else if (offset >= count && count > 0) setOffset(Math.floor(count / pageSize - 1) * pageSize); else if (offset % pageSize) setOffset(offset - (offset % pageSize)); - }, [offset, pageSize, setOffset]); + }, [count, offset, pageSize, setOffset]); return (
@@ -104,7 +104,7 @@ export default function Table({ items, count, headers, mutate, actions, offset, )) ) : ( - + no entries diff --git a/packages/dashboard/src/config.js b/packages/dashboard/src/config.js index 326ec4e9..70cf9342 100644 --- a/packages/dashboard/src/config.js +++ b/packages/dashboard/src/config.js @@ -1,13 +1,4 @@ export default { - // https://github.com/ory/kratos-selfservice-ui-node#configuration - kratos: { - // The URL where ORY Kratos's Public API is located at. If this app and ORY Kratos are running in the same - // private network, this should be the private network address (e.g. kratos-public.svc.cluster.local) - public: process.env.NEXT_PUBLIC_KRATOS_PUBLIC_URL.replace(/\/+$/, ""), - // The URL where ORY Kratos's public API is located, when accessible from the public internet via ORY Oathkeeper. - // This could be for example http://kratos.my-app.com/. - browser: process.env.NEXT_PUBLIC_KRATOS_BROWSER_URL.replace(/\/+$/, ""), - }, tiers: { starter: { id: "starter", tier: 1, name: "Free", description: "Pin up to 100GB" }, }, diff --git a/packages/dashboard/src/pages/_app.js b/packages/dashboard/src/pages/_app.js index 811d3a0d..cf1d18e6 100644 --- a/packages/dashboard/src/pages/_app.js +++ b/packages/dashboard/src/pages/_app.js @@ -4,8 +4,13 @@ import { ToastContainer } from "react-toastify"; import Head from "next/head"; import "normalize.css"; import "react-toastify/dist/ReactToastify.css"; -import "tailwindcss/tailwind.css"; -import "@fontsource/metropolis/all.css"; +import "../../styles/globals.css"; +import "@fontsource/sora/300.css"; // light +import "@fontsource/sora/400.css"; // normal +import "@fontsource/sora/500.css"; // medium +import "@fontsource/sora/600.css"; // semibold +import "@fontsource/source-sans-pro/400.css"; // normal +import "@fontsource/source-sans-pro/600.css"; // semibold const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY); diff --git a/packages/dashboard/src/pages/api/accounts/login.js b/packages/dashboard/src/pages/api/accounts/login.js deleted file mode 100644 index 89bad4dc..00000000 --- a/packages/dashboard/src/pages/api/accounts/login.js +++ /dev/null @@ -1,21 +0,0 @@ -import superagent from "superagent"; - -export default async (req, res) => { - if (req.cookies.ory_kratos_session) { - try { - const { header } = await superagent - .post("http://oathkeeper:4455/login") - .set("cookie", `ory_kratos_session=${req.cookies.ory_kratos_session}`); - - res.setHeader("Set-Cookie", header["set-cookie"]); - res.redirect(req.query.return_to ?? "/"); - } catch (error) { - console.log(`Cookie is present but authentication failed: ${error.message}`); - - // credentials were correct but accounts service failed - res.redirect("/.ory/kratos/public/self-service/browser/flows/logout"); - } - } else { - res.redirect("/auth/login"); // redirect to login page if kratos session is missing - } -}; diff --git a/packages/dashboard/src/pages/api/stripe/billing.js b/packages/dashboard/src/pages/api/stripe/billing.js index 0c855ec4..58ef4bc2 100644 --- a/packages/dashboard/src/pages/api/stripe/billing.js +++ b/packages/dashboard/src/pages/api/stripe/billing.js @@ -1,4 +1,4 @@ -import ky from "ky/umd"; +import ky from "ky"; import Stripe from "stripe"; import { StatusCodes } from "http-status-codes"; @@ -11,10 +11,10 @@ const getStripeCustomer = (stripeCustomerId = null) => { return stripe.customers.create(); }; -export default async (req, res) => { +export default async function billingApi(req, res) { try { - const authorization = req.headers.authorization; // authorization header from request - const { stripeCustomerId } = await ky("http://accounts:3000/user", { headers: { authorization } }).json(); + const cookie = req.headers.cookie; // cookie header from request + const { stripeCustomerId } = await ky("http://accounts:3000/user", { headers: { cookie } }).json(); const customer = await getStripeCustomer(stripeCustomerId); const session = await stripe.billingPortal.sessions.create({ customer: customer.id, @@ -25,4 +25,4 @@ export default async (req, res) => { } catch ({ message }) { res.status(StatusCodes.BAD_REQUEST).json({ error: { message } }); } -}; +} diff --git a/packages/dashboard/src/pages/api/stripe/checkout.js b/packages/dashboard/src/pages/api/stripe/checkout.js index 879d8efd..9da694cb 100644 --- a/packages/dashboard/src/pages/api/stripe/checkout.js +++ b/packages/dashboard/src/pages/api/stripe/checkout.js @@ -1,11 +1,11 @@ -import ky from "ky/umd"; +import ky from "ky"; import Stripe from "stripe"; import { StatusCodes } from "http-status-codes"; import { isPaidTier } from "../../../services/tiers"; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); -const getStripeCustomer = async (user, authorization) => { +const getStripeCustomer = async (user, cookie) => { if (user.stripeCustomerId) { return stripe.customers.retrieve(user.stripeCustomerId); } @@ -13,12 +13,12 @@ const getStripeCustomer = async (user, authorization) => { const customer = await stripe.customers.create(); // update user instance and include the customer id once created - await ky.put(`http://accounts:3000/user`, { headers: { authorization }, json: { stripeCustomerId: customer.id } }); + await ky.put("http://accounts:3000/user", { headers: { cookie }, json: { stripeCustomerId: customer.id } }); return customer; }; -export default async (req, res) => { +export default async function checkoutApi(req, res) { if (req.method !== "POST") { return res.status(StatusCodes.NOT_FOUND).end(); } @@ -30,8 +30,8 @@ export default async (req, res) => { } try { - const authorization = req.headers.authorization; // authorization header from request - const user = await ky("http://accounts:3000/user", { headers: { authorization } }).json(); + const cookie = req.headers.cookie; // cookie header from request + const user = await ky("http://accounts:3000/user", { headers: { cookie } }).json(); if (isPaidTier(user.tier)) { const message = `Customer can have only one active subscription at a time, use Stripe Customer Portal to manage active subscription`; @@ -39,7 +39,7 @@ export default async (req, res) => { return res.status(StatusCodes.BAD_REQUEST).json({ error: { message } }); } - const customer = await getStripeCustomer(user, authorization); + const customer = await getStripeCustomer(user, cookie); const session = await stripe.checkout.sessions.create({ mode: "subscription", payment_method_types: ["card"], @@ -55,4 +55,4 @@ export default async (req, res) => { } catch (error) { res.status(StatusCodes.BAD_REQUEST).json({ error: { message: error.message } }); } -}; +} diff --git a/packages/dashboard/src/pages/api/stripe/subscription.js b/packages/dashboard/src/pages/api/stripe/subscription.js deleted file mode 100644 index 3526d5ac..00000000 --- a/packages/dashboard/src/pages/api/stripe/subscription.js +++ /dev/null @@ -1,23 +0,0 @@ -import ky from "ky/umd"; -import Stripe from "stripe"; -import { StatusCodes } from "http-status-codes"; - -const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); - -export default async (req, res) => { - try { - const authorization = req.headers.authorization; // authorization header from request - const { stripeCustomerId } = await ky("http://accounts:3000/user", { headers: { authorization } }).json(); - const stripeCustomer = await stripe.customers.retrieve(stripeCustomerId, { expand: ["subscriptions"] }); - const { subscriptions } = stripeCustomer; - - // todo: find a better way to get current subscription - if (subscriptions.total_count) { - return res.json(subscriptions.data[0]); - } - - res.status(StatusCodes.NO_CONTENT).end(); - } catch ({ message }) { - res.status(StatusCodes.BAD_REQUEST).json({ error: { message } }); - } -}; diff --git a/packages/dashboard/src/pages/api/stubs/stripe/prices.js b/packages/dashboard/src/pages/api/stubs/stripe/prices.js deleted file mode 100644 index ebf013a3..00000000 --- a/packages/dashboard/src/pages/api/stubs/stripe/prices.js +++ /dev/null @@ -1,37 +0,0 @@ -export default (req, res) => { - res.json([ - { - id: "price_1IReYFIzjULiPWN6DqN2DwjN", - name: "Skynet Extreme", - description: "Skynet Extreme description", - tier: 4, - price: 80, - currency: "usd", - stripe: "price_1IReYFIzjULiPWN6DqN2DwjN", - productId: "prod_J3m6IuVyh3XOc5", - livemode: false, - }, - { - id: "price_1IReY5IzjULiPWN6AxPytHEG", - name: "Skynet Pro", - description: "Skynet Pro description", - tier: 3, - price: 20, - currency: "usd", - stripe: "price_1IReY5IzjULiPWN6AxPytHEG", - productId: "prod_J3m6ioQg90kZj5", - livemode: false, - }, - { - id: "price_1IReXpIzjULiPWN66PvsxHL4", - name: "Skynet Plus", - description: "Skynet Plus description", - tier: 2, - price: 5, - currency: "usd", - stripe: "price_1IReXpIzjULiPWN66PvsxHL4", - productId: "prod_J3m6xMfDiz2LGE", - livemode: false, - }, - ]); -}; diff --git a/packages/dashboard/src/pages/api/stubs/user.js b/packages/dashboard/src/pages/api/stubs/user.js deleted file mode 100644 index 409bf333..00000000 --- a/packages/dashboard/src/pages/api/stubs/user.js +++ /dev/null @@ -1,5 +0,0 @@ -import user from "./user.json"; - -export default (req, res) => { - res.json(user); -}; diff --git a/packages/dashboard/src/pages/api/stubs/user.json b/packages/dashboard/src/pages/api/stubs/user.json deleted file mode 100644 index f41dab0e..00000000 --- a/packages/dashboard/src/pages/api/stubs/user.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "firstName": "John", - "lastName": "Doe", - "email": "john@example.com", - "sub": "ab776d6d-f324-4fa7-4k21-7587d5215481", - "tier": 1, - "subscribedUntil": "0001-01-01T00:00:00Z", - "subscriptionStatus": "active", - "subscriptionCancelAt": "2021-04-21T00:00:00Z", - "subscriptionCancelAtPeriodEnd": true, - "stripeCustomerId": "cus_J0iYnAp6LRgsTI" -} diff --git a/packages/dashboard/src/pages/api/stubs/user/downloads.js b/packages/dashboard/src/pages/api/stubs/user/downloads.js deleted file mode 100644 index c4a24c03..00000000 --- a/packages/dashboard/src/pages/api/stubs/user/downloads.js +++ /dev/null @@ -1,8 +0,0 @@ -import items from "./downloads.json"; - -export default (req, res) => { - const offset = parseInt(req.query?.offset ?? 0, 10); - const pageSize = parseInt(req.query?.pageSize ?? 10, 10); - - res.json({ items: items.slice(offset, offset + pageSize), count: items.length, pageSize, offset }); -}; diff --git a/packages/dashboard/src/pages/api/stubs/user/downloads.json b/packages/dashboard/src/pages/api/stubs/user/downloads.json deleted file mode 100644 index edf6ff0d..00000000 --- a/packages/dashboard/src/pages/api/stubs/user/downloads.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "id": 1111, - "skylink": "PAL0w4SdA5rFCDGEutgpeQ50Om-YkBabtXVOJAkmedslKw", - "name": "ugabuga.pdf", - "size": 123123, - "downloadedOn": "2020-04-02T08:02:17-05:00" - }, - { - "id": 2222, - "skylink": "XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg", - "name": "ugabuga.pdf", - "size": 8912739812, - "downloadedOn": "2020-04-02T08:02:17-05:00" - }, - { - "id": 3333, - "skylink": "IADUs8d9CQjUO34LmdaaNPK_STuZo24rpKVfYW3wPPM2uQ", - "name": "ugabuga.pdf", - "size": 123123, - "downloadedOn": "2020-04-02T08:02:17-05:00" - }, - { - "id": 4444, - "skylink": "_A2zt5SKoqwnnZU4cBF8uBycSKULXMyeg1c5ZISBr2Q3dA", - "name": "ugabuga.pdf", - "size": 83943, - "downloadedOn": "2020-04-02T08:02:17-05:00" - }, - { - "id": 5555, - "skylink": "AAC0uO43g64ULpyrW0zO3bjEknSFbAhm8c-RFP21EQlmSQ", - "name": "ugabuga.pdf", - "size": 3290489120, - "downloadedOn": "2020-04-02T08:02:17-05:00" - }, - { - "id": 6666, - "skylink": "CACqf4NlIMlA0CCCieYGjpViPGyfyJ4v1x3bmuCKZX8FKA", - "name": "ugabuga.pdf", - "size": 1290389, - "downloadedOn": "2020-04-02T08:02:17-05:00" - } -] diff --git a/packages/dashboard/src/pages/api/stubs/user/stats.js b/packages/dashboard/src/pages/api/stubs/user/stats.js deleted file mode 100644 index 81a65545..00000000 --- a/packages/dashboard/src/pages/api/stubs/user/stats.js +++ /dev/null @@ -1,5 +0,0 @@ -import stats from "./stats.json"; - -export default (req, res) => { - res.json(stats); -}; diff --git a/packages/dashboard/src/pages/api/stubs/user/stats.json b/packages/dashboard/src/pages/api/stubs/user/stats.json deleted file mode 100644 index 29696ca2..00000000 --- a/packages/dashboard/src/pages/api/stubs/user/stats.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "storageUsed": 809500672, - "numRegReads": 0, - "numRegWrites": 0, - "numUploads": 13, - "numDownloads": 78, - "totalUploadsSize": 618649028, - "totalDownloadsSize": 32307956843, - "bwUploads": 2810183680, - "bwDownloads": 32323934976, - "bwRegReads": 0, - "bwRegWrites": 0 -} diff --git a/packages/dashboard/src/pages/api/stubs/user/uploads.js b/packages/dashboard/src/pages/api/stubs/user/uploads.js deleted file mode 100644 index ad8b3d20..00000000 --- a/packages/dashboard/src/pages/api/stubs/user/uploads.js +++ /dev/null @@ -1,8 +0,0 @@ -import items from "./uploads.json"; - -export default (req, res) => { - const offset = parseInt(req.query?.offset ?? 0, 10); - const pageSize = parseInt(req.query?.pageSize ?? 10, 10); - - res.json({ items: items.slice(offset, offset + pageSize), count: items.length, pageSize, offset }); -}; diff --git a/packages/dashboard/src/pages/api/stubs/user/uploads.json b/packages/dashboard/src/pages/api/stubs/user/uploads.json deleted file mode 100644 index efc42359..00000000 --- a/packages/dashboard/src/pages/api/stubs/user/uploads.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "id": 1111, - "skylink": "PAL0w4SdA5rFCDGEutgpeQ50Om-YkBabtXVOJAkmedslKw", - "name": "ugabuga.pdf", - "size": 123123, - "uploadedOn": "2020-04-02T08:02:17-05:00" - }, - { - "id": 2222, - "skylink": "XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg", - "name": "ugabuga.pdf", - "size": 8912739812, - "uploadedOn": "2020-04-02T08:02:17-05:00" - }, - { - "id": 3333, - "skylink": "IADUs8d9CQjUO34LmdaaNPK_STuZo24rpKVfYW3wPPM2uQ", - "name": "ugabuga.pdf", - "size": 123123, - "uploadedOn": "2020-04-02T08:02:17-05:00" - }, - { - "id": 4444, - "skylink": "_A2zt5SKoqwnnZU4cBF8uBycSKULXMyeg1c5ZISBr2Q3dA", - "name": "ugabuga.pdf", - "size": 83943, - "uploadedOn": "2020-04-02T08:02:17-05:00" - }, - { - "id": 5555, - "skylink": "AAC0uO43g64ULpyrW0zO3bjEknSFbAhm8c-RFP21EQlmSQ", - "name": "ugabuga.pdf", - "size": 3290489120, - "uploadedOn": "2020-04-02T08:02:17-05:00" - }, - { - "id": 6666, - "skylink": "CACqf4NlIMlA0CCCieYGjpViPGyfyJ4v1x3bmuCKZX8FKA", - "name": "ugabuga.pdf", - "size": 1290389, - "uploadedOn": "2020-04-02T08:02:17-05:00" - } -] diff --git a/packages/dashboard/src/pages/auth/login.js b/packages/dashboard/src/pages/auth/login.js index f9e8ab45..46b807f6 100644 --- a/packages/dashboard/src/pages/auth/login.js +++ b/packages/dashboard/src/pages/auth/login.js @@ -1,65 +1,48 @@ import Link from "next/link"; -import { Configuration, PublicApi } from "@ory/kratos-client"; -import config from "../../config"; +import { useRouter } from "next/router"; +import * as Yup from "yup"; +import accountsApi from "../../services/accountsApi"; +import useAnonRoute from "../../services/useAnonRoute"; import SelfServiceForm from "../../components/Form/SelfServiceForm"; -const kratos = new PublicApi(new Configuration({ basePath: config.kratos.public })); - -export async function getServerSideProps(context) { - const flow = context.query.flow; - const redirect = encodeURIComponent(`/api/accounts/login?return_to=${context.query.return_to ?? "/"}`); - - if (process.env.NODE_ENV === "development") { - return { props: { flow: require("../../../stubs/login.json") } }; - } - - // The flow is used to identify the login and registration flow and - // return data like the csrf_token and so on. - if (!flow || typeof flow !== "string") { - // No flow ID found in URL, initializing login flow. - return { - redirect: { - permanent: false, - destination: `${config.kratos.browser}/self-service/login/browser?return_to=${redirect}`, - }, - }; - } - - try { - const { status, data } = await kratos.getSelfServiceLoginFlow(flow); - - if (status === 200) return { props: { flow: data } }; - - throw new Error(`Failed to retrieve flow ${flow} with code ${status}`); - } catch (error) { - console.log(`Unexpected error retrieving login flow: ${error.message}`); - - return { - redirect: { - permanent: false, - destination: `${config.kratos.browser}/self-service/login/browser?return_to=${redirect}`, - }, - }; - } -} - -const fieldsConfig = { - identifier: { +const fieldsConfig = [ + { + name: "email", + type: "text", label: "Email address", autoComplete: "email", position: 0, }, - password: { + { + name: "password", + type: "password", label: "Password", autoComplete: "current-password", position: 1, }, - csrf_token: { - position: 99, - }, -}; +]; + +const validationSchema = Yup.object().shape({ + email: Yup.string().required("Email is required").email("This email is invalid"), + password: Yup.string().required("Password is required"), +}); + +export default function Login() { + useAnonRoute(); // ensure user is not logged in + + const router = useRouter(); + + const onSubmit = async (values) => { + await accountsApi.post("login", { + json: { + email: values.email, + password: values.password, + }, + }); + + router.push("/"); + }; -export default function Login({ flow }) { return (
@@ -82,14 +65,19 @@ export default function Login({ flow }) { sign up {" "} - if you don't have one yet + if you don't have one yet

- + diff --git a/packages/dashboard/src/pages/recovery.js b/packages/dashboard/src/pages/auth/recovery.js similarity index 69% rename from packages/dashboard/src/pages/recovery.js rename to packages/dashboard/src/pages/auth/recovery.js index e64a4213..05f94d85 100644 --- a/packages/dashboard/src/pages/recovery.js +++ b/packages/dashboard/src/pages/auth/recovery.js @@ -1,57 +1,39 @@ +import * as React from "react"; import Link from "next/link"; -import { Configuration, PublicApi } from "@ory/kratos-client"; -import config from "../config"; -import SelfServiceForm from "../components/Form/SelfServiceForm"; +import * as Yup from "yup"; +import accountsApi from "../../services/accountsApi"; +import useAnonRoute from "../../services/useAnonRoute"; +import SelfServiceForm from "../../components/Form/SelfServiceForm"; -const kratos = new PublicApi(new Configuration({ basePath: config.kratos.public })); - -export async function getServerSideProps(context) { - const flow = context.query.flow; - - if (process.env.NODE_ENV === "development") { - return { props: { flow: require("../../stubs/recovery.json") } }; - } - - // The flow is used to identify the login and registration flow and - // return data like the csrf_token and so on. - if (!flow || typeof flow !== "string") { - // No flow ID found in URL, initializing recovery flow. - return { - redirect: { - permanent: false, - destination: `${config.kratos.browser}/self-service/recovery/browser`, - }, - }; - } - - try { - const { status, data } = await kratos.getSelfServiceRecoveryFlow(flow); - - if (status === 200) return { props: { flow: data } }; - - throw new Error(`Failed to retrieve flow ${flow} with code ${status}`); - } catch (error) { - return { - redirect: { - permanent: false, - destination: `${config.kratos.browser}/self-service/recovery/browser`, - }, - }; - } -} - -const fieldsConfig = { - email: { - label: "Your email", +const fieldsConfig = [ + { + name: "email", + type: "text", + label: "Email address", autoComplete: "email", position: 0, }, - csrf_token: { - position: 99, - }, -}; +]; + +const validationSchema = Yup.object().shape({ + email: Yup.string().required("Email is required").email("This email is invalid"), +}); + +export default function Recovery() { + useAnonRoute(); // ensure user is not logged in + + const [success, setSuccess] = React.useState(false); + + const onSubmit = async (values) => { + await accountsApi.post("user/recover/request", { + json: { + email: values.email, + }, + }); + + setSuccess(true); + }; -export default function Recovery({ flow }) { return (
@@ -84,12 +66,20 @@ export default function Recovery({ flow }) {

- + {!success && ( + + )} + + {success && ( +

+ Account recovery requested, please follow instructions sent in email. +

+ )}
); } diff --git a/packages/dashboard/src/pages/auth/registration.js b/packages/dashboard/src/pages/auth/registration.js index 23414f72..c790f99a 100644 --- a/packages/dashboard/src/pages/auth/registration.js +++ b/packages/dashboard/src/pages/auth/registration.js @@ -1,88 +1,66 @@ import Link from "next/link"; -import { Configuration, PublicApi } from "@ory/kratos-client"; -import { getIn } from "formik"; -import config from "../../config"; +import { useRouter } from "next/router"; import levenshtein from "fast-levenshtein"; +import * as Yup from "yup"; +import accountsApi from "../../services/accountsApi"; +import useAnonRoute from "../../services/useAnonRoute"; import lcs from "../../services/longestCommonSequence"; import SelfServiceForm from "../../components/Form/SelfServiceForm"; -const kratos = new PublicApi(new Configuration({ basePath: config.kratos.public })); - -export async function getServerSideProps(context) { - const flow = context.query.flow; - const redirect = encodeURIComponent(`/api/accounts/login?return_to=${context.query.return_to ?? "/"}`); - - if (process.env.NODE_ENV === "development") { - return { props: { flow: require("../../../stubs/registration.json") } }; - } - - // The flow is used to identify the login and registration flow and - // return data like the csrf_token and so on. - if (!flow || typeof flow !== "string") { - // No flow ID found in URL, initializing registration flow. - return { - redirect: { - permanent: false, - destination: `${config.kratos.browser}/self-service/registration/browser?return_to=${redirect}`, - }, - }; - } - - try { - const { status, data } = await kratos.getSelfServiceRegistrationFlow(flow); - - if (status === 200) return { props: { flow: data } }; - - throw new Error(`Failed to retrieve flow ${flow} with code ${status}`); - } catch (error) { - console.log(`Unexpected error retrieving registration flow: ${error.message}`); - - return { - redirect: { - permanent: false, - destination: `${config.kratos.browser}/self-service/registration/browser?return_to=${redirect}`, - }, - }; - } -} - -const fieldsConfig = { - "traits.email": { +const fieldsConfig = [ + { + name: "email", + type: "text", label: "Email address", autoComplete: "email", position: 0, }, - password: { + { + name: "password", + type: "password", label: "Password", autoComplete: "new-password", position: 1, - checks: [ - { - label: "At least 6 characters long", - validate: (values, field) => { - const value = getIn(values, field); - - return value && value.length > 5; - }, - }, - { - label: "Significantly different from the email", - validate: (values, field) => { - const value = getIn(values, field); - const email = getIn(values, "traits.email"); - - // levenshtein distance higher than 5 and longest common sequence shorter than half of the password - return value && email && levenshtein.get(value, email) > 5 && lcs(value, email).length / value.length <= 0.5; - }, - }, - ], }, - csrf_token: { - position: 99, + { + name: "confirmPassword", + type: "password", + label: "Password repeated", + autoComplete: "new-password", + position: 2, }, -}; +]; + +const validationSchema = Yup.object().shape({ + email: Yup.string().required("Email is required").email("This email is invalid"), + password: Yup.string() + .required("Password is required") + .min(6, "Password has to be at least 6 characters long") + .test("levenshtein", "This password is too similar to your email", function (value) { + const email = this.parent.email; + + // levenshtein distance higher than 5 and longest common sequence shorter than half of the password + return value && email && levenshtein.get(value, email) > 5 && lcs(value, email).length / value.length <= 0.5; + }), + confirmPassword: Yup.string().oneOf([Yup.ref("password"), null], "Passwords must match"), +}); + +export default function Registration() { + useAnonRoute(); // ensure user is not logged in + + const router = useRouter(); + + const onSubmit = async (values) => { + await accountsApi.post("user", { + json: { + email: values.email, + password: values.password, + }, + }); + + router.push("/"); + }; -export default function Registration({ flow }) { return (
@@ -109,7 +87,12 @@ export default function Registration({ flow }) {

- +
); } diff --git a/packages/dashboard/src/pages/downloads.js b/packages/dashboard/src/pages/downloads.js index d18257f7..c94bee3a 100644 --- a/packages/dashboard/src/pages/downloads.js +++ b/packages/dashboard/src/pages/downloads.js @@ -3,12 +3,10 @@ import prettyBytes from "pretty-bytes"; import { useState } from "react"; import Layout from "../components/Layout"; import Table from "../components/Table"; -import authServerSideProps from "../services/authServerSideProps"; import { SkynetClient } from "skynet-js"; import useAccountsApi from "../services/useAccountsApi"; const skynetClient = new SkynetClient(process.env.NEXT_PUBLIC_SKYNET_PORTAL_API); -const apiPrefix = process.env.NODE_ENV === "development" ? "/api/stubs" : ""; const getSkylinkLink = ({ skylink }) => skynetClient.getSkylinkUrl(skylink); const getRelativeDate = ({ downloadedOn }) => dayjs(downloadedOn).format("YYYY-MM-DD HH:mm:ss"); const headers = [ @@ -36,22 +34,15 @@ const headers = [ ]; const actions = []; -export const getServerSideProps = authServerSideProps(async (context, api) => { - const initialData = await api.get("user/downloads?pageSize=10&offset=0").json(); - - return { props: { initialData } }; -}); - -export default function Downloads({ initialData }) { +export default function Downloads() { const [offset, setOffset] = useState(0); - const { data } = useAccountsApi(`${apiPrefix}/user/downloads?pageSize=10&offset=${offset}`, { - initialData: offset === 0 ? initialData : undefined, + const { data } = useAccountsApi(`user/downloads?pageSize=10&offset=${offset}`, { revalidateOnMount: true, }); // preload next page if it exists (based on the response from the current page query) const nextPageOffset = data && data.offset + data.pageSize < data.count ? data.offset + data.pageSize : offset; - useAccountsApi(`${apiPrefix}/user/downloads?pageSize=10&offset=${nextPageOffset}`); + useAccountsApi(`user/downloads?pageSize=10&offset=${nextPageOffset}`); return ( diff --git a/packages/dashboard/src/pages/index.js b/packages/dashboard/src/pages/index.js index c3e9d809..cbb2e68b 100644 --- a/packages/dashboard/src/pages/index.js +++ b/packages/dashboard/src/pages/index.js @@ -4,23 +4,14 @@ import relativeTime from "dayjs/plugin/relativeTime"; import prettyBytes from "pretty-bytes"; import Link from "next/link"; import Layout from "../components/Layout"; -import authServerSideProps from "../services/authServerSideProps"; import { SkynetClient } from "skynet-js"; import config from "../config"; import useAccountsApi from "../services/useAccountsApi"; -import { isFreeTier } from "../services/tiers"; +import React from "react"; dayjs.extend(relativeTime); const skynetClient = new SkynetClient(process.env.NEXT_PUBLIC_SKYNET_PORTAL_API); -const apiPrefix = process.env.NODE_ENV === "development" ? "/api/stubs" : ""; - -export const getServerSideProps = authServerSideProps(async (context, api) => { - const stripe = await api.get("stripe/prices").json(); - const plans = [config.tiers.starter, ...stripe].sort((a, b) => a.tier - b.tier); - - return { props: { plans } }; -}); function SkylinkList({ items = [], timestamp }) { return ( @@ -99,13 +90,19 @@ function SkylinkList({ items = [], timestamp }) { ); } -export default function Home({ plans }) { - const { data: user } = useAccountsApi(`${apiPrefix}/user`); - const { data: stats } = useAccountsApi(`${apiPrefix}/user/stats`); - const { data: downloads } = useAccountsApi(`${apiPrefix}/user/downloads?pageSize=3&offset=0`); - const { data: uploads } = useAccountsApi(`${apiPrefix}/user/uploads?pageSize=3&offset=0`); +export default function Home() { + const { data: prices } = useAccountsApi("stripe/prices"); + const { data: user } = useAccountsApi("user"); + const { data: stats } = useAccountsApi("user/stats"); + const { data: downloads } = useAccountsApi("user/downloads?pageSize=3&offset=0"); + const { data: uploads } = useAccountsApi("user/uploads?pageSize=3&offset=0"); + const [plans, setPlans] = React.useState([config.tiers.starter]); - const activePlan = plans.find(({ tier }) => (user ? user.tier === tier : isFreeTier(tier))); + React.useEffect(() => { + if (prices) setPlans((plans) => [...plans, ...prices].sort((a, b) => a.tier - b.tier)); + }, [setPlans, prices]); + + const activePlan = plans.find(({ tier }) => user && user.tier === tier); return ( @@ -135,7 +132,7 @@ export default function Home({ plans }) {
Current plan
-
{activePlan.name}
+
{activePlan?.name}
diff --git a/packages/dashboard/src/pages/payments.js b/packages/dashboard/src/pages/payments.js index 94289e2d..48bbe5ba 100644 --- a/packages/dashboard/src/pages/payments.js +++ b/packages/dashboard/src/pages/payments.js @@ -1,16 +1,13 @@ import dayjs from "dayjs"; import Layout from "../components/Layout"; -import ky from "ky/umd"; -import { useEffect, useState } from "react"; -import authServerSideProps from "../services/authServerSideProps"; +import ky from "ky"; +import * as React from "react"; import classnames from "classnames"; import prettyBytes from "pretty-bytes"; import config from "../config"; import useAccountsApi from "../services/useAccountsApi"; import { isFreeTier, isPaidTier } from "../services/tiers"; -const apiPrefix = process.env.NODE_ENV === "development" ? "/api/stubs" : ""; - const ActiveBadge = () => { return ( @@ -19,22 +16,23 @@ const ActiveBadge = () => { ); }; -export const getServerSideProps = authServerSideProps(async (context, api) => { - const [user, stats, stripe] = await Promise.all([ - api.get("user").json(), - api.get("user/stats").json(), - api.get("stripe/prices").json(), - ]); - const plans = [config.tiers.starter, ...stripe].sort((a, b) => a.tier - b.tier); +export default function Payments() { + const { data: user } = useAccountsApi("user"); + const { data: stats } = useAccountsApi("user/stats"); + const { data: prices } = useAccountsApi("stripe/prices"); + const [plans, setPlans] = React.useState([config.tiers.starter]); + const [selectedPlan, setSelectedPlan] = React.useState(null); - return { props: { plans, user, stats } }; -}); + React.useEffect(() => { + if (prices) setPlans((plans) => [...plans, ...prices].sort((a, b) => a.tier - b.tier)); + }, [setPlans, prices]); + + const activePlan = plans.find(({ tier }) => user && user.tier === tier); + + React.useEffect(() => { + setSelectedPlan(activePlan); + }, [activePlan, setSelectedPlan]); -export default function Payments({ plans, user: initialUserData, stats: initialStatsData }) { - const { data: user } = useAccountsApi(`${apiPrefix}/user`, { initialData: initialUserData }); - const { data: stats } = useAccountsApi(`${apiPrefix}/user/stats`, { initialData: initialStatsData }); - const [selectedPlan, setSelectedPlan] = useState(plans.find(({ tier }) => isFreeTier(tier))); - const activePlan = plans.find(({ tier }) => (user ? user.tier === tier : isFreeTier(tier))); const handleSubscribe = async () => { try { const price = selectedPlan.stripe; @@ -46,12 +44,6 @@ export default function Payments({ plans, user: initialUserData, stats: initialS } }; - useEffect(() => { - if (activePlan && isPaidTier(activePlan.tier)) { - setSelectedPlan(activePlan); - } - }, [activePlan, selectedPlan, setSelectedPlan]); - return (
diff --git a/packages/dashboard/src/pages/plans.js b/packages/dashboard/src/pages/plans.js index ee319e69..7935f0f4 100644 --- a/packages/dashboard/src/pages/plans.js +++ b/packages/dashboard/src/pages/plans.js @@ -41,7 +41,7 @@ export default function Payments() {
-

What's included

+

What's included

  • {/* Heroicon name: solid/check */} @@ -96,7 +96,7 @@ export default function Payments() {
-

What's included

+

What's included

  • {/* Heroicon name: solid/check */} @@ -168,7 +168,7 @@ export default function Payments() {
-

What's included

+

What's included

  • {/* Heroicon name: solid/check */} @@ -257,7 +257,7 @@ export default function Payments() {
-

What's included

+

What's included

  • {/* Heroicon name: solid/check */} diff --git a/packages/dashboard/src/pages/settings.js b/packages/dashboard/src/pages/settings.js deleted file mode 100644 index 2c17a337..00000000 --- a/packages/dashboard/src/pages/settings.js +++ /dev/null @@ -1,79 +0,0 @@ -import { Configuration, PublicApi } from "@ory/kratos-client"; -import Layout from "../components/Layout"; -import config from "../config"; -import SelfServiceForm from "../components/Form/SelfServiceForm"; -import authServerSideProps from "../services/authServerSideProps"; - -const kratos = new PublicApi(new Configuration({ basePath: config.kratos.public })); - -export const getServerSideProps = authServerSideProps(async (context) => { - const flow = context.query.flow; - - if (process.env.NODE_ENV === "development") { - return { props: { flow: require("../../stubs/settings.json") } }; - } - - // The flow is used to identify the login and registration flow and - // return data like the csrf_token and so on. - if (!flow || typeof flow !== "string") { - // No flow ID found in URL, initializing settings flow. - return { - redirect: { - permanent: false, - destination: `${config.kratos.browser}/self-service/settings/browser`, - }, - }; - } - - try { - const { status, data } = await kratos.getSelfServiceSettingsFlow(flow, { - headers: { cookie: context.req.headers.cookie }, - }); - - if (status === 200) return { props: { flow: data } }; - - throw new Error(`Failed to retrieve flow ${flow} with code ${status}`); - } catch (error) { - return { - redirect: { - permanent: false, - destination: `${config.kratos.browser}/self-service/settings/browser`, - }, - }; - } -}); - -const fieldsConfig = { - "traits.email": { - label: "Email address", - autoComplete: "email", - position: 0, - }, - password: { - label: "Password", - autoComplete: "new-password", - position: 1, - }, - csrf_token: { - position: 99, - }, -}; - -export default function Settings({ flow }) { - const profileConfig = flow.methods.profile.config; - const passwordConfig = flow.methods.password.config; - - return ( - -
    - - -
    -
    - ); -} diff --git a/packages/dashboard/src/pages/uploads.js b/packages/dashboard/src/pages/uploads.js index ff452f49..937542f5 100644 --- a/packages/dashboard/src/pages/uploads.js +++ b/packages/dashboard/src/pages/uploads.js @@ -1,16 +1,14 @@ import dayjs from "dayjs"; import prettyBytes from "pretty-bytes"; import { useState } from "react"; -import ky from "ky/umd"; +import ky from "ky"; import { toast } from "react-toastify"; import Layout from "../components/Layout"; import Table from "../components/Table"; -import authServerSideProps from "../services/authServerSideProps"; import { SkynetClient } from "skynet-js"; import useAccountsApi from "../services/useAccountsApi"; const skynetClient = new SkynetClient(process.env.NEXT_PUBLIC_SKYNET_PORTAL_API); -const apiPrefix = process.env.NODE_ENV === "development" ? "/api/stubs" : ""; const getSkylinkLink = ({ skylink }) => skynetClient.getSkylinkUrl(skylink); const getRelativeDate = ({ uploadedOn }) => dayjs(uploadedOn).format("YYYY-MM-DD HH:mm:ss"); const headers = [ @@ -40,7 +38,7 @@ const actions = [ { name: "Unpin Skylink", action: async ({ skylink }, mutate) => { - await toast.promise(ky.delete(`/user/uploads/${skylink}`), { + await toast.promise(ky.delete(`/services/user/uploads/${skylink}`), { pending: "Unpinning Skylink", success: "Skylink unpinned", error: (error) => error.message, @@ -51,22 +49,15 @@ const actions = [ }, ]; -export const getServerSideProps = authServerSideProps(async (context, api) => { - const initialData = await api.get("user/uploads?pageSize=10&offset=0").json(); - - return { props: { initialData } }; -}); - -export default function Uploads({ initialData }) { +export default function Uploads() { const [offset, setOffset] = useState(0); - const { data, mutate } = useAccountsApi(`${apiPrefix}/user/uploads?pageSize=10&offset=${offset}`, { - initialData: offset === 0 ? initialData : undefined, + const { data, mutate } = useAccountsApi(`user/uploads?pageSize=10&offset=${offset}`, { revalidateOnMount: true, }); // preload next page if it exists (based on the response from the current page query) const nextPageOffset = data && data.offset + data.pageSize < data.count ? data.offset + data.pageSize : offset; - useAccountsApi(`${apiPrefix}/user/uploads?pageSize=10&offset=${nextPageOffset}`); + useAccountsApi(`user/uploads?pageSize=10&offset=${nextPageOffset}`); return ( diff --git a/packages/dashboard/src/pages/user/confirm.js b/packages/dashboard/src/pages/user/confirm.js new file mode 100644 index 00000000..104fefb5 --- /dev/null +++ b/packages/dashboard/src/pages/user/confirm.js @@ -0,0 +1,57 @@ +import Link from "next/link"; +import { useRouter } from "next/router"; +import accountsApi from "../../services/accountsApi"; +import useAnonRoute from "../../services/useAnonRoute"; +import React from "react"; + +export default function Recover() { + useAnonRoute(); // ensure user is not logged in + + const router = useRouter(); + const [error, setError] = React.useState(""); + const [confirmed, setConfirmed] = React.useState(false); + + React.useEffect(() => { + async function confirm() { + try { + await accountsApi.get("user/confirm", { searchParams: { token: router.query.token } }); + + setConfirmed(true); + + setTimeout(() => { + router.push("/"); + }, 5000); + } catch (error) { + if (error.response) { + const data = await error.response.json(); + + setError(data.message ?? error.toString()); + } else { + setError(error.toString()); + } + } + } + + if (router.query.token) confirm(); + }, [router, setConfirmed]); + + return ( +
    +
    + {!confirmed && !error && ( +

    Confirming your email, please wait.

    + )} + {confirmed && ( +

    + Email confirmed! You will be redirected to the{" "} + + dashboard + {" "} + in 3 seconds. +

    + )} + {error &&

    {error}

    } +
    +
    + ); +} diff --git a/packages/dashboard/src/pages/error.js b/packages/dashboard/src/pages/user/recover.js similarity index 61% rename from packages/dashboard/src/pages/error.js rename to packages/dashboard/src/pages/user/recover.js index 19a1e7b1..8f6337d8 100644 --- a/packages/dashboard/src/pages/error.js +++ b/packages/dashboard/src/pages/user/recover.js @@ -1,31 +1,52 @@ -import Link from "next/link"; -import { Configuration, PublicApi } from "@ory/kratos-client"; -import config from "../config"; +import * as Yup from "yup"; +import { useRouter } from "next/router"; +import accountsApi from "../../services/accountsApi"; +import useAnonRoute from "../../services/useAnonRoute"; +import SelfServiceForm from "../../components/Form/SelfServiceForm"; -const kratos = new PublicApi(new Configuration({ basePath: config.kratos.public })); +const fieldsConfig = [ + { + name: "password", + type: "password", + label: "Password", + autoComplete: "new-password", + position: 0, + }, + { + name: "confirmPassword", + type: "password", + label: "Password repeated", + autoComplete: "new-password", + position: 1, + }, + { + name: "token", + type: "hidden", + }, +]; -export async function getServerSideProps(context) { - const error = context.query.error; +const validationSchema = Yup.object().shape({ + password: Yup.string().required("Password is required").min(6, "Password has to be at least 6 characters long"), + confirmPassword: Yup.string().oneOf([Yup.ref("password"), null], "Passwords must match"), +}); - // No error was send, redirecting back to home. - if (!error || typeof error !== "string") { - console.log("No error ID found in URL, redirecting to homepage."); +export default function Recover() { + useAnonRoute(); // ensure user is not logged in - return { redirect: { permanent: false, destination: "/" } }; - } + const router = useRouter(); - try { - const { status, data } = await kratos.getSelfServiceError(error); + const onSubmit = async (values) => { + await accountsApi.post("user/recover", { + json: { + token: router.query.token, + password: values.password, + confirmPassword: values.confirmPassword, + }, + }); - if ("errors" in data) return { props: { errors: data.errors } }; + router.push("/"); + }; - throw new Error(`Expected error ${error} to contain "errors" but got ${JSON.stringify(data)}`); - } catch (error) { - return { redirect: { permanent: false, destination: "/" } }; - } -} - -export default function Error({ errors }) { return (
    @@ -42,27 +63,15 @@ export default function Error({ errors }) { fillRule="evenodd" /> -

    An error occurred

    -
    -
    -
    - {errors.map((error, index) => ( -
    1 ? "mt-3 sm:mt-5" : ""} text-center`}> - -
    -

    {error.reason}

    -
    -
    - ))} -
    -
    -
    - - back to homepage - +

    Set new password

    + +
    ); } diff --git a/packages/dashboard/src/pages/user/settings.js b/packages/dashboard/src/pages/user/settings.js new file mode 100644 index 00000000..f2e1fd77 --- /dev/null +++ b/packages/dashboard/src/pages/user/settings.js @@ -0,0 +1,85 @@ +import * as Yup from "yup"; +import Layout from "../../components/Layout"; +import SelfServiceForm from "../../components/Form/SelfServiceForm"; +import accountsApi from "../../services/accountsApi"; + +const profileConfig = [ + { + name: "email", + type: "text", + label: "New email address", + autoComplete: "email", + position: 0, + }, + { + name: "confirmEmail", + type: "text", + label: "New email address repeated", + autoComplete: "email", + position: 1, + }, +]; + +const passwordConfig = [ + { + name: "password", + type: "password", + label: "New password", + position: 1, + }, + { + name: "confirmPassword", + type: "password", + label: "New password repeated", + position: 2, + }, +]; + +const emailValidationSchema = Yup.object().shape({ + email: Yup.string().required("Email is required").email("This email is invalid"), + confirmEmail: Yup.string().oneOf([Yup.ref("email"), null], "Emails must match"), +}); + +const passwordValidationSchema = Yup.object().shape({ + password: Yup.string().required("Password is required").min(6, "Password has to be at least 6 characters long"), + confirmPassword: Yup.string().oneOf([Yup.ref("password"), null], "Passwords must match"), +}); + +export default function Settings() { + const onEmailSubmit = async (values) => { + await accountsApi.put("user", { + json: { + email: values.email, + }, + }); + }; + + const onPasswordSubmit = async (values) => { + await accountsApi.put("user", { + json: { + password: values.password, + }, + }); + }; + + return ( + +
    + + +
    +
    + ); +} diff --git a/packages/dashboard/src/pages/verify.js b/packages/dashboard/src/pages/verify.js deleted file mode 100644 index adcde201..00000000 --- a/packages/dashboard/src/pages/verify.js +++ /dev/null @@ -1,103 +0,0 @@ -import Link from "next/link"; -import { Configuration, PublicApi } from "@ory/kratos-client"; -import config from "../config"; -import SelfServiceForm from "../components/Form/SelfServiceForm"; -import { useEffect } from "react"; - -const kratos = new PublicApi(new Configuration({ basePath: config.kratos.public })); - -export async function getServerSideProps(context) { - const flow = context.query.flow; - - // if (process.env.NODE_ENV === "development") { - // return { props: { flow: require("../../stubs/recovery.json") } }; - // } - - if (!flow || typeof flow !== "string") { - return { - redirect: { - permanent: false, - destination: `${config.kratos.browser}/self-service/verification/browser`, - }, - }; - } - - try { - const { status, data } = await kratos.getSelfServiceVerificationFlow(flow); - - if (status === 200) return { props: { flow: data } }; - - throw new Error(`Failed to retrieve flow ${flow} with code ${status}`); - } catch (error) { - return { - redirect: { - permanent: false, - destination: `${config.kratos.browser}/self-service/verification/browser`, - }, - }; - } -} - -const fieldsConfig = { - email: { - label: "Your email", - autoComplete: "email", - position: 0, - }, - csrf_token: { - position: 99, - }, -}; - -export default function Verify({ flow }) { - const state = flow.state; - - useEffect(() => { - if (state === "passed_challenge") { - setTimeout(() => (window.location = "/"), 5000); - } - }, [state]); - - return ( -
    -
    - - - -

    - {flow.state === "passed_challenge" ? "Verification successful!" : "Account verification"} -

    - - {flow.state === "passed_challenge" && ( - <> -

    You will be redirected automatically

    -

    - - go to dashboard - -

    - - )} -
    - - {flow.state !== "passed_challenge" && ( - - )} -
    - ); -} diff --git a/packages/dashboard/src/services/accountsApi.js b/packages/dashboard/src/services/accountsApi.js new file mode 100644 index 00000000..fafbfe86 --- /dev/null +++ b/packages/dashboard/src/services/accountsApi.js @@ -0,0 +1,5 @@ +import ky from "ky"; + +const prefix = process.env.NEXT_PUBLIC_SKYNET_DASHBOARD_URL ?? ""; + +export default ky.create({ prefixUrl: `${prefix}/api` }); diff --git a/packages/dashboard/src/services/authServerSideProps.js b/packages/dashboard/src/services/authServerSideProps.js deleted file mode 100644 index 83c848d3..00000000 --- a/packages/dashboard/src/services/authServerSideProps.js +++ /dev/null @@ -1,37 +0,0 @@ -import ky from "ky/umd"; - -const isProduction = process.env.NODE_ENV === "production"; - -export default function authServerSideProps(getServerSideProps) { - return function authenticate(context) { - const authCookies = ["ory_kratos_session", "skynet-jwt"]; - - if (isProduction && !authCookies.every((cookie) => context.req.cookies[cookie])) { - // it is higly unusual that some of the cookies would be set but other would not - if (authCookies.some((cookie) => context.req.cookies[cookie])) { - console.log( - "Unexpected auth cookies state!", - authCookies.map((cookie) => `[${cookie}] is ${context.req.cookies[cookie] ? "set" : "not set"}`) - ); - } - - return { - redirect: { - permanent: false, - destination: `/api/accounts/login?return_to=${encodeURIComponent(context.resolvedUrl)}`, - }, - }; - } - - if (getServerSideProps) { - const api = ky.create({ - headers: { cookie: context.req.headers.cookie }, - prefixUrl: isProduction ? "http://oathkeeper:4455" : "http://localhost:3000/api/stubs", - }); - - return getServerSideProps(context, api); - } - - return { props: {} }; - }; -} diff --git a/packages/dashboard/src/services/useAccountsApi.js b/packages/dashboard/src/services/useAccountsApi.js index 169b12d9..83c7bd35 100644 --- a/packages/dashboard/src/services/useAccountsApi.js +++ b/packages/dashboard/src/services/useAccountsApi.js @@ -1,15 +1,21 @@ import useSWR from "swr"; +import { useRouter } from "next/router"; import { StatusCodes } from "http-status-codes"; -const fetcher = (url) => - fetch(url).then((res) => { +const prefix = process.env.NEXT_PUBLIC_SKYNET_DASHBOARD_URL ?? ""; + +const fetcher = (url, router) => { + return fetch(url).then((res) => { if (res.status === StatusCodes.UNAUTHORIZED) { - window.location.href = `/auth/login?return_to=${encodeURIComponent(window.location.href)}`; + router.push(`/auth/login?return_to=${encodeURIComponent(window.location.href)}`); } return res.json(); }); +}; export default function useAccountsApi(key, config) { - return useSWR(key, fetcher, config); + const router = useRouter(); + + return useSWR(`${prefix}/api/${key}`, (url) => fetcher(url, router), config); } diff --git a/packages/dashboard/src/services/useAnonRoute.js b/packages/dashboard/src/services/useAnonRoute.js new file mode 100644 index 00000000..179f7529 --- /dev/null +++ b/packages/dashboard/src/services/useAnonRoute.js @@ -0,0 +1,16 @@ +import useSWR from "swr"; +import { useRouter } from "next/router"; +import { StatusCodes } from "http-status-codes"; + +const prefix = process.env.NEXT_PUBLIC_SKYNET_DASHBOARD_URL ?? ""; +const fetcher = (url, router) => { + return fetch(url).then((res) => { + if (res.status === StatusCodes.OK) router.push("/"); + }); +}; + +export default function useAnonRoute() { + const router = useRouter(); + + return useSWR(`${prefix}/api/user`, (url) => fetcher(url, router)); +} diff --git a/packages/dashboard/stubs/login.json b/packages/dashboard/stubs/login.json deleted file mode 100644 index bb136cd8..00000000 --- a/packages/dashboard/stubs/login.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "id": "bda73c77-1e21-4bfd-b85a-322fce2e4576", - "expires_at": "2020-01-28T13:48:04.690715Z", - "issued_at": "2020-01-28T13:38:04.690732Z", - "request_url": "http://127.0.0.1:4455/auth/browser/login", - "methods": { - "oidc": { - "method": "oidc", - "config": { - "action": "http://127.0.0.1:4455/.ory/kratos/public/auth/browser/methods/oidc/auth/bda73c77-1e21-4bfd-b85a-322fce2e4576", - "method": "POST", - "fields": [ - { - "name": "csrf_token", - "type": "hidden", - "required": true, - "value": "QJreyXtUD4oUSJfGNjA/+6ydsQyq0o/rfTL6QK86VadVFg6mwgX5x1QHVQ6uRqKxmwAcavQup3ILCSwl7ke97g==" - } - ] - } - }, - "password": { - "method": "password", - "config": { - "action": "http://127.0.0.1:4455/.ory/kratos/public/auth/browser/methods/password/login?request=bda73c77-1e21-4bfd-b85a-322fce2e4576", - "method": "POST", - "fields": [ - { - "name": "csrf_token", - "type": "hidden", - "required": true, - "value": "M1gAKA8fIhw4JOpQ/5m9mKARBAvKhzWkyhbxjtZNLG8m1NBHtk7UUXhrKJhn7yDSl4ypbZR7HT28LSfrlzDEJg==" - }, - { "name": "identifier", "type": "text", "required": true, "value": "asfdasdffads" }, - { "name": "password", "type": "password", "required": true } - ], - "errors": [ - { - "message": "The provided credentials are invalid. Check for spelling mistakes in your password or username, email address, or phone number." - } - ] - } - } - } -} diff --git a/packages/dashboard/stubs/recovery.json b/packages/dashboard/stubs/recovery.json deleted file mode 100644 index 28fde87a..00000000 --- a/packages/dashboard/stubs/recovery.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "id": "01e21a99-8e69-41f9-b3ba-4967f714c8eb", - "type": "browser", - "expires_at": "2021-03-18T15:46:30.634635Z", - "issued_at": "2021-03-18T14:46:30.634635Z", - "request_url": "http://oathkeeper:4455/self-service/recovery/browser", - "messages": null, - "methods": { - "link": { - "method": "link", - "config": { - "action": "http://127.0.0.1:4455/.ory/kratos/public/self-service/recovery/methods/link?flow=01e21a99-8e69-41f9-b3ba-4967f714c8eb", - "method": "POST", - "fields": [ - { - "name": "csrf_token", - "type": "hidden", - "required": true, - "value": "XvPfLJzxmcTWnr2rmLzFcED9Ef1PIkqSBQgx5t0yu0WuIp2S6ll+B9cQ0ClIcLQ==" - }, - { - "name": "email", - "type": "email", - "required": true - } - ] - } - } - }, - "state": "choose_method" -} diff --git a/packages/dashboard/stubs/registration.json b/packages/dashboard/stubs/registration.json deleted file mode 100644 index 4fe796ae..00000000 --- a/packages/dashboard/stubs/registration.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "id": "dbff7b96-8116-42c5-8624-f9fb28f1db15", - "expires_at": "2020-01-28T13:49:01.2274112Z", - "issued_at": "2020-01-28T13:39:01.2274261Z", - "request_url": "http://127.0.0.1:4455/auth/browser/registration", - "methods": { - "oidc": { - "method": "oidc", - "config": { - "action": "http://127.0.0.1:4455/.ory/kratos/public/auth/browser/methods/oidc/auth/dbff7b96-8116-42c5-8624-f9fb28f1db15", - "method": "POST", - "fields": [ - { - "name": "csrf_token", - "type": "hidden", - "required": true, - "value": "xwb6A6iHdsguYwkAM6m3jj196E7TcmiWpAavIRxuAgXSiipsEdaAhW4sy8ir3yrECuBFKI2OQA/SPXlEXRPqTA==" - } - ] - } - }, - "password": { - "method": "password", - "config": { - "errors": [ - { - "message": "The provided credentials are invalid. Check for spelling mistakes in your password or username, email address, or phone number." - } - ], - "action": "http://127.0.0.1:4455/.ory/kratos/public/auth/browser/methods/password/registration?request=dbff7b96-8116-42c5-8624-f9fb28f1db15", - "method": "POST", - "fields": [ - { - "name": "csrf_token", - "type": "hidden", - "required": true, - "value": "xLg4B9WnuC0Ue+j9ay5EQvleaJpOl0H9xJJ7W3+Bwv7RNOhobPZOYFQ0KjXzWNkIzsPF/BBraWSyqa0+Pvwqtw==" - }, - { - "name": "password", - "type": "password", - "required": true, - "errors": [{ "message": "password: Is required" }] - }, - { - "name": "traits.email", - "type": "text", - "value": "", - "errors": [ - { "message": "traits.email: String length must be greater than or equal to 3" }, - { "message": "traits.email: Does not match format 'email'" } - ] - } - ] - } - } - } -} diff --git a/packages/dashboard/stubs/settings.json b/packages/dashboard/stubs/settings.json deleted file mode 100644 index c7502b31..00000000 --- a/packages/dashboard/stubs/settings.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "id": "e01f6bf9-845c-4c4b-a3ce-60691dd7a97c", - "type": "browser", - "expires_at": "2021-02-18T13:31:43.947193Z", - "issued_at": "2021-02-18T12:31:43.947193Z", - "request_url": "http://oathkeeper:4455/self-service/settings/browser", - "messages": null, - "methods": { - "password": { - "method": "password", - "config": { - "action": "https://account.siasky.xyz/.ory/kratos/public/self-service/settings/methods/password?flow=e01f6bf9-845c-4c4b-a3ce-60691dd7a97c", - "method": "POST", - "fields": [ - { "name": "password", "type": "password", "required": true }, - { - "name": "csrf_token", - "type": "hidden", - "required": true, - "value": "i33iydUBN6jqwrkHlLPZ3ap7Ah4uC0UrTadn7zKT0jyouDpr+DF0/1Hbkshye9t7IKwyzOcLt7i6oR/OoEVg+g==" - } - ] - } - }, - "profile": { - "method": "profile", - "config": { - "action": "https://account.siasky.xyz/.ory/kratos/public/self-service/settings/methods/profile?flow=e01f6bf9-845c-4c4b-a3ce-60691dd7a97c", - "method": "POST", - "fields": [ - { - "name": "csrf_token", - "type": "hidden", - "required": true, - "value": "i33iydUBN6jqwrkHlLPZ3ap7Ah4uC0UrTadn7zKT0jyouDpr+DF0/1Hbkshye9t7IKwyzOcLt7i6oR/OoEVg+g==" - }, - { "name": "traits.email", "type": "email", "value": "karol@nebulous.tech" } - ] - } - } - }, - "identity": { - "id": "ab776d6d-f324-4fa7-a728-7587d5215481", - "schema_id": "default", - "schema_url": "", - "traits": { "email": "karol@nebulous.tech" } - }, - "state": "show_form" -} diff --git a/packages/dashboard/styles/Home.module.css b/packages/dashboard/styles/Home.module.css deleted file mode 100644 index 80745811..00000000 --- a/packages/dashboard/styles/Home.module.css +++ /dev/null @@ -1,122 +0,0 @@ -.container { - min-height: 100vh; - padding: 0 0.5rem; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} - -.main { - padding: 5rem 0; - flex: 1; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} - -.footer { - width: 100%; - height: 100px; - border-top: 1px solid #eaeaea; - display: flex; - justify-content: center; - align-items: center; -} - -.footer img { - margin-left: 0.5rem; -} - -.footer a { - display: flex; - justify-content: center; - align-items: center; -} - -.title a { - color: #0070f3; - text-decoration: none; -} - -.title a:hover, -.title a:focus, -.title a:active { - text-decoration: underline; -} - -.title { - margin: 0; - line-height: 1.15; - font-size: 4rem; -} - -.title, -.description { - text-align: center; -} - -.description { - line-height: 1.5; - font-size: 1.5rem; -} - -.code { - background: #fafafa; - border-radius: 5px; - padding: 0.75rem; - font-size: 1.1rem; - font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, - monospace; -} - -.grid { - display: flex; - align-items: center; - justify-content: center; - flex-wrap: wrap; - max-width: 800px; - margin-top: 3rem; -} - -.card { - margin: 1rem; - flex-basis: 45%; - padding: 1.5rem; - text-align: left; - color: inherit; - text-decoration: none; - border: 1px solid #eaeaea; - border-radius: 10px; - transition: color 0.15s ease, border-color 0.15s ease; -} - -.card:hover, -.card:focus, -.card:active { - color: #0070f3; - border-color: #0070f3; -} - -.card h3 { - margin: 0 0 1rem 0; - font-size: 1.5rem; -} - -.card p { - margin: 0; - font-size: 1.25rem; - line-height: 1.5; -} - -.logo { - height: 1em; -} - -@media (max-width: 600px) { - .grid { - width: 100%; - flex-direction: column; - } -} diff --git a/packages/dashboard/styles/globals.css b/packages/dashboard/styles/globals.css index e2e6d0f0..b5c61c95 100644 --- a/packages/dashboard/styles/globals.css +++ b/packages/dashboard/styles/globals.css @@ -1,16 +1,3 @@ -html, -body { - padding: 0; - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, - Helvetica Neue, sans-serif; -} - -a { - color: inherit; - text-decoration: none; -} - -* { - box-sizing: border-box; -} +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/packages/dashboard/tailwind.config.js b/packages/dashboard/tailwind.config.js index 09477280..880247ae 100644 --- a/packages/dashboard/tailwind.config.js +++ b/packages/dashboard/tailwind.config.js @@ -1,18 +1,65 @@ +const defaultTheme = require("tailwindcss/defaultTheme"); +const plugin = require("tailwindcss/plugin"); + +const colors = { + primary: { light: "#33D17E", DEFAULT: "#00c65e" }, + warning: "#ffd567", + error: "#ED5454", + palette: { + 100: "#f5f7f7", + 200: "#d4dddb", + 300: "#9e9e9e", + 400: "#555555", + 500: "#242424", + 600: "#0d0d0d", + }, +}; + module.exports = { - purge: ["./src/**/*.js"], + purge: ["./src/**/*.{js,jsx,ts,tsx}"], darkMode: false, // or 'media' or 'class' theme: { + screens: { + sm: "640px", + tablet: "640px", + md: "768px", + lg: "1024px", + desktop: "1024px", + xl: "1280px", + hires: "1408px", + "2xl": "1536px", + }, + backgroundColor: (theme) => ({ ...theme("colors"), ...colors }), + borderColor: (theme) => ({ ...theme("colors"), ...colors }), + textColor: (theme) => ({ ...theme("colors"), ...colors }), + placeholderColor: (theme) => ({ ...theme("colors"), ...colors }), extend: { fontFamily: { - sans: ["Metropolis", "Helvetica", "Arial", "Sans-Serif"], + sans: ["Sora", ...defaultTheme.fontFamily.sans], + content: ["Source\\ Sans\\ Pro", ...defaultTheme.fontFamily.sans], }, - }, - }, - variants: { - extend: { backgroundColor: ["disabled"], textColor: ["disabled"], }, }, - plugins: [require("@tailwindcss/forms")], + variants: { + extend: { + animation: ["hover"], + rotate: ["hover"], + backgroundColor: ["disabled"], + textColor: ["disabled"], + margin: ["first"], + }, + }, + plugins: [ + require("@tailwindcss/typography"), + require("@tailwindcss/forms"), + plugin(function ({ addBase, theme }) { + addBase({ + body: { + color: theme("textColor.palette.600"), + }, + }); + }), + ], }; diff --git a/packages/dashboard/yarn.lock b/packages/dashboard/yarn.lock index 89fd96c2..e4dd2bd8 100644 --- a/packages/dashboard/yarn.lock +++ b/packages/dashboard/yarn.lock @@ -42,6 +42,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/runtime-corejs3@^7.10.2": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.16.3.tgz#1e25de4fa994c57c18e5fdda6cc810dac70f5590" + integrity sha512-IAdDC7T0+wEB4y2gbIL0uOXEYpiZEeuFUTVbdGq+UwCcF35T/tS8KrmMomEwEc5wBbyfH3PJVpTSUqrhPDXFcQ== + dependencies: + core-js-pure "^3.19.0" + regenerator-runtime "^0.13.4" + "@babel/runtime@7.15.4", "@babel/runtime@^7.11.2", "@babel/runtime@^7.15.4": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" @@ -49,6 +57,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.10.2": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.3.tgz#b86f0db02a04187a3c17caa77de69840165d42d5" + integrity sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/types@7.15.0": version "7.15.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.0.tgz#61af11f2286c4e9c69ca8deb5f4375a73c72dcbd" @@ -57,10 +72,30 @@ "@babel/helper-validator-identifier" "^7.14.9" to-fast-properties "^2.0.0" -"@fontsource/metropolis@4.5.0": +"@eslint/eslintrc@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" + integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^13.9.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@fontsource/sora@4.5.0": version "4.5.0" - resolved "https://registry.yarnpkg.com/@fontsource/metropolis/-/metropolis-4.5.0.tgz#69f4fc76a6c8fb6b6d1feb0f927e353505dc371f" - integrity sha512-y0xYEftAq22M+zkS8AWIjrSHP8ZdtSy3D0DUJKIzbVleqvQ8O1YUZiYGjYvJewy5f9aycnAhT4koMv7r9T8Jkw== + resolved "https://registry.yarnpkg.com/@fontsource/sora/-/sora-4.5.0.tgz#bfd505c063fbfd77b42b1a8a05025aac52d4ea5f" + integrity sha512-bXr7HZPHh/dtfcp9UfEIrYhiMzmcsGvooz9kkmxi5iYwuqs4O1YWfkNbbPSMoRH/cucrMtlGUuC9eRbFx4Yn5Q== + +"@fontsource/source-sans-pro@4.5.0": + version "4.5.0" + resolved "https://registry.yarnpkg.com/@fontsource/source-sans-pro/-/source-sans-pro-4.5.0.tgz#19726a3c609f9450bfc53811b8497d4684ff2111" + integrity sha512-+ze+nO9dVN5pAVg9CdQmVgR6f8kDpq/elHMGcyx3qsW4+TN4mI7EuMdNzKP3E1xeZwTHSmHY5bezpfFHX7bQsg== "@hapi/accept@5.0.2": version "5.0.2" @@ -82,6 +117,20 @@ resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.0.tgz#f3933a44e365864f4dad5db94158106d511e8131" integrity sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug== +"@humanwhocodes/config-array@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" + integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== + dependencies: + "@humanwhocodes/object-schema" "^1.2.0" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.0": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + "@napi-rs/triples@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@napi-rs/triples/-/triples-1.0.3.tgz#76d6d0c3f4d16013c61e45dfca5ff1e6c31ae53c" @@ -92,6 +141,13 @@ resolved "https://registry.yarnpkg.com/@next/env/-/env-12.0.3.tgz#e676b4d1454d8b6be433a348e99f2b8276ab6cd7" integrity sha512-QcdlpcwIH9dYcVlNAU+gXaqHA/omskbRlb+R3vN7LlB2EgLt+9WQwbokcHOsNyt4pI7kDM67W4tr9l7dWnlGdQ== +"@next/eslint-plugin-next@12.0.3": + version "12.0.3" + resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.0.3.tgz#3945c251d551bacc3712d4a18d6ca56d2938f175" + integrity sha512-P7i+bMypneQcoRN+CX79xssvvIJCaw7Fndzbe7/lB0+LyRbVvGVyMUsFmLLbSxtZq4hvFMJ1p8wML/gsulMZWQ== + dependencies: + glob "7.1.7" + "@next/polyfill-module@12.0.3": version "12.0.3" resolved "https://registry.yarnpkg.com/@next/polyfill-module/-/polyfill-module-12.0.3.tgz#4217e5284762124bf9fe2505622c4de89998f7a2" @@ -195,12 +251,10 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@ory/kratos-client@0.5.4-alpha.1": - version "0.5.4-alpha.1" - resolved "https://registry.yarnpkg.com/@ory/kratos-client/-/kratos-client-0.5.4-alpha.1.tgz#6a87a90fd858fc4cb792253b109ea53884098107" - integrity sha512-koqwcEtEtGoHdX/WU3O4u6UmbMzbmbA06t5qIZv9S4YauxHZIVZM3VMws1ZK5ObgAMI6O5dCs4WYJrJq+QN48g== - dependencies: - axios "^0.19.2" +"@rushstack/eslint-patch@^1.0.6": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323" + integrity sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A== "@stripe/react-stripe-js@1.6.0": version "1.6.0" @@ -221,6 +275,21 @@ dependencies: mini-svg-data-uri "^1.2.3" +"@tailwindcss/typography@0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.4.1.tgz#51ddbceea6a0ee9902c649dbe58871c81a831212" + integrity sha512-ovPPLUhs7zAIJfr0y1dbGlyCuPhpuv/jpBoFgqAc658DWGGrOBWBMpAWLw2KlzbNeVk4YBJMzue1ekvIbdw6XA== + dependencies: + lodash.castarray "^4.4.0" + lodash.isplainobject "^4.0.6" + lodash.merge "^4.6.2" + lodash.uniq "^4.5.0" + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + "@types/lodash@^4.14.175": version "4.14.175" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.175.tgz#b78dfa959192b01fae0ad90e166478769b215f45" @@ -236,6 +305,55 @@ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== +"@typescript-eslint/parser@^4.20.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.33.0.tgz#dfe797570d9694e560528d18eecad86c8c744899" + integrity sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA== + dependencies: + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" + debug "^4.3.1" + +"@typescript-eslint/scope-manager@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3" + integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + +"@typescript-eslint/types@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" + integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== + +"@typescript-eslint/typescript-estree@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609" + integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + debug "^4.3.1" + globby "^11.0.3" + is-glob "^4.0.1" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/visitor-keys@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd" + integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg== + dependencies: + "@typescript-eslint/types" "4.33.0" + eslint-visitor-keys "^2.0.0" + +acorn-jsx@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + acorn-node@^1.6.1: version "1.8.2" resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8" @@ -255,16 +373,41 @@ acorn@8.5.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2" integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q== -acorn@^7.0.0: +acorn@^7.0.0, acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.7.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.7.1.tgz#52be6f1736b076074798124293618f132ad07a7e" + integrity sha512-gPpOObTO1QjbnN1sVMjJcp1TF9nggMfO4MBR5uQl6ZVTOaEPq5i4oq/6R9q2alMMPB3eg53wFv1RuJBLuxf3Hw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + anser@1.4.9: version "1.4.9" resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.9.tgz#1f85423a5dcf8da4631a341665ff675b96845760" integrity sha512-AI+BjTeGt2+WFk4eWcqbQ7snZpDBt8SaLlj0RT2h5xfdWaiy51OjYvqwMrNzJLGy8iOAL6nKDITWO+rd4MkYEA== +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -277,7 +420,7 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -297,6 +440,55 @@ arg@^5.0.1: resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb" integrity sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA== +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +aria-query@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" + integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA== + dependencies: + "@babel/runtime" "^7.10.2" + "@babel/runtime-corejs3" "^7.10.2" + +array-includes@^3.1.1, array-includes@^3.1.3, array-includes@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9" + integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + get-intrinsic "^1.1.1" + is-string "^1.0.7" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array.prototype.flat@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13" + integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + +array.prototype.flatmap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz#908dc82d8a406930fdf38598d51e7411d18d4446" + integrity sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.19.0" + asn1.js@^5.2.0: version "5.4.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" @@ -317,6 +509,16 @@ assert@2.0.0: object-is "^1.0.1" util "^0.12.0" +ast-types-flow@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" + integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + async@^1.5.0: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -344,13 +546,23 @@ available-typed-arrays@^1.0.5: resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== -axios@0.21.4, axios@^0.19.2, axios@^0.21.0: +axe-core@^4.0.2: + version "4.3.5" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.3.5.tgz#78d6911ba317a8262bfee292aeafcc1e04b49cc5" + integrity sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA== + +axios@^0.21.0: version "0.21.4" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== dependencies: follow-redirects "^1.14.0" +axobject-query@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" + integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -572,7 +784,7 @@ chalk@4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.1.2: +chalk@^4.0.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -727,6 +939,11 @@ copy-text-to-clipboard@^3.0.1: resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c" integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q== +core-js-pure@^3.19.0: + version "3.19.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.19.1.tgz#edffc1fc7634000a55ba05e95b3f0fe9587a5aa4" + integrity sha512-Q0Knr8Es84vtv62ei6/6jXH/7izKmOrtrxH9WJTHLCMAVeU+8TF8z8Nr08CsH4Ot0oJKzBzJJL9SJBYIv7WlfQ== + cosmiconfig@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" @@ -769,6 +986,15 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + crypto-browserify@3.12.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -820,6 +1046,11 @@ cssnano-simple@3.0.0: dependencies: cssnano-preset-simple "^3.0.0" +damerau-levenshtein@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d" + integrity sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw== + data-uri-to-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636" @@ -830,20 +1061,32 @@ dayjs@1.10.7: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.7.tgz#2cf5f91add28116748440866a0a1d26f3a6ce468" integrity sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig== -debug@2: +debug@2, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@^4.1.1: +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.0.1, debug@^4.1.1, debug@^4.3.1: version "4.3.2" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== dependencies: ms "2.1.2" +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + deepmerge@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170" @@ -907,11 +1150,32 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + dlv@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + domain-browser@4.19.0: version "4.19.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-4.19.0.tgz#1093e17c0a17dbd521182fe90d49ac1370054af1" @@ -947,6 +1211,16 @@ elliptic@^6.5.3: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.0.0: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" @@ -959,6 +1233,13 @@ encoding@0.1.13: dependencies: iconv-lite "^0.6.2" +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -990,6 +1271,32 @@ es-abstract@^1.18.5: string.prototype.trimstart "^1.0.4" unbox-primitive "^1.0.1" +es-abstract@^1.19.0, es-abstract@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" + integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.1.1" + get-symbol-description "^1.0.0" + has "^1.0.3" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + is-callable "^1.2.4" + is-negative-zero "^2.0.1" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.1" + is-string "^1.0.7" + is-weakref "^1.0.1" + object-inspect "^1.11.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.1" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -1014,6 +1321,229 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-config-next@12.0.3: + version "12.0.3" + resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.0.3.tgz#a85ad423997f098b41b61c279472e0642e200a9e" + integrity sha512-q+mX6jhk3HrCo39G18MLhiC6f8zJnTA00f30RSuVUWsv45SQUm6r62oXVqrbAgMEybe0yx/GDRvfA6LvSolw6Q== + dependencies: + "@next/eslint-plugin-next" "12.0.3" + "@rushstack/eslint-patch" "^1.0.6" + "@typescript-eslint/parser" "^4.20.0" + eslint-import-resolver-node "^0.3.4" + eslint-import-resolver-typescript "^2.4.0" + eslint-plugin-import "^2.22.1" + eslint-plugin-jsx-a11y "^6.4.1" + eslint-plugin-react "^7.23.1" + eslint-plugin-react-hooks "^4.2.0" + +eslint-import-resolver-node@^0.3.4, eslint-import-resolver-node@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" + integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== + dependencies: + debug "^3.2.7" + resolve "^1.20.0" + +eslint-import-resolver-typescript@^2.4.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.5.0.tgz#07661966b272d14ba97f597b51e1a588f9722f0a" + integrity sha512-qZ6e5CFr+I7K4VVhQu3M/9xGv9/YmwsEXrsm3nimw8vWaVHRDrQRp26BgCypTxBp3vUp4o5aVEJRiy0F2DFddQ== + dependencies: + debug "^4.3.1" + glob "^7.1.7" + is-glob "^4.0.1" + resolve "^1.20.0" + tsconfig-paths "^3.9.0" + +eslint-module-utils@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz#b435001c9f8dd4ab7f6d0efcae4b9696d4c24b7c" + integrity sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ== + dependencies: + debug "^3.2.7" + find-up "^2.1.0" + pkg-dir "^2.0.0" + +eslint-plugin-import@^2.22.1: + version "2.25.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz#a554b5f66e08fb4f6dc99221866e57cfff824766" + integrity sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg== + dependencies: + array-includes "^3.1.4" + array.prototype.flat "^1.2.5" + debug "^2.6.9" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.6" + eslint-module-utils "^2.7.1" + has "^1.0.3" + is-core-module "^2.8.0" + is-glob "^4.0.3" + minimatch "^3.0.4" + object.values "^1.1.5" + resolve "^1.20.0" + tsconfig-paths "^3.11.0" + +eslint-plugin-jsx-a11y@^6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz#a2d84caa49756942f42f1ffab9002436391718fd" + integrity sha512-0rGPJBbwHoGNPU73/QCLP/vveMlM1b1Z9PponxO87jfr6tuH5ligXbDT6nHSSzBC8ovX2Z+BQu7Bk5D/Xgq9zg== + dependencies: + "@babel/runtime" "^7.11.2" + aria-query "^4.2.2" + array-includes "^3.1.1" + ast-types-flow "^0.0.7" + axe-core "^4.0.2" + axobject-query "^2.2.0" + damerau-levenshtein "^1.0.6" + emoji-regex "^9.0.0" + has "^1.0.3" + jsx-ast-utils "^3.1.0" + language-tags "^1.0.5" + +eslint-plugin-react-hooks@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172" + integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA== + +eslint-plugin-react@^7.23.1: + version "7.27.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.27.0.tgz#f952c76517a3915b81c7788b220b2b4c96703124" + integrity sha512-0Ut+CkzpppgFtoIhdzi2LpdpxxBvgFf99eFqWxJnUrO7mMe0eOiNpou6rvNYeVVV6lWZvTah0BFne7k5xHjARg== + dependencies: + array-includes "^3.1.4" + array.prototype.flatmap "^1.2.5" + doctrine "^2.1.0" + estraverse "^5.3.0" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.0.4" + object.entries "^1.1.5" + object.fromentries "^2.0.5" + object.hasown "^1.1.0" + object.values "^1.1.5" + prop-types "^15.7.2" + resolve "^2.0.0-next.3" + semver "^6.3.0" + string.prototype.matchall "^4.0.6" + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint@<8.0.0: + version "7.32.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" + integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== + dependencies: + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.4.3" + "@humanwhocodes/config-array" "^0.5.0" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + escape-string-regexp "^4.0.0" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.1.2" + globals "^13.6.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.9" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + etag@1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" @@ -1047,7 +1577,12 @@ express-unless@^1.0.0: resolved "https://registry.yarnpkg.com/express-unless/-/express-unless-1.0.0.tgz#ecd1c354c5ccf7709a8a17ece617934e037cccd8" integrity sha512-zXSSClWBPfcSYjg0hcQNompkFN/MxQQ53eyrzm9BYgik2ut2I7PxAf2foVqBRMYCwWaZx/aWodi+uk76npdSAw== -fast-glob@^3.2.7: +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.1.1, fast-glob@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== @@ -1058,6 +1593,11 @@ fast-glob@^3.2.7: merge2 "^1.3.0" micromatch "^4.0.4" +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + fast-levenshtein@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz#37b899ae47e1090e40e3fd2318e4d5f0142ca912" @@ -1065,6 +1605,11 @@ fast-levenshtein@3.0.0: dependencies: fastest-levenshtein "^1.0.7" +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + fast-safe-stringify@^2.0.7: version "2.1.1" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" @@ -1082,6 +1627,13 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -1098,6 +1650,13 @@ find-cache-dir@3.3.1: make-dir "^3.0.2" pkg-dir "^4.1.0" +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + find-up@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -1106,6 +1665,19 @@ find-up@^4.0.0: locate-path "^5.0.0" path-exists "^4.0.0" +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" + integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== + follow-redirects@^1.14.0: version "1.14.4" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379" @@ -1172,6 +1744,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" @@ -1215,7 +1792,19 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@^7.0.0, glob@^7.1.3: +glob@7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.1.3, glob@^7.1.7: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -1227,6 +1816,25 @@ glob@^7.0.0, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" +globals@^13.6.0, globals@^13.9.0: + version "13.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.0.tgz#4d733760304230a0082ed96e21e5c565f898089e" + integrity sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg== + dependencies: + type-fest "^0.20.2" + +globby@^11.0.3: + version "11.0.4" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" + integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.8" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" @@ -1364,6 +1972,16 @@ ieee754@^1.1.4, ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.4: + version "5.1.9" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.9.tgz#9ec1a5cbe8e1446ec60d4420060d43aa6e7382fb" + integrity sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ== + image-size@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.0.0.tgz#58b31fe4743b1cec0a0ac26f5c914d3c5b2f0750" @@ -1378,7 +1996,7 @@ import-cwd@^3.0.0: dependencies: import-from "^3.0.0" -import-fresh@^3.2.1: +import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -1393,6 +2011,11 @@ import-from@^3.0.0: dependencies: resolve-from "^5.0.0" +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -1479,6 +2102,13 @@ is-core-module@^2.2.0: dependencies: has "^1.0.3" +is-core-module@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548" + integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw== + dependencies: + has "^1.0.3" + is-date-object@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" @@ -1491,6 +2121,11 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + is-generator-function@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" @@ -1498,6 +2133,13 @@ is-generator-function@^1.0.7: dependencies: has-tostringtag "^1.0.0" +is-glob@^4.0.0, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.2.tgz#859fc2e731e58c902f99fcabccb75a7dd07d29d8" @@ -1538,6 +2180,11 @@ is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-shared-array-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" + integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -1563,6 +2210,18 @@ is-typed-array@^1.1.3, is-typed-array@^1.1.7: foreach "^2.0.5" has-tostringtag "^1.0.0" +is-weakref@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.1.tgz#842dba4ec17fa9ac9850df2d6efbc1737274f2a2" + integrity sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ== + dependencies: + call-bind "^1.0.0" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + jest-worker@27.0.0-next.5: version "27.0.0-next.5" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.0-next.5.tgz#5985ee29b12a4e191f4aae4bb73b97971d86ec28" @@ -1577,11 +2236,34 @@ jest-worker@27.0.0-next.5: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -1614,6 +2296,14 @@ jsonwebtoken@^8.1.0: ms "^2.1.1" semver "^5.6.0" +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz#720b97bfe7d901b927d87c3773637ae8ea48781b" + integrity sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA== + dependencies: + array-includes "^3.1.3" + object.assign "^4.1.2" + jwa@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" @@ -1631,10 +2321,30 @@ jws@^3.2.2: jwa "^1.4.1" safe-buffer "^5.0.1" -ky@0.25.1: - version "0.25.1" - resolved "https://registry.yarnpkg.com/ky/-/ky-0.25.1.tgz#0df0bd872a9cc57e31acd5dbc1443547c881bfbc" - integrity sha512-PjpCEWlIU7VpiMVrTwssahkYXX1by6NCT0fhTUX34F3DTinARlgMpriuroolugFPcMgpPWrOW4mTb984Qm1RXA== +ky@0.28.7: + version "0.28.7" + resolved "https://registry.yarnpkg.com/ky/-/ky-0.28.7.tgz#10c42be863fb96c1846d6e71e229263ffb72eb15" + integrity sha512-a23i6qSr/ep15vdtw/zyEQIDLoUaKDg9Jf04CYl/0ns/wXNYna26zJpI+MeIFaPeDvkrjLPrKtKOiiI3IE53RQ== + +language-subtag-registry@~0.3.2: + version "0.3.21" + resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" + integrity sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg== + +language-tags@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a" + integrity sha1-0yHbxNowuovzAk4ED6XBRmH5GTo= + dependencies: + language-subtag-registry "~0.3.2" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" lilconfig@^2.0.3: version "2.0.3" @@ -1655,6 +2365,14 @@ loader-utils@1.2.3: emojis-list "^2.0.0" json5 "^1.0.1" +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -1667,6 +2385,11 @@ lodash-es@^4.17.21: resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== +lodash.castarray@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115" + integrity sha1-wCUTUV4wna3dTCTGDP3c9ZdtkRU= + lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" @@ -1697,6 +2420,11 @@ lodash.isstring@^4.0.1: resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + lodash.once@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" @@ -1717,6 +2445,16 @@ lodash.topath@^4.5.2: resolved "https://registry.yarnpkg.com/lodash.topath/-/lodash.topath-4.5.2.tgz#3616351f3bba61994a0931989660bd03254fd009" integrity sha1-NhY1Hzu6YZlKCTGYlmC9AyVP0Ak= +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= + lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -1857,6 +2595,11 @@ nanoid@^3.1.23, nanoid@^3.1.30: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362" integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ== +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + next@12.0.3: version "12.0.3" resolved "https://registry.yarnpkg.com/next/-/next-12.0.3.tgz#325732ceb4193306a9a31912815fc570d1a66641" @@ -2006,6 +2749,41 @@ object.assign@^4.1.2: has-symbols "^1.0.1" object-keys "^1.1.1" +object.entries@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861" + integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.fromentries@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.5.tgz#7b37b205109c21e741e605727fe8b0ad5fa08251" + integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.hasown@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.0.tgz#7232ed266f34d197d15cac5880232f7a4790afe5" + integrity sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.values@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" + integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -2013,6 +2791,18 @@ once@^1.3.0: dependencies: wrappy "1" +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + os-browserify@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" @@ -2025,6 +2815,13 @@ p-limit@3.1.0: dependencies: yocto-queue "^0.1.0" +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -2032,6 +2829,13 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + p-locate@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" @@ -2039,6 +2843,11 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -2082,6 +2891,11 @@ path-browserify@1.0.1, path-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -2092,6 +2906,11 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + path-parse@^1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" @@ -2123,6 +2942,13 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= + dependencies: + find-up "^2.1.0" + pkg-dir@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -2195,6 +3021,11 @@ postcss@8.3.11, postcss@^8.1.6, postcss@^8.2.1: picocolors "^1.0.0" source-map-js "^0.6.2" +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + prettier@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.4.1.tgz#671e11c89c14a4cfc876ce564106c4a6726c9f5c" @@ -2215,6 +3046,11 @@ process@0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" @@ -2400,6 +3236,24 @@ regenerator-runtime@^0.13.4: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== +regexp.prototype.flags@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" + integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +regexpp@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" @@ -2423,6 +3277,14 @@ resolve@^1.20.0: is-core-module "^2.2.0" path-parse "^1.0.6" +resolve@^2.0.0-next.3: + version "2.0.0-next.3" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.3.tgz#d41016293d4a8586a39ca5d9b5f15cbea1f55e46" + integrity sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -2438,7 +3300,7 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@^3.0.0: +rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -2488,12 +3350,12 @@ semver@^5.6.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0: +semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.3.2: +semver@^7.2.1, semver@^7.3.2, semver@^7.3.5: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== @@ -2518,6 +3380,18 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + shell-quote@1.7.3: version "1.7.3" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" @@ -2563,6 +3437,20 @@ skynet-js@3.0.2: url-join "^4.0.1" url-parse "^1.4.7" +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + source-map-js@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" @@ -2585,6 +3473,11 @@ source-map@^0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + stacktrace-parser@0.1.10: version "0.1.10" resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" @@ -2627,6 +3520,29 @@ string-hash@1.1.3: resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs= +string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.matchall@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz#5abb5dabc94c7b0ea2380f65ba610b3a544b15fa" + integrity sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + get-intrinsic "^1.1.1" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + regexp.prototype.flags "^1.3.1" + side-channel "^1.0.4" + string.prototype.trimend@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" @@ -2650,17 +3566,27 @@ string_decoder@1.3.0, string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -strip-ansi@6.0.1: +strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" -stripe@8.186.1: - version "8.186.1" - resolved "https://registry.yarnpkg.com/stripe/-/stripe-8.186.1.tgz#fb717cfcb8c2e73c91e3873dc286f3e8442bfb65" - integrity sha512-BBByVyqKEBY2GNQDLmfwL1RtfsPmjForD+up7tu+P7KYxxvwEzF1gM2Iv4npfOQevGaBmR70sxIWRwn7utS5pg== +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +stripe@8.188.0: + version "8.188.0" + resolved "https://registry.yarnpkg.com/stripe/-/stripe-8.188.0.tgz#1d892c2f9000847c627db06a374529e7fbd2b83e" + integrity sha512-AW5IOKq4y+ENfHddJPrLL/GSvGj1MnBvUe6QMI1z27x/4pMNrU7v0ZqzRSJCihWqP0tUuCmQibSYSbsV4XJ3zA== dependencies: "@types/node" ">=8.1.0" qs "^6.6.0" @@ -2734,6 +3660,17 @@ swr@1.0.1: dependencies: dequal "2.0.2" +table@^6.0.9: + version "6.7.3" + resolved "https://registry.yarnpkg.com/table/-/table-6.7.3.tgz#255388439715a738391bd2ee4cbca89a4d05a9b7" + integrity sha512-5DkIxeA7XERBqMwJq0aHZOdMadBx4e6eDoFRuyT5VR82J0Ycg2DwM6GfA/EQAhJ+toRTaS1lIdSQCqgrmhPnlw== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + tailwindcss@2.2.19: version "2.2.19" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-2.2.19.tgz#540e464832cd462bb9649c1484b0a38315c2653c" @@ -2772,6 +3709,11 @@ tailwindcss@2.2.19: resolve "^1.20.0" tmp "^0.2.1" +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + timers-browserify@2.0.12: version "2.0.12" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" @@ -2825,11 +3767,28 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" -tslib@^1.10.0: +tsconfig-paths@^3.11.0, tsconfig-paths@^3.9.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz#954c1fe973da6339c78e06b03ce2e48810b65f36" + integrity sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.0" + strip-bom "^3.0.0" + +tslib@^1.10.0, tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + tty-browserify@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" @@ -2840,6 +3799,18 @@ tweetnacl@^1.0.3: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + type-fest@^0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" @@ -2865,6 +3836,13 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + url-join@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" @@ -2902,6 +3880,11 @@ util@0.12.4, util@^0.12.0: safe-buffer "^5.1.2" which-typed-array "^1.1.2" +v8-compile-cache@^2.0.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + vm-browserify@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" @@ -2952,6 +3935,18 @@ which-typed-array@^1.1.2: has-tostringtag "^1.0.0" is-typed-array "^1.1.7" +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"