From 9151f4cb6de24f0ac2deaf5954ab4ceff8595d3c Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sat, 31 Oct 2020 21:53:46 +0200 Subject: [PATCH] Add server with basic auth stuff --- .editorconfig | 19 + .gitignore | 2 + MANIFEST.in | 4 + optional-requirements.txt | 10 + requirements.txt | 6 +- setup.py | 22 + sticker/import.py | 4 +- sticker/server/__init__.py | 0 sticker/server/__main__.py | 53 + sticker/server/api/__init__.py | 38 + sticker/server/api/auth.py | 216 ++++ sticker/server/api/errors.py | 110 ++ sticker/server/api/fed_connector.py | 110 ++ sticker/server/api/packs.py | 52 + sticker/server/api/setup.py | 19 + sticker/server/config.py | 55 + sticker/server/database/__init__.py | 6 + sticker/server/database/access_token.py | 71 ++ sticker/server/database/base.py | 9 + sticker/server/database/pack.py | 58 + sticker/server/database/sticker.py | 49 + sticker/server/database/upgrade.py | 56 + sticker/server/database/user.py | 95 ++ sticker/server/example-config.yaml | 74 ++ sticker/server/frontend | 1 + sticker/server/server.py | 50 + sticker/server/static.py | 106 ++ web/.eslintrc.json | 196 +++ web/index.html | 10 +- web/lib/common/preact.module-9c264606.js | 3 + web/lib/htm/preact.js | 9 +- web/lib/preact/hooks.js | 5 + web/package.json | 14 +- web/setup/index.html | 23 + web/src/Button.js | 30 + web/src/{spinner.js => Spinner.js} | 4 +- web/src/setup/LoginView.js | 215 ++++ web/src/setup/index.js | 20 + web/src/setup/matrix-api.js | 102 ++ web/src/setup/tryGet.js | 67 + web/src/{ => widget}/frequently-used.js | 0 web/src/{ => widget}/index.js | 144 ++- web/src/{ => widget}/widget-api.js | 0 web/style/button.css | 1 + web/style/button.sass | 60 + web/style/setup-login.css | 1 + web/style/setup-login.sass | 105 ++ web/style/setup.css | 1 + web/style/setup.sass | 18 + web/style/theme.css | 0 web/style/theme.sass | 33 + web/style/{index.css => widget.css} | 0 web/style/{index.sass => widget.sass} | 0 web/yarn.lock | 1478 ++++++++++++++++------ 54 files changed, 3415 insertions(+), 419 deletions(-) create mode 100644 .editorconfig create mode 100644 MANIFEST.in create mode 100644 optional-requirements.txt create mode 100644 sticker/server/__init__.py create mode 100644 sticker/server/__main__.py create mode 100644 sticker/server/api/__init__.py create mode 100644 sticker/server/api/auth.py create mode 100644 sticker/server/api/errors.py create mode 100644 sticker/server/api/fed_connector.py create mode 100644 sticker/server/api/packs.py create mode 100644 sticker/server/api/setup.py create mode 100644 sticker/server/config.py create mode 100644 sticker/server/database/__init__.py create mode 100644 sticker/server/database/access_token.py create mode 100644 sticker/server/database/base.py create mode 100644 sticker/server/database/pack.py create mode 100644 sticker/server/database/sticker.py create mode 100644 sticker/server/database/upgrade.py create mode 100644 sticker/server/database/user.py create mode 100644 sticker/server/example-config.yaml create mode 120000 sticker/server/frontend create mode 100644 sticker/server/server.py create mode 100644 sticker/server/static.py create mode 100644 web/.eslintrc.json create mode 100644 web/lib/common/preact.module-9c264606.js create mode 100644 web/lib/preact/hooks.js create mode 100644 web/setup/index.html create mode 100644 web/src/Button.js rename web/src/{spinner.js => Spinner.js} (93%) create mode 100644 web/src/setup/LoginView.js create mode 100644 web/src/setup/index.js create mode 100644 web/src/setup/matrix-api.js create mode 100644 web/src/setup/tryGet.js rename web/src/{ => widget}/frequently-used.js (100%) rename web/src/{ => widget}/index.js (73%) rename web/src/{ => widget}/widget-api.js (100%) create mode 100644 web/style/button.css create mode 100644 web/style/button.sass create mode 100644 web/style/setup-login.css create mode 100644 web/style/setup-login.sass create mode 100644 web/style/setup.css create mode 100644 web/style/setup.sass create mode 100644 web/style/theme.css create mode 100644 web/style/theme.sass rename web/style/{index.css => widget.css} (100%) rename web/style/{index.sass => widget.sass} (100%) diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6a10e78 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.py] +max_line_length = 99 + +[*.js] +max_line_length = 100 +indent_style = tab + +[*.{json,sass}] +indent_size = 2 diff --git a/.gitignore b/.gitignore index b2a42f7..b8fc8c7 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ web/lib/import-map.json *.session /*.json *.bak +*.log +config.yaml diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..daa36da --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,4 @@ +include README.md +include LICENSE +include requirements.txt +include optional-requirements.txt diff --git a/optional-requirements.txt b/optional-requirements.txt new file mode 100644 index 0000000..ac71e85 --- /dev/null +++ b/optional-requirements.txt @@ -0,0 +1,10 @@ +# Format: #/name defines a new extras_require group called name +# Uncommented lines after the group definition insert things into that group. + +#/server +mautrix==0.8.0rc4 +asyncpg>=0.20,<0.22 +attrs +setuptools +aiodns +ruamel.yaml diff --git a/requirements.txt b/requirements.txt index 6d89dbf..d6c9172 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ -aiohttp -yarl +aiohttp>=3,<4 +yarl>=1,<2 pillow -telethon +telethon>=1.16 cryptg python-magic diff --git a/setup.py b/setup.py index 524eaa7..6e8cb41 100644 --- a/setup.py +++ b/setup.py @@ -5,6 +5,19 @@ from sticker.get_version import git_tag, git_revision, version, linkified_versio with open("requirements.txt") as reqs: install_requires = reqs.read().splitlines() +with open("optional-requirements.txt") as reqs: + extras_require = {} + current = [] + for line in reqs.read().splitlines(): + if line.startswith("#/"): + extras_require[line[2:]] = current = [] + elif not line or line.startswith("#"): + continue + else: + current.append(line) + +extras_require["all"] = list({dep for deps in extras_require.values() for dep in deps}) + try: long_desc = open("README.md").read() except IOError: @@ -34,6 +47,7 @@ setuptools.setup( packages=setuptools.find_packages(), install_requires=install_requires, + extras_require=extras_require, python_requires="~=3.6", classifiers=[ @@ -45,9 +59,17 @@ setuptools.setup( "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", ], entry_points={"console_scripts": [ "sticker-import=sticker.import:cmd", "sticker-pack=sticker.pack:cmd", + "sticker-server=sticker.server:cmd", ]}, + package_data={"sticker.server": [ + "example-config.yaml", + + "frontend/index.html", "frontend/setup/index.html", + "frontend/src/*", "frontend/lib/*/*.js", "frontend/res/*", "frontend/style/*.css", + ]} ) diff --git a/sticker/import.py b/sticker/import.py index 6846184..ef9b087 100644 --- a/sticker/import.py +++ b/sticker/import.py @@ -117,6 +117,8 @@ async def reupload_pack(client: TelegramClient, pack: StickerSetFull, output_dir pack_url_regex = re.compile(r"^(?:(?:https?://)?(?:t|telegram)\.(?:me|dog)/addstickers/)?" r"([A-Za-z0-9-_]+)" r"(?:\.json)?$") +api_id = 298751 +api_hash = "cb676d6bae20553c9996996a8f52b4d7" parser = argparse.ArgumentParser() @@ -132,7 +134,7 @@ parser.add_argument("pack", help="Sticker pack URLs to import", action="append", async def main(args: argparse.Namespace) -> None: await matrix.load_config(args.config) - client = TelegramClient(args.session, 298751, "cb676d6bae20553c9996996a8f52b4d7") + client = TelegramClient(args.session, api_id, api_hash) await client.start() if args.list: diff --git a/sticker/server/__init__.py b/sticker/server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sticker/server/__main__.py b/sticker/server/__main__.py new file mode 100644 index 0000000..27ec3e2 --- /dev/null +++ b/sticker/server/__main__.py @@ -0,0 +1,53 @@ +# maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +# Copyright (C) 2020 Tulir Asokan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +from mautrix.util.program import Program +from mautrix.util.async_db import Database + +from .config import Config +from .server import Server +from .database import upgrade_table, Base +from ..version import version + + +class StickerServer(Program): + module = "sticker.server" + name = "maunium-stickerpicker server" + version = version + command = "python -m sticker.server" + description = "Server for maunium-stickerpicker" + + config_class = Config + + config: Config + server: Server + database: Database + + async def start(self) -> None: + self.database = Database(url=self.config["database"], upgrade_table=upgrade_table) + Base.db = self.database + self.server = Server(self.config) + + await self.database.start() + await self.server.start() + + await super().start() + + async def stop(self) -> None: + await super().stop() + await self.server.stop() + + +StickerServer().run() diff --git a/sticker/server/api/__init__.py b/sticker/server/api/__init__.py new file mode 100644 index 0000000..d438ce0 --- /dev/null +++ b/sticker/server/api/__init__.py @@ -0,0 +1,38 @@ +# maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +# Copyright (C) 2020 Tulir Asokan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +from aiohttp import web + +from ..config import Config +from .auth import (routes as auth_routes, init as auth_init, + token_middleware, widget_secret_middleware) +from .fed_connector import init as init_fed_connector +from .packs import routes as packs_routes, init as packs_init +from .setup import routes as setup_routes + +integrations_app = web.Application() +integrations_app.add_routes(auth_routes) + +packs_app = web.Application(middlewares=[widget_secret_middleware]) +packs_app.add_routes(packs_routes) + +setup_app = web.Application(middlewares=[token_middleware]) +setup_app.add_routes(setup_routes) + + +def init(config: Config) -> None: + init_fed_connector() + auth_init(config) + packs_init(config) diff --git a/sticker/server/api/auth.py b/sticker/server/api/auth.py new file mode 100644 index 0000000..7de0b13 --- /dev/null +++ b/sticker/server/api/auth.py @@ -0,0 +1,216 @@ +# maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +# Copyright (C) 2020 Tulir Asokan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +from typing import Tuple, Callable, Awaitable, Optional, TYPE_CHECKING +import logging +import json + +from mautrix.client import Client +from mautrix.types import UserID +from mautrix.util.logging import TraceLogger +from aiohttp import web, hdrs, ClientError, ClientSession +from yarl import URL + +from ..database import AccessToken, User +from ..config import Config +from .errors import Error +from . import fed_connector + +if TYPE_CHECKING: + from typing import TypedDict + + + class OpenIDPayload(TypedDict): + access_token: str + token_type: str + matrix_server_name: str + expires_in: int + + + class OpenIDResponse(TypedDict): + sub: str + +Handler = Callable[[web.Request], Awaitable[web.Response]] + +log: TraceLogger = logging.getLogger("mau.api.auth") +routes = web.RouteTableDef() +config: Config + + +def get_ip(request: web.Request) -> str: + if config["server.trust_forward_headers"]: + try: + return request.headers["X-Forwarded-For"] + except KeyError: + pass + return request.remote + + +def get_auth_header(request: web.Request) -> str: + try: + auth = request.headers["Authorization"] + if not auth.startswith("Bearer "): + raise Error.invalid_auth_header + return auth[len("Bearer "):] + except KeyError: + raise Error.missing_auth_header + + +async def get_user(request: web.Request) -> Tuple[User, AccessToken]: + auth = get_auth_header(request) + try: + token_id, token_val = auth.split(":") + token_id = int(token_id) + except ValueError: + raise Error.invalid_auth_token + token = await AccessToken.get(token_id) + if not token or not token.check(token_val): + raise Error.invalid_auth_token + elif token.expired: + raise Error.auth_token_expired + await token.update_ip(get_ip(request)) + return await User.get(token.user_id), token + + +@web.middleware +async def token_middleware(request: web.Request, handler: Handler) -> web.Response: + if request.method == hdrs.METH_OPTIONS: + return await handler(request) + user, token = await get_user(request) + request["user"] = user + request["token"] = token + return await handler(request) + + +async def get_widget_user(request: web.Request) -> User: + try: + user_id = UserID(request.headers["X-Matrix-User-ID"]) + except KeyError: + raise Error.missing_user_id_header + user = await User.get(user_id) + if user is None: + raise Error.user_not_found + return user + + +@web.middleware +async def widget_secret_middleware(request: web.Request, handler: Handler) -> web.Response: + if request.method == hdrs.METH_OPTIONS: + return await handler(request) + user = await get_widget_user(request) + request["user"] = user + return await handler(request) + + +account_cors_headers = { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "OPTIONS, GET, POST", + "Access-Control-Allow-Headers": "Authorization, Content-Type", +} + + +@routes.get("/account") +async def get_auth(request: web.Request) -> web.Response: + user, token = await get_user(request) + return web.json_response({"user_id": token.user_id}, headers=account_cors_headers) + + +async def check_openid_token(homeserver: str, token: str) -> Optional[UserID]: + server_info = await fed_connector.resolve_server_name(homeserver) + headers = {"Host": server_info.host_header} + userinfo_url = URL.build(scheme="https", host=server_info.host, port=server_info.port, + path="/_matrix/federation/v1/openid/userinfo", + query={"access_token": token}) + try: + async with fed_connector.http.get(userinfo_url, headers=headers) as resp: + data: 'OpenIDResponse' = await resp.json() + return UserID(data["sub"]) + except (ClientError, json.JSONDecodeError, KeyError, ValueError) as e: + log.debug(f"Failed to check OpenID token from {homeserver}", exc_info=True) + return None + + +@routes.route(hdrs.METH_OPTIONS, "/account/register") +@routes.route(hdrs.METH_OPTIONS, "/account/logout") +@routes.route(hdrs.METH_OPTIONS, "/account") +async def cors_token(_: web.Request) -> web.Response: + return web.Response(status=200, headers=account_cors_headers) + + +async def resolve_client_well_known(server_name: str) -> str: + url = URL.build(scheme="https", host=server_name, port=443, path="/.well-known/matrix/client") + async with ClientSession() as sess, sess.get(url) as resp: + data = await resp.json() + return data["m.homeserver"]["base_url"] + + +@routes.post("/account/register") +async def exchange_token(request: web.Request) -> web.Response: + try: + data: 'OpenIDPayload' = await request.json() + except json.JSONDecodeError: + raise Error.request_not_json + try: + matrix_server_name = data["matrix_server_name"] + access_token = data["access_token"] + except KeyError: + raise Error.invalid_openid_payload + log.trace(f"Validating OpenID token from {matrix_server_name}") + user_id = await check_openid_token(matrix_server_name, access_token) + if user_id is None: + raise Error.invalid_openid_token + _, homeserver = Client.parse_user_id(user_id) + if homeserver != data["matrix_server_name"]: + raise Error.homeserver_mismatch + + permissions = config.get_permissions(user_id) + if not permissions.access: + raise Error.no_access + + try: + log.trace(f"Trying to resolve {matrix_server_name}'s client .well-known") + homeserver_url = await resolve_client_well_known(matrix_server_name) + log.trace(f"Got {homeserver_url} from {matrix_server_name}'s client .well-known") + except (ClientError, json.JSONDecodeError, KeyError, ValueError, TypeError): + log.trace(f"Failed to resolve {matrix_server_name}'s client .well-known", exc_info=True) + raise Error.client_well_known_error + + user = await User.get(user_id) + if user is None: + log.debug(f"Creating user {user_id} with homeserver client URL {homeserver_url}") + user = User.new(user_id, homeserver_url=homeserver_url) + await user.insert() + elif user.homeserver_url != homeserver_url: + log.debug(f"Updating {user_id}'s homeserver client URL from {user.homeserver_url} " + f"to {homeserver_url}") + await user.set_homeserver_url(homeserver_url) + token = await user.new_access_token(get_ip(request)) + return web.json_response({ + "user_id": user_id, + "token": token, + "permissions": permissions._asdict(), + }, headers=account_cors_headers) + + +@routes.post("/account/logout") +async def logout(request: web.Request) -> web.Response: + user, token = await get_user(request) + await token.delete() + return web.json_response({}, status=204, headers=account_cors_headers) + + +def init(cfg: Config) -> None: + global config + config = cfg diff --git a/sticker/server/api/errors.py b/sticker/server/api/errors.py new file mode 100644 index 0000000..f84df57 --- /dev/null +++ b/sticker/server/api/errors.py @@ -0,0 +1,110 @@ +# maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +# Copyright (C) 2020 Tulir Asokan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +from typing import Dict +import json + +from aiohttp import web + + +class _ErrorMeta: + def __init__(self, *args, **kwargs) -> None: + pass + + @staticmethod + def _make_error(errcode: str, error: str) -> Dict[str, str]: + return { + "body": json.dumps({ + "error": error, + "errcode": errcode, + }).encode("utf-8"), + "content_type": "application/json", + "headers": { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "OPTIONS, GET, POST, PUT, DELETE, HEAD", + "Access-Control-Allow-Headers": "Authorization, Content-Type", + } + } + + @property + def request_not_json(self) -> web.HTTPException: + return web.HTTPBadRequest(**self._make_error("M_NOT_JSON", + "Request body is not valid JSON")) + + @property + def missing_auth_header(self) -> web.HTTPException: + return web.HTTPForbidden(**self._make_error("M_MISSING_TOKEN", + "Missing authorization header")) + + @property + def missing_user_id_header(self) -> web.HTTPException: + return web.HTTPForbidden(**self._make_error("NET.MAUNIUM_MISSING_USER_ID", + "Missing user ID header")) + + @property + def user_not_found(self) -> web.HTTPException: + return web.HTTPNotFound(**self._make_error("NET.MAUNIUM_USER_NOT_FOUND", + "User not found")) + + @property + def invalid_auth_header(self) -> web.HTTPException: + return web.HTTPForbidden(**self._make_error("M_UNKNOWN_TOKEN", + "Invalid authorization header")) + + @property + def invalid_auth_token(self) -> web.HTTPException: + return web.HTTPForbidden(**self._make_error("M_UNKNOWN_TOKEN", + "Invalid authorization token")) + + @property + def auth_token_expired(self) -> web.HTTPException: + return web.HTTPForbidden(**self._make_error("NET.MAUNIUM_TOKEN_EXPIRED", + "Authorization token has expired")) + + @property + def invalid_openid_payload(self) -> web.HTTPException: + return web.HTTPBadRequest(**self._make_error("M_BAD_JSON", "Missing one or more " + "fields in OpenID payload")) + + @property + def invalid_openid_token(self) -> web.HTTPException: + return web.HTTPForbidden(**self._make_error("M_UNKNOWN_TOKEN", + "Invalid OpenID token")) + + @property + def no_access(self) -> web.HTTPException: + return web.HTTPUnauthorized(**self._make_error( + "M_UNAUTHORIZED", + "You are not authorized to access this maunium-stickerpicker instance")) + + @property + def homeserver_mismatch(self) -> web.HTTPException: + return web.HTTPUnauthorized(**self._make_error( + "M_UNAUTHORIZED", "Request matrix_server_name and OpenID sub homeserver don't match")) + + @property + def pack_not_found(self) -> web.HTTPException: + return web.HTTPNotFound(**self._make_error("NET.MAUNIUM_PACK_NOT_FOUND", + "Sticker pack not found")) + + @property + def client_well_known_error(self) -> web.HTTPException: + return web.HTTPForbidden(**self._make_error("NET.MAUNIUM_CLIENT_WELL_KNOWN_ERROR", + "Failed to resolve homeserver URL " + "from client .well-known")) + + +class Error(metaclass=_ErrorMeta): + pass diff --git a/sticker/server/api/fed_connector.py b/sticker/server/api/fed_connector.py new file mode 100644 index 0000000..a67266b --- /dev/null +++ b/sticker/server/api/fed_connector.py @@ -0,0 +1,110 @@ +from typing import Tuple, Any, NamedTuple, Dict, Optional +from time import time +import ipaddress +import logging +import asyncio +import json + +from mautrix.util.logging import TraceLogger +from aiohttp import ClientRequest, TCPConnector, ClientSession, ClientTimeout, ClientError +from aiohttp.client_proto import ResponseHandler +from yarl import URL +import aiodns + +log: TraceLogger = logging.getLogger("mau.federation") + + +class ResolvedServerName(NamedTuple): + host_header: str + host: str + port: int + expire: int + + +class ServerNameSplit(NamedTuple): + host: str + port: Optional[int] + is_ip: bool + + +dns_resolver: aiodns.DNSResolver +http: ClientSession +server_name_cache: Dict[str, ResolvedServerName] = {} + + +class MatrixFederationTCPConnector(TCPConnector): + """An extension to aiohttp's TCPConnector that correctly sets the TLS SNI for Matrix federation + requests, where the TCP host may not match the SNI/Host header.""" + + async def _wrap_create_connection(self, *args: Any, server_hostname: str, req: ClientRequest, + **kwargs: Any) -> Tuple[asyncio.Transport, ResponseHandler]: + split = parse_server_name(req.headers["Host"]) + return await super()._wrap_create_connection(*args, server_hostname=split.host, + req=req, **kwargs) + + +def parse_server_name(name: str) -> ServerNameSplit: + port_split = name.rsplit(":", 1) + if len(port_split) == 2 and port_split[1].isdecimal(): + name, port = port_split + else: + port = None + try: + ipaddress.ip_address(name) + is_ip = True + except ValueError: + is_ip = False + res = ServerNameSplit(host=name, port=port, is_ip=is_ip) + log.trace(f"Parsed server name {name} into {res}") + return res + + +async def resolve_server_name(server_name: str) -> ResolvedServerName: + try: + cached = server_name_cache[server_name] + if cached.expire > int(time()): + log.trace(f"Using cached server name resolution for {server_name}: {cached}") + return cached + except KeyError: + log.trace(f"No cached server name resolution for {server_name}") + + host_header = server_name + hostname, port, is_ip = parse_server_name(host_header) + ttl = 86400 + if port is None and not is_ip: + well_known_url = URL.build(scheme="https", host=host_header, port=443, + path="/.well-known/matrix/server") + try: + log.trace(f"Requesting {well_known_url} to resolve {server_name}'s .well-known") + async with http.get(well_known_url) as resp: + if resp.status == 200: + well_known_data = await resp.json() + host_header = well_known_data["m.server"] + log.debug(f"Got {host_header} from {server_name}'s .well-known") + hostname, port, is_ip = parse_server_name(host_header) + else: + log.trace(f"Got non-200 status {resp.status} from {server_name}'s .well-known") + except (ClientError, json.JSONDecodeError, KeyError, ValueError) as e: + log.debug(f"Failed to fetch .well-known for {server_name}: {e}") + if port is None and not is_ip: + log.trace(f"Querying SRV at _matrix._tcp.{host_header}") + res = await dns_resolver.query(f"_matrix._tcp.{host_header}", "SRV") + if res: + hostname = res[0].host + port = res[0].port + ttl = max(res[0].ttl, 300) + log.debug(f"Got {hostname}:{port} from {host_header}'s Matrix SRV record") + else: + log.trace(f"No SRV records found at _matrix._tcp.{host_header}") + result = ResolvedServerName(host_header=host_header, host=hostname, port=port or 8448, + expire=int(time()) + ttl) + server_name_cache[server_name] = result + log.debug(f"Resolved server name {server_name} -> {result}") + return result + + +def init(): + global http, dns_resolver + dns_resolver = aiodns.DNSResolver(loop=asyncio.get_running_loop()) + http = ClientSession(timeout=ClientTimeout(total=10), + connector=MatrixFederationTCPConnector()) diff --git a/sticker/server/api/packs.py b/sticker/server/api/packs.py new file mode 100644 index 0000000..e048da4 --- /dev/null +++ b/sticker/server/api/packs.py @@ -0,0 +1,52 @@ +# maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +# Copyright (C) 2020 Tulir Asokan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +from aiohttp import web + +from ..database import User +from ..config import Config +from .errors import Error + +routes = web.RouteTableDef() +config: Config + + +@routes.get("/index.json") +async def get_packs(req: web.Request) -> web.Response: + user: User = req["user"] + packs = await user.get_packs() + return web.json_response({ + "homeserver_url": user.homeserver_url, + "is_sticker_server": True, + "packs": [f"{pack.id}.json" for pack in packs], + }) + + +@routes.get("/{pack_id}.json") +async def get_pack(req: web.Request) -> web.Response: + user: User = req["user"] + pack = await user.get_pack(req.match_info["pack_id"]) + if pack is None: + raise Error.pack_not_found + stickers = await pack.get_stickers() + return web.json_response({ + **pack.to_dict(), + "stickers": [sticker.to_dict() for sticker in stickers], + }) + + +def init(cfg: Config) -> None: + global config + config = cfg diff --git a/sticker/server/api/setup.py b/sticker/server/api/setup.py new file mode 100644 index 0000000..7a9dc30 --- /dev/null +++ b/sticker/server/api/setup.py @@ -0,0 +1,19 @@ +# maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +# Copyright (C) 2020 Tulir Asokan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from aiohttp import web + +routes = web.RouteTableDef() diff --git a/sticker/server/config.py b/sticker/server/config.py new file mode 100644 index 0000000..0bab3a4 --- /dev/null +++ b/sticker/server/config.py @@ -0,0 +1,55 @@ +# maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +# Copyright (C) 2020 Tulir Asokan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +from typing import NamedTuple + +from mautrix.util.config import BaseFileConfig, ConfigUpdateHelper +from mautrix.types import UserID +from mautrix.client import Client + + +class Permissions(NamedTuple): + access: bool = False + create_packs: bool = False + telegram_import: bool = False + + +class Config(BaseFileConfig): + def do_update(self, helper: ConfigUpdateHelper) -> None: + copy = helper.copy + + copy("database") + + copy("server.host") + copy("server.port") + copy("server.public_url") + copy("server.override_resource_path") + copy("server.trust_forward_headers") + + copy("telegram_import.bot_token") + copy("telegram_import.homeserver.address") + copy("telegram_import.homeserver.access_token") + + copy("permissions") + + copy("logging") + + def get_permissions(self, mxid: UserID) -> Permissions: + _, homeserver = Client.parse_user_id(mxid) + return Permissions(**{ + **self["permissions"].get("*", {}), + **self["permissions"].get(homeserver, {}), + **self["permissions"].get(mxid, {}), + }) diff --git a/sticker/server/database/__init__.py b/sticker/server/database/__init__.py new file mode 100644 index 0000000..051dc4e --- /dev/null +++ b/sticker/server/database/__init__.py @@ -0,0 +1,6 @@ +from .base import Base +from .upgrade import upgrade_table +from .sticker import Sticker +from .pack import Pack +from .access_token import AccessToken +from .user import User diff --git a/sticker/server/database/access_token.py b/sticker/server/database/access_token.py new file mode 100644 index 0000000..1771328 --- /dev/null +++ b/sticker/server/database/access_token.py @@ -0,0 +1,71 @@ +# maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +# Copyright (C) 2020 Tulir Asokan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +from typing import Optional, ClassVar +from datetime import datetime, timedelta +import hashlib + +from attr import dataclass +import asyncpg + +from mautrix.types import UserID + +from .base import Base + + +@dataclass(kw_only=True) +class AccessToken(Base): + token_expiry: ClassVar[timedelta] = timedelta(days=1) + + user_id: UserID + token_id: int + token_hash: bytes + last_seen_ip: str + last_seen_date: datetime + + @classmethod + async def get(cls, token_id: int) -> Optional['AccessToken']: + q = "SELECT user_id, token_hash, last_seen_ip, last_seen_date FROM pack WHERE token_id=$1" + row: asyncpg.Record = await cls.db.fetchrow(q, token_id) + if row is None: + return None + return cls(**row, token_id=token_id) + + async def update_ip(self, ip: str) -> None: + if self.last_seen_ip == ip and (self.last_seen_date.replace(second=0, microsecond=0) + == datetime.now().replace(second=0, microsecond=0)): + # Same IP and last seen on this minute, skip update + return + q = ("UPDATE access_token SET last_seen_ip=$3, last_seen_date=current_timestamp " + "WHERE token_id=$1 RETURNING last_seen_date") + self.last_seen_date = await self.db.fetchval(q, self.token_id, ip) + self.last_seen_ip = ip + + def check(self, token: str) -> bool: + return self.token_hash == hashlib.sha256(token.encode("utf-8")).digest() + + @property + def expired(self) -> bool: + return self.last_seen_date + self.token_expiry < datetime.now() + + async def delete(self) -> None: + await self.db.execute("DELETE FROM access_token WHERE token_id=$1", self.token_id) + + @classmethod + async def insert(cls, user_id: UserID, token: str, ip: str) -> int: + q = ("INSERT INTO access_token (user_id, token_hash, last_seen_ip, last_seen_date) " + "VALUES ($1, $2, $3, current_timestamp) RETURNING token_id") + hashed = hashlib.sha256(token.encode("utf-8")).digest() + return await cls.db.fetchval(q, user_id, hashed, ip) diff --git a/sticker/server/database/base.py b/sticker/server/database/base.py new file mode 100644 index 0000000..e456327 --- /dev/null +++ b/sticker/server/database/base.py @@ -0,0 +1,9 @@ +from typing import ClassVar, TYPE_CHECKING + +from mautrix.util.async_db import Database + +fake_db = Database("") if TYPE_CHECKING else None + + +class Base: + db: ClassVar[Database] = fake_db diff --git a/sticker/server/database/pack.py b/sticker/server/database/pack.py new file mode 100644 index 0000000..3c2e530 --- /dev/null +++ b/sticker/server/database/pack.py @@ -0,0 +1,58 @@ +# maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +# Copyright (C) 2020 Tulir Asokan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +from typing import List, Dict, Any + +from attr import dataclass + +from mautrix.types import UserID + +from .base import Base +from .sticker import Sticker + + +@dataclass(kw_only=True) +class Pack(Base): + id: str + owner: UserID + title: str + meta: Dict[str, Any] + + async def delete(self) -> None: + await self.db.execute("DELETE FROM pack WHERE id=$1", self.id) + + async def insert(self) -> None: + await self.db.execute("INSERT INTO pack (id, owner, title, meta) VALUES ($1, $2, $3, $4)", + self.id, self.owner, self.title, self.meta) + + async def get_stickers(self) -> List[Sticker]: + res = await self.db.fetch('SELECT id, url, body, meta, "order" ' + 'FROM sticker WHERE pack_id=$1 ORDER BY "order"', self.id) + return [Sticker(**row, pack_id=self.id) for row in res] + + async def set_stickers(self, stickers: List[Sticker]) -> None: + data = ((sticker.id, self.id, sticker.url, sticker.body, sticker.meta, order) + for order, sticker in enumerate(stickers)) + columns = ["id", "pack_id", "url", "body", "meta", "order"] + async with self.db.acquire() as conn, conn.transaction(): + await conn.execute("DELETE FROM sticker WHERE pack_id=$1", self.id) + await conn.copy_records_to_table("sticker", records=data, columns=columns) + + def to_dict(self) -> Dict[str, Any]: + return { + **self.meta, + "title": self.title, + "id": self.id, + } diff --git a/sticker/server/database/sticker.py b/sticker/server/database/sticker.py new file mode 100644 index 0000000..03aa21c --- /dev/null +++ b/sticker/server/database/sticker.py @@ -0,0 +1,49 @@ +# maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +# Copyright (C) 2020 Tulir Asokan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +from typing import Dict, Any + +from attr import dataclass +import attr + +from mautrix.types import ContentURI + +from .base import Base + + +@dataclass(kw_only=True) +class Sticker(Base): + pack_id: str + order: int + id: str + url: ContentURI = attr.ib(order=False) + body: str = attr.ib(order=False) + meta: Dict[str, Any] = attr.ib(order=False) + + async def delete(self) -> None: + await self.db.execute("DELETE FROM sticker WHERE id=$1", self.id) + + async def insert(self) -> None: + await self.db.execute('INSERT INTO sticker (id, pack_id, url, body, meta, "order") ' + "VALUES ($1, $2, $3, $4, $5, $6)", + self.id, self.pack_id, self.url, self.body, self.meta, self.order) + + def to_dict(self) -> Dict[str, Any]: + return { + **self.meta, + "body": self.body, + "url": self.url, + "id": self.id, + } diff --git a/sticker/server/database/upgrade.py b/sticker/server/database/upgrade.py new file mode 100644 index 0000000..b2c98be --- /dev/null +++ b/sticker/server/database/upgrade.py @@ -0,0 +1,56 @@ +# maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +# Copyright (C) 2020 Tulir Asokan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +from asyncpg import Connection + +from mautrix.util.async_db.upgrade import UpgradeTable + +upgrade_table = UpgradeTable() + + +@upgrade_table.register(description="Initial revision") +async def upgrade_v1(conn: Connection) -> None: + await conn.execute("""CREATE TABLE "user" ( + id TEXT PRIMARY KEY, + widget_secret TEXT NOT NULL, + homeserver_url TEXT NOT NULL + )""") + await conn.execute("""CREATE TABLE access_token ( + token_id SERIAL PRIMARY KEY, + user_id TEXT NOT NULL REFERENCES "user"(id) ON DELETE CASCADE, + token_hash BYTEA NOT NULL, + last_seen_ip TEXT, + last_seen_date TIMESTAMP + )""") + await conn.execute("""CREATE TABLE pack ( + id TEXT PRIMARY KEY, + owner TEXT REFERENCES "user"(id) ON DELETE SET NULL, + title TEXT NOT NULL, + meta JSONB NOT NULL + )""") + await conn.execute("""CREATE TABLE user_pack ( + user_id TEXT REFERENCES "user"(id) ON DELETE CASCADE, + pack_id TEXT REFERENCES pack(id) ON DELETE CASCADE, + "order" INT NOT NULL DEFAULT 0, + PRIMARY KEY (user_id, pack_id) + )""") + await conn.execute("""CREATE TABLE sticker ( + id TEXT PRIMARY KEY, + pack_id TEXT NOT NULL REFERENCES pack(id) ON DELETE CASCADE, + url TEXT NOT NULL, + body TEXT NOT NULL, + meta JSONB NOT NULL, + "order" INT NOT NULL DEFAULT 0 + )""") diff --git a/sticker/server/database/user.py b/sticker/server/database/user.py new file mode 100644 index 0000000..138efda --- /dev/null +++ b/sticker/server/database/user.py @@ -0,0 +1,95 @@ +# maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +# Copyright (C) 2020 Tulir Asokan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +from typing import Optional, List, ClassVar +import random +import string + +from attr import dataclass +import asyncpg + +from mautrix.types import UserID + +from .base import Base +from .pack import Pack +from .access_token import AccessToken + + +@dataclass(kw_only=True) +class User(Base): + token_charset: ClassVar[str] = string.ascii_letters + string.digits + + id: UserID + widget_secret: str + homeserver_url: str + + @classmethod + def _random_token(cls) -> str: + return "".join(random.choices(cls.token_charset, k=64)) + + @classmethod + def new(cls, id: UserID, homeserver_url: str) -> 'User': + return User(id=id, widget_secret=cls._random_token(), homeserver_url=homeserver_url) + + @classmethod + async def get(cls, id: UserID) -> Optional['User']: + q = 'SELECT id, widget_secret, homeserver_url FROM "user" WHERE id=$1' + row: asyncpg.Record = await cls.db.fetchrow(q, id) + if row is None: + return None + return cls(**row) + + async def regenerate_widget_secret(self) -> None: + self.widget_secret = self._random_token() + await self.db.execute('UPDATE "user" SET widget_secret=$1 WHERE id=$2', + self.widget_secret, self.id) + + async def set_homeserver_url(self, url: str) -> None: + self.homeserver_url = url + await self.db.execute('UPDATE "user" SET homeserver_url=$1 WHERE id=$2', url, self.id) + + async def new_access_token(self, ip: str) -> str: + token = self._random_token() + token_id = await AccessToken.insert(self.id, token, ip) + return f"{token_id}:{token}" + + async def delete(self) -> None: + await self.db.execute('DELETE FROM "user" WHERE id=$1', self.id) + + async def insert(self) -> None: + q = 'INSERT INTO "user" (id, widget_secret, homeserver_url) VALUES ($1, $2, $3)' + await self.db.execute(q, self.id, self.widget_secret, self.homeserver_url) + + async def get_packs(self) -> List[Pack]: + res = await self.db.fetch("SELECT id, owner, title, meta FROM user_pack " + "LEFT JOIN pack ON pack.id=user_pack.pack_id " + 'WHERE user_id=$1 ORDER BY "order"', self.id) + return [Pack(**row) for row in res] + + async def get_pack(self, pack_id: str) -> Optional[Pack]: + row = await self.db.fetchrow("SELECT id, owner, title, meta FROM user_pack " + "LEFT JOIN pack ON pack.id=user_pack.pack_id " + "WHERE user_id=$1 AND pack_id=$2", self.id, pack_id) + if row is None: + return None + return Pack(**row) + + async def set_packs(self, packs: List[Pack]) -> None: + data = ((self.id, pack.id, order) + for order, pack in enumerate(packs)) + columns = ["user_id", "pack_id", "order"] + async with self.db.acquire() as conn, conn.transaction(): + await conn.execute("DELETE FROM user_pack WHERE user_id=$1", self.id) + await conn.copy_records_to_table("user_pack", records=data, columns=columns) diff --git a/sticker/server/example-config.yaml b/sticker/server/example-config.yaml new file mode 100644 index 0000000..d19d8dd --- /dev/null +++ b/sticker/server/example-config.yaml @@ -0,0 +1,74 @@ +# Postgres database URL for storing sticker packs and other things. +database: postgres://username:password@hostname/dbname + +# Settings for the actual HTTP server +server: + # The IP and port to listen to. + hostname: 0.0.0.0 + port: 29329 + # Public base URL where the server is visible. + public_url: https://example.com + # Override path from where to load UI resources. + # Set to false to using pkg_resources to find the path. + override_resource_path: false + # Whether or not to trust X-Forwarded-For headers for determining the request IP. + trust_forward_headers: false + +# Telegram configuration for downloading sticker packs. In the future, this will be client-side and +# none of this configuration will be necessary. +telegram_import: + # Create your own bot at https://t.me/BotFather + bot_token: null + + # Matrix homeserver access details. This is only used for uploading Telegram-imported stickers. + homeserver: + address: https://example.com + access_token: null + +# Permissions for who is allowed to use the sticker picker. +# +# Values are objects that should contain boolean values each permission: +# access - Access the sticker picker and use existing packs. +# create_packs - Create packs by uploading images. +# telegram_import - Create packs by importing from Telegram. Images are stored on +# +# Permission keys may be user IDs, server names or "*". If a server name or user ID permission +# doesn't specify some keys, they'll be inherited from the higher level. +permissions: + "*": + access: true + create_packs: true + telegram_import: false + "example.com": + telegram_import: true + +# Python logging configuration. +# +# See Configuration dictionary schema in the Python documentation for more info: +# https://docs.python.org/3.9/library/logging.config.html#configuration-dictionary-schema +logging: + version: 1 + formatters: + colored: + (): mautrix.util.logging.ColorFormatter + format: "[%(asctime)s] [%(levelname)s@%(name)s] %(message)s" + normal: + format: "[%(asctime)s] [%(levelname)s@%(name)s] %(message)s" + handlers: + file: + class: logging.handlers.RotatingFileHandler + formatter: normal + filename: ./sticker.server.log + maxBytes: 10485760 + backupCount: 10 + console: + class: logging.StreamHandler + formatter: colored + loggers: + mau: + level: DEBUG + aiohttp: + level: INFO + root: + level: DEBUG + handlers: [file, console] diff --git a/sticker/server/frontend b/sticker/server/frontend new file mode 120000 index 0000000..aeac1b5 --- /dev/null +++ b/sticker/server/frontend @@ -0,0 +1 @@ +../../web/ \ No newline at end of file diff --git a/sticker/server/server.py b/sticker/server/server.py new file mode 100644 index 0000000..5270a72 --- /dev/null +++ b/sticker/server/server.py @@ -0,0 +1,50 @@ +# maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +# Copyright (C) 2020 Tulir Asokan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +from pkg_resources import resource_filename +from aiohttp import web + +from .api import packs_app, setup_app, integrations_app, init as init_api +from .static import StaticResource +from .config import Config + + +class Server: + config: Config + runner: web.AppRunner + app: web.Application + site: web.TCPSite + + def __init__(self, config: Config) -> None: + init_api(config) + self.config = config + self.app = web.Application() + self.app.add_subapp("/_matrix/integrations/v1", integrations_app) + self.app.add_subapp("/setup/api", setup_app) + self.app.add_subapp("/packs", packs_app) + + resource_path = (config["server.override_resource_path"] + or resource_filename("sticker.server", "frontend")) + self.app.router.register_resource(StaticResource("/", resource_path, name="frontend")) + self.runner = web.AppRunner(self.app) + + async def start(self) -> None: + await self.runner.setup() + self.site = web.TCPSite(self.runner, self.config["server.host"], + self.config["server.port"]) + await self.site.start() + + async def stop(self) -> None: + await self.runner.cleanup() diff --git a/sticker/server/static.py b/sticker/server/static.py new file mode 100644 index 0000000..c1af7e4 --- /dev/null +++ b/sticker/server/static.py @@ -0,0 +1,106 @@ +# Simplified version of aiohttp's StaticResource with support for index.html +# https://github.com/aio-libs/aiohttp/blob/v3.6.2/aiohttp/web_urldispatcher.py#L496-L678 +# Licensed under Apache 2.0 +from typing import Callable, Awaitable, Tuple, Optional, Union, Dict, Set, Iterator, Any +from pathlib import Path, PurePath + +from aiohttp.web import (Request, StreamResponse, FileResponse, ResourceRoute, AbstractResource, + AbstractRoute, UrlMappingMatchInfo, HTTPNotFound, HTTPForbidden) +from aiohttp.abc import AbstractMatchInfo +from yarl import URL + +Handler = Callable[[Request], Awaitable[StreamResponse]] + + +class StaticResource(AbstractResource): + def __init__(self, prefix: str, directory: Union[str, PurePath], *, name: Optional[str] = None, + error_path: Optional[str] = "index.html", chunk_size: int = 256 * 1024) -> None: + super().__init__(name=name) + try: + directory = Path(directory).resolve() + if not directory.is_dir(): + raise ValueError("Not a directory") + except (FileNotFoundError, ValueError) as error: + raise ValueError(f"No directory exists at '{directory}'") from error + self._directory = directory + self._chunk_size = chunk_size + self._prefix = prefix + self._error_file = (directory / error_path) if error_path else None + + self._routes = { + "GET": ResourceRoute("GET", self._handle, self), + "HEAD": ResourceRoute("HEAD", self._handle, self), + } + + @property + def canonical(self) -> str: + return self._prefix + + def add_prefix(self, prefix: str) -> None: + assert prefix.startswith("/") + assert not prefix.endswith("/") + assert len(prefix) > 1 + self._prefix = prefix + self._prefix + + def raw_match(self, prefix: str) -> bool: + return False + + def url_for(self, *, filename: Union[str, Path]) -> URL: + if isinstance(filename, Path): + filename = str(filename) + while filename.startswith("/"): + filename = filename[1:] + return URL.build(path=f"{self._prefix}/{filename}") + + def get_info(self) -> Dict[str, Any]: + return { + "directory": self._directory, + "prefix": self._prefix, + } + + def set_options_route(self, handler: Handler) -> None: + if "OPTIONS" in self._routes: + raise RuntimeError("OPTIONS route was set already") + self._routes["OPTIONS"] = ResourceRoute("OPTIONS", handler, self) + + async def resolve(self, request: Request) -> Tuple[Optional[AbstractMatchInfo], Set[str]]: + path = request.rel_url.raw_path + method = request.method + allowed_methods = set(self._routes) + if not path.startswith(self._prefix): + return None, set() + + if method not in allowed_methods: + return None, allowed_methods + + return UrlMappingMatchInfo({ + "filename": URL.build(path=path[len(self._prefix):], encoded=True).path + }, self._routes[method]), allowed_methods + + def __len__(self) -> int: + return len(self._routes) + + def __iter__(self) -> Iterator[AbstractRoute]: + return iter(self._routes.values()) + + async def _handle(self, request: Request) -> StreamResponse: + try: + filename = Path(request.match_info["filename"]) + if not filename.anchor: + filepath = (self._directory / filename).resolve() + if filepath.is_file(): + return FileResponse(filepath, chunk_size=self._chunk_size) + index_path = (self._directory / filename / "index.html").resolve() + if index_path.is_file(): + return FileResponse(index_path, chunk_size=self._chunk_size) + except (ValueError, FileNotFoundError) as error: + raise HTTPNotFound() from error + except HTTPForbidden: + raise + except Exception as error: + request.app.logger.exception("Error while trying to serve static file") + raise HTTPNotFound() from error + + def __repr__(self) -> str: + name = f"'{self.name}'" if self.name is not None else "" + return f" {self._directory!r}>" diff --git a/web/.eslintrc.json b/web/.eslintrc.json new file mode 100644 index 0000000..15cd07c --- /dev/null +++ b/web/.eslintrc.json @@ -0,0 +1,196 @@ +{ + "env": { + "es6": true, + "browser": true + }, + "extends": [ + "eslint:recommended", + "plugin:import/errors", + "plugin:import/warnings" + ], + "parser": "@babel/eslint-parser", + "parserOptions": { + "sourceType": "module", + "requireConfigFile": false + }, + "plugins": [ + "import", + "react-hooks" + ], + "rules": { + "indent": [ + "error", + "tab" + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "double", + { + "avoidEscape": true + } + ], + "semi": [ + "error", + "never" + ], + "comma-dangle": [ + "error", + "only-multiline" + ], + "comma-spacing": [ + "error", + { + "after": true + } + ], + "eol-last": [ + "error", + "always" + ], + "no-trailing-spaces": [ + "error" + ], + "camelcase": [ + "error", + { + "properties": "always" + } + ], + "import/no-unresolved": "off", + "import/named": "error", + "import/namespace": "error", + "import/default": "error", + "import/export": "error", + "import/order": [ + "error", + { + "newlines-between": "always", + "pathGroups": [ + { + "pattern": "{.,..,../..,../../..,../../../..}/lib/**", + "group": "external" + } + ], + "groups": [ + "builtin", + "external", + [ + "internal", + "sibling", + "parent" + ], + "index" + ] + } + ], + "max-len": [ + "error", + { + "code": 100 + } + ], + "prefer-const": [ + "error", + { + "destructuring": "all", + "ignoreReadBeforeAssign": false + } + ], + "arrow-spacing": [ + "error", + { + "before": true, + "after": true + } + ], + "space-before-blocks": [ + "error", + "always" + ], + "object-curly-spacing": [ + "error", + "always" + ], + "array-bracket-spacing": [ + "error", + "never" + ], + "space-in-parens": [ + "error", + "never" + ], + "keyword-spacing": [ + "error", + { + "before": true, + "after": true + } + ], + "key-spacing": [ + "error", + { + "afterColon": true + } + ], + "template-curly-spacing": [ + "error", + "never" + ], + "no-empty": [ + "error", + { + "allowEmptyCatch": true + } + ], + "arrow-body-style": [ + "error", + "as-needed" + ], + "no-multiple-empty-lines": [ + "error", + { + "max": 1, + "maxBOF": 0, + "maxEOF": 0 + } + ], + "no-prototype-builtins": "off", + "dot-notation": [ + "error", + { + "allowKeywords": true + } + ], + "quote-props": [ + "error", + "as-needed" + ], + "no-multi-spaces": [ + "error" + ], + "space-infix-ops": [ + "error" + ], + "object-curly-newline": [ + "error", + { + "multiline": false, + "consistent": true + } + ], + "no-mixed-operators": [ + "error" + ], + "no-extra-parens": [ + "error", + "all", + { + "nestedBinaryExpressions": false + } + ] + } +} diff --git a/web/index.html b/web/index.html index 6312814..1732daf 100644 --- a/web/index.html +++ b/web/index.html @@ -5,15 +5,15 @@ Maunium sticker picker - - - + + + - + - + diff --git a/web/lib/common/preact.module-9c264606.js b/web/lib/common/preact.module-9c264606.js new file mode 100644 index 0000000..ae52298 --- /dev/null +++ b/web/lib/common/preact.module-9c264606.js @@ -0,0 +1,3 @@ +var n,u,i,t,o,r,f={},e=[],c=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function s(n,l){for(var u in l)n[u]=l[u];return n}function a(n){var l=n.parentNode;l&&l.removeChild(n);}function h(n,l,u){var i,t,o,r=arguments,f={};for(o in l)"key"==o?i=l[o]:"ref"==o?t=l[o]:f[o]=l[o];if(arguments.length>3)for(u=[u],o=3;o1&&T(t,l,u),l=x(u,t,t,n.__k,null,t.__e,l),"function"==typeof n.type&&(n.__d=l)));}function $(l,u,i,t,o,r,f,e,c){var a,h,v,y,_,w,k,g,b,x,A,P=u.type;if(void 0!==u.constructor)return null;null!=i.__h&&(c=i.__h,e=u.__e=i.__e,u.__h=null,r=[e]),(a=n.__b)&&a(u);try{n:if("function"==typeof P){if(g=u.props,b=(a=P.contextType)&&t[a.__c],x=a?b?b.props.value:a.__:t,i.__c?k=(h=u.__c=i.__c).__=h.__E:("prototype"in P&&P.prototype.render?u.__c=h=new P(g,x):(u.__c=h=new d(g,x),h.constructor=P,h.render=M),b&&b.sub(h),h.props=g,h.state||(h.state={}),h.context=x,h.__n=t,v=h.__d=!0,h.__h=[]),null==h.__s&&(h.__s=h.state),null!=P.getDerivedStateFromProps&&(h.__s==h.state&&(h.__s=s({},h.__s)),s(h.__s,P.getDerivedStateFromProps(g,h.__s))),y=h.props,_=h.state,v)null==P.getDerivedStateFromProps&&null!=h.componentWillMount&&h.componentWillMount(),null!=h.componentDidMount&&h.__h.push(h.componentDidMount);else {if(null==P.getDerivedStateFromProps&&g!==y&&null!=h.componentWillReceiveProps&&h.componentWillReceiveProps(g,x),!h.__e&&null!=h.shouldComponentUpdate&&!1===h.shouldComponentUpdate(g,h.__s,x)||u.__v===i.__v){h.props=g,h.state=h.__s,u.__v!==i.__v&&(h.__d=!1),h.__v=u,u.__e=i.__e,u.__k=i.__k,h.__h.length&&f.push(h),T(u,e,l);break n}null!=h.componentWillUpdate&&h.componentWillUpdate(g,h.__s,x),null!=h.componentDidUpdate&&h.__h.push(function(){h.componentDidUpdate(y,_,w);});}h.context=x,h.props=g,h.state=h.__s,(a=n.__r)&&a(u),h.__d=!1,h.__v=u,h.__P=l,a=h.render(h.props,h.state,h.context),h.state=h.__s,null!=h.getChildContext&&(t=s(s({},t),h.getChildContext())),v||null==h.getSnapshotBeforeUpdate||(w=h.getSnapshotBeforeUpdate(y,_)),A=null!=a&&a.type==p&&null==a.key?a.props.children:a,m(l,Array.isArray(A)?A:[A],u,i,t,o,r,f,e,c),h.base=u.__e,u.__h=null,h.__h.length&&f.push(h),k&&(h.__E=h.__=null),h.__e=!1;}else null==r&&u.__v===i.__v?(u.__k=i.__k,u.__e=i.__e):u.__e=H(i.__e,u,i,t,o,r,f,c);(a=n.diffed)&&a(u);}catch(l){u.__v=null,(c||null!=r)&&(u.__e=e,u.__h=!!c,r[r.indexOf(e)]=null),n.__e(l,u,i);}return u.__e}function j(l,u){n.__c&&n.__c(u,l),l.some(function(u){try{l=u.__h,u.__h=[],l.some(function(n){n.call(u);});}catch(l){n.__e(l,u.__v);}});}function H(n,l,u,i,t,o,r,c){var s,a,h,v,y,p=u.props,d=l.props;if(t="svg"===l.type||t,null!=o)for(s=0;s3)for(u=[u],o=3;o1&&N(t,l,u),l=x(u,t,t,n.__k,null,t.__e,l),"function"==typeof n.type&&(n.__d=l)));}function T(l,u,i,t,o,r,f,e,c){var a,v,h,y,_,w,k,m,b,x,A,P=u.type;if(void 0!==u.constructor)return null;(a=n.__b)&&a(u);try{n:if("function"==typeof P){if(m=u.props,b=(a=P.contextType)&&t[a.__c],x=a?b?b.props.value:a.__:t,i.__c?k=(v=u.__c=i.__c).__=v.__E:("prototype"in P&&P.prototype.render?u.__c=v=new P(m,x):(u.__c=v=new d(m,x),v.constructor=P,v.render=L),b&&b.sub(v),v.props=m,v.state||(v.state={}),v.context=x,v.__n=t,h=v.__d=!0,v.__h=[]),null==v.__s&&(v.__s=v.state),null!=P.getDerivedStateFromProps&&(v.__s==v.state&&(v.__s=s({},v.__s)),s(v.__s,P.getDerivedStateFromProps(m,v.__s))),y=v.props,_=v.state,h)null==P.getDerivedStateFromProps&&null!=v.componentWillMount&&v.componentWillMount(),null!=v.componentDidMount&&v.__h.push(v.componentDidMount);else {if(null==P.getDerivedStateFromProps&&m!==y&&null!=v.componentWillReceiveProps&&v.componentWillReceiveProps(m,x),!v.__e&&null!=v.shouldComponentUpdate&&!1===v.shouldComponentUpdate(m,v.__s,x)||u.__v===i.__v){v.props=m,v.state=v.__s,u.__v!==i.__v&&(v.__d=!1),v.__v=u,u.__e=i.__e,u.__k=i.__k,v.__h.length&&f.push(v),N(u,e,l);break n}null!=v.componentWillUpdate&&v.componentWillUpdate(m,v.__s,x),null!=v.componentDidUpdate&&v.__h.push(function(){v.componentDidUpdate(y,_,w);});}v.context=x,v.props=m,v.state=v.__s,(a=n.__r)&&a(u),v.__d=!1,v.__v=u,v.__P=l,a=v.render(v.props,v.state,v.context),v.state=v.__s,null!=v.getChildContext&&(t=s(s({},t),v.getChildContext())),h||null==v.getSnapshotBeforeUpdate||(w=v.getSnapshotBeforeUpdate(y,_)),A=null!=a&&a.type==p&&null==a.key?a.props.children:a,g(l,Array.isArray(A)?A:[A],u,i,t,o,r,f,e,c),v.base=u.__e,v.__h.length&&f.push(v),k&&(v.__E=v.__=null),v.__e=!1;}else null==r&&u.__v===i.__v?(u.__k=i.__k,u.__e=i.__e):u.__e=j(i.__e,u,i,t,o,r,f,c);(a=n.diffed)&&a(u);}catch(l){u.__v=null,n.__e(l,u,i);}return u.__e}function $(l,u){n.__c&&n.__c(u,l),l.some(function(u){try{l=u.__h,u.__h=[],l.some(function(n){n.call(u);});}catch(l){n.__e(l,u.__v);}});}function j(n,l,u,i,t,o,r,c){var s,a,v,h,y,p=u.props,d=l.props;if(t="svg"===l.type||t,null!=o)for(s=0;s=5&&((e||!n&&5===r)&&(h.push(r,0,e,s),r=6),n&&(h.push(r,n,0,s),r=6)),e="";},a=0;a"===t?(r=1,e=""):e=t+e[0]:u?t===u?u="":e+=t:'"'===t||"'"===t?u=t:">"===t?(p(),r=1):r&&("="===t?(r=5,s=e,e=""):"/"===t&&(r<5||">"===n[a][l+1])?(p(),3===r&&(h=h[0]),r=h,(h=h[0]).push(2,0,r),r=0):" "===t||"\t"===t||"\n"===t||"\r"===t?(p(),r=2):e+=t),3===r&&"!--"===e&&(r=4,h=h[0]);}return p(),h}(s)),r),arguments,[])).length>1?r:r[0]} +var n=function(t,s,r,e){var u;s[0]=0;for(var h=1;h=5&&((e||!n&&5===r)&&(h.push(r,0,e,s),r=6),n&&(h.push(r,n,0,s),r=6)),e="";},a=0;a"===t?(r=1,e=""):e=t+e[0]:u?t===u?u="":e+=t:'"'===t||"'"===t?u=t:">"===t?(p(),r=1):r&&("="===t?(r=5,s=e,e=""):"/"===t&&(r<5||">"===n[a][l+1])?(p(),3===r&&(h=h[0]),r=h,(h=h[0]).push(2,0,r),r=0):" "===t||"\t"===t||"\n"===t||"\r"===t?(p(),r=2):e+=t),3===r&&"!--"===e&&(r=4,h=h[0]);}return p(),h}(s)),r),arguments,[])).length>1?r:r[0]} -var m$1=e$1.bind(v); +var m=e.bind(h); -export { d as Component, v as h, m$1 as html, M as render }; +export { m as html }; diff --git a/web/lib/preact/hooks.js b/web/lib/preact/hooks.js new file mode 100644 index 0000000..092ac43 --- /dev/null +++ b/web/lib/preact/hooks.js @@ -0,0 +1,5 @@ +import { n } from '../common/preact.module-9c264606.js'; + +var t,u,r,o=0,i=[],c=n.__r,f=n.diffed,e=n.__c,a=n.unmount;function v(t,r){n.__h&&n.__h(u,t,o||r),o=0;var i=u.__H||(u.__H={__:[],__h:[]});return t>=i.__.length&&i.__.push({}),i.__[t]}function m(n){return o=1,p(k,n)}function p(n,r,o){var i=v(t++,2);return i.t=n,i.__c||(i.__=[o?o(r):k(void 0,r),function(n){var t=i.t(i.__[0],n);i.__[0]!==t&&(i.__=[t,i.__[1]],i.__c.setState({}));}],i.__c=u),i.__}function y(r,o){var i=v(t++,3);!n.__s&&j(i.__H,o)&&(i.__=r,i.__H=o,u.__H.__h.push(i));}function l(r,o){var i=v(t++,4);!n.__s&&j(i.__H,o)&&(i.__=r,i.__H=o,u.__h.push(i));}function h(n){return o=5,_(function(){return {current:n}},[])}function s(n,t,u){o=6,l(function(){"function"==typeof n?n(t()):n&&(n.current=t());},null==u?u:u.concat(n));}function _(n,u){var r=v(t++,7);return j(r.__H,u)&&(r.__=n(),r.__H=u,r.__h=n),r.__}function A(n,t){return o=8,_(function(){return n},t)}function F(n){var r=u.context[n.__c],o=v(t++,9);return o.__c=n,r?(null==o.__&&(o.__=!0,r.sub(u)),r.props.value):n.__}function T(t,u){n.useDebugValue&&n.useDebugValue(u?u(t):t);}function d(n){var r=v(t++,10),o=m();return r.__=n,u.componentDidCatch||(u.componentDidCatch=function(n){r.__&&r.__(n),o[1](n);}),[o[0],function(){o[1](void 0);}]}function q(){i.forEach(function(t){if(t.__P)try{t.__H.__h.forEach(b),t.__H.__h.forEach(g),t.__H.__h=[];}catch(u){t.__H.__h=[],n.__e(u,t.__v);}}),i=[];}n.__r=function(n){c&&c(n),t=0;var r=(u=n.__c).__H;r&&(r.__h.forEach(b),r.__h.forEach(g),r.__h=[]);},n.diffed=function(t){f&&f(t);var u=t.__c;u&&u.__H&&u.__H.__h.length&&(1!==i.push(u)&&r===n.requestAnimationFrame||((r=n.requestAnimationFrame)||function(n){var t,u=function(){clearTimeout(r),x&&cancelAnimationFrame(t),setTimeout(n);},r=setTimeout(u,100);x&&(t=requestAnimationFrame(u));})(q));},n.__c=function(t,u){u.some(function(t){try{t.__h.forEach(b),t.__h=t.__h.filter(function(n){return !n.__||g(n)});}catch(r){u.some(function(n){n.__h&&(n.__h=[]);}),u=[],n.__e(r,t.__v);}}),e&&e(t,u);},n.unmount=function(t){a&&a(t);var u=t.__c;if(u&&u.__H)try{u.__H.__.forEach(b);}catch(t){n.__e(t,u.__v);}};var x="function"==typeof requestAnimationFrame;function b(n){"function"==typeof n.__c&&n.__c();}function g(n){n.__c=n.__();}function j(n,t){return !n||n.length!==t.length||t.some(function(t,u){return t!==n[u]})}function k(n,t){return "function"==typeof t?t(n):t} + +export { A as useCallback, F as useContext, T as useDebugValue, y as useEffect, d as useErrorBoundary, s as useImperativeHandle, l as useLayoutEffect, _ as useMemo, p as useReducer, h as useRef, m as useState }; diff --git a/web/package.json b/web/package.json index 66d3722..fb1ee59 100644 --- a/web/package.json +++ b/web/package.json @@ -12,7 +12,8 @@ }, "snowpack": { "install": [ - "htm/preact" + "htm/preact", + "preact/hooks" ], "installOptions": { "sourceMap": false, @@ -22,10 +23,15 @@ }, "dependencies": { "htm": "^3.0.4", - "preact": "^10.4.8", - "snowpack": "^2.10.3" + "preact": "^10.5.5", + "snowpack": "^2.16.1" }, "devDependencies": { - "node-sass": "^4.14.1" + "@babel/core": "^7.12.3", + "@babel/eslint-parser": "^7.12.1", + "eslint": "^7.12.1", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-react-hooks": "^4.2.0", + "node-sass": "^5.0.0" } } diff --git a/web/setup/index.html b/web/setup/index.html new file mode 100644 index 0000000..ab57406 --- /dev/null +++ b/web/setup/index.html @@ -0,0 +1,23 @@ + + + + + + Setup - Maunium sticker picker + + + + + + + + + + + + + + + + + diff --git a/web/src/Button.js b/web/src/Button.js new file mode 100644 index 0000000..3523e45 --- /dev/null +++ b/web/src/Button.js @@ -0,0 +1,30 @@ +// maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +// Copyright (C) 2020 Tulir Asokan +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +import { html } from "../lib/htm/preact.js" + +const Button = ({ + type = "button", class: className = "", children, + variant = "filled", size = "normal", + ...customProps +}) => { + const props = { + class: `mau-button variant-${variant} size-${size} ${className}`, + type, ...customProps, + } + return html`` +} + +export default Button diff --git a/web/src/spinner.js b/web/src/Spinner.js similarity index 93% rename from web/src/spinner.js rename to web/src/Spinner.js index e89dd02..885794f 100644 --- a/web/src/spinner.js +++ b/web/src/Spinner.js @@ -15,7 +15,7 @@ // along with this program. If not, see . import { html } from "../lib/htm/preact.js" -export const Spinner = ({ size = 40, noCenter = false, noMargin = false, green = false }) => { +const Spinner = ({ size = 40, noCenter = false, noMargin = false, green = false }) => { let margin = 0 if (!isNaN(+size)) { size = +size @@ -39,3 +39,5 @@ export const Spinner = ({ size = 40, noCenter = false, noMargin = false, green = } return comp } + +export default Spinner diff --git a/web/src/setup/LoginView.js b/web/src/setup/LoginView.js new file mode 100644 index 0000000..ce5abe7 --- /dev/null +++ b/web/src/setup/LoginView.js @@ -0,0 +1,215 @@ +// maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +// Copyright (C) 2020 Tulir Asokan +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +import { useEffect, useLayoutEffect, useRef, useState } from "../../lib/preact/hooks.js" +import { html } from "../../lib/htm/preact.js" + +import { + getLoginFlows, + loginMatrix, + requestIntegrationToken, + requestOpenIDToken, + resolveWellKnown, +} from "./matrix-api.js" +import Button from "../Button.js" +import Spinner from "../Spinner.js" + +const query = Object.fromEntries(location.search + .substr(1).split("&") + .map(part => part.split("=")) + .map(([key, value = ""]) => [key, value])) + +const LoginView = ({ onLoggedIn }) => { + const usernameWrapperRef = useRef() + const usernameRef = useRef() + const serverRef = useRef() + const passwordRef = useRef() + const previousServerValue = useRef() + const [loading, setLoading] = useState(false) + const [userIDFocused, setUserIDFocused] = useState(false) + const [supportedFlows, setSupportedFlows] = useState(["m.login.password"]) + const [username, setUsername] = useState("") + const [server, setServer] = useState("") + const [serverURL, setServerURL] = useState("") + const [password, setPassword] = useState("") + const [error, setError] = useState(null) + + const keyDown = evt => { + if ((evt.target.name === "username" && evt.key === ":") || evt.key === "Enter") { + if (evt.target.name === "username") { + serverRef.current.focus() + } else if (evt.target.name === "server") { + passwordRef.current.focus() + } + evt.preventDefault() + } else if (evt.target.name === "server" && !evt.target.value && evt.key === "Backspace") { + usernameRef.current.focus() + } + } + + const paste = evt => { + if (usernameRef.current.value !== "" || serverRef.current.value !== "") { + return + } + + let data = evt.clipboardData.getData("text") + if (data.startsWith("@")) { + data = data.substr(1) + } + const separator = data.indexOf(":") + if (separator === -1) { + setUsername(data) + } else { + setUsername(data.substr(0, separator)) + setServer(data.substr(separator + 1)) + serverRef.current.focus() + } + evt.preventDefault() + } + + useLayoutEffect(() => usernameRef.current.focus(), []) + const onFocus = () => setUserIDFocused(true) + const onBlur = () => { + setUserIDFocused(false) + if (previousServerValue.current !== server && server) { + previousServerValue.current = server + setSupportedFlows(null) + setError(null) + resolveWellKnown(server).then(url => { + setServerURL(url) + localStorage.mxServerName = server + localStorage.mxHomeserver = url + return getLoginFlows(url) + }).then(flows => { + setSupportedFlows(flows) + }).catch(err => { + setError(err.message) + setSupportedFlows(["m.login.password"]) + }) + } + } + + useEffect(() => { + if (localStorage.mxHomeserver && query.loginToken) { + console.log("Found homeserver in localstorage and loginToken in query, " + + "attempting SSO token login") + setError(null) + setLoading(true) + submit(query.loginToken, localStorage.mxHomeserver) + .catch(err => console.error("Fatal error:", err)) + .finally(() => setLoading(false)) + const url = new URL(location.href) + url.searchParams.delete("loginToken") + history.replaceState({}, document.title, url.toString()) + } + }, []) + + const submit = async (token, serverURLOverride) => { + let authInfo + if (token) { + authInfo = { + type: "m.login.token", + token, + } + } else { + authInfo = { + type: "m.login.password", + identifier: { + type: "m.id.user", + user: username, + }, + password, + } + } + try { + const actualServerURL = serverURLOverride || serverURL + const [accessToken, userID, realURL] = await loginMatrix(actualServerURL, authInfo) + console.log(userID, realURL) + const openIDToken = await requestOpenIDToken(realURL, userID, accessToken) + console.log(openIDToken) + const integrationData = await requestIntegrationToken(openIDToken) + console.log(integrationData) + localStorage.mxAccessToken = accessToken + localStorage.mxUserID = userID + localStorage.accessToken = integrationData.token + onLoggedIn() + } catch (err) { + setError(err.message) + } + } + + const onSubmit = evt => { + evt.preventDefault() + setError(null) + setLoading(true) + submit() + .catch(err => console.error("Fatal error:", err)) + .finally(() => setLoading(false)) + } + + const startSSOLogin = () => { + const redir = encodeURIComponent(location.href) + location.href = `${serverURL}/_matrix/client/r0/login/sso/redirect?redirectUrl=${redir}` + } + + const usernameWrapperClick = evt => evt.target === usernameWrapperRef.current + && usernameRef.current.focus() + + const ssoButton = html` + <${Button} type="button" disabled=${!serverURL} onClick=${startSSOLogin} + title=${!serverURL ? "Enter your server name before using SSO" : undefined}> + ${loading ? html`<${Spinner} size=30/>` : "Log in with SSO"} + + ` + + const disablePwLogin = !username || !server || !serverURL + const loginButton = html` + <${Button} type="submit" disabled=${disablePwLogin} + title=${disablePwLogin ? "Fill out the form before submitting" : undefined}> + ${loading ? html`<${Spinner} size=30/>` : "Log in"} + + ` + + return html` +
+ +
` +} + +export default LoginView diff --git a/web/src/setup/index.js b/web/src/setup/index.js new file mode 100644 index 0000000..efa122e --- /dev/null +++ b/web/src/setup/index.js @@ -0,0 +1,20 @@ +// maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +// Copyright (C) 2020 Tulir Asokan +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +import { html, render } from "../../lib/htm/preact.js" + +import LoginView from "./LoginView.js" + +render(html`<${LoginView} onLoggedIn=${() => console.log("Logged in")}/>`, document.body) diff --git a/web/src/setup/matrix-api.js b/web/src/setup/matrix-api.js new file mode 100644 index 0000000..09ef99b --- /dev/null +++ b/web/src/setup/matrix-api.js @@ -0,0 +1,102 @@ +// maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +// Copyright (C) 2020 Tulir Asokan +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +import { tryFetch, integrationPrefix } from "./tryGet.js" + +export const resolveWellKnown = async (server) => { + try { + const resp = await fetch(`https://${server}/.well-known/matrix/client`) + const data = await resp.json() + let url = data["m.homeserver"].base_url + if (url.endsWith("/")) { + url = url.slice(0, -1) + } + return url + } catch (err) { + console.error("Resolution failed:", err) + throw new Error(`Failed to resolve Matrix URL for ${server}`) + } +} + +export const getLoginFlows = async (address) => { + const data = await tryFetch(`${address}/_matrix/client/r0/login`, {}, + { service: address, requestType: "get login flows" }) + const flows = [] + for (const flow of data.flows) { + flows.push(flow.type) + } + return flows +} + +export const loginMatrix = async (address, authInfo) => { + const data = await tryFetch(`${address}/_matrix/client/r0/login`, { + method: "POST", + body: JSON.stringify({ + ...authInfo, + /* eslint-disable camelcase */ + device_id: "maunium-stickerpicker", + initial_device_display_name: "maunium-stickerpicker", + /* eslint-enable camelcase */ + }), + headers: { + "Content-Type": "application/json", + }, + }, { + service: address, + requestType: "login", + }) + if (data.well_known && data.well_known["m.homeserver"]) { + address = data.well_known["m.homeserver"].base_url || address + if (address.endsWith("/")) { + address = address.slice(0, -1) + } + } + return [data.access_token, data.user_id, address] +} + +export const requestOpenIDToken = (address, userID, accessToken) => tryFetch( + `${address}/_matrix/client/r0/user/${userID}/openid/request_token`, + { + method: "POST", + body: "{}", + headers: { + Authorization: `Bearer ${accessToken}`, + "Content-Type": "application/json", + }, + }, + { + service: "OpenID", + requestType: "token", + }, +) + +export const requestIntegrationToken = tokenData => tryFetch( + `${integrationPrefix}/account/register`, { + method: "POST", + body: JSON.stringify(tokenData), + headers: { + "Content-Type": "application/json", + }, + }, + { + service: "sticker server", + requestType: "register", + }) + +export const logout = () => tryFetch(`${integrationPrefix}/account/logout`, { method: "POST" }, { + service: "sticker server", + requestType: "logout", +}) diff --git a/web/src/setup/tryGet.js b/web/src/setup/tryGet.js new file mode 100644 index 0000000..39d3680 --- /dev/null +++ b/web/src/setup/tryGet.js @@ -0,0 +1,67 @@ +// maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +// Copyright (C) 2020 Tulir Asokan +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +export const integrationPrefix = "../_matrix/integrations/v1" + +export const queryToURL = (url, query) => { + if (!Array.isArray(query)) { + query = Object.entries(query) + } + query = query.map(([key, value]) => + [key, typeof value === "string" ? value : JSON.stringify(value)]) + url = `${url}?${new URLSearchParams(query)}` + return url +} + +export const tryFetch = async (url, options, reqInfo) => { + if (options.query) { + url = queryToURL(url, options.query) + delete options.query + } + options.headers = { + Authorization: `Bearer ${localStorage.accessToken}`, + ...options.headers, + } + const reqName = `${reqInfo.service} ${reqInfo.requestType}` + let resp + try { + resp = await fetch(url, options) + } catch (err) { + console.error(reqName, "request failed:", err) + throw new Error(`Failed to contact ${reqInfo.service}`) + } + if (resp.status === 502) { + console.error("Unexpected", reqName, "request bad gateway:", await resp.text()) + throw new Error(`Failed to contact ${reqInfo.service}`) + } + if (reqInfo.raw) { + return resp + } else if (resp.status === 204) { + return + } + let data + try { + data = await resp.json() + } catch (err) { + console.error(reqName, "request JSON parse failed:", err) + throw new Error(`Invalid response from ${reqInfo.service}`) + } + if (resp.status >= 400) { + console.error("Unexpected", reqName, "request status:", resp.status, data) + throw new Error(data.error || data.message || `Invalid response from ${reqInfo.service}`) + } + return data +} diff --git a/web/src/frequently-used.js b/web/src/widget/frequently-used.js similarity index 100% rename from web/src/frequently-used.js rename to web/src/widget/frequently-used.js diff --git a/web/src/index.js b/web/src/widget/index.js similarity index 73% rename from web/src/index.js rename to web/src/widget/index.js index 5de4bd5..1859387 100644 --- a/web/src/index.js +++ b/web/src/widget/index.js @@ -13,8 +13,9 @@ // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import { html, render, Component } from "../lib/htm/preact.js" -import { Spinner } from "./spinner.js" +import { html, render, Component } from "../../lib/htm/preact.js" + +import Spinner from "../Spinner.js" import * as widgetAPI from "./widget-api.js" import * as frequent from "./frequently-used.js" @@ -24,23 +25,25 @@ const PACKS_BASE_URL = "packs" // This is updated from packs/index.json let HOMESERVER_URL = "https://matrix-client.matrix.org" +// eslint-disable-next-line max-len const makeThumbnailURL = mxc => `${HOMESERVER_URL}/_matrix/media/r0/thumbnail/${mxc.substr(6)}?height=128&width=128&method=scale` // We need to detect iOS webkit because it has a bug related to scrolling non-fixed divs // This is also used to fix scrolling to sections on Element iOS -const isMobileSafari = navigator.userAgent.match(/(iPod|iPhone|iPad)/) && navigator.userAgent.match(/AppleWebKit/) +const isMobileSafari = navigator.userAgent.match(/(iPod|iPhone|iPad)/) + && navigator.userAgent.match(/AppleWebKit/) -export const parseQuery = str => Object.fromEntries( - str.split("&") - .map(part => part.split("=")) - .map(([key, value = ""]) => [key, value])) +const query = Object.fromEntries(location.search + .substr(1).split("&") + .map(part => part.split("=")) + .map(([key, value = ""]) => [key, value])) const supportedThemes = ["light", "dark", "black"] class App extends Component { constructor(props) { super(props) - this.defaultTheme = parseQuery(location.search.substr(1)).theme + this.defaultTheme = query.theme this.state = { packs: [], loading: true, @@ -61,7 +64,8 @@ class App extends Component { this.defaultTheme = "light" } this.stickersByID = new Map(JSON.parse(localStorage.mauFrequentlyUsedStickerCache || "[]")) - this.state.frequentlyUsed.stickers = this._getStickersByID(this.state.frequentlyUsed.stickerIDs) + this.state.frequentlyUsed.stickers = this._getStickersByID( + this.state.frequentlyUsed.stickerIDs) this.imageObserver = null this.packListRef = null this.navRef = null @@ -86,12 +90,14 @@ class App extends Component { stickers, }, }) - localStorage.mauFrequentlyUsedStickerCache = JSON.stringify(stickers.map(sticker => [sticker.id, sticker])) + localStorage.mauFrequentlyUsedStickerCache = JSON.stringify( + stickers.map(sticker => [sticker.id, sticker])) } setStickersPerRow(val) { localStorage.mauStickersPerRow = val - document.documentElement.style.setProperty("--stickers-per-row", localStorage.mauStickersPerRow) + document.documentElement.style.setProperty("--stickers-per-row", + localStorage.mauStickersPerRow) this.setState({ stickersPerRow: val, }) @@ -116,20 +122,34 @@ class App extends Component { } _loadPacks(disableCache = false) { - const cache = disableCache ? "no-cache" : undefined - fetch(`${PACKS_BASE_URL}/index.json`, { cache }).then(async indexRes => { + const args = { + cache: disableCache ? "no-cache" : undefined, + headers: query.user_id && query.token ? { + Authorization: `Bearer ${query.token}`, + "X-Matrix-User-ID": query.user_id, + } : {}, + } + fetch(`${PACKS_BASE_URL}/index.json`, args).then(async indexRes => { if (indexRes.status >= 400) { - this.setState({ - loading: false, - error: indexRes.status !== 404 ? indexRes.statusText : null, - }) + try { + const errData = await indexRes.json() + this.setState({ + loading: false, + error: errData.error, + }) + } catch (err) { + this.setState({ + loading: false, + error: indexRes.status !== 404 ? indexRes.statusText : null, + }) + } return } const indexData = await indexRes.json() HOMESERVER_URL = indexData.homeserver_url || HOMESERVER_URL // TODO only load pack metadata when scrolled into view? for (const packFile of indexData.packs) { - const packRes = await fetch(`${PACKS_BASE_URL}/${packFile}`, { cache }) + const packRes = await fetch(`${PACKS_BASE_URL}/${packFile}`, args) const packData = await packRes.json() for (const sticker of packData.stickers) { this.stickersByID.set(sticker.id, sticker) @@ -140,11 +160,15 @@ class App extends Component { }) } this.updateFrequentlyUsed() - }, error => this.setState({ loading: false, error })) + }, error => this.setState({ + loading: false, + error, + })) } componentDidMount() { - document.documentElement.style.setProperty("--stickers-per-row", this.state.stickersPerRow.toString()) + document.documentElement.style.setProperty("--stickers-per-row", + this.state.stickersPerRow.toString()) this._loadPacks() this.imageObserver = new IntersectionObserver(this.observeImageIntersections, { rootMargin: "100px", @@ -226,27 +250,37 @@ class App extends Component { render() { const theme = `theme-${this.state.theme}` if (this.state.loading) { - return html`
<${Spinner} size=${80} green />
` + return html` +
+ <${Spinner} size=${80} green /> +
` } else if (this.state.error) { - return html`
-

Failed to load packs

-

${this.state.error}

-
` + return html` +
+

Failed to load packs

+

${this.state.error}

+
` } else if (this.state.packs.length === 0) { - return html`

No packs found 😿

` + return html` +

No packs found 😿

` } - return html`
- -
this.packListRef = elem}> - <${Pack} pack=${this.state.frequentlyUsed} send=${this.sendSticker} /> - ${this.state.packs.map(pack => html`<${Pack} id=${pack.id} pack=${pack} send=${this.sendSticker} />`)} - <${Settings} app=${this}/> -
-
` + return html` +
+ +
this.packListRef = elem}> + <${Pack} pack=${this.state.frequentlyUsed} send=${this.sendSticker}/> + ${this.state.packs.map(pack => html` + <${Pack} id=${pack.id} pack=${pack} send=${this.sendSticker}/>`)} + <${Settings} app=${this}/> +
+
` } } @@ -257,9 +291,9 @@ const Settings = ({ app }) => html`
- app.setStickersPerRow(evt.target.value)} /> + app.setStickersPerRow(evt.target.value)}/>
@@ -278,25 +312,34 @@ const Settings = ({ app }) => html` // open the link in the browser instead of just scrolling there, so we need to scroll manually: const scrollToSection = (evt, id) => { const pack = document.getElementById(`pack-${id}`) - pack.scrollIntoView({ block: "start", behavior: "instant" }) + pack.scrollIntoView({ + block: "start", + behavior: "instant", + }) evt.preventDefault() } -const NavBarItem = ({ pack, iconOverride = null }) => html` +const NavBarItem = ({ + pack, + iconOverride = null, +}) => html` scrollToSection(evt, pack.id)) : undefined}> + onClick=${isMobileSafari ? evt => scrollToSection(evt, pack.id) : undefined}>
${iconOverride ? html` - + ` : html` ${pack.stickers[0].body} + alt=${pack.stickers[0].body} class="visible" /> `}
` -const Pack = ({ pack, send }) => html` +const Pack = ({ + pack, + send, +}) => html`

${pack.title}

@@ -307,9 +350,12 @@ const Pack = ({ pack, send }) => html`
` -const Sticker = ({ content, send }) => html` +const Sticker = ({ + content, + send, +}) => html`
- ${content.body} + ${content.body}/
` diff --git a/web/src/widget-api.js b/web/src/widget/widget-api.js similarity index 100% rename from web/src/widget-api.js rename to web/src/widget/widget-api.js diff --git a/web/style/button.css b/web/style/button.css new file mode 100644 index 0000000..e3f8e84 --- /dev/null +++ b/web/style/button.css @@ -0,0 +1 @@ +button.mau-button{cursor:pointer;margin:.5rem 0;border-radius:.25rem;font-size:1rem;box-sizing:border-box;padding:0}button.mau-button:disabled{cursor:default}button.mau-button.size-thick{height:3rem}button.mau-button.size-normal{height:2.5rem}button.mau-button.size-thin{height:2rem}button.mau-button.variant-filled{background-color:#2e7d32;color:#fff;border:none}button.mau-button.variant-filled:hover{background-color:#005005}button.mau-button.variant-filled:disabled{background-color:#CCC;color:#212121}button.mau-button.variant-outlined{background-color:#fff;border:2px solid #2e7d32;color:#2e7d32}button.mau-button.variant-outlined:hover{background-color:#60ad5e}button.mau-button.variant-outlined:disabled{background-color:#fff;border-color:#CCC} diff --git a/web/style/button.sass b/web/style/button.sass new file mode 100644 index 0000000..853ad24 --- /dev/null +++ b/web/style/button.sass @@ -0,0 +1,60 @@ +// maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +// Copyright (C) 2020 Tulir Asokan +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +@import theme.sass + +button.mau-button + cursor: pointer + margin: .5rem 0 + border-radius: .25rem + font-size: 1rem + box-sizing: border-box + padding: 0 + + &:disabled + cursor: default + + &.size-thick + height: 3rem + + &.size-normal + height: 2.5rem + + &.size-thin + height: 2rem + + &.variant-filled + background-color: $primary + color: $primaryContrastText + border: none + + &:hover + background-color: $primaryDark + + &:disabled + background-color: $disabled + color: $text + + &.variant-outlined + background-color: $background + border: 2px solid $primary + color: $primary + + &:hover + background-color: $primaryLight + + &:disabled + background-color: $background + border-color: $disabled diff --git a/web/style/setup-login.css b/web/style/setup-login.css new file mode 100644 index 0000000..87cfbf4 --- /dev/null +++ b/web/style/setup-login.css @@ -0,0 +1 @@ +main.login-view{position:fixed;top:0;bottom:0;right:0;left:0;background-color:#2e7d32;display:flex;justify-content:space-around}main.login-view form.login-box{background-color:#fff;width:25rem;height:22.5rem;padding:2.5rem 2.5rem 2rem;margin-top:3rem;border-radius:.25rem;box-sizing:border-box;display:flex;flex-direction:column}main.login-view form.login-box.has-error{min-height:27rem;height:auto;margin-bottom:auto}main.login-view form.login-box h1{color:#2e7d32;margin:.5rem auto 3rem;font-size:1.5rem}main.login-view form.login-box .input{margin:.5rem 0;border-radius:.25rem;border:1px solid #DDD;padding:1px}main.login-view form.login-box .input:hover,main.login-view form.login-box .input:focus,main.login-view form.login-box .input.focus{border-color:#2e7d32}main.login-view form.login-box .input:focus,main.login-view form.login-box .input.focus{border-width:2px;padding:0}main.login-view form.login-box .username{display:flex;cursor:text}main.login-view form.login-box .username>input{border:none;padding:.75rem .125rem;color:#212121;min-width:0;font-size:1rem}main.login-view form.login-box .username>input:last-of-type{padding-right:.5rem;border-radius:0 .25rem .25rem 0}main.login-view form.login-box .username>input:focus{outline:none}main.login-view form.login-box .username>span{user-select:none;padding:.75rem 0;color:#212121}main.login-view form.login-box .username>span:first-of-type{padding-left:.5rem}main.login-view form.login-box .password{font-size:1rem;margin:.5rem 0;border-radius:.25rem;border:1px solid #DDD;padding:calc(.75rem + 1px) 1rem;box-sizing:border-box}main.login-view form.login-box .password:hover:not(:disabled),main.login-view form.login-box .password:focus:not(:disabled){border-color:#2e7d32}main.login-view form.login-box .password:focus{padding:0.75rem calc(1rem - 1px);border-width:2px;outline:none}main.login-view form.login-box .button-group{display:flex;gap:4px}main.login-view form.login-box .button-group button{width:100%}main.login-view form.login-box .error{padding:1rem;border-radius:.25rem;border:2px solid #B71C1C;background-color:#F7A9A1;margin:.5rem 0;width:100%;box-sizing:border-box} diff --git a/web/style/setup-login.sass b/web/style/setup-login.sass new file mode 100644 index 0000000..1981ee7 --- /dev/null +++ b/web/style/setup-login.sass @@ -0,0 +1,105 @@ +// maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +// Copyright (C) 2020 Tulir Asokan +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +@import theme.sass + +main.login-view + position: fixed + top: 0 + bottom: 0 + right: 0 + left: 0 + background-color: $primary + display: flex + justify-content: space-around + + form.login-box + background-color: $background + width: 25rem + height: 22.5rem + padding: 2.5rem 2.5rem 2rem + margin-top: 3rem + border-radius: .25rem + box-sizing: border-box + display: flex + flex-direction: column + + &.has-error + min-height: 27rem + height: auto + margin-bottom: auto + + h1 + color: $primary + margin: .5rem auto 3rem + font-size: 1.5rem + + .input + margin: .5rem 0 + border-radius: .25rem + border: 1px solid $border + padding: 1px + + &:hover, &:focus, &.focus + border-color: $primary + + &:focus, &.focus + border-width: 2px + padding: 0 + + .username + display: flex + cursor: text + + & > input + border: none + padding: .75rem .125rem + color: $text + min-width: 0 + font-size: 1rem + + &:last-of-type + padding-right: .5rem + border-radius: 0 .25rem .25rem 0 + + &:focus + outline: none + + & > span + user-select: none + padding: .75rem 0 + color: $text + + &:first-of-type + padding-left: .5rem + + .password + @include input + + .button-group + display: flex + gap: 4px + + button + width: 100% + + .error + padding: 1rem + border-radius: .25rem + border: 2px solid $errorDark + background-color: $error + margin: .5rem 0 + width: 100% + box-sizing: border-box diff --git a/web/style/setup.css b/web/style/setup.css new file mode 100644 index 0000000..53d162d --- /dev/null +++ b/web/style/setup.css @@ -0,0 +1 @@ +body{font-family:sans-serif} diff --git a/web/style/setup.sass b/web/style/setup.sass new file mode 100644 index 0000000..bcd43f5 --- /dev/null +++ b/web/style/setup.sass @@ -0,0 +1,18 @@ +// maunium-stickerpicker - A fast and simple Matrix sticker picker widget. +// Copyright (C) 2020 Tulir Asokan +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +body + font-family: sans-serif diff --git a/web/style/theme.css b/web/style/theme.css new file mode 100644 index 0000000..e69de29 diff --git a/web/style/theme.sass b/web/style/theme.sass new file mode 100644 index 0000000..3a7638d --- /dev/null +++ b/web/style/theme.sass @@ -0,0 +1,33 @@ +// Material UI green 800 +$primary: #2e7d32 +$primaryDark: #005005 +$primaryLight: #60ad5e +// Material UI blue 700 +$secondary: #1976d2 +$secondaryDark: #004ba0 +$secondaryLight: #63a4ff + +$error: #F7A9A1 +$errorDark: #B71C1C + +$primaryContrastText: white +$background: white +$text: #212121 +$border: #DDD +$disabled: #CCC + +@mixin input + font-size: 1rem + margin: .5rem 0 + border-radius: .25rem + border: 1px solid $border + padding: calc(.75rem + 1px) 1rem + box-sizing: border-box + + &:hover:not(:disabled), &:focus:not(:disabled) + border-color: $primary + + &:focus + padding: .75rem calc(1rem - 1px) + border-width: 2px + outline: none diff --git a/web/style/index.css b/web/style/widget.css similarity index 100% rename from web/style/index.css rename to web/style/widget.css diff --git a/web/style/index.sass b/web/style/widget.sass similarity index 100% rename from web/style/index.sass rename to web/style/widget.sass diff --git a/web/yarn.lock b/web/yarn.lock index 52a7954..f6cc97a 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -2,23 +2,143 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== dependencies: "@babel/highlight" "^7.10.4" -"@babel/helper-plugin-utils@^7.10.4": +"@babel/core@^7.12.3": + version "7.12.3" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.3.tgz#1b436884e1e3bff6fb1328dc02b208759de92ad8" + integrity sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.1" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.1" + "@babel/parser" "^7.12.3" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/eslint-parser@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.12.1.tgz#b3ae38e6174d2d0d2d00d2dcd919b4086b6bb8f0" + integrity sha512-cc7WQHnHQY3++/bghgbDtPx+5bf6xTsokyGzV6Qzh65NLz/unv+mPQuACkQ9GFhIhcTFv6yqwNaEcfX7EkOEsg== + dependencies: + eslint-scope "5.1.0" + eslint-visitor-keys "^1.3.0" + semver "^6.3.0" + +"@babel/generator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.1.tgz#0d70be32bdaa03d7c51c8597dda76e0df1f15468" + integrity sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg== + dependencies: + "@babel/types" "^7.12.1" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-function-name@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" - integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== + dependencies: + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-get-function-arity@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-member-expression-to-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz#fba0f2fcff3fba00e6ecb664bb5e6e26e2d6165c" + integrity sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ== + dependencies: + "@babel/types" "^7.12.1" + +"@babel/helper-module-imports@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.1.tgz#1644c01591a15a2f084dd6d092d9430eb1d1216c" + integrity sha512-ZeC1TlMSvikvJNy1v/wPIazCu3NdOwgYZLIkmIyAsGhqkNpiDoQQRmaCK8YP4Pq3GPTLPV9WXaPCJKvx06JxKA== + dependencies: + "@babel/types" "^7.12.1" + +"@babel/helper-module-transforms@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" + integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== + dependencies: + "@babel/helper-module-imports" "^7.12.1" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-simple-access" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/helper-validator-identifier" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + lodash "^4.17.19" + +"@babel/helper-optimise-call-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" + integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-replace-supers@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.1.tgz#f15c9cc897439281891e11d5ce12562ac0cf3fa9" + integrity sha512-zJjTvtNJnCFsCXVi5rUInstLd/EIVNmIKA1Q9ynESmMBWPWd+7sdR+G4/wdu+Mppfep0XLyG2m7EBPvjCeFyrw== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.12.1" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + +"@babel/helper-simple-access@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" + integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== + dependencies: + "@babel/types" "^7.12.1" + +"@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== + dependencies: + "@babel/types" "^7.11.0" "@babel/helper-validator-identifier@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== +"@babel/helpers@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.1.tgz#8a8261c1d438ec18cb890434df4ec768734c1e79" + integrity sha512-9JoDSBGoWtmbay98efmT2+mySkwjzeFeAL9BuWNoVQpkPFQF8SIIFUfY5os9u8wVzglzoiPRSW7cuJmBDUt43g== + dependencies: + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + "@babel/highlight@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" @@ -28,12 +148,59 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/plugin-syntax-import-meta@^7.10.4": +"@babel/parser@^7.10.4", "@babel/parser@^7.12.1", "@babel/parser@^7.12.3": + version "7.12.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.3.tgz#a305415ebe7a6c7023b40b5122a0662d928334cd" + integrity sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw== + +"@babel/template@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/traverse@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.1.tgz#941395e0c5cc86d5d3e75caa095d3924526f0c1e" + integrity sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.1" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.12.1" + "@babel/types" "^7.12.1" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + +"@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.1.tgz#e109d9ab99a8de735be287ee3d6a9947a190c4ae" + integrity sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + +"@eslint/eslintrc@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.1.tgz#f72069c330461a06684d119384435e12a5d76e3c" + integrity sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.19" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" "@npmcli/move-file@^1.0.1": version "1.0.1" @@ -90,6 +257,14 @@ is-module "^1.0.0" resolve "^1.17.0" +"@rollup/plugin-replace@^2.3.3": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.3.4.tgz#7dd84c17755d62b509577f2db37eb524d7ca88ca" + integrity sha512-waBhMzyAtjCL1GwZes2jaE9MjuQ/DQF2BatH3fRivUF3z0JBFrU0U6iBNC/4WR+2rLKhaAhPWDNPYp4mI6RqdQ== + dependencies: + "@rollup/pluginutils" "^3.1.0" + magic-string "^0.25.7" + "@rollup/pluginutils@^3.0.4", "@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" @@ -99,44 +274,22 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@sindresorhus/is@^3.1.1": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-3.1.2.tgz#548650de521b344e3781fbdb0ece4aa6f729afb8" - integrity sha512-JiX9vxoKMmu8Y3Zr2RVathBL1Cdu4Nt4MuNWemt1Nc06A0RAin9c5FArkhGsyMBWfCu4zj+9b+GxtjAnE4qqLQ== - -"@snowpack/plugin-build-script@^2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@snowpack/plugin-build-script/-/plugin-build-script-2.0.6.tgz#95c85cc6c4c53763a91a2d170633918ecd0d3cc8" - integrity sha512-qtvXQq54MaBYJrCTa+DaK/KzUXYBkRukaGzIdhpqW/xzOknCjpufiQIy0VUzxwRQk0OlLC6/h3sV1hSMsoTVJw== +"@snowpack/plugin-build-script@^2.0.11": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@snowpack/plugin-build-script/-/plugin-build-script-2.0.11.tgz#50eb2b6127c8863cbbc6a3105042713e16818869" + integrity sha512-bLi7W0ry5OAhCEGuBL3PdLchWU+WaXa2aJYSJapt4FsfhUiNwi+ua1qiZ0syaXXfRq/2jx9eEkx4G7TGB8Kvsg== dependencies: execa "^4.0.3" npm-run-path "^4.0.1" -"@snowpack/plugin-run-script@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@snowpack/plugin-run-script/-/plugin-run-script-2.1.1.tgz#f0f71cab5e0a482dfceb3306ae3e7d9cab859746" - integrity sha512-ZLOcu6n+eLDNxTxKlKK/+smn9PWr/epUKGPw8tBHr3qdKQ64WNpCVr0jnafanzWpzQWD8k92J8POfskKMuEI5Q== +"@snowpack/plugin-run-script@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@snowpack/plugin-run-script/-/plugin-run-script-2.2.0.tgz#26b434af5f23dbe3bc189dcacdca5834113b79bc" + integrity sha512-wv+ttz7wXD/R+IoIuZqdwy4foP3yq986dPVMGTl2N6ipWo5PAHAQ3n6A83efT/K4zQ1h+RibF3k4yr92qu3jNg== dependencies: execa "^4.0.3" npm-run-path "^4.0.1" -"@szmarczak/http-timer@^4.0.5": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.5.tgz#bfbd50211e9dfa51ba07da58a14cdfd333205152" - integrity sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ== - dependencies: - defer-to-connect "^2.0.0" - -"@types/cacheable-request@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.1.tgz#5d22f3dded1fd3a84c0bbeb5039a7419c2c91976" - integrity sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ== - dependencies: - "@types/http-cache-semantics" "*" - "@types/keyv" "*" - "@types/node" "*" - "@types/responselike" "*" - "@types/estree@*": version "0.0.45" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884" @@ -147,17 +300,10 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== -"@types/http-cache-semantics@*": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz#9140779736aa2655635ee756e2467d787cfe8a2a" - integrity sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A== - -"@types/keyv@*": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.1.tgz#e45a45324fca9dab716ab1230ee249c9fb52cfa7" - integrity sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw== - dependencies: - "@types/node" "*" +"@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/node@*": version "14.6.4" @@ -176,18 +322,21 @@ dependencies: "@types/node" "*" -"@types/responselike@*", "@types/responselike@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" - integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== - dependencies: - "@types/node" "*" - abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +acorn-jsx@^5.2.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== + +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== + address@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" @@ -201,6 +350,16 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" +ajv@^6.10.0, ajv@^6.10.2, 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@^6.12.3: version "6.12.4" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" @@ -216,6 +375,11 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= +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@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -231,6 +395,11 @@ ansi-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -243,6 +412,13 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.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== + dependencies: + color-convert "^2.0.1" + anymatch@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" @@ -264,11 +440,35 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" +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" + array-find-index@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= +array-includes@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" + integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0" + is-string "^1.0.5" + +array.prototype.flat@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b" + integrity sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -281,6 +481,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + async-foreach@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" @@ -318,13 +523,6 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= - dependencies: - inherits "~2.0.0" - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -373,29 +571,19 @@ cacache@^15.0.0: tar "^6.0.2" unique-filename "^1.1.1" -cacheable-lookup@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.3.tgz#049fdc59dffdd4fc285e8f4f82936591bd59fec3" - integrity sha512-W+JBqF9SWe18A72XFzN/V/CULFzPm7sBXzzR6ekkE+3tLG72wFZrBiBZhrZuDoYexop4PHJVdFAKb/Nj9+tm9w== - -cacheable-request@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.1.tgz#062031c2856232782ed694a257fa35da93942a58" - integrity sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^4.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^2.0.0" - cachedir@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== +call-bind@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce" + integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.0" + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -444,6 +632,14 @@ chalk@^2.0.0, chalk@^2.4.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chokidar@^3.4.0: version "3.4.2" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d" @@ -464,6 +660,11 @@ chownr@^2.0.0: resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== +cjs-module-lexer@^0.4.0: + version "0.4.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-0.4.3.tgz#9e31f7fe701f5fcee5793f77ab4e58fa8dcde8bc" + integrity sha512-5RLK0Qfs0PNDpEyBXIr3bIT1Muw3ojSlvpw6dAmkUcO0+uTrsBn7GuEIgx40u+OzbCBLDta7nvmud85P4EmTsQ== + clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -478,13 +679,6 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -497,11 +691,23 @@ color-convert@^1.9.0: dependencies: color-name "1.1.3" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -531,6 +737,18 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= + +convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -547,15 +765,7 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -cross-spawn@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" - integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI= - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - -cross-spawn@^7.0.0: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -603,34 +813,41 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -debug@^2.6.0: +debug@^2.6.0, 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.0.1, debug@^4.1.0, debug@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + dependencies: + ms "2.1.2" + decamelize@^1.1.2, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= -decompress-response@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" - integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== - dependencies: - mimic-response "^3.1.0" +deep-is@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= deepmerge@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== -defer-to-connect@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.0.tgz#83d6b199db041593ac84d781b5222308ccf4c2c1" - integrity sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg== +define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" delayed-stream@~1.0.0: version "1.0.0" @@ -650,6 +867,21 @@ detect-port@^1.3.0: address "^1.0.1" debug "^2.6.0" +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +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" + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -670,6 +902,18 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" +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" + +env-paths@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" + integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== + error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -677,21 +921,240 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-module-lexer@^0.3.17: - version "0.3.25" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.3.25.tgz#24a1abcb9c5dc96923a8e42be033b801f788de06" - integrity sha512-H9VoFD5H9zEfiOX2LeTWDwMvAbLqcAyA2PIb40TOAvGpScOjit02oTGWgIh+M0rx2eJOKyJVM9wtpKFVgnyC3A== +es-abstract@^1.17.0, es-abstract@^1.17.0-next.1: + version "1.17.7" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" + integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-regex "^1.1.1" + object-inspect "^1.8.0" + object-keys "^1.1.1" + object.assign "^4.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" -esbuild@^0.6.11: - version "0.6.33" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.6.33.tgz#13504da1a582b892ae37ea303566d9f419e5a70e" - integrity sha512-TGf0q04top/0mVst0IzcbgAYc9W1W+ovbrZAHAQSUB2U+lYMu9Fwd8lkGxlhMdnctjEunGBD0qwahJj6k40izA== +es-abstract@^1.18.0-next.1: + version "1.18.0-next.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" + integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-negative-zero "^2.0.0" + is-regex "^1.1.1" + object-inspect "^1.8.0" + object-keys "^1.1.1" + object.assign "^4.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + +es-module-lexer@^0.3.24: + version "0.3.26" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.3.26.tgz#7b507044e97d5b03b01d4392c74ffeb9c177a83b" + integrity sha512-Va0Q/xqtrss45hWzP8CZJwzGSZJjDM5/MJRE3IXXnUCcVLElR9BRaE9F62BopysASyc4nM3uwhSW7FFB9nlWAA== + +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" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +esbuild@^0.7.0: + version "0.7.22" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.7.22.tgz#9149b903f8128b7c45a754046c24199d76bbe08e" + integrity sha512-B43SYg8LGWYTCv9Gs0RnuLNwjzpuWOoCaZHTWEDEf5AfrnuDMerPVMdCEu7xOdhFvQ+UqfP2MGU9lxEy0JzccA== escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +esinstall@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/esinstall/-/esinstall-0.3.6.tgz#6f54d6a05bbfbc945548c7af89a2fd2d67dab5ce" + integrity sha512-tmtJ0fNXv0C3t37zRuR/WUEVyKsTLvxcWPPe5OlT3QhJiWo7du/HXVUMOX4DTn6ob6jf6zSb0KQJFpHUhBCyHQ== + dependencies: + "@rollup/plugin-alias" "^3.0.1" + "@rollup/plugin-commonjs" "^15.0.0" + "@rollup/plugin-inject" "^4.0.2" + "@rollup/plugin-json" "^4.0.0" + "@rollup/plugin-node-resolve" "^9.0.0" + "@rollup/plugin-replace" "^2.3.3" + cjs-module-lexer "^0.4.0" + es-module-lexer "^0.3.24" + is-builtin-module "^3.0.0" + kleur "^4.1.1" + mkdirp "^1.0.3" + rimraf "^3.0.0" + rollup "^2.23.0" + rollup-plugin-node-polyfills "^0.2.1" + validate-npm-package-name "^3.0.0" + +eslint-import-resolver-node@^0.3.4: + version "0.3.4" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" + integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== + dependencies: + debug "^2.6.9" + resolve "^1.13.1" + +eslint-module-utils@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6" + integrity sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA== + dependencies: + debug "^2.6.9" + pkg-dir "^2.0.0" + +eslint-plugin-import@^2.22.1: + version "2.22.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702" + integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw== + dependencies: + array-includes "^3.1.1" + array.prototype.flat "^1.2.3" + contains-path "^0.1.0" + debug "^2.6.9" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.4" + eslint-module-utils "^2.6.0" + has "^1.0.3" + minimatch "^3.0.4" + object.values "^1.1.1" + read-pkg-up "^2.0.0" + resolve "^1.17.0" + tsconfig-paths "^3.9.0" + +eslint-plugin-react-hooks@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556" + integrity sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ== + +eslint-scope@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" + integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +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.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + +eslint@^7.12.1: + version "7.12.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.12.1.tgz#bd9a81fa67a6cfd51656cdb88812ce49ccec5801" + integrity sha512-HlMTEdr/LicJfN08LB3nM1rRYliDXOmfoO4vj39xN6BLpFzF00hbwBoqHk8UcJ2M/3nlARZWy/mslvGEuZFvsg== + dependencies: + "@babel/code-frame" "^7.0.0" + "@eslint/eslintrc" "^0.2.1" + 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" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.0" + esquery "^1.2.0" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.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 "^4.17.19" + 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 "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348" + integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.2.0" + 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.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" + integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.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: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + estree-walker@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" @@ -707,6 +1170,11 @@ estree-walker@^2.0.1: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.1.tgz#f8e030fb21cefa183b44b7ad516b747434e7a3e0" integrity sha512-tF0hv+Yi2Ot1cwj9eYHtxC0jB9bmjacjQs6ZBTj82H8JwUywFuc+7E83NWfNMwHXZc11mjfFcVXPe9gEP4B8dg== +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" @@ -757,11 +1225,23 @@ fast-json-stable-stringify@^2.0.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@^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= + fastparse@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -786,6 +1266,13 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" +find-up@^2.0.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@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -793,7 +1280,7 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -find-up@^4.0.0, find-up@^4.1.0: +find-up@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== @@ -801,6 +1288,28 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flatted@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + follow-redirects@^1.0.0: version "1.13.0" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" @@ -837,15 +1346,15 @@ fsevents@~2.1.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== -fstream@^1.0.0, fstream@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" - integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" +function-bind@^1.1.1: + version "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= gauge@~2.7.3: version "2.7.4" @@ -868,17 +1377,31 @@ gaze@^1.0.0: dependencies: globule "^1.0.0" +gensync@^1.0.0-beta.1: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + get-caller-file@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-intrinsic@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be" + integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= -get-stream@^5.0.0, get-stream@^5.1.0: +get-stream@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== @@ -892,7 +1415,7 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -glob-parent@~5.1.0: +glob-parent@^5.0.0, glob-parent@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== @@ -911,6 +1434,18 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, gl once "^1.3.0" path-is-absolute "^1.0.0" +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^12.1.0: + version "12.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== + dependencies: + type-fest "^0.8.1" + globule@^1.0.0: version "1.3.2" resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.2.tgz#d8bdd9e9e4eef8f96e245999a5dee7eb5d8529c4" @@ -920,24 +1455,7 @@ globule@^1.0.0: lodash "~4.17.10" minimatch "~3.0.2" -got@^11.1.4: - version "11.6.1" - resolved "https://registry.yarnpkg.com/got/-/got-11.6.1.tgz#a307122fc136c446f676f7b939d89dbc6ed6b909" - integrity sha512-6izGvOsrd/4CsIdQMgweFOTCtS4sAwJTuCzIuVoTbCDzt3+wa3eGIHhSIMgEF6gfCDenslGlMUmAdPap5DkirQ== - dependencies: - "@sindresorhus/is" "^3.1.1" - "@szmarczak/http-timer" "^4.0.5" - "@types/cacheable-request" "^6.0.1" - "@types/responselike" "^1.0.0" - cacheable-lookup "^5.0.3" - cacheable-request "^7.0.1" - decompress-response "^6.0.0" - http2-wrapper "^1.0.0-beta.5.2" - lowercase-keys "^2.0.0" - p-cancelable "^2.0.0" - responselike "^2.0.0" - -graceful-fs@^4.1.2: +graceful-fs@^4.1.2, graceful-fs@^4.2.3: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== @@ -972,11 +1490,28 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + hosted-git-info@^2.1.4: version "2.8.8" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" @@ -987,11 +1522,6 @@ htm@^3.0.4: resolved "https://registry.yarnpkg.com/htm/-/htm-3.0.4.tgz#c90c891645d2d792bdb9f8c867964b18e3503718" integrity sha512-VRdvxX3tmrXuT/Ovt59NMp/ORMFi4bceFMDjos1PV4E0mV+5votuID8R60egR9A4U8nLt238R/snlJGz3UYiTQ== -http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== - http-proxy@^1.18.1: version "1.18.1" resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" @@ -1010,13 +1540,10 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -http2-wrapper@^1.0.0-beta.5.2: - version "1.0.0-beta.5.2" - resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.0-beta.5.2.tgz#8b923deb90144aea65cf834b016a340fc98556f3" - integrity sha512-xYz9goEyBnC8XwXDTuC/MZ6t+MrKVQZOk4s7+PaDkwIsQd8IwqvM+0M6bA/2lvG8GHXcPdf+MejTUeO2LCPCeQ== - dependencies: - quick-lru "^5.1.1" - resolve-alpn "^1.0.0" +httpie@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/httpie/-/httpie-1.1.2.tgz#e76a6792c2172446ea6df8805977a6f57bc9615d" + integrity sha512-VQ82oXG95oY1fQw/XecHuvcFBA+lZQ9Vwj1RfLcO8a7HpDd4cc2ukwpJt+TUlFaLUAzZErylxWu6wclJ1rUhUQ== human-signals@^1.1.1: version "1.1.1" @@ -1028,7 +1555,12 @@ icss-replace-symbols@1.1.0, icss-replace-symbols@^1.1.0: resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= -import-fresh@^3.2.1: +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== + +import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== @@ -1041,11 +1573,6 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= -in-publish@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.1.tgz#948b1a535c8030561cea522f73f78f4be357e00c" - integrity sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ== - indent-string@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" @@ -1071,7 +1598,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@~2.0.0, inherits@~2.0.3: +inherits@2, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -1095,6 +1622,23 @@ is-builtin-module@^3.0.0: dependencies: builtin-modules "^3.0.0" +is-callable@^1.1.4, is-callable@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" + integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== + +is-core-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.0.0.tgz#58531b70aed1db7c0e8d4eb1a0a2d1ddd64bd12d" + integrity sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw== + dependencies: + has "^1.0.3" + +is-date-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== + is-docker@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" @@ -1122,7 +1666,7 @@ is-fullwidth-code-point@^2.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= -is-glob@^4.0.1, is-glob@~4.0.1: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== @@ -1134,6 +1678,11 @@ is-module@^1.0.0: resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= +is-negative-zero@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" + integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -1146,11 +1695,30 @@ is-reference@^1.2.1: dependencies: "@types/estree" "*" +is-regex@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== + dependencies: + has-symbols "^1.0.1" + is-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== + +is-symbol@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== + dependencies: + has-symbols "^1.0.1" + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -1168,7 +1736,7 @@ is-wsl@^2.1.1: dependencies: is-docker "^2.0.0" -isarray@~1.0.0: +isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= @@ -1198,15 +1766,23 @@ js-tokens@^4.0.0: 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.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" + integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== json-parse-even-better-errors@^2.3.0: version "2.3.1" @@ -1223,15 +1799,34 @@ json-schema@0.2.3: resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= +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= + json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -jsonschema@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.2.6.tgz#52b0a8e9dc06bbae7295249d03e4b9faee8a0c0b" - integrity sha512-SqhURKZG07JyKKeo/ir24QnS4/BV7a6gQy93bUSe4lUdNp0QNpIz2c9elWJQ9dpc5cQYY6cvCzgRwy0MQCLyqA== +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +json5@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" + +jsonschema@~1.2.5: + version "1.2.11" + resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.2.11.tgz#7a799cc2aa5a285d893203e8dc81f5becbfb0e91" + integrity sha512-XNZHs3N1IOa3lPKm//npxMhOdaoPw+MvEV0NIgxcER83GTJcG13rehtWmpBCfEt8DrtYwIkMTs8bdXoYs4fvnQ== jsprim@^1.2.2: version "1.4.1" @@ -1243,17 +1838,18 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -keyv@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.0.1.tgz#9fe703cb4a94d6d11729d320af033307efd02ee6" - integrity sha512-xz6Jv6oNkbhrFCvCP7HQa8AaII8y8LRpoSm661NOKLr4uHuBwhX4epXrPQgF3+xdJnN4Esm5X0xwY4bOlALOtw== - dependencies: - json-buffer "3.0.1" +kleur@^4.1.1: + version "4.1.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.3.tgz#8d262a56d79a137ee1b706e967c0b08a7fef4f4c" + integrity sha512-H1tr8QP2PxFTNwAFM74Mui2b6ovcY9FoxJefgrwxY+OCJcq01k5nvhf4M/KnizzrJvLRap5STUy7dgDV35iUBw== -kleur@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.1.tgz#80b49dd7d1afeba41b8dcdf4ecfff9252205fc52" - integrity sha512-BsNhM6T/yTWFG580CRnYhT3LfUuPK7Hwrm+W2H0G8lK/nogalP5Nsrh/cHjxVVkzl0sFm7z8b8rNcZCfKxeoxA== +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" lines-and-columns@^1.1.6: version "1.1.6" @@ -1271,6 +1867,24 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +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@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -1286,7 +1900,14 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" -lodash@^4.0.0, lodash@^4.17.15, lodash@~4.17.10: +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash@^4.0.0, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@~4.17.10: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -1299,19 +1920,6 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -lru-cache@^4.0.1: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -1376,16 +1984,6 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-response@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -mimic-response@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" - integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== - minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -1393,7 +1991,7 @@ minimatch@^3.0.4, minimatch@~3.0.2: dependencies: brace-expansion "^1.1.7" -minimist@^1.1.3, minimist@^1.2.5: +minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -1434,7 +2032,7 @@ minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" -"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@^0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -1451,56 +2049,63 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + nan@^2.13.2: version "2.14.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== -node-gyp@^3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" - integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA== - dependencies: - fstream "^1.0.0" - glob "^7.0.3" - graceful-fs "^4.1.2" - mkdirp "^0.5.0" - nopt "2 || 3" - npmlog "0 || 1 || 2 || 3 || 4" - osenv "0" - request "^2.87.0" - rimraf "2" - semver "~5.3.0" - tar "^2.0.0" - which "1" +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= -node-sass@^4.14.1: - version "4.14.1" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5" - integrity sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g== +node-gyp@^7.1.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-7.1.2.tgz#21a810aebb187120251c3bcec979af1587b188ae" + integrity sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ== + dependencies: + env-paths "^2.2.0" + glob "^7.1.4" + graceful-fs "^4.2.3" + nopt "^5.0.0" + npmlog "^4.1.2" + request "^2.88.2" + rimraf "^3.0.2" + semver "^7.3.2" + tar "^6.0.2" + which "^2.0.2" + +node-sass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-5.0.0.tgz#4e8f39fbef3bac8d2dc72ebe3b539711883a78d2" + integrity sha512-opNgmlu83ZCF792U281Ry7tak9IbVC+AKnXGovcQ8LG8wFaJv6cLnRlc6DIHlmNxWEexB5bZxi9SZ9JyUuOYjw== dependencies: async-foreach "^0.1.3" chalk "^1.1.1" - cross-spawn "^3.0.0" + cross-spawn "^7.0.3" gaze "^1.0.0" get-stdin "^4.0.1" glob "^7.0.3" - in-publish "^2.0.0" lodash "^4.17.15" meow "^3.7.0" mkdirp "^0.5.1" nan "^2.13.2" - node-gyp "^3.8.0" + node-gyp "^7.1.0" npmlog "^4.0.0" request "^2.88.0" sass-graph "2.2.5" stdout-stream "^1.4.0" "true-case-path" "^1.0.2" -"nopt@2 || 3": - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== dependencies: abbrev "1" @@ -1519,11 +2124,6 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -normalize-url@^4.1.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" - integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== - npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" @@ -1531,7 +2131,7 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0: +npmlog@^4.0.0, npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -1556,6 +2156,36 @@ object-assign@^4.0.1, object-assign@^4.1.0: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= +object-inspect@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" + integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== + +object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +object.values@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" + integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -1578,34 +2208,30 @@ open@^7.0.4: is-docker "^2.0.0" is-wsl "^2.1.1" -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-tmpdir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -osenv@0: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== +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: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -p-cancelable@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.0.0.tgz#4a3740f5bdaf5ed5d7c3e34882c6fb5d6b266a6e" - integrity sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg== + 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" p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= +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.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" @@ -1613,6 +2239,20 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" +p-limit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe" + integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg== + 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@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -1627,6 +2267,13 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + p-map@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" @@ -1634,21 +2281,26 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" -p-queue@^6.2.1: - version "6.6.1" - resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.1.tgz#578891ada028a61371ec2692b26614d1b7d2b10a" - integrity sha512-miQiSxLYPYBxGkrldecZC18OTLjdUqnlRebGzPRiVxB8mco7usCmm7hFuxiTvp93K18JnLtE4KMMycjAu/cQQg== +p-queue@^6.6.1: + version "6.6.2" + resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.2.tgz#2068a9dcf8e67dd0ec3e7a2bcb76810faa85e426" + integrity sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ== dependencies: eventemitter3 "^4.0.4" - p-timeout "^3.1.0" + p-timeout "^3.2.0" -p-timeout@^3.1.0: +p-timeout@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== dependencies: p-finally "^1.0.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" @@ -1719,6 +2371,13 @@ path-type@^1.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= + dependencies: + pify "^2.0.0" + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -1751,6 +2410,13 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= +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" @@ -1807,26 +2473,31 @@ postcss@^6.0.1: source-map "^0.6.1" supports-color "^5.4.0" -preact@^10.4.8: - version "10.4.8" - resolved "https://registry.yarnpkg.com/preact/-/preact-10.4.8.tgz#8517b106cc5591eb675237c93da99ac052cf4756" - integrity sha512-uVLeEAyRsCkUEFhVHlOu17OxcrwC7+hTGZ08kBoLBiGHiZooUZuibQnphgMKftw/rqYntNMyhVCPqQhcyAGHag== +preact@^10.5.5: + version "10.5.5" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.5.5.tgz#c6c172ca751df27483350b8ab622abc12956e997" + integrity sha512-5ONLNH1SXMzzbQoExZX4TELemNt+TEDb622xXFNfZngjjM9qtrzseJt+EfiUu4TZ6EJ95X5sE1ES4yqHFSIdhg== + +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== process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +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== + promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= - psl@^1.1.28: version "1.8.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" @@ -1850,11 +2521,6 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -quick-lru@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" - integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== - read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -1863,6 +2529,14 @@ read-pkg-up@^1.0.1: find-up "^1.0.0" read-pkg "^1.0.0" +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" @@ -1872,6 +2546,15 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + readable-stream@^2.0.1, readable-stream@^2.0.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" @@ -1900,6 +2583,11 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" +regexpp@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" @@ -1907,7 +2595,7 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@^2.87.0, request@^2.88.0: +request@^2.88.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -1948,11 +2636,6 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= -resolve-alpn@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.0.0.tgz#745ad60b3d6aff4b4a48e01b8c0bdc70959e0e8c" - integrity sha512-rTuiIEqFmGxne4IovivKSDzld2lWW9QCjqv80SYjPgf+gS35eaCAjaP54CCwGAwBtnCsvNLYtqxe1Nw+i6JEmA== - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -1970,17 +2653,18 @@ resolve@^1.10.0, resolve@^1.17.0: dependencies: path-parse "^1.0.6" -responselike@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.0.tgz#26391bcc3174f750f9a79eacc40a12a5c42d7723" - integrity sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw== +resolve@^1.13.1, resolve@^1.3.2: + version "1.18.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.18.1.tgz#018fcb2c5b207d2a6424aee361c5a266da8f4130" + integrity sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA== dependencies: - lowercase-keys "^2.0.0" + is-core-module "^2.0.0" + path-parse "^1.0.6" -rimraf@2: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: glob "^7.1.3" @@ -2054,20 +2738,20 @@ scss-tokenizer@^0.2.3: js-base64 "^2.1.8" source-map "^0.4.2" -"semver@2 || 3 || 4 || 5": +"semver@2 || 3 || 4 || 5", semver@^5.4.1: version "5.7.1" 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@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= +semver@^7.2.1, semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" @@ -2096,19 +2780,22 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -snowpack@^2.10.3: - version "2.10.3" - resolved "https://registry.yarnpkg.com/snowpack/-/snowpack-2.10.3.tgz#e8cff3282072c6ade4cc2e53762bc8cd7f3888ac" - integrity sha512-g7uKpnJYx/8sVvmoqVuXBYOxN6YRZEu1CAw7yOYdR1FjmsiLb4T2HF7AGlkzVCFw5FDNg3IIwOM+6bxgPRSM+w== +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== dependencies: - "@babel/plugin-syntax-import-meta" "^7.10.4" - "@rollup/plugin-alias" "^3.0.1" - "@rollup/plugin-commonjs" "^15.0.0" - "@rollup/plugin-inject" "^4.0.2" - "@rollup/plugin-json" "^4.0.0" - "@rollup/plugin-node-resolve" "^9.0.0" - "@snowpack/plugin-build-script" "^2.0.6" - "@snowpack/plugin-run-script" "^2.1.1" + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + +snowpack@^2.16.1: + version "2.16.1" + resolved "https://registry.yarnpkg.com/snowpack/-/snowpack-2.16.1.tgz#c05bbe5a6ada14917759e3525c2879c9cfe4cc2b" + integrity sha512-BvvNxCISztDWKnn5umlXdzAzAXUwpV1Bs7/80s37CoxWDhWyX4SUOv8uZ9a1K6Gb1cBR9V4nwO0nUuYN6lxSIg== + dependencies: + "@snowpack/plugin-build-script" "^2.0.11" + "@snowpack/plugin-run-script" "^2.2.0" cacache "^15.0.0" cachedir "^2.3.0" chokidar "^3.4.0" @@ -2117,31 +2804,30 @@ snowpack@^2.10.3: css-modules-loader-core "^1.1.0" deepmerge "^4.2.2" detect-port "^1.3.0" - es-module-lexer "^0.3.17" - esbuild "^0.6.11" + es-module-lexer "^0.3.24" + esbuild "^0.7.0" + esinstall "^0.3.6" etag "^1.8.1" execa "^4.0.3" find-cache-dir "^3.3.1" - find-up "^4.1.0" + find-up "^5.0.0" glob "^7.1.4" - got "^11.1.4" http-proxy "^1.18.1" - is-builtin-module "^3.0.0" + httpie "^1.1.2" isbinaryfile "^4.0.6" - jsonschema "^1.2.5" - kleur "^4.1.0" + jsonschema "~1.2.5" + kleur "^4.1.1" mime-types "^2.1.26" mkdirp "^1.0.3" npm-run-path "^4.0.1" open "^7.0.4" - p-queue "^6.2.1" + p-queue "^6.6.1" resolve-from "^5.0.0" rimraf "^3.0.0" - rollup "^2.23.0" - rollup-plugin-node-polyfills "^0.2.1" signal-exit "^3.0.3" + source-map "^0.7.3" + strip-ansi "^6.0.0" strip-comments "^2.0.1" - tar "^6.0.1" validate-npm-package-name "^3.0.0" ws "^7.3.0" yargs-parser "^18.1.3" @@ -2153,7 +2839,7 @@ source-map@^0.4.2: dependencies: amdefine ">=0.0.4" -source-map@^0.5.6: +source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -2163,6 +2849,11 @@ source-map@^0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +source-map@^0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + sourcemap-codec@^1.4.4: version "1.4.8" resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" @@ -2194,6 +2885,11 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== +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= + sshpk@^1.7.0: version "1.16.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" @@ -2249,6 +2945,22 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string.prototype.trimend@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz#6ddd9a8796bc714b489a3ae22246a208f37bfa46" + integrity sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + +string.prototype.trimstart@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz#22d45da81015309cd0cdd79787e8919fc5c613e7" + integrity sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -2277,6 +2989,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" @@ -2284,6 +3003,11 @@ strip-bom@^2.0.0: dependencies: is-utf8 "^0.2.0" +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-comments@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-comments/-/strip-comments-2.0.1.tgz#4ad11c3fbcac177a67a40ac224ca339ca1c1ba9b" @@ -2301,6 +3025,11 @@ strip-indent@^1.0.1: dependencies: get-stdin "^4.0.1" +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== + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -2320,16 +3049,24 @@ supports-color@^5.3.0, supports-color@^5.4.0: dependencies: has-flag "^3.0.0" -tar@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" - integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: - block-stream "*" - fstream "^1.0.12" - inherits "2" + has-flag "^4.0.0" -tar@^6.0.1, tar@^6.0.2: +table@^5.2.3: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + +tar@^6.0.2: version "6.0.5" resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.5.tgz#bde815086e10b39f1dcd298e89d596e1535e200f" integrity sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg== @@ -2341,6 +3078,16 @@ tar@^6.0.1, tar@^6.0.2: mkdirp "^1.0.3" yallist "^4.0.0" +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= + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -2368,6 +3115,16 @@ trim-newlines@^1.0.0: dependencies: glob "^7.1.2" +tsconfig-paths@^3.9.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" + integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.0" + strip-bom "^3.0.0" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -2380,6 +3137,18 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +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.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + unique-filename@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" @@ -2411,6 +3180,11 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +v8-compile-cache@^2.0.3: + version "2.2.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" + integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== + validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -2440,14 +3214,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1, which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^2.0.1: +which@^2.0.1, which@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== @@ -2461,6 +3228,11 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2" +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== + wrap-ansi@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" @@ -2475,6 +3247,13 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + ws@^7.3.0: version "7.3.1" resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8" @@ -2485,11 +3264,6 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"