mirror of https://github.com/coder/code-server.git
Merge pull request #3422 from cdr/jsjoeio/fix-password-hash
fix: use sufficient computational effort for password hash
This commit is contained in:
commit
717eaa6470
|
@ -59,6 +59,7 @@ VS Code v0.00.0
|
|||
- chore: cross-compile docker images with buildx #3166 @oxy
|
||||
- chore: update node to v14 #3458 @oxy
|
||||
- chore: update .gitignore #3557 @cuining
|
||||
- fix: use sufficient computational effort for password hash #3422 @jsjoeio
|
||||
|
||||
### Development
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# This is due to an upstream issue with RHEL7/CentOS 7 comptability with node-argon2
|
||||
# See: https://github.com/cdr/code-server/pull/3422#pullrequestreview-677765057
|
||||
export npm_config_build_from_source=true
|
||||
|
||||
main() {
|
||||
cd "$(dirname "${0}")/../.."
|
||||
source ./ci/lib.sh
|
||||
|
|
|
@ -18,6 +18,9 @@ detect_arch() {
|
|||
}
|
||||
|
||||
ARCH="${NPM_CONFIG_ARCH:-$(detect_arch)}"
|
||||
# This is due to an upstream issue with RHEL7/CentOS 7 comptability with node-argon2
|
||||
# See: https://github.com/cdr/code-server/pull/3422#pullrequestreview-677765057
|
||||
export npm_config_build_from_source=true
|
||||
|
||||
main() {
|
||||
# Grabs the major version of node from $npm_config_user_agent which looks like
|
||||
|
|
|
@ -205,17 +205,18 @@ Again, please follow [./guide.md](./guide.md) for our recommendations on setting
|
|||
|
||||
Yes you can! Set the value of `hashed-password` instead of `password`. Generate the hash with:
|
||||
|
||||
```
|
||||
printf "thisismypassword" | sha256sum | cut -d' ' -f1
|
||||
```shell
|
||||
echo -n "password" | npx argon2-cli -e
|
||||
$argon2i$v=19$m=4096,t=3,p=1$wst5qhbgk2lu1ih4dmuxvg$ls1alrvdiwtvzhwnzcm1dugg+5dto3dt1d5v9xtlws4
|
||||
```
|
||||
|
||||
Of course replace `thisismypassword` with your actual password.
|
||||
Of course replace `thisismypassword` with your actual password and **remember to put it inside quotes**!
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
auth: password
|
||||
hashed-password: 1da9133ab9dbd11d2937ec8d312e1e2569857059e73cc72df92e670928983ab5 # You got this from the command above
|
||||
hashed-password: "$argon2i$v=19$m=4096,t=3,p=1$wST5QhBgk2lu1ih4DMuxvg$LS1alrVdIWtvZHwnzCM1DUGg+5DTO3Dt1d5v9XtLws4"
|
||||
```
|
||||
|
||||
## How do I securely access web services?
|
||||
|
|
|
@ -88,6 +88,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@coder/logger": "1.1.16",
|
||||
"argon2": "^0.28.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"compression": "^1.7.4",
|
||||
"cookie-parser": "^1.4.5",
|
||||
|
|
|
@ -114,7 +114,7 @@ const options: Options<Required<Args>> = {
|
|||
"hashed-password": {
|
||||
type: "string",
|
||||
description:
|
||||
"The password hashed with SHA-256 for password authentication (can only be passed in via $HASHED_PASSWORD or the config file). \n" +
|
||||
"The password hashed with argon2 for password authentication (can only be passed in via $HASHED_PASSWORD or the config file). \n" +
|
||||
"Takes precedence over 'password'.",
|
||||
},
|
||||
cert: {
|
||||
|
@ -240,6 +240,19 @@ export const optionDescriptions = (): string[] => {
|
|||
})
|
||||
}
|
||||
|
||||
export function splitOnFirstEquals(str: string): string[] {
|
||||
// we use regex instead of "=" to ensure we split at the first
|
||||
// "=" and return the following substring with it
|
||||
// important for the hashed-password which looks like this
|
||||
// $argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY
|
||||
// 2 means return two items
|
||||
// Source: https://stackoverflow.com/a/4607799/3015595
|
||||
// We use the ? to say the the substr after the = is optional
|
||||
const split = str.split(/=(.+)?/, 2)
|
||||
|
||||
return split
|
||||
}
|
||||
|
||||
export const parse = (
|
||||
argv: string[],
|
||||
opts?: {
|
||||
|
@ -250,6 +263,7 @@ export const parse = (
|
|||
if (opts?.configFile) {
|
||||
msg = `error reading ${opts.configFile}: ${msg}`
|
||||
}
|
||||
|
||||
return new Error(msg)
|
||||
}
|
||||
|
||||
|
@ -270,7 +284,7 @@ export const parse = (
|
|||
let key: keyof Args | undefined
|
||||
let value: string | undefined
|
||||
if (arg.startsWith("--")) {
|
||||
const split = arg.replace(/^--/, "").split("=", 2)
|
||||
const split = splitOnFirstEquals(arg.replace(/^--/, ""))
|
||||
key = split[0] as keyof Args
|
||||
value = split[1]
|
||||
} else {
|
||||
|
|
|
@ -2,13 +2,12 @@ import { field, logger } from "@coder/logger"
|
|||
import * as express from "express"
|
||||
import * as expressCore from "express-serve-static-core"
|
||||
import qs from "qs"
|
||||
import safeCompare from "safe-compare"
|
||||
import { HttpCode, HttpError } from "../common/http"
|
||||
import { normalize, Options } from "../common/util"
|
||||
import { AuthType, DefaultedArgs } from "./cli"
|
||||
import { commit, rootPath } from "./constants"
|
||||
import { Heart } from "./heart"
|
||||
import { hash } from "./util"
|
||||
import { getPasswordMethod, IsCookieValidArgs, isCookieValid, sanitizeString } from "./util"
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
|
@ -45,8 +44,13 @@ export const replaceTemplates = <T extends object>(
|
|||
/**
|
||||
* Throw an error if not authorized. Call `next` if provided.
|
||||
*/
|
||||
export const ensureAuthenticated = (req: express.Request, _?: express.Response, next?: express.NextFunction): void => {
|
||||
if (!authenticated(req)) {
|
||||
export const ensureAuthenticated = async (
|
||||
req: express.Request,
|
||||
_?: express.Response,
|
||||
next?: express.NextFunction,
|
||||
): Promise<void> => {
|
||||
const isAuthenticated = await authenticated(req)
|
||||
if (!isAuthenticated) {
|
||||
throw new HttpError("Unauthorized", HttpCode.Unauthorized)
|
||||
}
|
||||
if (next) {
|
||||
|
@ -57,20 +61,27 @@ export const ensureAuthenticated = (req: express.Request, _?: express.Response,
|
|||
/**
|
||||
* Return true if authenticated via cookies.
|
||||
*/
|
||||
export const authenticated = (req: express.Request): boolean => {
|
||||
export const authenticated = async (req: express.Request): Promise<boolean> => {
|
||||
switch (req.args.auth) {
|
||||
case AuthType.None:
|
||||
case AuthType.None: {
|
||||
return true
|
||||
case AuthType.Password:
|
||||
}
|
||||
case AuthType.Password: {
|
||||
// The password is stored in the cookie after being hashed.
|
||||
return !!(
|
||||
req.cookies.key &&
|
||||
(req.args["hashed-password"]
|
||||
? safeCompare(req.cookies.key, req.args["hashed-password"])
|
||||
: req.args.password && safeCompare(req.cookies.key, hash(req.args.password)))
|
||||
)
|
||||
default:
|
||||
const hashedPasswordFromArgs = req.args["hashed-password"]
|
||||
const passwordMethod = getPasswordMethod(hashedPasswordFromArgs)
|
||||
const isCookieValidArgs: IsCookieValidArgs = {
|
||||
passwordMethod,
|
||||
cookieKey: sanitizeString(req.cookies.key),
|
||||
passwordFromArgs: req.args.password || "",
|
||||
hashedPasswordFromArgs: req.args["hashed-password"],
|
||||
}
|
||||
|
||||
return await isCookieValid(isCookieValidArgs)
|
||||
}
|
||||
default: {
|
||||
throw new Error(`Unsupported auth type ${req.args.auth}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,14 +32,15 @@ const maybeProxy = (req: Request): string | undefined => {
|
|||
return port
|
||||
}
|
||||
|
||||
router.all("*", (req, res, next) => {
|
||||
router.all("*", async (req, res, next) => {
|
||||
const port = maybeProxy(req)
|
||||
if (!port) {
|
||||
return next()
|
||||
}
|
||||
|
||||
// Must be authenticated to use the proxy.
|
||||
if (!authenticated(req)) {
|
||||
const isAuthenticated = await authenticated(req)
|
||||
if (!isAuthenticated) {
|
||||
// Let the assets through since they're used on the login page.
|
||||
if (req.path.startsWith("/static/") && req.method === "GET") {
|
||||
return next()
|
||||
|
@ -73,14 +74,14 @@ router.all("*", (req, res, next) => {
|
|||
|
||||
export const wsRouter = WsRouter()
|
||||
|
||||
wsRouter.ws("*", (req, _, next) => {
|
||||
wsRouter.ws("*", async (req, _, next) => {
|
||||
const port = maybeProxy(req)
|
||||
if (!port) {
|
||||
return next()
|
||||
}
|
||||
|
||||
// Must be authenticated to use the proxy.
|
||||
ensureAuthenticated(req)
|
||||
await ensureAuthenticated(req)
|
||||
|
||||
proxy.ws(req, req.ws, req.head, {
|
||||
ignorePath: true,
|
||||
|
|
|
@ -98,8 +98,8 @@ export const register = async (
|
|||
app.all("/proxy/(:port)(/*)?", (req, res) => {
|
||||
pathProxy.proxy(req, res)
|
||||
})
|
||||
wsApp.get("/proxy/(:port)(/*)?", (req) => {
|
||||
pathProxy.wsProxy(req as pluginapi.WebsocketRequest)
|
||||
wsApp.get("/proxy/(:port)(/*)?", async (req) => {
|
||||
await pathProxy.wsProxy(req as pluginapi.WebsocketRequest)
|
||||
})
|
||||
// These two routes pass through the path directly.
|
||||
// So the proxied app must be aware it is running
|
||||
|
@ -109,8 +109,8 @@ export const register = async (
|
|||
passthroughPath: true,
|
||||
})
|
||||
})
|
||||
wsApp.get("/absproxy/(:port)(/*)?", (req) => {
|
||||
pathProxy.wsProxy(req as pluginapi.WebsocketRequest, {
|
||||
wsApp.get("/absproxy/(:port)(/*)?", async (req) => {
|
||||
await pathProxy.wsProxy(req as pluginapi.WebsocketRequest, {
|
||||
passthroughPath: true,
|
||||
})
|
||||
})
|
||||
|
|
|
@ -2,10 +2,9 @@ import { Router, Request } from "express"
|
|||
import { promises as fs } from "fs"
|
||||
import { RateLimiter as Limiter } from "limiter"
|
||||
import * as path from "path"
|
||||
import safeCompare from "safe-compare"
|
||||
import { rootPath } from "../constants"
|
||||
import { authenticated, getCookieDomain, redirect, replaceTemplates } from "../http"
|
||||
import { hash, humanPath } from "../util"
|
||||
import { getPasswordMethod, handlePasswordValidation, humanPath, sanitizeString } from "../util"
|
||||
|
||||
export enum Cookie {
|
||||
Key = "key",
|
||||
|
@ -49,9 +48,9 @@ const limiter = new RateLimiter()
|
|||
|
||||
export const router = Router()
|
||||
|
||||
router.use((req, res, next) => {
|
||||
router.use(async (req, res, next) => {
|
||||
const to = (typeof req.query.to === "string" && req.query.to) || "/"
|
||||
if (authenticated(req)) {
|
||||
if (await authenticated(req)) {
|
||||
return redirect(req, res, to, { to: undefined })
|
||||
}
|
||||
next()
|
||||
|
@ -62,24 +61,31 @@ router.get("/", async (req, res) => {
|
|||
})
|
||||
|
||||
router.post("/", async (req, res) => {
|
||||
const password = sanitizeString(req.body.password)
|
||||
const hashedPasswordFromArgs = req.args["hashed-password"]
|
||||
|
||||
try {
|
||||
// Check to see if they exceeded their login attempts
|
||||
if (!limiter.canTry()) {
|
||||
throw new Error("Login rate limited!")
|
||||
}
|
||||
|
||||
if (!req.body.password) {
|
||||
if (!password) {
|
||||
throw new Error("Missing password")
|
||||
}
|
||||
|
||||
if (
|
||||
req.args["hashed-password"]
|
||||
? safeCompare(hash(req.body.password), req.args["hashed-password"])
|
||||
: req.args.password && safeCompare(req.body.password, req.args.password)
|
||||
) {
|
||||
const passwordMethod = getPasswordMethod(hashedPasswordFromArgs)
|
||||
const { isPasswordValid, hashedPassword } = await handlePasswordValidation({
|
||||
passwordMethod,
|
||||
hashedPasswordFromArgs,
|
||||
passwordFromRequestBody: password,
|
||||
passwordFromArgs: req.args.password,
|
||||
})
|
||||
|
||||
if (isPasswordValid) {
|
||||
// The hash does not add any actual security but we do it for
|
||||
// obfuscation purposes (and as a side effect it handles escaping).
|
||||
res.cookie(Cookie.Key, hash(req.body.password), {
|
||||
res.cookie(Cookie.Key, hashedPassword, {
|
||||
domain: getCookieDomain(req.headers.host || "", req.args["proxy-domain"]),
|
||||
path: req.body.base || "/",
|
||||
sameSite: "lax",
|
||||
|
|
|
@ -45,13 +45,13 @@ export function proxy(
|
|||
})
|
||||
}
|
||||
|
||||
export function wsProxy(
|
||||
export async function wsProxy(
|
||||
req: pluginapi.WebsocketRequest,
|
||||
opts?: {
|
||||
passthroughPath?: boolean
|
||||
},
|
||||
): void {
|
||||
ensureAuthenticated(req)
|
||||
): Promise<void> {
|
||||
await ensureAuthenticated(req)
|
||||
_proxy.ws(req, req.ws, req.head, {
|
||||
ignorePath: true,
|
||||
target: getProxyTarget(req, opts?.passthroughPath),
|
||||
|
|
|
@ -18,7 +18,7 @@ router.get("/(:commit)(/*)?", async (req, res) => {
|
|||
// Used by VS Code to load extensions into the web worker.
|
||||
const tar = getFirstString(req.query.tar)
|
||||
if (tar) {
|
||||
ensureAuthenticated(req)
|
||||
await ensureAuthenticated(req)
|
||||
let stream: Readable = tarFs.pack(pathToFsPath(tar))
|
||||
if (req.headers["accept-encoding"] && req.headers["accept-encoding"].includes("gzip")) {
|
||||
logger.debug("gzipping tar", field("path", tar))
|
||||
|
@ -43,7 +43,8 @@ router.get("/(:commit)(/*)?", async (req, res) => {
|
|||
|
||||
// Make sure it's in code-server if you aren't authenticated. This lets
|
||||
// unauthenticated users load the login assets.
|
||||
if (!resourcePath.startsWith(rootPath) && !authenticated(req)) {
|
||||
const isAuthenticated = await authenticated(req)
|
||||
if (!resourcePath.startsWith(rootPath) && !isAuthenticated) {
|
||||
throw new HttpError("Unauthorized", HttpCode.Unauthorized)
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,8 @@ export const router = Router()
|
|||
const vscode = new VscodeProvider()
|
||||
|
||||
router.get("/", async (req, res) => {
|
||||
if (!authenticated(req)) {
|
||||
const isAuthenticated = await authenticated(req)
|
||||
if (!isAuthenticated) {
|
||||
return redirect(req, res, "login", {
|
||||
// req.baseUrl can be blank if already at the root.
|
||||
to: req.baseUrl && req.baseUrl !== "/" ? req.baseUrl : undefined,
|
||||
|
|
176
src/node/util.ts
176
src/node/util.ts
|
@ -1,3 +1,5 @@
|
|||
import { logger } from "@coder/logger"
|
||||
import * as argon2 from "argon2"
|
||||
import * as cp from "child_process"
|
||||
import * as crypto from "crypto"
|
||||
import envPaths from "env-paths"
|
||||
|
@ -5,6 +7,7 @@ import { promises as fs } from "fs"
|
|||
import * as net from "net"
|
||||
import * as os from "os"
|
||||
import * as path from "path"
|
||||
import safeCompare from "safe-compare"
|
||||
import * as util from "util"
|
||||
import xdgBasedir from "xdg-basedir"
|
||||
|
||||
|
@ -115,10 +118,181 @@ export const generatePassword = async (length = 24): Promise<string> => {
|
|||
return buffer.toString("hex").substring(0, length)
|
||||
}
|
||||
|
||||
export const hash = (str: string): string => {
|
||||
/**
|
||||
* Used to hash the password.
|
||||
*/
|
||||
export const hash = async (password: string): Promise<string> => {
|
||||
try {
|
||||
return await argon2.hash(password)
|
||||
} catch (error) {
|
||||
logger.error(error)
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to verify if the password matches the hash
|
||||
*/
|
||||
export const isHashMatch = async (password: string, hash: string) => {
|
||||
if (password === "" || hash === "") {
|
||||
return false
|
||||
}
|
||||
try {
|
||||
return await argon2.verify(hash, password)
|
||||
} catch (error) {
|
||||
logger.error(error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to hash the password using the sha256
|
||||
* algorithm. We only use this to for checking
|
||||
* the hashed-password set in the config.
|
||||
*
|
||||
* Kept for legacy reasons.
|
||||
*/
|
||||
export const hashLegacy = (str: string): string => {
|
||||
return crypto.createHash("sha256").update(str).digest("hex")
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to check if the password matches the hash using
|
||||
* the hashLegacy function
|
||||
*/
|
||||
export const isHashLegacyMatch = (password: string, hashPassword: string) => {
|
||||
const hashedWithLegacy = hashLegacy(password)
|
||||
return safeCompare(hashedWithLegacy, hashPassword)
|
||||
}
|
||||
|
||||
const passwordMethods = ["SHA256", "ARGON2", "PLAIN_TEXT"] as const
|
||||
export type PasswordMethod = typeof passwordMethods[number]
|
||||
|
||||
/**
|
||||
* Used to determine the password method.
|
||||
*
|
||||
* There are three options for the return value:
|
||||
* 1. "SHA256" -> the legacy hashing algorithm
|
||||
* 2. "ARGON2" -> the newest hashing algorithm
|
||||
* 3. "PLAIN_TEXT" -> regular ol' password with no hashing
|
||||
*
|
||||
* @returns {PasswordMethod} "SHA256" | "ARGON2" | "PLAIN_TEXT"
|
||||
*/
|
||||
export function getPasswordMethod(hashedPassword: string | undefined): PasswordMethod {
|
||||
if (!hashedPassword) {
|
||||
return "PLAIN_TEXT"
|
||||
}
|
||||
|
||||
// This is the new hashing algorithm
|
||||
if (hashedPassword.includes("$argon")) {
|
||||
return "ARGON2"
|
||||
}
|
||||
|
||||
// This is the legacy hashing algorithm
|
||||
return "SHA256"
|
||||
}
|
||||
|
||||
type PasswordValidation = {
|
||||
isPasswordValid: boolean
|
||||
hashedPassword: string
|
||||
}
|
||||
|
||||
type HandlePasswordValidationArgs = {
|
||||
/** The PasswordMethod */
|
||||
passwordMethod: PasswordMethod
|
||||
/** The password provided by the user */
|
||||
passwordFromRequestBody: string
|
||||
/** The password set in PASSWORD or config */
|
||||
passwordFromArgs: string | undefined
|
||||
/** The hashed-password set in HASHED_PASSWORD or config */
|
||||
hashedPasswordFromArgs: string | undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a password is valid and also returns the hash
|
||||
* using the PasswordMethod
|
||||
*/
|
||||
export async function handlePasswordValidation({
|
||||
passwordMethod,
|
||||
passwordFromArgs,
|
||||
passwordFromRequestBody,
|
||||
hashedPasswordFromArgs,
|
||||
}: HandlePasswordValidationArgs): Promise<PasswordValidation> {
|
||||
const passwordValidation = <PasswordValidation>{
|
||||
isPasswordValid: false,
|
||||
hashedPassword: "",
|
||||
}
|
||||
|
||||
switch (passwordMethod) {
|
||||
case "PLAIN_TEXT": {
|
||||
const isValid = passwordFromArgs ? safeCompare(passwordFromRequestBody, passwordFromArgs) : false
|
||||
passwordValidation.isPasswordValid = isValid
|
||||
|
||||
const hashedPassword = await hash(passwordFromRequestBody)
|
||||
passwordValidation.hashedPassword = hashedPassword
|
||||
break
|
||||
}
|
||||
case "SHA256": {
|
||||
const isValid = isHashLegacyMatch(passwordFromRequestBody, hashedPasswordFromArgs || "")
|
||||
passwordValidation.isPasswordValid = isValid
|
||||
|
||||
passwordValidation.hashedPassword = hashedPasswordFromArgs || (await hashLegacy(passwordFromRequestBody))
|
||||
break
|
||||
}
|
||||
case "ARGON2": {
|
||||
const isValid = await isHashMatch(passwordFromRequestBody, hashedPasswordFromArgs || "")
|
||||
passwordValidation.isPasswordValid = isValid
|
||||
|
||||
passwordValidation.hashedPassword = hashedPasswordFromArgs || ""
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
return passwordValidation
|
||||
}
|
||||
|
||||
export type IsCookieValidArgs = {
|
||||
passwordMethod: PasswordMethod
|
||||
cookieKey: string
|
||||
hashedPasswordFromArgs: string | undefined
|
||||
passwordFromArgs: string | undefined
|
||||
}
|
||||
|
||||
/** Checks if a req.cookies.key is valid using the PasswordMethod */
|
||||
export async function isCookieValid({
|
||||
passwordFromArgs = "",
|
||||
cookieKey,
|
||||
hashedPasswordFromArgs = "",
|
||||
passwordMethod,
|
||||
}: IsCookieValidArgs): Promise<boolean> {
|
||||
let isValid = false
|
||||
switch (passwordMethod) {
|
||||
case "PLAIN_TEXT":
|
||||
isValid = await isHashMatch(passwordFromArgs, cookieKey)
|
||||
break
|
||||
case "ARGON2":
|
||||
case "SHA256":
|
||||
isValid = safeCompare(cookieKey, hashedPasswordFromArgs)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
return isValid
|
||||
}
|
||||
|
||||
/** Ensures that the input is sanitized by checking
|
||||
* - it's a string
|
||||
* - greater than 0 characters
|
||||
* - trims whitespace
|
||||
*/
|
||||
export function sanitizeString(str: string): string {
|
||||
// Very basic sanitization of string
|
||||
// Credit: https://stackoverflow.com/a/46719000/3015595
|
||||
return typeof str === "string" && str.trim().length > 0 ? str.trim() : ""
|
||||
}
|
||||
|
||||
const mimeTypes: { [key: string]: string } = {
|
||||
".aac": "audio/x-aac",
|
||||
".avi": "video/x-msvideo",
|
||||
|
|
|
@ -8,21 +8,21 @@ import {
|
|||
Config,
|
||||
globalSetup,
|
||||
} from "@playwright/test"
|
||||
import * as crypto from "crypto"
|
||||
import * as argon2 from "argon2"
|
||||
import path from "path"
|
||||
import { PASSWORD } from "./utils/constants"
|
||||
import * as wtfnode from "./utils/wtfnode"
|
||||
|
||||
// Playwright doesn't like that ../src/node/util has an enum in it
|
||||
// so I had to copy hash in separately
|
||||
const hash = (str: string): string => {
|
||||
return crypto.createHash("sha256").update(str).digest("hex")
|
||||
const hash = async (str: string): Promise<string> => {
|
||||
return await argon2.hash(str)
|
||||
}
|
||||
|
||||
const cookieToStore = {
|
||||
sameSite: "Lax" as const,
|
||||
name: "key",
|
||||
value: hash(PASSWORD),
|
||||
value: "",
|
||||
domain: "localhost",
|
||||
path: "/",
|
||||
expires: -1,
|
||||
|
@ -38,6 +38,8 @@ globalSetup(async () => {
|
|||
wtfnode.setup()
|
||||
}
|
||||
|
||||
cookieToStore.value = await hash(PASSWORD)
|
||||
|
||||
const storage = {
|
||||
cookies: [cookieToStore],
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"@types/jsdom": "^16.2.6",
|
||||
"@types/node-fetch": "^2.5.8",
|
||||
"@types/supertest": "^2.0.10",
|
||||
"argon2": "^0.28.0",
|
||||
"jest": "^26.6.3",
|
||||
"jsdom": "^16.4.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
|
|
|
@ -3,7 +3,7 @@ import { promises as fs } from "fs"
|
|||
import * as net from "net"
|
||||
import * as os from "os"
|
||||
import * as path from "path"
|
||||
import { Args, parse, setDefaults, shouldOpenInExistingInstance } from "../../src/node/cli"
|
||||
import { Args, parse, setDefaults, shouldOpenInExistingInstance, splitOnFirstEquals } from "../../src/node/cli"
|
||||
import { tmpdir } from "../../src/node/constants"
|
||||
import { paths } from "../../src/node/util"
|
||||
|
||||
|
@ -306,7 +306,8 @@ describe("parser", () => {
|
|||
})
|
||||
|
||||
it("should use env var hashed password", async () => {
|
||||
process.env.HASHED_PASSWORD = "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" // test
|
||||
process.env.HASHED_PASSWORD =
|
||||
"$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY" // test
|
||||
const args = parse([])
|
||||
expect(args).toEqual({
|
||||
_: [],
|
||||
|
@ -316,7 +317,8 @@ describe("parser", () => {
|
|||
expect(defaultArgs).toEqual({
|
||||
...defaults,
|
||||
_: [],
|
||||
"hashed-password": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
|
||||
"hashed-password":
|
||||
"$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY",
|
||||
usingEnvHashedPassword: true,
|
||||
})
|
||||
})
|
||||
|
@ -335,6 +337,33 @@ describe("parser", () => {
|
|||
"proxy-domain": ["coder.com", "coder.org"],
|
||||
})
|
||||
})
|
||||
it("should allow '=,$/' in strings", async () => {
|
||||
const args = parse([
|
||||
"--enable-proposed-api",
|
||||
"$argon2i$v=19$m=4096,t=3,p=1$0qr/o+0t00hsbjfqcksfdq$ofcm4rl6o+b7oxpua4qlxubypbbpsf+8l531u7p9hyy",
|
||||
])
|
||||
expect(args).toEqual({
|
||||
_: [],
|
||||
"enable-proposed-api": [
|
||||
"$argon2i$v=19$m=4096,t=3,p=1$0qr/o+0t00hsbjfqcksfdq$ofcm4rl6o+b7oxpua4qlxubypbbpsf+8l531u7p9hyy",
|
||||
],
|
||||
})
|
||||
})
|
||||
it("should parse options with double-dash and multiple equal signs ", async () => {
|
||||
const args = parse(
|
||||
[
|
||||
"--hashed-password=$argon2i$v=19$m=4096,t=3,p=1$0qr/o+0t00hsbjfqcksfdq$ofcm4rl6o+b7oxpua4qlxubypbbpsf+8l531u7p9hyy",
|
||||
],
|
||||
{
|
||||
configFile: "/pathtoconfig",
|
||||
},
|
||||
)
|
||||
expect(args).toEqual({
|
||||
_: [],
|
||||
"hashed-password":
|
||||
"$argon2i$v=19$m=4096,t=3,p=1$0qr/o+0t00hsbjfqcksfdq$ofcm4rl6o+b7oxpua4qlxubypbbpsf+8l531u7p9hyy",
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("cli", () => {
|
||||
|
@ -409,3 +438,28 @@ describe("cli", () => {
|
|||
expect(await shouldOpenInExistingInstance(args)).toStrictEqual(undefined)
|
||||
})
|
||||
})
|
||||
|
||||
describe("splitOnFirstEquals", () => {
|
||||
it("should split on the first equals", () => {
|
||||
const testStr = "enabled-proposed-api=test=value"
|
||||
const actual = splitOnFirstEquals(testStr)
|
||||
const expected = ["enabled-proposed-api", "test=value"]
|
||||
expect(actual).toEqual(expect.arrayContaining(expected))
|
||||
})
|
||||
it("should split on first equals regardless of multiple equals signs", () => {
|
||||
const testStr =
|
||||
"hashed-password=$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY"
|
||||
const actual = splitOnFirstEquals(testStr)
|
||||
const expected = [
|
||||
"hashed-password",
|
||||
"$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY",
|
||||
]
|
||||
expect(actual).toEqual(expect.arrayContaining(expected))
|
||||
})
|
||||
it("should always return the first element before an equals", () => {
|
||||
const testStr = "auth="
|
||||
const actual = splitOnFirstEquals(testStr)
|
||||
const expected = ["auth"]
|
||||
expect(actual).toEqual(expect.arrayContaining(expected))
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
import {
|
||||
hash,
|
||||
isHashMatch,
|
||||
handlePasswordValidation,
|
||||
PasswordMethod,
|
||||
getPasswordMethod,
|
||||
hashLegacy,
|
||||
isHashLegacyMatch,
|
||||
isCookieValid,
|
||||
sanitizeString,
|
||||
} from "../../../src/node/util"
|
||||
|
||||
describe("getEnvPaths", () => {
|
||||
describe("on darwin", () => {
|
||||
let ORIGINAL_PLATFORM = ""
|
||||
|
@ -145,3 +157,253 @@ describe("getEnvPaths", () => {
|
|||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("hash", () => {
|
||||
it("should return a hash of the string passed in", async () => {
|
||||
const plainTextPassword = "mySecretPassword123"
|
||||
const hashed = await hash(plainTextPassword)
|
||||
expect(hashed).not.toBe(plainTextPassword)
|
||||
})
|
||||
})
|
||||
|
||||
describe("isHashMatch", () => {
|
||||
it("should return true if the password matches the hash", async () => {
|
||||
const password = "codeserver1234"
|
||||
const _hash = await hash(password)
|
||||
const actual = await isHashMatch(password, _hash)
|
||||
expect(actual).toBe(true)
|
||||
})
|
||||
it("should return false if the password does not match the hash", async () => {
|
||||
const password = "password123"
|
||||
const _hash = await hash(password)
|
||||
const actual = await isHashMatch("otherPassword123", _hash)
|
||||
expect(actual).toBe(false)
|
||||
})
|
||||
it("should return true with actual hash", async () => {
|
||||
const password = "password123"
|
||||
const _hash = "$argon2i$v=19$m=4096,t=3,p=1$EAoczTxVki21JDfIZpTUxg$rkXgyrW4RDGoDYrxBFD4H2DlSMEhP4h+Api1hXnGnFY"
|
||||
const actual = await isHashMatch(password, _hash)
|
||||
expect(actual).toBe(true)
|
||||
})
|
||||
it("should return false if the password is empty", async () => {
|
||||
const password = ""
|
||||
const _hash = "$argon2i$v=19$m=4096,t=3,p=1$EAoczTxVki21JDfIZpTUxg$rkXgyrW4RDGoDYrxBFD4H2DlSMEhP4h+Api1hXnGnFY"
|
||||
const actual = await isHashMatch(password, _hash)
|
||||
expect(actual).toBe(false)
|
||||
})
|
||||
it("should return false if the hash is empty", async () => {
|
||||
const password = "hellowpasssword"
|
||||
const _hash = ""
|
||||
const actual = await isHashMatch(password, _hash)
|
||||
expect(actual).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe("hashLegacy", () => {
|
||||
it("should return a hash of the string passed in", () => {
|
||||
const plainTextPassword = "mySecretPassword123"
|
||||
const hashed = hashLegacy(plainTextPassword)
|
||||
expect(hashed).not.toBe(plainTextPassword)
|
||||
})
|
||||
})
|
||||
|
||||
describe("isHashLegacyMatch", () => {
|
||||
it("should return true if is match", () => {
|
||||
const password = "password123"
|
||||
const _hash = hashLegacy(password)
|
||||
expect(isHashLegacyMatch(password, _hash)).toBe(true)
|
||||
})
|
||||
it("should return false if is match", () => {
|
||||
const password = "password123"
|
||||
const _hash = hashLegacy(password)
|
||||
expect(isHashLegacyMatch("otherPassword123", _hash)).toBe(false)
|
||||
})
|
||||
it("should return true if hashed from command line", () => {
|
||||
const password = "password123"
|
||||
// Hashed using printf "password123" | sha256sum | cut -d' ' -f1
|
||||
const _hash = "ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f"
|
||||
expect(isHashLegacyMatch(password, _hash)).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("getPasswordMethod", () => {
|
||||
it("should return PLAIN_TEXT for no hashed password", () => {
|
||||
const hashedPassword = undefined
|
||||
const passwordMethod = getPasswordMethod(hashedPassword)
|
||||
const expected: PasswordMethod = "PLAIN_TEXT"
|
||||
expect(passwordMethod).toEqual(expected)
|
||||
})
|
||||
it("should return ARGON2 for password with 'argon2'", () => {
|
||||
const hashedPassword =
|
||||
"$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY"
|
||||
const passwordMethod = getPasswordMethod(hashedPassword)
|
||||
const expected: PasswordMethod = "ARGON2"
|
||||
expect(passwordMethod).toEqual(expected)
|
||||
})
|
||||
it("should return SHA256 for password with legacy hash", () => {
|
||||
const hashedPassword = "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af"
|
||||
const passwordMethod = getPasswordMethod(hashedPassword)
|
||||
const expected: PasswordMethod = "SHA256"
|
||||
expect(passwordMethod).toEqual(expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe("handlePasswordValidation", () => {
|
||||
it("should return true with a hashedPassword for a PLAIN_TEXT password", async () => {
|
||||
const p = "password"
|
||||
const passwordValidation = await handlePasswordValidation({
|
||||
passwordMethod: "PLAIN_TEXT",
|
||||
passwordFromRequestBody: p,
|
||||
passwordFromArgs: p,
|
||||
hashedPasswordFromArgs: undefined,
|
||||
})
|
||||
|
||||
const matchesHash = await isHashMatch(p, passwordValidation.hashedPassword)
|
||||
|
||||
expect(passwordValidation.isPasswordValid).toBe(true)
|
||||
expect(matchesHash).toBe(true)
|
||||
})
|
||||
it("should return false when PLAIN_TEXT password doesn't match args", async () => {
|
||||
const p = "password"
|
||||
const passwordValidation = await handlePasswordValidation({
|
||||
passwordMethod: "PLAIN_TEXT",
|
||||
passwordFromRequestBody: "password1",
|
||||
passwordFromArgs: p,
|
||||
hashedPasswordFromArgs: undefined,
|
||||
})
|
||||
|
||||
const matchesHash = await isHashMatch(p, passwordValidation.hashedPassword)
|
||||
|
||||
expect(passwordValidation.isPasswordValid).toBe(false)
|
||||
expect(matchesHash).toBe(false)
|
||||
})
|
||||
it("should return true with a hashedPassword for a SHA256 password", async () => {
|
||||
const p = "helloworld"
|
||||
const passwordValidation = await handlePasswordValidation({
|
||||
passwordMethod: "SHA256",
|
||||
passwordFromRequestBody: p,
|
||||
passwordFromArgs: undefined,
|
||||
hashedPasswordFromArgs: "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af",
|
||||
})
|
||||
|
||||
const matchesHash = isHashLegacyMatch(p, passwordValidation.hashedPassword)
|
||||
|
||||
expect(passwordValidation.isPasswordValid).toBe(true)
|
||||
expect(matchesHash).toBe(true)
|
||||
})
|
||||
it("should return false when SHA256 password doesn't match hash", async () => {
|
||||
const p = "helloworld1"
|
||||
const passwordValidation = await handlePasswordValidation({
|
||||
passwordMethod: "SHA256",
|
||||
passwordFromRequestBody: p,
|
||||
passwordFromArgs: undefined,
|
||||
hashedPasswordFromArgs: "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af",
|
||||
})
|
||||
|
||||
const matchesHash = isHashLegacyMatch(p, passwordValidation.hashedPassword)
|
||||
|
||||
expect(passwordValidation.isPasswordValid).toBe(false)
|
||||
expect(matchesHash).toBe(false)
|
||||
})
|
||||
it("should return true with a hashedPassword for a ARGON2 password", async () => {
|
||||
const p = "password"
|
||||
const passwordValidation = await handlePasswordValidation({
|
||||
passwordMethod: "ARGON2",
|
||||
passwordFromRequestBody: p,
|
||||
passwordFromArgs: undefined,
|
||||
hashedPasswordFromArgs:
|
||||
"$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY",
|
||||
})
|
||||
|
||||
const matchesHash = await isHashMatch(p, passwordValidation.hashedPassword)
|
||||
|
||||
expect(passwordValidation.isPasswordValid).toBe(true)
|
||||
expect(matchesHash).toBe(true)
|
||||
})
|
||||
it("should return false when ARGON2 password doesn't match hash", async () => {
|
||||
const p = "password1"
|
||||
const passwordValidation = await handlePasswordValidation({
|
||||
passwordMethod: "ARGON2",
|
||||
passwordFromRequestBody: p,
|
||||
passwordFromArgs: undefined,
|
||||
hashedPasswordFromArgs:
|
||||
"$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY",
|
||||
})
|
||||
|
||||
const matchesHash = await isHashMatch(p, passwordValidation.hashedPassword)
|
||||
|
||||
expect(passwordValidation.isPasswordValid).toBe(false)
|
||||
expect(matchesHash).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe("isCookieValid", () => {
|
||||
it("should be valid if hashed-password for SHA256 matches cookie.key", async () => {
|
||||
const isValid = await isCookieValid({
|
||||
passwordMethod: "SHA256",
|
||||
cookieKey: "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af",
|
||||
hashedPasswordFromArgs: "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af",
|
||||
passwordFromArgs: undefined,
|
||||
})
|
||||
expect(isValid).toBe(true)
|
||||
})
|
||||
it("should be invalid if hashed-password for SHA256 does not match cookie.key", async () => {
|
||||
const isValid = await isCookieValid({
|
||||
passwordMethod: "SHA256",
|
||||
cookieKey: "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb9442bb6f8f8f07af",
|
||||
hashedPasswordFromArgs: "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af",
|
||||
passwordFromArgs: undefined,
|
||||
})
|
||||
expect(isValid).toBe(false)
|
||||
})
|
||||
it("should be valid if hashed-password for ARGON2 matches cookie.key", async () => {
|
||||
const isValid = await isCookieValid({
|
||||
passwordMethod: "ARGON2",
|
||||
cookieKey: "$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY",
|
||||
hashedPasswordFromArgs:
|
||||
"$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY",
|
||||
passwordFromArgs: undefined,
|
||||
})
|
||||
expect(isValid).toBe(true)
|
||||
})
|
||||
it("should be invalid if hashed-password for ARGON2 does not match cookie.key", async () => {
|
||||
const isValid = await isCookieValid({
|
||||
passwordMethod: "ARGON2",
|
||||
cookieKey: "$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9H",
|
||||
hashedPasswordFromArgs:
|
||||
"$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY",
|
||||
passwordFromArgs: undefined,
|
||||
})
|
||||
expect(isValid).toBe(false)
|
||||
})
|
||||
it("should be valid if password for PLAIN_TEXT matches cookie.key", async () => {
|
||||
const isValid = await isCookieValid({
|
||||
passwordMethod: "PLAIN_TEXT",
|
||||
cookieKey: "$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY",
|
||||
passwordFromArgs: "password",
|
||||
hashedPasswordFromArgs: undefined,
|
||||
})
|
||||
expect(isValid).toBe(true)
|
||||
})
|
||||
it("should be invalid if hashed-password for PLAIN_TEXT does not match cookie.key", async () => {
|
||||
const isValid = await isCookieValid({
|
||||
passwordMethod: "PLAIN_TEXT",
|
||||
cookieKey: "$argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9H",
|
||||
passwordFromArgs: "password1234",
|
||||
hashedPasswordFromArgs: undefined,
|
||||
})
|
||||
expect(isValid).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe("sanitizeString", () => {
|
||||
it("should return an empty string if passed a type other than a string", () => {
|
||||
expect(sanitizeString({} as string)).toBe("")
|
||||
})
|
||||
it("should trim whitespace", () => {
|
||||
expect(sanitizeString(" hello ")).toBe("hello")
|
||||
})
|
||||
it("should always return an empty string", () => {
|
||||
expect(sanitizeString(" ")).toBe("")
|
||||
})
|
||||
})
|
||||
|
|
271
test/yarn.lock
271
test/yarn.lock
|
@ -1258,6 +1258,26 @@
|
|||
"@types/yargs" "^15.0.0"
|
||||
chalk "^4.0.0"
|
||||
|
||||
"@mapbox/node-pre-gyp@^1.0.1":
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz#2a0b32fcb416fb3f2250fd24cb2a81421a4f5950"
|
||||
integrity sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==
|
||||
dependencies:
|
||||
detect-libc "^1.0.3"
|
||||
https-proxy-agent "^5.0.0"
|
||||
make-dir "^3.1.0"
|
||||
node-fetch "^2.6.1"
|
||||
nopt "^5.0.0"
|
||||
npmlog "^4.1.2"
|
||||
rimraf "^3.0.2"
|
||||
semver "^7.3.4"
|
||||
tar "^6.1.0"
|
||||
|
||||
"@phc/format@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@phc/format/-/format-1.0.0.tgz#b5627003b3216dc4362125b13f48a4daa76680e4"
|
||||
integrity sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==
|
||||
|
||||
"@playwright/test@^0.1101.0-alpha2":
|
||||
version "0.1101.0-alpha2"
|
||||
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-0.1101.0-alpha2.tgz#a1121ac70e6ac986532ea63c6f565f06fae99364"
|
||||
|
@ -1439,6 +1459,11 @@ abab@^2.0.3:
|
|||
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
|
||||
integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==
|
||||
|
||||
abbrev@1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
||||
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
|
||||
|
||||
acorn-globals@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45"
|
||||
|
@ -1481,6 +1506,16 @@ ansi-escapes@^4.2.1:
|
|||
dependencies:
|
||||
type-fest "^0.11.0"
|
||||
|
||||
ansi-regex@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
||||
integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
|
||||
|
||||
ansi-regex@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
|
||||
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
|
||||
|
||||
ansi-regex@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
|
||||
|
@ -1516,6 +1551,29 @@ anymatch@^3.0.3:
|
|||
normalize-path "^3.0.0"
|
||||
picomatch "^2.0.4"
|
||||
|
||||
aproba@^1.0.3:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
|
||||
integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
|
||||
|
||||
are-we-there-yet@~1.1.2:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
|
||||
integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==
|
||||
dependencies:
|
||||
delegates "^1.0.0"
|
||||
readable-stream "^2.0.6"
|
||||
|
||||
argon2@^0.28.0:
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/argon2/-/argon2-0.28.0.tgz#b32ea7526457f5593dda51c5a8e542bde3ba2621"
|
||||
integrity sha512-bFgoLJbfNVbceXO9h8wKytoqBWyDsROp0HVlhtpyXCwq/izvMJ7CKZdDQp8y0T4yKAQHKD1vuW0C1INdjYdRsw==
|
||||
dependencies:
|
||||
"@mapbox/node-pre-gyp" "^1.0.1"
|
||||
"@phc/format" "^1.0.0"
|
||||
node-addon-api "^3.0.2"
|
||||
opencollective-postinstall "^2.0.3"
|
||||
|
||||
argparse@^1.0.7:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
|
||||
|
@ -1845,6 +1903,11 @@ char-regex@^1.0.2:
|
|||
resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
|
||||
integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==
|
||||
|
||||
chownr@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
|
||||
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
|
||||
|
||||
ci-info@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
|
||||
|
@ -1879,6 +1942,11 @@ co@^4.6.0:
|
|||
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
|
||||
integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
|
||||
|
||||
code-point-at@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
|
||||
|
||||
collect-v8-coverage@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59"
|
||||
|
@ -1948,6 +2016,11 @@ concat-map@0.0.1:
|
|||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
console-control-strings@^1.0.0, console-control-strings@~1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
|
||||
integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
|
||||
|
||||
convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
|
||||
|
@ -1973,7 +2046,7 @@ core-js-compat@^3.9.0, core-js-compat@^3.9.1:
|
|||
browserslist "^4.16.3"
|
||||
semver "7.0.0"
|
||||
|
||||
core-util-is@1.0.2:
|
||||
core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
@ -2104,6 +2177,16 @@ delayed-stream@~1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
|
||||
|
||||
delegates@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
|
||||
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
|
||||
|
||||
detect-libc@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
|
||||
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
|
||||
|
||||
detect-newline@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
|
||||
|
@ -2442,6 +2525,13 @@ fragment-cache@^0.2.1:
|
|||
dependencies:
|
||||
map-cache "^0.2.2"
|
||||
|
||||
fs-minipass@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
||||
integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
|
@ -2476,6 +2566,20 @@ function-bind@^1.1.1:
|
|||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||
|
||||
gauge@~2.7.3:
|
||||
version "2.7.4"
|
||||
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
|
||||
integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=
|
||||
dependencies:
|
||||
aproba "^1.0.3"
|
||||
console-control-strings "^1.0.0"
|
||||
has-unicode "^2.0.0"
|
||||
object-assign "^4.1.0"
|
||||
signal-exit "^3.0.0"
|
||||
string-width "^1.0.1"
|
||||
strip-ansi "^3.0.1"
|
||||
wide-align "^1.1.0"
|
||||
|
||||
gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2:
|
||||
version "1.0.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||
|
@ -2586,6 +2690,11 @@ has-symbols@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
|
||||
integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==
|
||||
|
||||
has-unicode@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
|
||||
integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
|
||||
|
||||
has-value@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
|
||||
|
@ -2691,7 +2800,7 @@ inflight@^1.0.4:
|
|||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@^2.0.3, inherits@~2.0.0:
|
||||
inherits@2, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
@ -2788,6 +2897,18 @@ is-extendable@^1.0.1:
|
|||
dependencies:
|
||||
is-plain-object "^2.0.4"
|
||||
|
||||
is-fullwidth-code-point@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
|
||||
integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
|
||||
dependencies:
|
||||
number-is-nan "^1.0.0"
|
||||
|
||||
is-fullwidth-code-point@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
|
||||
integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
|
||||
|
||||
is-fullwidth-code-point@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||
|
@ -2849,7 +2970,7 @@ is-wsl@^2.2.0:
|
|||
dependencies:
|
||||
is-docker "^2.0.0"
|
||||
|
||||
isarray@1.0.0:
|
||||
isarray@1.0.0, isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||
|
@ -3473,7 +3594,7 @@ lru-cache@^6.0.0:
|
|||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
make-dir@^3.0.0:
|
||||
make-dir@^3.0.0, make-dir@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
|
||||
integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
|
||||
|
@ -3575,6 +3696,21 @@ minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5:
|
|||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||
|
||||
minipass@^3.0.0:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd"
|
||||
integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
minizlib@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
|
||||
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
yallist "^4.0.0"
|
||||
|
||||
mixin-deep@^1.2.0:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
|
||||
|
@ -3583,7 +3719,7 @@ mixin-deep@^1.2.0:
|
|||
for-in "^1.0.2"
|
||||
is-extendable "^1.0.1"
|
||||
|
||||
mkdirp@1.x:
|
||||
mkdirp@1.x, mkdirp@^1.0.3:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
|
@ -3637,6 +3773,11 @@ nice-try@^1.0.4:
|
|||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||
|
||||
node-addon-api@^3.0.2:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161"
|
||||
integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==
|
||||
|
||||
node-fetch@^2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
|
||||
|
@ -3669,6 +3810,13 @@ node-releases@^1.1.71:
|
|||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe"
|
||||
integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==
|
||||
|
||||
nopt@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
|
||||
integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==
|
||||
dependencies:
|
||||
abbrev "1"
|
||||
|
||||
normalize-package-data@^2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
|
||||
|
@ -3705,6 +3853,21 @@ npm-run-path@^4.0.0:
|
|||
dependencies:
|
||||
path-key "^3.0.0"
|
||||
|
||||
npmlog@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
|
||||
integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
|
||||
dependencies:
|
||||
are-we-there-yet "~1.1.2"
|
||||
console-control-strings "~1.1.0"
|
||||
gauge "~2.7.3"
|
||||
set-blocking "~2.0.0"
|
||||
|
||||
number-is-nan@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
||||
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
|
||||
|
||||
nwsapi@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
|
||||
|
@ -3715,6 +3878,11 @@ oauth-sign@~0.9.0:
|
|||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||
|
||||
object-assign@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
||||
object-copy@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
|
||||
|
@ -3767,6 +3935,11 @@ onetime@^5.1.0:
|
|||
dependencies:
|
||||
mimic-fn "^2.1.0"
|
||||
|
||||
opencollective-postinstall@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259"
|
||||
integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==
|
||||
|
||||
optionator@^0.8.1:
|
||||
version "0.8.3"
|
||||
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
|
||||
|
@ -3938,6 +4111,11 @@ pretty-format@^26.0.0, pretty-format@^26.4.2, pretty-format@^26.6.2:
|
|||
ansi-styles "^4.0.0"
|
||||
react-is "^17.0.1"
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||
|
||||
progress@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
||||
|
@ -4017,6 +4195,19 @@ read-pkg@^5.2.0:
|
|||
parse-json "^5.0.0"
|
||||
type-fest "^0.6.0"
|
||||
|
||||
readable-stream@^2.0.6:
|
||||
version "2.3.7"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.3"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~2.0.0"
|
||||
safe-buffer "~5.1.1"
|
||||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readable-stream@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||
|
@ -4216,7 +4407,7 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
|
|||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
|
||||
safe-buffer@~5.1.1:
|
||||
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
|
@ -4277,7 +4468,14 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
|
|||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
|
||||
set-blocking@^2.0.0:
|
||||
semver@^7.3.4:
|
||||
version "7.3.5"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
|
||||
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
set-blocking@^2.0.0, set-blocking@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
|
||||
|
@ -4486,6 +4684,23 @@ string-length@^4.0.1:
|
|||
char-regex "^1.0.2"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
string-width@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
|
||||
integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
|
||||
dependencies:
|
||||
code-point-at "^1.0.0"
|
||||
is-fullwidth-code-point "^1.0.0"
|
||||
strip-ansi "^3.0.0"
|
||||
|
||||
"string-width@^1.0.2 || 2":
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
|
||||
integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
|
||||
dependencies:
|
||||
is-fullwidth-code-point "^2.0.0"
|
||||
strip-ansi "^4.0.0"
|
||||
|
||||
string-width@^4.1.0, string-width@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5"
|
||||
|
@ -4502,6 +4717,27 @@ string_decoder@^1.1.1:
|
|||
dependencies:
|
||||
safe-buffer "~5.2.0"
|
||||
|
||||
string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
|
||||
integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
|
||||
dependencies:
|
||||
ansi-regex "^2.0.0"
|
||||
|
||||
strip-ansi@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
|
||||
integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
|
||||
dependencies:
|
||||
ansi-regex "^3.0.0"
|
||||
|
||||
strip-ansi@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
|
||||
|
@ -4576,6 +4812,18 @@ symbol-tree@^3.2.4:
|
|||
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
|
||||
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
|
||||
|
||||
tar@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83"
|
||||
integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==
|
||||
dependencies:
|
||||
chownr "^2.0.0"
|
||||
fs-minipass "^2.0.0"
|
||||
minipass "^3.0.0"
|
||||
minizlib "^2.1.1"
|
||||
mkdirp "^1.0.3"
|
||||
yallist "^4.0.0"
|
||||
|
||||
terminal-link@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994"
|
||||
|
@ -4785,7 +5033,7 @@ use@^3.1.0:
|
|||
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
|
||||
integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
|
||||
|
||||
util-deprecate@^1.0.1:
|
||||
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
|
@ -4897,6 +5145,13 @@ which@^2.0.1, which@^2.0.2:
|
|||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
wide-align@^1.1.0:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
|
||||
integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==
|
||||
dependencies:
|
||||
string-width "^1.0.2 || 2"
|
||||
|
||||
word-wrap@~1.2.3:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
||||
|
|
|
@ -145,12 +145,16 @@ export const proxy: ProxyServer
|
|||
/**
|
||||
* Middleware to ensure the user is authenticated. Throws if they are not.
|
||||
*/
|
||||
export function ensureAuthenticated(req: express.Request, res?: express.Response, next?: express.NextFunction): void
|
||||
export function ensureAuthenticated(
|
||||
req: express.Request,
|
||||
res?: express.Response,
|
||||
next?: express.NextFunction,
|
||||
): Promise<void>
|
||||
|
||||
/**
|
||||
* Returns true if the user is authenticated.
|
||||
*/
|
||||
export function authenticated(req: express.Request): boolean
|
||||
export function authenticated(req: express.Request): Promise<void>
|
||||
|
||||
/**
|
||||
* Replace variables in HTML: TO, BASE, CS_STATIC_BASE, and OPTIONS.
|
||||
|
|
230
yarn.lock
230
yarn.lock
|
@ -896,6 +896,21 @@
|
|||
resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c"
|
||||
integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==
|
||||
|
||||
"@mapbox/node-pre-gyp@^1.0.1":
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz#2a0b32fcb416fb3f2250fd24cb2a81421a4f5950"
|
||||
integrity sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==
|
||||
dependencies:
|
||||
detect-libc "^1.0.3"
|
||||
https-proxy-agent "^5.0.0"
|
||||
make-dir "^3.1.0"
|
||||
node-fetch "^2.6.1"
|
||||
nopt "^5.0.0"
|
||||
npmlog "^4.1.2"
|
||||
rimraf "^3.0.2"
|
||||
semver "^7.3.4"
|
||||
tar "^6.1.0"
|
||||
|
||||
"@mrmlnc/readdir-enhanced@^2.2.1":
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
|
||||
|
@ -971,6 +986,11 @@
|
|||
"@parcel/utils" "^1.11.0"
|
||||
physical-cpu-count "^2.0.0"
|
||||
|
||||
"@phc/format@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@phc/format/-/format-1.0.0.tgz#b5627003b3216dc4362125b13f48a4daa76680e4"
|
||||
integrity sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==
|
||||
|
||||
"@schemastore/package@^0.0.6":
|
||||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@schemastore/package/-/package-0.0.6.tgz#9a76713da1c7551293b7e72e4f387f802bfd5d81"
|
||||
|
@ -1317,6 +1337,11 @@ abab@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
|
||||
integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==
|
||||
|
||||
abbrev@1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
||||
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
|
||||
|
||||
accepts@~1.3.5, accepts@~1.3.7:
|
||||
version "1.3.7"
|
||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
|
||||
|
@ -1397,6 +1422,11 @@ ansi-colors@^4.1.1:
|
|||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
||||
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
|
||||
|
||||
ansi-regex@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
||||
integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
|
||||
|
||||
ansi-regex@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
|
||||
|
@ -1436,11 +1466,34 @@ anymatch@^2.0.0:
|
|||
micromatch "^3.1.4"
|
||||
normalize-path "^2.1.1"
|
||||
|
||||
aproba@^1.0.3:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
|
||||
integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
|
||||
|
||||
are-we-there-yet@~1.1.2:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
|
||||
integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==
|
||||
dependencies:
|
||||
delegates "^1.0.0"
|
||||
readable-stream "^2.0.6"
|
||||
|
||||
arg@^4.1.0:
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
|
||||
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
|
||||
|
||||
argon2@^0.28.0:
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/argon2/-/argon2-0.28.0.tgz#b32ea7526457f5593dda51c5a8e542bde3ba2621"
|
||||
integrity sha512-bFgoLJbfNVbceXO9h8wKytoqBWyDsROp0HVlhtpyXCwq/izvMJ7CKZdDQp8y0T4yKAQHKD1vuW0C1INdjYdRsw==
|
||||
dependencies:
|
||||
"@mapbox/node-pre-gyp" "^1.0.1"
|
||||
"@phc/format" "^1.0.0"
|
||||
node-addon-api "^3.0.2"
|
||||
opencollective-postinstall "^2.0.3"
|
||||
|
||||
argparse@^1.0.7:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
|
||||
|
@ -2110,6 +2163,11 @@ chownr@^1.1.1:
|
|||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
||||
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
|
||||
|
||||
chownr@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
|
||||
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
|
||||
|
||||
cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
|
||||
|
@ -2175,6 +2233,11 @@ coa@^2.0.2:
|
|||
chalk "^2.4.1"
|
||||
q "^1.1.2"
|
||||
|
||||
code-point-at@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
|
||||
|
||||
codecov@^3.8.1:
|
||||
version "3.8.2"
|
||||
resolved "https://registry.yarnpkg.com/codecov/-/codecov-3.8.2.tgz#ab24f18783998c39e809ea210af899f8dbcc790e"
|
||||
|
@ -2316,6 +2379,11 @@ console-browserify@^1.1.0:
|
|||
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
|
||||
integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==
|
||||
|
||||
console-control-strings@^1.0.0, console-control-strings@~1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
|
||||
integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
|
||||
|
||||
constants-browserify@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
|
||||
|
@ -2848,6 +2916,11 @@ delayed-stream@~1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
|
||||
|
||||
delegates@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
|
||||
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
|
||||
|
||||
depd@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
||||
|
@ -2866,6 +2939,11 @@ destroy@~1.0.4:
|
|||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
|
||||
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
|
||||
|
||||
detect-libc@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
|
||||
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
|
||||
|
||||
diff@^4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
|
||||
|
@ -3730,6 +3808,13 @@ fs-extra@^8.1.0:
|
|||
jsonfile "^4.0.0"
|
||||
universalify "^0.1.0"
|
||||
|
||||
fs-minipass@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
||||
integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
|
@ -3761,6 +3846,20 @@ functional-red-black-tree@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
|
||||
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
|
||||
|
||||
gauge@~2.7.3:
|
||||
version "2.7.4"
|
||||
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
|
||||
integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=
|
||||
dependencies:
|
||||
aproba "^1.0.3"
|
||||
console-control-strings "^1.0.0"
|
||||
has-unicode "^2.0.0"
|
||||
object-assign "^4.1.0"
|
||||
signal-exit "^3.0.0"
|
||||
string-width "^1.0.1"
|
||||
strip-ansi "^3.0.1"
|
||||
wide-align "^1.1.0"
|
||||
|
||||
gensync@^1.0.0-beta.2:
|
||||
version "1.0.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||
|
@ -3949,6 +4048,11 @@ has-symbols@^1.0.1, has-symbols@^1.0.2:
|
|||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
|
||||
integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==
|
||||
|
||||
has-unicode@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
|
||||
integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
|
||||
|
||||
has-value@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
|
||||
|
@ -4438,6 +4542,18 @@ is-extglob@^2.1.0, is-extglob@^2.1.1:
|
|||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
|
||||
|
||||
is-fullwidth-code-point@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
|
||||
integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
|
||||
dependencies:
|
||||
number-is-nan "^1.0.0"
|
||||
|
||||
is-fullwidth-code-point@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
|
||||
integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
|
||||
|
||||
is-fullwidth-code-point@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||
|
@ -4928,6 +5044,13 @@ magic-string@^0.22.4:
|
|||
dependencies:
|
||||
vlq "^0.2.2"
|
||||
|
||||
make-dir@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
|
||||
integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
|
||||
dependencies:
|
||||
semver "^6.0.0"
|
||||
|
||||
make-error@^1.1.1:
|
||||
version "1.3.6"
|
||||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
|
||||
|
@ -5172,6 +5295,21 @@ minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.5:
|
|||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||
|
||||
minipass@^3.0.0:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd"
|
||||
integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
minizlib@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
|
||||
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
|
||||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
yallist "^4.0.0"
|
||||
|
||||
mixin-deep@^1.2.0:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
|
||||
|
@ -5192,6 +5330,11 @@ mkdirp@^0.5.1, mkdirp@~0.5.1:
|
|||
dependencies:
|
||||
minimist "^1.2.5"
|
||||
|
||||
mkdirp@^1.0.3:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
|
@ -5269,6 +5412,11 @@ node-addon-api@^1.7.1:
|
|||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.2.tgz#3df30b95720b53c24e59948b49532b662444f54d"
|
||||
integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==
|
||||
|
||||
node-addon-api@^3.0.2:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161"
|
||||
integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==
|
||||
|
||||
node-fetch@^2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
|
||||
|
@ -5313,6 +5461,13 @@ node-releases@^1.1.71:
|
|||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb"
|
||||
integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==
|
||||
|
||||
nopt@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
|
||||
integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==
|
||||
dependencies:
|
||||
abbrev "1"
|
||||
|
||||
normalize-package-data@^2.3.2, normalize-package-data@^2.5.0, normalize-package-data@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.1.tgz#98dc56dfe6755d99b1c53f046e1e3d2dde55a1c7"
|
||||
|
@ -5355,6 +5510,16 @@ normalize-url@^4.5.0:
|
|||
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129"
|
||||
integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==
|
||||
|
||||
npmlog@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
|
||||
integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
|
||||
dependencies:
|
||||
are-we-there-yet "~1.1.2"
|
||||
console-control-strings "~1.1.0"
|
||||
gauge "~2.7.3"
|
||||
set-blocking "~2.0.0"
|
||||
|
||||
nth-check@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c"
|
||||
|
@ -5374,6 +5539,11 @@ num2fraction@^1.2.2:
|
|||
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
|
||||
integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=
|
||||
|
||||
number-is-nan@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
||||
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
|
||||
|
||||
nwsapi@^2.1.3:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
|
||||
|
@ -5384,7 +5554,7 @@ oauth-sign@~0.9.0:
|
|||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||
|
||||
object-assign@^4.1.1:
|
||||
object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
@ -5482,6 +5652,11 @@ onetime@^2.0.0:
|
|||
dependencies:
|
||||
mimic-fn "^1.0.0"
|
||||
|
||||
opencollective-postinstall@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259"
|
||||
integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==
|
||||
|
||||
opn@^5.1.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc"
|
||||
|
@ -6760,7 +6935,7 @@ readable-stream@1.1.x:
|
|||
isarray "0.0.1"
|
||||
string_decoder "~0.10.x"
|
||||
|
||||
readable-stream@^2.0.2, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.6:
|
||||
readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.6:
|
||||
version "2.3.7"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||
|
@ -7158,12 +7333,12 @@ semver@^5.4.1, semver@^5.5.0:
|
|||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
|
||||
semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
|
||||
semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
|
||||
semver@^7.0.0, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.5:
|
||||
semver@^7.0.0, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5:
|
||||
version "7.3.5"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
|
||||
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
|
||||
|
@ -7204,7 +7379,7 @@ serve-static@1.14.1, serve-static@^1.12.4:
|
|||
parseurl "~1.3.3"
|
||||
send "0.17.1"
|
||||
|
||||
set-blocking@^2.0.0:
|
||||
set-blocking@^2.0.0, set-blocking@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
|
||||
|
@ -7276,7 +7451,7 @@ shellcheck@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/shellcheck/-/shellcheck-1.0.0.tgz#263479d92c3708d63d98883f896481461cf17cd0"
|
||||
integrity sha512-CdKbWXOknBwE1wNQzAnwfLf7QNOu/yqyLSGBKoq2WuChEqfg7dnZJ1pHR2P463PbVpBRz3KGkYnXJCoQrPwtYA==
|
||||
|
||||
signal-exit@^3.0.2:
|
||||
signal-exit@^3.0.0, signal-exit@^3.0.2:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
|
||||
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
|
||||
|
@ -7559,6 +7734,23 @@ stream-http@^2.7.2:
|
|||
to-arraybuffer "^1.0.0"
|
||||
xtend "^4.0.0"
|
||||
|
||||
string-width@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
|
||||
integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
|
||||
dependencies:
|
||||
code-point-at "^1.0.0"
|
||||
is-fullwidth-code-point "^1.0.0"
|
||||
strip-ansi "^3.0.0"
|
||||
|
||||
"string-width@^1.0.2 || 2":
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
|
||||
integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
|
||||
dependencies:
|
||||
is-fullwidth-code-point "^2.0.0"
|
||||
strip-ansi "^4.0.0"
|
||||
|
||||
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5"
|
||||
|
@ -7603,6 +7795,13 @@ string_decoder@~1.1.1:
|
|||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
|
||||
integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
|
||||
dependencies:
|
||||
ansi-regex "^2.0.0"
|
||||
|
||||
strip-ansi@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
|
||||
|
@ -7823,6 +8022,18 @@ tar-stream@^2.1.4, tar-stream@^2.2.0:
|
|||
inherits "^2.0.3"
|
||||
readable-stream "^3.1.1"
|
||||
|
||||
tar@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83"
|
||||
integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==
|
||||
dependencies:
|
||||
chownr "^2.0.0"
|
||||
fs-minipass "^2.0.0"
|
||||
minipass "^3.0.0"
|
||||
minizlib "^2.1.1"
|
||||
mkdirp "^1.0.3"
|
||||
yallist "^4.0.0"
|
||||
|
||||
teeny-request@7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-7.0.1.tgz#bdd41fdffea5f8fbc0d29392cb47bec4f66b2b4c"
|
||||
|
@ -8527,6 +8738,13 @@ which@^2.0.1, which@^2.0.2:
|
|||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
wide-align@^1.1.0:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
|
||||
integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==
|
||||
dependencies:
|
||||
string-width "^1.0.2 || 2"
|
||||
|
||||
word-wrap@^1.2.3, word-wrap@~1.2.3:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
||||
|
|
Loading…
Reference in New Issue