├── .dockerignore ├── .eslintrc ├── .gitignore ├── .prettierrc ├── Dockerfile ├── Justfile ├── LICENSE ├── README.md ├── conf.example.toml ├── package.json ├── src ├── conf.ts ├── dbUtil.ts ├── index.ts └── webserver.ts ├── tsconfig.json └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "@typescript-eslint/indent": 0, 4 | "quotes": [1, "single", { "avoidEscape": true }], 5 | "linebreak-style": [2, "unix"], 6 | "semi": 0, 7 | "comma-dangle": [1, "only-multiline"], 8 | "no-console": 0, 9 | "no-global-assign": 0, 10 | "no-multiple-empty-lines": [2, { "max": 1 }], 11 | "no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }], 12 | "@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }], 13 | "prefer-const": [ 14 | "error", 15 | { 16 | "destructuring": "any", 17 | "ignoreReadBeforeAssign": false 18 | } 19 | ], 20 | "@typescript-eslint/explicit-function-return-type": 0, 21 | "@typescript-eslint/no-explicit-any": 0, 22 | "@typescript-eslint/no-non-null-assertion": 0, 23 | "@typescript-eslint/camelcase": 0, 24 | "react/prop-types": 0, 25 | "react-hooks/rules-of-hooks": "error", 26 | "react-hooks/exhaustive-deps": "warn", 27 | "@typescript-eslint/explicit-module-boundary-types": 0 28 | }, 29 | "env": { 30 | "es6": true, 31 | "browser": false, 32 | "node": true 33 | }, 34 | "extends": ["plugin:@typescript-eslint/recommended", "plugin:react/recommended", "prettier"], 35 | "parser": "@typescript-eslint/parser", 36 | "parserOptions": { 37 | "sourceType": "module", 38 | "ecmaFeatures": { 39 | "experimentalObjectRestSpread": true, 40 | "jsx": true 41 | }, 42 | "ecmaVersion": 2017 43 | }, 44 | "plugins": ["@typescript-eslint", "react", "react-hooks"], 45 | "globals": { 46 | "process": true, 47 | "ga": true, 48 | "module": true, 49 | "__dirname": true, 50 | "require": true 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | conf.toml 4 | yarn-error.log 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "jsxSingleQuote": true, 3 | "printWidth": 100, 4 | "singleQuote": true, 5 | "trailingComma": "es5", 6 | "arrowParens": "avoid" 7 | } 8 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:15.8.0-stretch-slim 2 | 3 | ADD . /app 4 | WORKDIR /app 5 | 6 | RUN yarn && yarn build 7 | 8 | CMD yarn start 9 | -------------------------------------------------------------------------------- /Justfile: -------------------------------------------------------------------------------- 1 | docker-build: 2 | docker build -t osutrack-api:latest . 3 | 4 | build-and-deploy: 5 | just docker-build 6 | docker save osutrack-api:latest | bzip2 > /tmp/osutrack-api.tar.bz2 7 | scp /tmp/osutrack-api.tar.bz2 debian@ameo.dev:/tmp/osutrack-api.tar.bz2 8 | ssh debian@ameo.dev -t 'cat /tmp/osutrack-api.tar.bz2 | bunzip2 | docker load && docker kill osutrack-api && docker container rm osutrack-api && docker run --name osutrack-api --restart=always -d -p 22000:22000 -v /opt/conf/osutrack/api-conf.toml:/opt/conf.toml osutrack-api:latest && rm /tmp/osutrack-api.tar.bz2' 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Casey Primozic https://cprimozic.net 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # osu!track API 2 | 3 | Exposes an API to [osu!track](https://ameobea.me/osutrack/) that allows data to be queried, users to be updated, and other things. 4 | 5 | ## Using the API 6 | 7 | Anyone is free to use the API for any purpose, but please keep your traffic reasonable. The one thing I request is that you do not use the API to scrape the full osu!track database or mass-update users. 8 | 9 | If you've got a question about a particular use-case or need data or functionality that this API doesn't provide, you can join the osu!track developers Discord: https://discord.gg/gjzBzCVFmy Feel free to @ me there (@ameo) and I'll answer any questions you have or help out if I can. 10 | 11 | If you encounter any bugs or issues with the API, please do the same! 12 | 13 | ## Endpoints 14 | 15 | The API is reachable at: https://osutrack-api.ameo.dev/ 16 | 17 | ### Update User 18 | 19 | `POST https://osutrack-api.ameo.dev/update?user={user}&mode={mode}` 20 | 21 | * `user` is the user ID of the user you'd like to update 22 | * `mode` is the gamemode you'd like to update; 0=osu!, 1=taiko, 2=ctb, 3=mania 23 | 24 | #### Returns 25 | 26 | This endpoint will return the difference in stats since the last update if successful: 27 | 28 | ``` 29 | { 30 | "username":"ameo", 31 | "mode":0, 32 | "playcount":0, 33 | "pp_rank":0, 34 | "pp_raw":0, 35 | "accuracy":0, 36 | "total_score":0, 37 | "ranked_score":0, 38 | "count300":0, 39 | "count50":0, 40 | "count100":0, 41 | "level":0, 42 | "count_rank_a":0, 43 | "count_rank_s":0, 44 | "count_rank_ss":0, 45 | "levelup":false, // whether or not the user leveled up since the last update 46 | "first":false, // whether this is the first update for the user, meaning that there was no previous update to compare to 47 | "exists":true, // whether the user exists or not; if this is false, check the user ID you provided 48 | // an array of new hiscores for the user 49 | "newhs": [ 50 | { 51 | "beatmap_id":"33394", 52 | "score_id":"85808923", 53 | "score":"5720257", 54 | "maxcombo":"494", 55 | "count50":"0", 56 | "count100":"9", 57 | "count300":"350", 58 | "countmiss":"0", 59 | "countkatu":"8", 60 | "countgeki":"45", 61 | "perfect":"1", 62 | "enabled_mods":"8", 63 | "user_id":"131464", 64 | "date":"2010-04-22 08:25:22", 65 | "rank":"SH", 66 | "pp":"82.9195", 67 | "replay_available":"0", 68 | "ranking":0 69 | } 70 | ] 71 | } 72 | ``` 73 | 74 | ### Get all stats updates for user 75 | 76 | `GET https://osutrack-api.ameo.dev/stats_history?user={user}&mode={mode}&from={from}&to={to}` 77 | 78 | * `user` is the user ID of the user for which to retrieve updates 79 | * `mode` is the gamemode you'd like to retrieve updates for; 0=osu!, 1=taiko, 2=ctb, 3=mania 80 | * `from` is optional, but if provided it is the start date of updates you'd like to retrieve in the format `YYYY-MM-DD` like `2020-01-01` 81 | * `to` is optional, but if provided it is the end date of updates you'd like to retrieve in the format `YYYY-MM-DD` like `2021-01-01` 82 | 83 | #### Returns 84 | 85 | If successful, returns an array of updates for the user in the selected mode like this: 86 | 87 | ``` 88 | [ 89 | { 90 | "count300":3788588, 91 | "count100":387592, 92 | "count50":42411, 93 | "playcount":23428, 94 | "ranked_score":"4306096061", 95 | "total_score":"19326454144", 96 | "pp_rank":79461, 97 | "level":99.1757, 98 | "pp_raw":4006.24, 99 | "accuracy":98.70355224609375, 100 | "count_rank_ss":31, 101 | "count_rank_s":408, 102 | "count_rank_a":568, 103 | "timestamp":"2021-02-04T23:24:42.000Z", 104 | } 105 | ] 106 | ``` 107 | 108 | ### Get all recorded hiscores for user 109 | 110 | `GET https://osutrack-api.ameo.dev/hiscores?user={user}&mode={mode}&from={from}&to={to}&userMode={userMode}` 111 | 112 | * `user` is the ID (default) or username of the user for which to return hiscores. See `userMode` for details 113 | * `mode` is the gamemode you'd like to fetch hiscores for; 0=osu!, 1=taiko, 2=ctb, 3=mania 114 | * `from` is optional, but if provided it is the start date of hiscores you'd like to retrieve in the format `YYYY-MM-DD` like `2020-01-01` 115 | * `to` is optional, but if provided it is the end date of hiscores you'd like to retrieve in the format `YYYY-MM-DD` like `2021-01-01` 116 | * `userMode` is optional can be one of either `id` or `username`. It defaults to `id`. It determines if `user` is interpreted as an ID or as a username. 117 | 118 | #### Returns 119 | 120 | If successful, returns an array of all recorded hiscores for the user in the selected mode like this: 121 | 122 | ``` 123 | [ 124 | { 125 | "beatmap_id":637549, 126 | "score":2423423, 127 | "pp":193.099, 128 | "mods":584, // Same format as osu! API: https://github.com/ppy/osu-api/wiki#mods 129 | "rank":"SH", 130 | "score_time":"2019-05-12T06:30:16.000Z", // Timestamp of when the play took place 131 | "update_time":"2019-05-12T06:30:40.000Z" // Timestamp of when osu!track recorded the play 132 | } 133 | ] 134 | ``` 135 | 136 | ### Get the peak rank + accuracy for a user 137 | 138 | `GET https://osutrack-api.ameo.dev/peak?user={user}&mode={mode}` 139 | 140 | * `user` is the user ID of the user you'd like to get data for 141 | * `mode` is the gamemode you'd like to get data for; 0=osu!, 1=taiko, 2=ctb, 3=mania 142 | 143 | #### Returns 144 | 145 | If successful, returns the best (lowest) global rank and accuracy for the user along with the timestamps at which they were at their best values: 146 | 147 | ``` 148 | [{ 149 | "best_global_rank": 7381, 150 | "best_rank_timestamp": "2015-04-24T12:44:15.000Z", 151 | "best_accuracy": 99.46027374267578, 152 | "best_acc_timestamp": "2024-03-14T01:06:02.000Z" 153 | }] 154 | ``` 155 | 156 | If user not found or no updates exist for the user, returns: 157 | 158 | ``` 159 | [{ 160 | "best_global_rank": null, 161 | "best_rank_timestamp": null, 162 | "best_accuracy": null, 163 | "best_acc_timestamp": null 164 | }] 165 | ``` 166 | 167 | ### Get the best plays by pp for all users in a given mode 168 | 169 | `GET https://osutrack-api.ameo.dev/bestplays?mode={mode}&from={from}&to={to}&limit={limit}` 170 | 171 | * `mode` is the gamemode you'd like to retrieve best plays for; 0=osu!, 1=taiko, 2=ctb, 3=mania 172 | * `from` is optional, but if provided it is the start date of scores you'd like to retrieve in the format `YYYY-MM-DD` like `2020-01-01` 173 | * `to` is optional, but if provided it is the end date of scores you'd like to retrieve in the format `YYYY-MM-DD` like `2021-01-01` 174 | * `limit` is how many scores you want to return, an optional number from 1 to 10000. Scores are returned in descending order by pp value. 175 | 176 | #### Returns 177 | 178 | ``` 179 | 180 | { 181 | "user": 6447454, 182 | "beatmap_id": 111680, 183 | "score": 25571304, 184 | "pp": 1144.15, 185 | "mods": 88, 186 | "rank": "A", 187 | "score_time": "2021-01-07T11:16:59.000Z", 188 | "update_time": "2021-01-16T14:59:17.000Z" 189 | }, 190 | { 191 | "user": 6447454, 192 | "beatmap_id": 1842043, 193 | "score": 63633373, 194 | "pp": 1092.05, 195 | "mods": 72, 196 | "rank": "SH", 197 | "score_time": "2021-01-12T07:25:34.000Z", 198 | "update_time": "2021-01-16T14:59:17.000Z" 199 | } 200 | ] 201 | ``` 202 | -------------------------------------------------------------------------------- /conf.example.toml: -------------------------------------------------------------------------------- 1 | # Config for the MySQL server 2 | [database] 3 | host = "example.com" 4 | username = "osutrack" 5 | password = "secret-password" 6 | database = "osutrack" 7 | 8 | [webserver] 9 | port = 8080 # port the webserver will listen on 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "osutrack-api", 3 | "version": "0.1.0", 4 | "description": "API for osu!track", 5 | "main": "src/index.ts", 6 | "repository": "https://github.com/Ameobea/osutrack-api", 7 | "author": "Casey Primozic (ameo) ", 8 | "license": "MIT", 9 | "private": false, 10 | "scripts": { 11 | "build": "tsc", 12 | "lint": "eslint src/**/*", 13 | "start": "tsc && NODE_PATH=./dist node dist/src/index.js", 14 | "prettier": "prettier --write src/**/*" 15 | }, 16 | "dependencies": { 17 | "@sentry/node": "^6.1.0", 18 | "@sentry/tracing": "^6.1.0", 19 | "express": "^4.17.1", 20 | "mysql": "^2.18.1", 21 | "node-fetch": "^2.6.1", 22 | "toml": "^3.0.0" 23 | }, 24 | "devDependencies": { 25 | "@types/express": "^4.17.11", 26 | "@types/mysql": "^2.15.17", 27 | "@types/node": "^14.14.28", 28 | "@types/node-fetch": "^2.5.8", 29 | "eslint": "^7.20.0", 30 | "eslint-config-prettier": "^7.2.0", 31 | "prettier": "^2.2.1", 32 | "typescript": "^4.1.5" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/conf.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | 3 | import toml from 'toml'; 4 | 5 | interface DbConf { 6 | host: string; 7 | username: string; 8 | password: string; 9 | database: string; 10 | } 11 | 12 | interface WebserverConf { 13 | port: number; 14 | } 15 | 16 | export interface Conf { 17 | database: DbConf; 18 | webserver: WebserverConf; 19 | } 20 | 21 | export let CONF: Conf = null as any; 22 | 23 | export const loadConf = async () => { 24 | const fileContent = await new Promise((resolve, reject) => 25 | fs.readFile(process.env.CONF_FILE_PATH || './conf.toml', {}, (err, data) => { 26 | if (!!err) { 27 | console.error('Failed to read config file: ', err); 28 | reject(err); 29 | return; 30 | } 31 | resolve(data.toString()); 32 | }) 33 | ); 34 | 35 | try { 36 | CONF = toml.parse(fileContent) as Conf; 37 | return CONF; 38 | } catch (err) { 39 | console.error('Failed to parse conf file: ', err); 40 | process.exit(1); 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /src/dbUtil.ts: -------------------------------------------------------------------------------- 1 | import mysql from 'mysql'; 2 | 3 | import type { Conf } from './conf'; 4 | 5 | export const createConnPool = (conf: Conf) => 6 | mysql.createPool({ 7 | connectionLimit: 10, 8 | host: conf.database.host, 9 | user: conf.database.username, 10 | password: conf.database.password, 11 | database: conf.database.database, 12 | charset: 'utf8mb4', 13 | bigNumberStrings: true, 14 | supportBigNumbers: true, 15 | }); 16 | 17 | export const query = async ( 18 | conn: mysql.Pool | mysql.PoolConnection, 19 | query: string, 20 | values?: any[] 21 | ): Promise => 22 | new Promise((resolve, reject) => 23 | conn.query(query, values, (err, res) => { 24 | if (!!err) { 25 | reject(err); 26 | return; 27 | } 28 | 29 | resolve(res as T[]); 30 | }) 31 | ); 32 | 33 | export const update = ( 34 | conn: mysql.Pool | mysql.PoolConnection, 35 | query: string, 36 | values?: any[] 37 | ): Promise<{ fieldCount: number; affectedRows: number; message: string; changedRows: number }> => 38 | new Promise((resolve, reject) => 39 | conn.query(query, values, (err, res) => { 40 | if (!!err) { 41 | reject(err); 42 | return; 43 | } 44 | 45 | resolve(res); 46 | }) 47 | ); 48 | 49 | export const insert = ( 50 | conn: mysql.Pool | mysql.PoolConnection, 51 | query: string, 52 | values: any[] 53 | ): Promise => 54 | new Promise((resolve, reject) => 55 | conn.query(query, values, (err, res) => { 56 | if (!!err) { 57 | reject(err); 58 | return; 59 | } 60 | 61 | resolve(res); 62 | }) 63 | ); 64 | 65 | export const _delete = ( 66 | conn: mysql.Pool | mysql.PoolConnection, 67 | query: string, 68 | values: any[] 69 | ): Promise<{ affectedRows: number }> => 70 | new Promise((resolve, reject) => 71 | conn.query(query, values, (err, res) => { 72 | if (!!err) { 73 | reject(err); 74 | return; 75 | } 76 | 77 | resolve(res); 78 | }) 79 | ); 80 | 81 | export const getConn = (pool: mysql.Pool): Promise => 82 | new Promise((resolve, reject) => 83 | pool.getConnection((err, res) => { 84 | if (!!err) { 85 | reject(err); 86 | return; 87 | } 88 | 89 | resolve(res); 90 | }) 91 | ); 92 | 93 | export const rollback = (conn: mysql.PoolConnection): Promise => 94 | new Promise((resolve, reject) => 95 | conn.rollback(err => { 96 | if (!!err) { 97 | reject(err); 98 | } else { 99 | resolve(); 100 | } 101 | }) 102 | ); 103 | 104 | export const commit = (conn: mysql.PoolConnection): Promise => 105 | new Promise((resolve, reject) => 106 | conn.commit(async err => { 107 | if (!!err) { 108 | await rollback(conn); 109 | reject(err); 110 | } else { 111 | resolve(); 112 | } 113 | }) 114 | ); 115 | 116 | export interface Update { 117 | count300: number; 118 | count100: number; 119 | count50: number; 120 | playcount: number; 121 | ranked_score: number; 122 | total_score: number; 123 | pp_rank: number; 124 | level: number; 125 | pp_raw: number; 126 | accuracy: number; 127 | count_rank_ss: number; 128 | count_rank_s: number; 129 | count_rank_a: number; 130 | timestamp: Date; 131 | } 132 | 133 | export interface HiscoreUpdate { 134 | beatmap_id: number; 135 | score: number; 136 | pp: number; 137 | mods: number; 138 | rank: string; 139 | score_time: Date; 140 | update_time: Date; 141 | } 142 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import * as Sentry from '@sentry/node'; 2 | 3 | import { loadConf } from './conf'; 4 | import { initExpress } from './webserver'; 5 | import { createConnPool } from './dbUtil'; 6 | 7 | Sentry.init({ 8 | dsn: 'https://5ff5ab6141e202e155c2c3a5055c7b9d@sentry.ameo.design/13', 9 | }); 10 | 11 | const init = async () => { 12 | const conf = await loadConf(); 13 | console.log('Loaded config'); 14 | 15 | console.log('Creating connection pool...'); 16 | const pool = createConnPool(conf); 17 | console.log('Created connection pool'); 18 | 19 | initExpress(pool); 20 | }; 21 | 22 | init(); 23 | -------------------------------------------------------------------------------- /src/webserver.ts: -------------------------------------------------------------------------------- 1 | import express, { Response } from 'express'; 2 | import mysql from 'mysql'; 3 | import fetch from 'node-fetch'; 4 | 5 | import { CONF } from './conf'; 6 | import { query, Update } from './dbUtil'; 7 | 8 | const validateUser = ( 9 | user: undefined | string | string[] | { [key: string]: any } 10 | ): number | undefined => { 11 | if (typeof user !== 'string') { 12 | return undefined; 13 | } 14 | const parsedUser = +user; 15 | if (Number.isNaN(parsedUser) || parsedUser <= 0 || parseInt(user) !== parsedUser) { 16 | return undefined; 17 | } 18 | return parsedUser; 19 | }; 20 | 21 | const validateMode = ( 22 | mode: undefined | string | string[] | { [key: string]: any } 23 | ): number | undefined => { 24 | if (typeof mode !== 'string') { 25 | return undefined; 26 | } 27 | if (mode !== '0' && mode !== '1' && mode !== '2' && mode !== '3') { 28 | return undefined; 29 | } 30 | return +mode; 31 | }; 32 | 33 | const validateLimit = ( 34 | limit: undefined | string | string[] | { [key: string]: any } 35 | ): number | undefined => { 36 | if (limit === undefined) { 37 | return 100; 38 | } 39 | if (typeof limit !== 'string') { 40 | return undefined; 41 | } 42 | const parsed = +limit; 43 | if (Math.round(parsed) !== parsed || parsed <= 0 || parsed > 10_000) { 44 | return undefined; 45 | } 46 | return parsed; 47 | }; 48 | 49 | const validateDate = ( 50 | date: undefined | string | string[] | { [key: string]: any } 51 | ): Date | undefined => { 52 | if (typeof date !== 'string') { 53 | return undefined; 54 | } 55 | const d = new Date(date); 56 | if (Number.isNaN(d.getDate())) { 57 | return undefined; 58 | } 59 | return d; 60 | }; 61 | 62 | enum UserMode { 63 | ID, 64 | Username, 65 | } 66 | 67 | const validateUserMode = ( 68 | userMode: undefined | string | string[] | { [key: string]: any } 69 | ): UserMode => { 70 | if (typeof userMode !== 'string') { 71 | return UserMode.ID; 72 | } 73 | switch (userMode) { 74 | case 'id': 75 | return UserMode.ID; 76 | case 'username': 77 | return UserMode.Username; 78 | default: 79 | return UserMode.ID; 80 | } 81 | }; 82 | 83 | const getIDFromUsername = async ( 84 | pool: mysql.Pool, 85 | username: string, 86 | gameMode: number 87 | ): Promise<{ didUpdate: boolean; id: number } | undefined> => { 88 | const queryRes = await query<{ osu_id: number }>( 89 | pool, 90 | 'SELECT osu_id FROM `users` WHERE `username` = ?', 91 | [username] 92 | ); 93 | if (queryRes.length === 1) { 94 | return { didUpdate: false, id: queryRes[0].osu_id }; 95 | } 96 | 97 | try { 98 | console.log(`User ${username} not found in DB; fetching from base osu!track API...`); 99 | const res = await fetch( 100 | `https://ameobea.me/osutrack/api/get_user.php?user=${username}&mode=${gameMode}` 101 | ); 102 | if (!res.ok) { 103 | const text = await res.text(); 104 | console.error('Failed to fetch from base osu!track API: ', text); 105 | return undefined; 106 | } 107 | 108 | const resJson = await res.json(); 109 | if (!resJson.exists) { 110 | return undefined; 111 | } 112 | return { didUpdate: true, id: parseInt(resJson.user, 10) }; 113 | } catch (err) { 114 | console.error('Failed to fetch from base osu!track API: ', err); 115 | return undefined; 116 | } 117 | }; 118 | 119 | const invalidUser = (res: Response) => 120 | res 121 | .status(400) 122 | .send( 123 | 'Invalid or missing `user` param; must be a valid osu! user ID (default) or username (if `userMode` is set to `username`)' 124 | ); 125 | 126 | const invalidMode = (res: Response) => 127 | res 128 | .status(400) 129 | .send( 130 | 'Invalid or missing `mode` param; must be a valid osu! game mode; 0=osu!, 1=taiko, 2=ctb, 3=mania' 131 | ); 132 | 133 | const invalidLimit = (res: Response) => 134 | res 135 | .status(400) 136 | .send( 137 | 'Invalid `limit` param; must be a non-zero integer greater than 0 and less than or equal to 10000' 138 | ); 139 | 140 | export const initExpress = (pool: mysql.Pool) => { 141 | const app = express(); 142 | 143 | app.post('/update', async (req, res) => { 144 | const { user: rawUserID, mode } = req.query; 145 | 146 | const parsedUserID = validateUser(rawUserID); 147 | if (!parsedUserID) { 148 | return invalidUser(res); 149 | } 150 | const parsedMode = validateMode(mode); 151 | if (parsedMode === undefined) { 152 | return invalidMode(res); 153 | } 154 | 155 | try { 156 | // Let the existing osu!track API endpoint handle this 157 | const rawProxyRes = await fetch( 158 | `https://ameobea.me/osutrack/api/get_changes.php?mode=${parsedMode}&id=${parsedUserID}` 159 | ); 160 | if (rawProxyRes.status === 404) { 161 | return res.status(404).json({ error: 'User not found' }); 162 | } else if (rawProxyRes.status !== 200) { 163 | throw await rawProxyRes.text(); 164 | } 165 | const proxyRes = await rawProxyRes.text(); 166 | 167 | try { 168 | const parsed = JSON.parse(proxyRes); 169 | res.status(200).json(parsed); 170 | } catch (err) { 171 | console.error('Non-JSON response from base osu!track API: ', proxyRes); 172 | res.status(500).send('Internal error when updating user'); 173 | } 174 | } catch (err) { 175 | console.error('Failed to fetch from base osu!track API: ', err); 176 | res.status(500).send('Internal error when updating user'); 177 | } 178 | }); 179 | 180 | app.get('/stats_history', async (req, res) => { 181 | const { user: rawUserID, mode, from: rawFrom, to: rawTo } = req.query; 182 | 183 | const parsedUserID = validateUser(rawUserID); 184 | if (!parsedUserID) { 185 | return invalidUser(res); 186 | } 187 | const parsedMode = validateMode(mode); 188 | if (parsedMode === undefined) { 189 | return invalidMode(res); 190 | } 191 | 192 | const from = validateDate(rawFrom); 193 | const to = validateDate(rawTo); 194 | 195 | try { 196 | const queryRes = await query( 197 | pool, 198 | 'SELECT count300, count100, count50, playcount, ranked_score, total_score, pp_rank, level, pp_raw, accuracy, count_rank_ss, count_rank_s, count_rank_a, timestamp FROM `updates` WHERE `mode` = ? AND user = ? AND `timestamp` >= ? AND `timestamp` <= ? ORDER BY `timestamp` ASC', 199 | [parsedMode, parsedUserID, from ?? new Date('2000-01-01'), to ?? new Date('2800-01-01')] 200 | ); 201 | res.status(200).json(queryRes); 202 | } catch (err) { 203 | console.error('DB error: ', err); 204 | res.sendStatus(500); 205 | } 206 | }); 207 | 208 | app.get('/hiscores', async (req, res) => { 209 | const { 210 | user: rawUser, 211 | mode: gameMode, 212 | from: rawFrom, 213 | to: rawTo, 214 | userMode: rawUserMode, 215 | } = req.query; 216 | 217 | const parsedGameMode = validateMode(gameMode) ?? 0; 218 | const userMode = validateUserMode(rawUserMode); 219 | let didUpdate = false; 220 | const parsedUserID = await (async () => { 221 | if (userMode === undefined || userMode === UserMode.ID) { 222 | return validateUser(rawUser); 223 | } 224 | if (typeof rawUser !== 'string') { 225 | return undefined; 226 | } 227 | if (userMode === UserMode.Username) { 228 | const userIDRes = await getIDFromUsername(pool, rawUser, parsedGameMode); 229 | if (!userIDRes) { 230 | return undefined; 231 | } 232 | didUpdate = userIDRes.didUpdate; 233 | return userIDRes.id; 234 | } 235 | 236 | return undefined; 237 | })(); 238 | if (!parsedUserID) { 239 | return invalidUser(res); 240 | } 241 | 242 | if (parsedGameMode === undefined) { 243 | return invalidMode(res); 244 | } 245 | 246 | const from = validateDate(rawFrom); 247 | const to = validateDate(rawTo); 248 | 249 | try { 250 | const getHiscoresFromDB = () => 251 | query( 252 | pool, 253 | 'SELECT beatmap_id, score, pp, mods, rank, score_time, update_time FROM `hiscore_updates` WHERE `mode` = ? AND user = ? AND `score_time` >= ? AND `score_time` <= ? ORDER BY `score_time` ASC', 254 | [ 255 | parsedGameMode, 256 | parsedUserID, 257 | from ?? new Date('2000-01-01'), 258 | to ?? new Date('2800-01-01'), 259 | ] 260 | ); 261 | let queryRes = await getHiscoresFromDB(); 262 | if (!didUpdate && queryRes.length === 0) { 263 | console.log( 264 | 'Empty query result and `updateIfEmpty` is set to true; updating user id=' + parsedUserID 265 | ); 266 | await fetch( 267 | `https://ameobea.me/osutrack/api/get_changes.php?mode=${parsedGameMode}&id=${parsedUserID}` 268 | ); 269 | queryRes = await getHiscoresFromDB(); 270 | } 271 | 272 | res.status(200).json(queryRes); 273 | } catch (err) { 274 | console.error('DB error: ', err); 275 | res.sendStatus(500); 276 | } 277 | }); 278 | 279 | app.get('/peak', async (req, res) => { 280 | const { user: rawUserID, mode } = req.query; 281 | 282 | const parsedUserID = validateUser(rawUserID); 283 | if (!parsedUserID) { 284 | return invalidUser(res); 285 | } 286 | const parsedMode = validateMode(mode); 287 | if (parsedMode === undefined) { 288 | return invalidMode(res); 289 | } 290 | 291 | try { 292 | const queryRes = await query<{ 293 | best_global_rank: number | null | undefined; 294 | best_accuracy: number | null | undefined; 295 | best_rank_timestamp: Date | null | undefined; 296 | best_acc_timestamp: Date | null | undefined; 297 | }>( 298 | pool, 299 | ` 300 | SELECT 301 | MIN(pp_rank) AS best_global_rank, 302 | (SELECT MAX(timestamp) FROM updates WHERE user = ? AND mode = ? AND pp_rank = (SELECT MIN(pp_rank) FROM updates WHERE user = ? AND mode = ?)) AS best_rank_timestamp, 303 | MAX(accuracy) AS best_accuracy, 304 | (SELECT MAX(timestamp) FROM updates WHERE user = ? AND mode = ? AND accuracy = (SELECT MAX(accuracy) FROM updates WHERE user = ? AND mode = ?)) AS best_acc_timestamp 305 | FROM 306 | updates 307 | WHERE 308 | user = ? AND mode = ?`, 309 | [ 310 | parsedUserID, 311 | parsedMode, 312 | parsedUserID, 313 | parsedMode, 314 | parsedUserID, 315 | parsedMode, 316 | parsedUserID, 317 | parsedMode, 318 | parsedUserID, 319 | parsedMode, 320 | ] 321 | ); 322 | res.status(200).json(queryRes); 323 | } catch (err) { 324 | console.error('DB error: ', err); 325 | res.sendStatus(500); 326 | } 327 | }); 328 | 329 | app.get('/bestplays', async (req, res) => { 330 | const { mode, from: rawFrom, to: rawTo, limit: rawLimit } = req.query; 331 | 332 | const parsedMode = validateMode(mode); 333 | if (parsedMode === undefined) { 334 | return invalidMode(res); 335 | } 336 | 337 | const limit = validateLimit(rawLimit); 338 | if (limit === undefined) { 339 | return invalidLimit(res); 340 | } 341 | 342 | const from = validateDate(rawFrom); 343 | const to = validateDate(rawTo); 344 | 345 | try { 346 | const queryRes = await query( 347 | pool, 348 | 'SELECT user, beatmap_id, score, pp, mods, rank, score_time, update_time FROM `hiscore_updates` WHERE `mode` = ? AND `score_time` >= ? AND `score_time` <= ? ORDER BY `pp` DESC LIMIT ?', 349 | [parsedMode, from ?? new Date('2000-01-01'), to ?? new Date('2800-01-01'), limit] 350 | ); 351 | res.status(200).json(queryRes); 352 | } catch (err) { 353 | console.error('DB error: ', err); 354 | res.sendStatus(500); 355 | } 356 | }); 357 | 358 | app.listen(CONF.webserver.port, () => { 359 | console.log('Webserver listening on port ' + CONF.webserver.port); 360 | }); 361 | }; 362 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "resolveJsonModule": true, 4 | "allowJs": true, 5 | "moduleResolution": "node", 6 | "outDir": "dist", 7 | "lib": ["esnext", "dom"], 8 | "sourceMap": true, 9 | "rootDir": ".", 10 | "forceConsistentCasingInFileNames": true, 11 | "strictFunctionTypes": false, // This is required by Jantix 12 | "strict": true, 13 | "allowSyntheticDefaultImports": true, 14 | "esModuleInterop": true, 15 | "suppressImplicitAnyIndexErrors": false, 16 | "noUnusedLocals": true, 17 | "typeRoots": ["./node_modules/@types"], 18 | "types": [], 19 | "jsx": "react", 20 | "baseUrl": ".", 21 | "paths": { 22 | "*": ["./node_modules/@types/*", "*"] 23 | } 24 | }, 25 | "paths": { 26 | "src/*": ["src/**/*"] 27 | }, 28 | "include": ["./index.d.ts", "src/**/*"], 29 | "exclude": [ 30 | "node_modules", 31 | "dist", 32 | "scripts", 33 | "acceptance-tests", 34 | "webpack", 35 | "jest", 36 | "deprecated", 37 | "backend", 38 | "faust-compiler", 39 | "engine" 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@7.12.11": 6 | version "7.12.11" 7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" 8 | integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== 9 | dependencies: 10 | "@babel/highlight" "^7.10.4" 11 | 12 | "@babel/helper-validator-identifier@^7.12.11": 13 | version "7.12.11" 14 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" 15 | integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== 16 | 17 | "@babel/highlight@^7.10.4": 18 | version "7.12.13" 19 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.12.13.tgz#8ab538393e00370b26271b01fa08f7f27f2e795c" 20 | integrity sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww== 21 | dependencies: 22 | "@babel/helper-validator-identifier" "^7.12.11" 23 | chalk "^2.0.0" 24 | js-tokens "^4.0.0" 25 | 26 | "@eslint/eslintrc@^0.3.0": 27 | version "0.3.0" 28 | resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.3.0.tgz#d736d6963d7003b6514e6324bec9c602ac340318" 29 | integrity sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg== 30 | dependencies: 31 | ajv "^6.12.4" 32 | debug "^4.1.1" 33 | espree "^7.3.0" 34 | globals "^12.1.0" 35 | ignore "^4.0.6" 36 | import-fresh "^3.2.1" 37 | js-yaml "^3.13.1" 38 | lodash "^4.17.20" 39 | minimatch "^3.0.4" 40 | strip-json-comments "^3.1.1" 41 | 42 | "@sentry/core@6.1.0": 43 | version "6.1.0" 44 | resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.1.0.tgz#7dd4584dcaf2188a78b94b766068342e6ee65229" 45 | integrity sha512-57mXkp3NoyxRycXrL+Ec6bYS6UYJZp9tYX0lUp5Ry2M0FxDZ3Q4drkjr8MIQOhBaQXP2ukSX4QTVLGMPm60zMw== 46 | dependencies: 47 | "@sentry/hub" "6.1.0" 48 | "@sentry/minimal" "6.1.0" 49 | "@sentry/types" "6.1.0" 50 | "@sentry/utils" "6.1.0" 51 | tslib "^1.9.3" 52 | 53 | "@sentry/hub@6.1.0": 54 | version "6.1.0" 55 | resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.1.0.tgz#fb22734c91c9d68564737996bf28b7e032e3d8ee" 56 | integrity sha512-JnBSCgNg3VHiMojUl5tCHU8iWPVuE+qqENIzG9A722oJms1kKWBvWl+yQzhWBNdgk5qeAY3F5UzKWJZkbJ6xow== 57 | dependencies: 58 | "@sentry/types" "6.1.0" 59 | "@sentry/utils" "6.1.0" 60 | tslib "^1.9.3" 61 | 62 | "@sentry/minimal@6.1.0": 63 | version "6.1.0" 64 | resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.1.0.tgz#b3abf76d93b95477a3c1029db810818bdc56845f" 65 | integrity sha512-g6sfNKenL7wnsr/tibp8nFiMv/XRH0s0Pt4p151npmNI+SmjuUz3GGYEXk8ChCyaKldYKilkNOFdVXJxUf5gZw== 66 | dependencies: 67 | "@sentry/hub" "6.1.0" 68 | "@sentry/types" "6.1.0" 69 | tslib "^1.9.3" 70 | 71 | "@sentry/node@^6.1.0": 72 | version "6.1.0" 73 | resolved "https://registry.yarnpkg.com/@sentry/node/-/node-6.1.0.tgz#9e20443fdfd15e508da5c0b674ef32960e8a6380" 74 | integrity sha512-yOxYHoPxg8Br19QOsJbonP2uYirv1FFxdNkdeykfO2QBorRUkcirjET5qjRfz73jF1YYtUZBuxwR+f9ZOPqGTg== 75 | dependencies: 76 | "@sentry/core" "6.1.0" 77 | "@sentry/hub" "6.1.0" 78 | "@sentry/tracing" "6.1.0" 79 | "@sentry/types" "6.1.0" 80 | "@sentry/utils" "6.1.0" 81 | cookie "^0.4.1" 82 | https-proxy-agent "^5.0.0" 83 | lru_map "^0.3.3" 84 | tslib "^1.9.3" 85 | 86 | "@sentry/tracing@6.1.0", "@sentry/tracing@^6.1.0": 87 | version "6.1.0" 88 | resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.1.0.tgz#cefabd0e4794fefb6a0a17478a8f09b2f1f3d889" 89 | integrity sha512-s6a4Ra3hHn4awiNz4fOEK6TCV2w2iLcxdppijcYEB7S/1rJpmqZgHWDicqufbOmVMOLmyKLEQ7w+pZq3TR3WgQ== 90 | dependencies: 91 | "@sentry/hub" "6.1.0" 92 | "@sentry/minimal" "6.1.0" 93 | "@sentry/types" "6.1.0" 94 | "@sentry/utils" "6.1.0" 95 | tslib "^1.9.3" 96 | 97 | "@sentry/types@6.1.0": 98 | version "6.1.0" 99 | resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.1.0.tgz#5f9379229423ca1325acf6709e95687180f67132" 100 | integrity sha512-kIaN52Fw5K+2mKRaHE2YluJ+F/qMGSUzZXIFDNdC6OUMXQ4TM8gZTrITXs8CLDm7cK8iCqFCtzKOjKK6KyOKAg== 101 | 102 | "@sentry/utils@6.1.0": 103 | version "6.1.0" 104 | resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.1.0.tgz#52e3d7050983e685d3a48f9d2efa1e6eb4ae3e6d" 105 | integrity sha512-6JAplzUOS6bEwfX0PDRZBbYRvn9EN22kZfcL0qGHtM9L0QQ5ybjbbVwOpbXgRkiZx++dQbzLFtelxnDhsbFG+Q== 106 | dependencies: 107 | "@sentry/types" "6.1.0" 108 | tslib "^1.9.3" 109 | 110 | "@types/body-parser@*": 111 | version "1.19.0" 112 | resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f" 113 | integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ== 114 | dependencies: 115 | "@types/connect" "*" 116 | "@types/node" "*" 117 | 118 | "@types/connect@*": 119 | version "3.4.34" 120 | resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.34.tgz#170a40223a6d666006d93ca128af2beb1d9b1901" 121 | integrity sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ== 122 | dependencies: 123 | "@types/node" "*" 124 | 125 | "@types/express-serve-static-core@^4.17.18": 126 | version "4.17.18" 127 | resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.18.tgz#8371e260f40e0e1ca0c116a9afcd9426fa094c40" 128 | integrity sha512-m4JTwx5RUBNZvky/JJ8swEJPKFd8si08pPF2PfizYjGZOKr/svUWPcoUmLow6MmPzhasphB7gSTINY67xn3JNA== 129 | dependencies: 130 | "@types/node" "*" 131 | "@types/qs" "*" 132 | "@types/range-parser" "*" 133 | 134 | "@types/express@^4.17.11": 135 | version "4.17.11" 136 | resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.11.tgz#debe3caa6f8e5fcda96b47bd54e2f40c4ee59545" 137 | integrity sha512-no+R6rW60JEc59977wIxreQVsIEOAYwgCqldrA/vkpCnbD7MqTefO97lmoBe4WE0F156bC4uLSP1XHDOySnChg== 138 | dependencies: 139 | "@types/body-parser" "*" 140 | "@types/express-serve-static-core" "^4.17.18" 141 | "@types/qs" "*" 142 | "@types/serve-static" "*" 143 | 144 | "@types/mime@^1": 145 | version "1.3.2" 146 | resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" 147 | integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== 148 | 149 | "@types/mysql@^2.15.17": 150 | version "2.15.17" 151 | resolved "https://registry.yarnpkg.com/@types/mysql/-/mysql-2.15.17.tgz#18b9a64b3c83916e768cf0c1bd7469f7ecbb7484" 152 | integrity sha512-5vlnAFgdjFGqu3fHbd+pp+qL9mMty6c/N65TjsT5H+kfet50Qq4tXWMrD5lm/ftXeiEQwbAndZepB/eaLGaTew== 153 | dependencies: 154 | "@types/node" "*" 155 | 156 | "@types/node-fetch@^2.5.8": 157 | version "2.5.8" 158 | resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.8.tgz#e199c835d234c7eb0846f6618012e558544ee2fb" 159 | integrity sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw== 160 | dependencies: 161 | "@types/node" "*" 162 | form-data "^3.0.0" 163 | 164 | "@types/node@*", "@types/node@^14.14.28": 165 | version "14.14.28" 166 | resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.28.tgz#cade4b64f8438f588951a6b35843ce536853f25b" 167 | integrity sha512-lg55ArB+ZiHHbBBttLpzD07akz0QPrZgUODNakeC09i62dnrywr9mFErHuaPlB6I7z+sEbK+IYmplahvplCj2g== 168 | 169 | "@types/qs@*": 170 | version "6.9.5" 171 | resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.5.tgz#434711bdd49eb5ee69d90c1d67c354a9a8ecb18b" 172 | integrity sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ== 173 | 174 | "@types/range-parser@*": 175 | version "1.2.3" 176 | resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" 177 | integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== 178 | 179 | "@types/serve-static@*": 180 | version "1.13.9" 181 | resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.9.tgz#aacf28a85a05ee29a11fb7c3ead935ac56f33e4e" 182 | integrity sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA== 183 | dependencies: 184 | "@types/mime" "^1" 185 | "@types/node" "*" 186 | 187 | accepts@~1.3.7: 188 | version "1.3.7" 189 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" 190 | integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== 191 | dependencies: 192 | mime-types "~2.1.24" 193 | negotiator "0.6.2" 194 | 195 | acorn-jsx@^5.3.1: 196 | version "5.3.1" 197 | resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" 198 | integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== 199 | 200 | acorn@^7.4.0: 201 | version "7.4.1" 202 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" 203 | integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== 204 | 205 | agent-base@6: 206 | version "6.0.2" 207 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" 208 | integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== 209 | dependencies: 210 | debug "4" 211 | 212 | ajv@^6.10.0, ajv@^6.12.4: 213 | version "6.12.6" 214 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 215 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 216 | dependencies: 217 | fast-deep-equal "^3.1.1" 218 | fast-json-stable-stringify "^2.0.0" 219 | json-schema-traverse "^0.4.1" 220 | uri-js "^4.2.2" 221 | 222 | ajv@^7.0.2: 223 | version "7.1.0" 224 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.1.0.tgz#f982ea7933dc7f1012eae9eec5a86687d805421b" 225 | integrity sha512-svS9uILze/cXbH0z2myCK2Brqprx/+JJYK5pHicT/GQiBfzzhUVAIT6MwqJg8y4xV/zoGsUeuPuwtoiKSGE15g== 226 | dependencies: 227 | fast-deep-equal "^3.1.1" 228 | json-schema-traverse "^1.0.0" 229 | require-from-string "^2.0.2" 230 | uri-js "^4.2.2" 231 | 232 | ansi-colors@^4.1.1: 233 | version "4.1.1" 234 | resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" 235 | integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== 236 | 237 | ansi-regex@^5.0.0: 238 | version "5.0.0" 239 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" 240 | integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== 241 | 242 | ansi-styles@^3.2.1: 243 | version "3.2.1" 244 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 245 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 246 | dependencies: 247 | color-convert "^1.9.0" 248 | 249 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 250 | version "4.3.0" 251 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 252 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 253 | dependencies: 254 | color-convert "^2.0.1" 255 | 256 | argparse@^1.0.7: 257 | version "1.0.10" 258 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 259 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 260 | dependencies: 261 | sprintf-js "~1.0.2" 262 | 263 | array-flatten@1.1.1: 264 | version "1.1.1" 265 | resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" 266 | integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= 267 | 268 | astral-regex@^2.0.0: 269 | version "2.0.0" 270 | resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" 271 | integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== 272 | 273 | asynckit@^0.4.0: 274 | version "0.4.0" 275 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 276 | integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= 277 | 278 | balanced-match@^1.0.0: 279 | version "1.0.0" 280 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 281 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 282 | 283 | bignumber.js@9.0.0: 284 | version "9.0.0" 285 | resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075" 286 | integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A== 287 | 288 | body-parser@1.19.0: 289 | version "1.19.0" 290 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" 291 | integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== 292 | dependencies: 293 | bytes "3.1.0" 294 | content-type "~1.0.4" 295 | debug "2.6.9" 296 | depd "~1.1.2" 297 | http-errors "1.7.2" 298 | iconv-lite "0.4.24" 299 | on-finished "~2.3.0" 300 | qs "6.7.0" 301 | raw-body "2.4.0" 302 | type-is "~1.6.17" 303 | 304 | brace-expansion@^1.1.7: 305 | version "1.1.11" 306 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 307 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 308 | dependencies: 309 | balanced-match "^1.0.0" 310 | concat-map "0.0.1" 311 | 312 | bytes@3.1.0: 313 | version "3.1.0" 314 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" 315 | integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== 316 | 317 | callsites@^3.0.0: 318 | version "3.1.0" 319 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" 320 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 321 | 322 | chalk@^2.0.0: 323 | version "2.4.2" 324 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 325 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 326 | dependencies: 327 | ansi-styles "^3.2.1" 328 | escape-string-regexp "^1.0.5" 329 | supports-color "^5.3.0" 330 | 331 | chalk@^4.0.0: 332 | version "4.1.0" 333 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" 334 | integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== 335 | dependencies: 336 | ansi-styles "^4.1.0" 337 | supports-color "^7.1.0" 338 | 339 | color-convert@^1.9.0: 340 | version "1.9.3" 341 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 342 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 343 | dependencies: 344 | color-name "1.1.3" 345 | 346 | color-convert@^2.0.1: 347 | version "2.0.1" 348 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 349 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 350 | dependencies: 351 | color-name "~1.1.4" 352 | 353 | color-name@1.1.3: 354 | version "1.1.3" 355 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 356 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 357 | 358 | color-name@~1.1.4: 359 | version "1.1.4" 360 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 361 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 362 | 363 | combined-stream@^1.0.8: 364 | version "1.0.8" 365 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 366 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 367 | dependencies: 368 | delayed-stream "~1.0.0" 369 | 370 | concat-map@0.0.1: 371 | version "0.0.1" 372 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 373 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 374 | 375 | content-disposition@0.5.3: 376 | version "0.5.3" 377 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" 378 | integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== 379 | dependencies: 380 | safe-buffer "5.1.2" 381 | 382 | content-type@~1.0.4: 383 | version "1.0.4" 384 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" 385 | integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== 386 | 387 | cookie-signature@1.0.6: 388 | version "1.0.6" 389 | resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" 390 | integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= 391 | 392 | cookie@0.4.0: 393 | version "0.4.0" 394 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" 395 | integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== 396 | 397 | cookie@^0.4.1: 398 | version "0.4.1" 399 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" 400 | integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== 401 | 402 | core-util-is@~1.0.0: 403 | version "1.0.2" 404 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 405 | integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= 406 | 407 | cross-spawn@^7.0.2: 408 | version "7.0.3" 409 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" 410 | integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 411 | dependencies: 412 | path-key "^3.1.0" 413 | shebang-command "^2.0.0" 414 | which "^2.0.1" 415 | 416 | debug@2.6.9: 417 | version "2.6.9" 418 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 419 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 420 | dependencies: 421 | ms "2.0.0" 422 | 423 | debug@4, debug@^4.0.1, debug@^4.1.1: 424 | version "4.3.1" 425 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" 426 | integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== 427 | dependencies: 428 | ms "2.1.2" 429 | 430 | deep-is@^0.1.3: 431 | version "0.1.3" 432 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" 433 | integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= 434 | 435 | delayed-stream@~1.0.0: 436 | version "1.0.0" 437 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 438 | integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= 439 | 440 | depd@~1.1.2: 441 | version "1.1.2" 442 | resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" 443 | integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= 444 | 445 | destroy@~1.0.4: 446 | version "1.0.4" 447 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" 448 | integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= 449 | 450 | doctrine@^3.0.0: 451 | version "3.0.0" 452 | resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" 453 | integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== 454 | dependencies: 455 | esutils "^2.0.2" 456 | 457 | ee-first@1.1.1: 458 | version "1.1.1" 459 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 460 | integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= 461 | 462 | emoji-regex@^8.0.0: 463 | version "8.0.0" 464 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 465 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 466 | 467 | encodeurl@~1.0.2: 468 | version "1.0.2" 469 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 470 | integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= 471 | 472 | enquirer@^2.3.5: 473 | version "2.3.6" 474 | resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" 475 | integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== 476 | dependencies: 477 | ansi-colors "^4.1.1" 478 | 479 | escape-html@~1.0.3: 480 | version "1.0.3" 481 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 482 | integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= 483 | 484 | escape-string-regexp@^1.0.5: 485 | version "1.0.5" 486 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 487 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 488 | 489 | eslint-config-prettier@^7.2.0: 490 | version "7.2.0" 491 | resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz#f4a4bd2832e810e8cc7c1411ec85b3e85c0c53f9" 492 | integrity sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg== 493 | 494 | eslint-scope@^5.1.1: 495 | version "5.1.1" 496 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" 497 | integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== 498 | dependencies: 499 | esrecurse "^4.3.0" 500 | estraverse "^4.1.1" 501 | 502 | eslint-utils@^2.1.0: 503 | version "2.1.0" 504 | resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" 505 | integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== 506 | dependencies: 507 | eslint-visitor-keys "^1.1.0" 508 | 509 | eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: 510 | version "1.3.0" 511 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" 512 | integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== 513 | 514 | eslint-visitor-keys@^2.0.0: 515 | version "2.0.0" 516 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" 517 | integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== 518 | 519 | eslint@^7.20.0: 520 | version "7.20.0" 521 | resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.20.0.tgz#db07c4ca4eda2e2316e7aa57ac7fc91ec550bdc7" 522 | integrity sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw== 523 | dependencies: 524 | "@babel/code-frame" "7.12.11" 525 | "@eslint/eslintrc" "^0.3.0" 526 | ajv "^6.10.0" 527 | chalk "^4.0.0" 528 | cross-spawn "^7.0.2" 529 | debug "^4.0.1" 530 | doctrine "^3.0.0" 531 | enquirer "^2.3.5" 532 | eslint-scope "^5.1.1" 533 | eslint-utils "^2.1.0" 534 | eslint-visitor-keys "^2.0.0" 535 | espree "^7.3.1" 536 | esquery "^1.4.0" 537 | esutils "^2.0.2" 538 | file-entry-cache "^6.0.0" 539 | functional-red-black-tree "^1.0.1" 540 | glob-parent "^5.0.0" 541 | globals "^12.1.0" 542 | ignore "^4.0.6" 543 | import-fresh "^3.0.0" 544 | imurmurhash "^0.1.4" 545 | is-glob "^4.0.0" 546 | js-yaml "^3.13.1" 547 | json-stable-stringify-without-jsonify "^1.0.1" 548 | levn "^0.4.1" 549 | lodash "^4.17.20" 550 | minimatch "^3.0.4" 551 | natural-compare "^1.4.0" 552 | optionator "^0.9.1" 553 | progress "^2.0.0" 554 | regexpp "^3.1.0" 555 | semver "^7.2.1" 556 | strip-ansi "^6.0.0" 557 | strip-json-comments "^3.1.0" 558 | table "^6.0.4" 559 | text-table "^0.2.0" 560 | v8-compile-cache "^2.0.3" 561 | 562 | espree@^7.3.0, espree@^7.3.1: 563 | version "7.3.1" 564 | resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" 565 | integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== 566 | dependencies: 567 | acorn "^7.4.0" 568 | acorn-jsx "^5.3.1" 569 | eslint-visitor-keys "^1.3.0" 570 | 571 | esprima@^4.0.0: 572 | version "4.0.1" 573 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 574 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 575 | 576 | esquery@^1.4.0: 577 | version "1.4.0" 578 | resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" 579 | integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== 580 | dependencies: 581 | estraverse "^5.1.0" 582 | 583 | esrecurse@^4.3.0: 584 | version "4.3.0" 585 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" 586 | integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== 587 | dependencies: 588 | estraverse "^5.2.0" 589 | 590 | estraverse@^4.1.1: 591 | version "4.3.0" 592 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" 593 | integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== 594 | 595 | estraverse@^5.1.0, estraverse@^5.2.0: 596 | version "5.2.0" 597 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" 598 | integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== 599 | 600 | esutils@^2.0.2: 601 | version "2.0.3" 602 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" 603 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 604 | 605 | etag@~1.8.1: 606 | version "1.8.1" 607 | resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" 608 | integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= 609 | 610 | express@^4.17.1: 611 | version "4.17.1" 612 | resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" 613 | integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== 614 | dependencies: 615 | accepts "~1.3.7" 616 | array-flatten "1.1.1" 617 | body-parser "1.19.0" 618 | content-disposition "0.5.3" 619 | content-type "~1.0.4" 620 | cookie "0.4.0" 621 | cookie-signature "1.0.6" 622 | debug "2.6.9" 623 | depd "~1.1.2" 624 | encodeurl "~1.0.2" 625 | escape-html "~1.0.3" 626 | etag "~1.8.1" 627 | finalhandler "~1.1.2" 628 | fresh "0.5.2" 629 | merge-descriptors "1.0.1" 630 | methods "~1.1.2" 631 | on-finished "~2.3.0" 632 | parseurl "~1.3.3" 633 | path-to-regexp "0.1.7" 634 | proxy-addr "~2.0.5" 635 | qs "6.7.0" 636 | range-parser "~1.2.1" 637 | safe-buffer "5.1.2" 638 | send "0.17.1" 639 | serve-static "1.14.1" 640 | setprototypeof "1.1.1" 641 | statuses "~1.5.0" 642 | type-is "~1.6.18" 643 | utils-merge "1.0.1" 644 | vary "~1.1.2" 645 | 646 | fast-deep-equal@^3.1.1: 647 | version "3.1.3" 648 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 649 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 650 | 651 | fast-json-stable-stringify@^2.0.0: 652 | version "2.1.0" 653 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 654 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 655 | 656 | fast-levenshtein@^2.0.6: 657 | version "2.0.6" 658 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" 659 | integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= 660 | 661 | file-entry-cache@^6.0.0: 662 | version "6.0.0" 663 | resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" 664 | integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA== 665 | dependencies: 666 | flat-cache "^3.0.4" 667 | 668 | finalhandler@~1.1.2: 669 | version "1.1.2" 670 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" 671 | integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== 672 | dependencies: 673 | debug "2.6.9" 674 | encodeurl "~1.0.2" 675 | escape-html "~1.0.3" 676 | on-finished "~2.3.0" 677 | parseurl "~1.3.3" 678 | statuses "~1.5.0" 679 | unpipe "~1.0.0" 680 | 681 | flat-cache@^3.0.4: 682 | version "3.0.4" 683 | resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" 684 | integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== 685 | dependencies: 686 | flatted "^3.1.0" 687 | rimraf "^3.0.2" 688 | 689 | flatted@^3.1.0: 690 | version "3.1.1" 691 | resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" 692 | integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== 693 | 694 | form-data@^3.0.0: 695 | version "3.0.0" 696 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" 697 | integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg== 698 | dependencies: 699 | asynckit "^0.4.0" 700 | combined-stream "^1.0.8" 701 | mime-types "^2.1.12" 702 | 703 | forwarded@~0.1.2: 704 | version "0.1.2" 705 | resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" 706 | integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= 707 | 708 | fresh@0.5.2: 709 | version "0.5.2" 710 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" 711 | integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= 712 | 713 | fs.realpath@^1.0.0: 714 | version "1.0.0" 715 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 716 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 717 | 718 | functional-red-black-tree@^1.0.1: 719 | version "1.0.1" 720 | resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" 721 | integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= 722 | 723 | glob-parent@^5.0.0: 724 | version "5.1.1" 725 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" 726 | integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== 727 | dependencies: 728 | is-glob "^4.0.1" 729 | 730 | glob@^7.1.3: 731 | version "7.1.6" 732 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" 733 | integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 734 | dependencies: 735 | fs.realpath "^1.0.0" 736 | inflight "^1.0.4" 737 | inherits "2" 738 | minimatch "^3.0.4" 739 | once "^1.3.0" 740 | path-is-absolute "^1.0.0" 741 | 742 | globals@^12.1.0: 743 | version "12.4.0" 744 | resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" 745 | integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== 746 | dependencies: 747 | type-fest "^0.8.1" 748 | 749 | has-flag@^3.0.0: 750 | version "3.0.0" 751 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 752 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 753 | 754 | has-flag@^4.0.0: 755 | version "4.0.0" 756 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 757 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 758 | 759 | http-errors@1.7.2: 760 | version "1.7.2" 761 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" 762 | integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== 763 | dependencies: 764 | depd "~1.1.2" 765 | inherits "2.0.3" 766 | setprototypeof "1.1.1" 767 | statuses ">= 1.5.0 < 2" 768 | toidentifier "1.0.0" 769 | 770 | http-errors@~1.7.2: 771 | version "1.7.3" 772 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" 773 | integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== 774 | dependencies: 775 | depd "~1.1.2" 776 | inherits "2.0.4" 777 | setprototypeof "1.1.1" 778 | statuses ">= 1.5.0 < 2" 779 | toidentifier "1.0.0" 780 | 781 | https-proxy-agent@^5.0.0: 782 | version "5.0.0" 783 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" 784 | integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== 785 | dependencies: 786 | agent-base "6" 787 | debug "4" 788 | 789 | iconv-lite@0.4.24: 790 | version "0.4.24" 791 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 792 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 793 | dependencies: 794 | safer-buffer ">= 2.1.2 < 3" 795 | 796 | ignore@^4.0.6: 797 | version "4.0.6" 798 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" 799 | integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== 800 | 801 | import-fresh@^3.0.0, import-fresh@^3.2.1: 802 | version "3.3.0" 803 | resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" 804 | integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== 805 | dependencies: 806 | parent-module "^1.0.0" 807 | resolve-from "^4.0.0" 808 | 809 | imurmurhash@^0.1.4: 810 | version "0.1.4" 811 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 812 | integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= 813 | 814 | inflight@^1.0.4: 815 | version "1.0.6" 816 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 817 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 818 | dependencies: 819 | once "^1.3.0" 820 | wrappy "1" 821 | 822 | inherits@2, inherits@2.0.4, inherits@~2.0.3: 823 | version "2.0.4" 824 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 825 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 826 | 827 | inherits@2.0.3: 828 | version "2.0.3" 829 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 830 | integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= 831 | 832 | ipaddr.js@1.9.1: 833 | version "1.9.1" 834 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" 835 | integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== 836 | 837 | is-extglob@^2.1.1: 838 | version "2.1.1" 839 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 840 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= 841 | 842 | is-fullwidth-code-point@^3.0.0: 843 | version "3.0.0" 844 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 845 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 846 | 847 | is-glob@^4.0.0, is-glob@^4.0.1: 848 | version "4.0.1" 849 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" 850 | integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== 851 | dependencies: 852 | is-extglob "^2.1.1" 853 | 854 | isarray@~1.0.0: 855 | version "1.0.0" 856 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 857 | integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= 858 | 859 | isexe@^2.0.0: 860 | version "2.0.0" 861 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 862 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 863 | 864 | js-tokens@^4.0.0: 865 | version "4.0.0" 866 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 867 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 868 | 869 | js-yaml@^3.13.1: 870 | version "3.14.1" 871 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" 872 | integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== 873 | dependencies: 874 | argparse "^1.0.7" 875 | esprima "^4.0.0" 876 | 877 | json-schema-traverse@^0.4.1: 878 | version "0.4.1" 879 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 880 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 881 | 882 | json-schema-traverse@^1.0.0: 883 | version "1.0.0" 884 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" 885 | integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== 886 | 887 | json-stable-stringify-without-jsonify@^1.0.1: 888 | version "1.0.1" 889 | resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" 890 | integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= 891 | 892 | levn@^0.4.1: 893 | version "0.4.1" 894 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" 895 | integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== 896 | dependencies: 897 | prelude-ls "^1.2.1" 898 | type-check "~0.4.0" 899 | 900 | lodash@^4.17.20: 901 | version "4.17.20" 902 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" 903 | integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== 904 | 905 | lru-cache@^6.0.0: 906 | version "6.0.0" 907 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" 908 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 909 | dependencies: 910 | yallist "^4.0.0" 911 | 912 | lru_map@^0.3.3: 913 | version "0.3.3" 914 | resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" 915 | integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0= 916 | 917 | media-typer@0.3.0: 918 | version "0.3.0" 919 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 920 | integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= 921 | 922 | merge-descriptors@1.0.1: 923 | version "1.0.1" 924 | resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" 925 | integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= 926 | 927 | methods@~1.1.2: 928 | version "1.1.2" 929 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 930 | integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= 931 | 932 | mime-db@1.45.0: 933 | version "1.45.0" 934 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" 935 | integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== 936 | 937 | mime-types@^2.1.12, mime-types@~2.1.24: 938 | version "2.1.28" 939 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" 940 | integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== 941 | dependencies: 942 | mime-db "1.45.0" 943 | 944 | mime@1.6.0: 945 | version "1.6.0" 946 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" 947 | integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== 948 | 949 | minimatch@^3.0.4: 950 | version "3.0.4" 951 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 952 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 953 | dependencies: 954 | brace-expansion "^1.1.7" 955 | 956 | ms@2.0.0: 957 | version "2.0.0" 958 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 959 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 960 | 961 | ms@2.1.1: 962 | version "2.1.1" 963 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" 964 | integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== 965 | 966 | ms@2.1.2: 967 | version "2.1.2" 968 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 969 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 970 | 971 | mysql@^2.18.1: 972 | version "2.18.1" 973 | resolved "https://registry.yarnpkg.com/mysql/-/mysql-2.18.1.tgz#2254143855c5a8c73825e4522baf2ea021766717" 974 | integrity sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig== 975 | dependencies: 976 | bignumber.js "9.0.0" 977 | readable-stream "2.3.7" 978 | safe-buffer "5.1.2" 979 | sqlstring "2.3.1" 980 | 981 | natural-compare@^1.4.0: 982 | version "1.4.0" 983 | resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" 984 | integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= 985 | 986 | negotiator@0.6.2: 987 | version "0.6.2" 988 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" 989 | integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== 990 | 991 | node-fetch@^2.6.1: 992 | version "2.6.1" 993 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" 994 | integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== 995 | 996 | on-finished@~2.3.0: 997 | version "2.3.0" 998 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" 999 | integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= 1000 | dependencies: 1001 | ee-first "1.1.1" 1002 | 1003 | once@^1.3.0: 1004 | version "1.4.0" 1005 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 1006 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 1007 | dependencies: 1008 | wrappy "1" 1009 | 1010 | optionator@^0.9.1: 1011 | version "0.9.1" 1012 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" 1013 | integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== 1014 | dependencies: 1015 | deep-is "^0.1.3" 1016 | fast-levenshtein "^2.0.6" 1017 | levn "^0.4.1" 1018 | prelude-ls "^1.2.1" 1019 | type-check "^0.4.0" 1020 | word-wrap "^1.2.3" 1021 | 1022 | parent-module@^1.0.0: 1023 | version "1.0.1" 1024 | resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" 1025 | integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 1026 | dependencies: 1027 | callsites "^3.0.0" 1028 | 1029 | parseurl@~1.3.3: 1030 | version "1.3.3" 1031 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 1032 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 1033 | 1034 | path-is-absolute@^1.0.0: 1035 | version "1.0.1" 1036 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1037 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 1038 | 1039 | path-key@^3.1.0: 1040 | version "3.1.1" 1041 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 1042 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 1043 | 1044 | path-to-regexp@0.1.7: 1045 | version "0.1.7" 1046 | resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" 1047 | integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= 1048 | 1049 | prelude-ls@^1.2.1: 1050 | version "1.2.1" 1051 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" 1052 | integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== 1053 | 1054 | prettier@^2.2.1: 1055 | version "2.2.1" 1056 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" 1057 | integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q== 1058 | 1059 | process-nextick-args@~2.0.0: 1060 | version "2.0.1" 1061 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" 1062 | integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== 1063 | 1064 | progress@^2.0.0: 1065 | version "2.0.3" 1066 | resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" 1067 | integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== 1068 | 1069 | proxy-addr@~2.0.5: 1070 | version "2.0.6" 1071 | resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" 1072 | integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== 1073 | dependencies: 1074 | forwarded "~0.1.2" 1075 | ipaddr.js "1.9.1" 1076 | 1077 | punycode@^2.1.0: 1078 | version "2.1.1" 1079 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 1080 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 1081 | 1082 | qs@6.7.0: 1083 | version "6.7.0" 1084 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" 1085 | integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== 1086 | 1087 | range-parser@~1.2.1: 1088 | version "1.2.1" 1089 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" 1090 | integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== 1091 | 1092 | raw-body@2.4.0: 1093 | version "2.4.0" 1094 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" 1095 | integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== 1096 | dependencies: 1097 | bytes "3.1.0" 1098 | http-errors "1.7.2" 1099 | iconv-lite "0.4.24" 1100 | unpipe "1.0.0" 1101 | 1102 | readable-stream@2.3.7: 1103 | version "2.3.7" 1104 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" 1105 | integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== 1106 | dependencies: 1107 | core-util-is "~1.0.0" 1108 | inherits "~2.0.3" 1109 | isarray "~1.0.0" 1110 | process-nextick-args "~2.0.0" 1111 | safe-buffer "~5.1.1" 1112 | string_decoder "~1.1.1" 1113 | util-deprecate "~1.0.1" 1114 | 1115 | regexpp@^3.1.0: 1116 | version "3.1.0" 1117 | resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" 1118 | integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== 1119 | 1120 | require-from-string@^2.0.2: 1121 | version "2.0.2" 1122 | resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" 1123 | integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== 1124 | 1125 | resolve-from@^4.0.0: 1126 | version "4.0.0" 1127 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" 1128 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 1129 | 1130 | rimraf@^3.0.2: 1131 | version "3.0.2" 1132 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" 1133 | integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 1134 | dependencies: 1135 | glob "^7.1.3" 1136 | 1137 | safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: 1138 | version "5.1.2" 1139 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 1140 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 1141 | 1142 | "safer-buffer@>= 2.1.2 < 3": 1143 | version "2.1.2" 1144 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 1145 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 1146 | 1147 | semver@^7.2.1: 1148 | version "7.3.4" 1149 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" 1150 | integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== 1151 | dependencies: 1152 | lru-cache "^6.0.0" 1153 | 1154 | send@0.17.1: 1155 | version "0.17.1" 1156 | resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" 1157 | integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== 1158 | dependencies: 1159 | debug "2.6.9" 1160 | depd "~1.1.2" 1161 | destroy "~1.0.4" 1162 | encodeurl "~1.0.2" 1163 | escape-html "~1.0.3" 1164 | etag "~1.8.1" 1165 | fresh "0.5.2" 1166 | http-errors "~1.7.2" 1167 | mime "1.6.0" 1168 | ms "2.1.1" 1169 | on-finished "~2.3.0" 1170 | range-parser "~1.2.1" 1171 | statuses "~1.5.0" 1172 | 1173 | serve-static@1.14.1: 1174 | version "1.14.1" 1175 | resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" 1176 | integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== 1177 | dependencies: 1178 | encodeurl "~1.0.2" 1179 | escape-html "~1.0.3" 1180 | parseurl "~1.3.3" 1181 | send "0.17.1" 1182 | 1183 | setprototypeof@1.1.1: 1184 | version "1.1.1" 1185 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" 1186 | integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== 1187 | 1188 | shebang-command@^2.0.0: 1189 | version "2.0.0" 1190 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 1191 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 1192 | dependencies: 1193 | shebang-regex "^3.0.0" 1194 | 1195 | shebang-regex@^3.0.0: 1196 | version "3.0.0" 1197 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 1198 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 1199 | 1200 | slice-ansi@^4.0.0: 1201 | version "4.0.0" 1202 | resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" 1203 | integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== 1204 | dependencies: 1205 | ansi-styles "^4.0.0" 1206 | astral-regex "^2.0.0" 1207 | is-fullwidth-code-point "^3.0.0" 1208 | 1209 | sprintf-js@~1.0.2: 1210 | version "1.0.3" 1211 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 1212 | integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= 1213 | 1214 | sqlstring@2.3.1: 1215 | version "2.3.1" 1216 | resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.1.tgz#475393ff9e91479aea62dcaf0ca3d14983a7fb40" 1217 | integrity sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A= 1218 | 1219 | "statuses@>= 1.5.0 < 2", statuses@~1.5.0: 1220 | version "1.5.0" 1221 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" 1222 | integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= 1223 | 1224 | string-width@^4.2.0: 1225 | version "4.2.0" 1226 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" 1227 | integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== 1228 | dependencies: 1229 | emoji-regex "^8.0.0" 1230 | is-fullwidth-code-point "^3.0.0" 1231 | strip-ansi "^6.0.0" 1232 | 1233 | string_decoder@~1.1.1: 1234 | version "1.1.1" 1235 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 1236 | integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== 1237 | dependencies: 1238 | safe-buffer "~5.1.0" 1239 | 1240 | strip-ansi@^6.0.0: 1241 | version "6.0.0" 1242 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" 1243 | integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== 1244 | dependencies: 1245 | ansi-regex "^5.0.0" 1246 | 1247 | strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: 1248 | version "3.1.1" 1249 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 1250 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 1251 | 1252 | supports-color@^5.3.0: 1253 | version "5.5.0" 1254 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 1255 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 1256 | dependencies: 1257 | has-flag "^3.0.0" 1258 | 1259 | supports-color@^7.1.0: 1260 | version "7.2.0" 1261 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 1262 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1263 | dependencies: 1264 | has-flag "^4.0.0" 1265 | 1266 | table@^6.0.4: 1267 | version "6.0.7" 1268 | resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34" 1269 | integrity sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g== 1270 | dependencies: 1271 | ajv "^7.0.2" 1272 | lodash "^4.17.20" 1273 | slice-ansi "^4.0.0" 1274 | string-width "^4.2.0" 1275 | 1276 | text-table@^0.2.0: 1277 | version "0.2.0" 1278 | resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" 1279 | integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= 1280 | 1281 | toidentifier@1.0.0: 1282 | version "1.0.0" 1283 | resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" 1284 | integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== 1285 | 1286 | toml@^3.0.0: 1287 | version "3.0.0" 1288 | resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" 1289 | integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== 1290 | 1291 | tslib@^1.9.3: 1292 | version "1.14.1" 1293 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" 1294 | integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== 1295 | 1296 | type-check@^0.4.0, type-check@~0.4.0: 1297 | version "0.4.0" 1298 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" 1299 | integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== 1300 | dependencies: 1301 | prelude-ls "^1.2.1" 1302 | 1303 | type-fest@^0.8.1: 1304 | version "0.8.1" 1305 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" 1306 | integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== 1307 | 1308 | type-is@~1.6.17, type-is@~1.6.18: 1309 | version "1.6.18" 1310 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" 1311 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== 1312 | dependencies: 1313 | media-typer "0.3.0" 1314 | mime-types "~2.1.24" 1315 | 1316 | typescript@^4.1.5: 1317 | version "4.1.5" 1318 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.5.tgz#123a3b214aaff3be32926f0d8f1f6e704eb89a72" 1319 | integrity sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA== 1320 | 1321 | unpipe@1.0.0, unpipe@~1.0.0: 1322 | version "1.0.0" 1323 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 1324 | integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= 1325 | 1326 | uri-js@^4.2.2: 1327 | version "4.4.1" 1328 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 1329 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 1330 | dependencies: 1331 | punycode "^2.1.0" 1332 | 1333 | util-deprecate@~1.0.1: 1334 | version "1.0.2" 1335 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1336 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= 1337 | 1338 | utils-merge@1.0.1: 1339 | version "1.0.1" 1340 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 1341 | integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= 1342 | 1343 | v8-compile-cache@^2.0.3: 1344 | version "2.2.0" 1345 | resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" 1346 | integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== 1347 | 1348 | vary@~1.1.2: 1349 | version "1.1.2" 1350 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 1351 | integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= 1352 | 1353 | which@^2.0.1: 1354 | version "2.0.2" 1355 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1356 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1357 | dependencies: 1358 | isexe "^2.0.0" 1359 | 1360 | word-wrap@^1.2.3: 1361 | version "1.2.3" 1362 | resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" 1363 | integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== 1364 | 1365 | wrappy@1: 1366 | version "1.0.2" 1367 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1368 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1369 | 1370 | yallist@^4.0.0: 1371 | version "4.0.0" 1372 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" 1373 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 1374 | --------------------------------------------------------------------------------