feat(tauri.js) add dependency manager command (#829)

This commit is contained in:
Lucas Fernandes Nogueira 2020-07-15 18:01:37 -03:00 committed by GitHub
parent 956c6d853e
commit 77282c1e51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 1124 additions and 74 deletions

View File

@ -0,0 +1,6 @@
---
"tauri.js": minor
---
Adds a dependency manager command to the Node.js CLI (`tauri deps`). The manager is able to install and update Rust and the Tauri ecosystem dependencies (npm package, crates, cargo subcommands).
Usage: `tauri deps install` and `tauri deps update`.

View File

@ -0,0 +1,22 @@
async function run() {
const {
installDependencies,
updateDependencies
} = require('../dist/api/dependency-manager')
const choice = process.argv[2]
if (choice === 'install') {
await installDependencies()
} else if (choice === 'update') {
await updateDependencies()
} else {
console.log(`
Description
Tauri dependency management script
Usage
$ tauri deps [install|update]
`)
}
}
run()

View File

@ -1,6 +1,6 @@
#!/usr/bin/env node
const cmds = ['init', 'dev', 'build', 'help', 'icon', 'info']
const cmds = ['init', 'dev', 'build', 'help', 'icon', 'info', 'deps']
const cmd = process.argv[2]
/**
@ -45,6 +45,8 @@ const tauri = function (command) {
console.log(`Invalid command ${command}. Use one of ${cmds.join(',')}.`)
}
}
module.exports = { tauri }
module.exports = {
tauri
}
tauri(cmd)

View File

@ -70,6 +70,7 @@
"ms": "2.1.2",
"png2icons": "2.0.1",
"read-chunk": "3.2.0",
"semver": "^7.3.2",
"sharp": "0.25.4",
"webpack-merge": "5.0.9",
"webpack-shell-plugin": "0.5.0"
@ -89,9 +90,11 @@
"@types/http-proxy": "1.17.4",
"@types/imagemin": "7.0.0",
"@types/imagemin-optipng": "5.2.0",
"@types/inquirer": "^6.5.0",
"@types/jsdom": "16.2.3",
"@types/lodash": "4.14.157",
"@types/ms": "0.7.31",
"@types/semver": "^7.3.1",
"@types/sharp": "0.25.0",
"@types/webpack-merge": "4.1.5",
"@typescript-eslint/eslint-plugin": "3.6.0",

Binary file not shown.

View File

@ -0,0 +1,553 @@
#!/bin/sh
# shellcheck shell=dash
# This is just a little script that can be downloaded from the internet to
# install rustup. It just does platform detection, downloads the installer
# and runs it.
# It runs on Unix shells like {a,ba,da,k,z}sh. It uses the common `local`
# extension. Note: Most shells limit `local` to 1 var per line, contra bash.
set -u
# If RUSTUP_UPDATE_ROOT is unset or empty, default it.
RUSTUP_UPDATE_ROOT="${RUSTUP_UPDATE_ROOT:-https://static.rust-lang.org/rustup}"
#XXX: If you change anything here, please make the same changes in setup_mode.rs
usage() {
cat 1>&2 <<EOF
rustup-init 1.22.1 (76644d669 2020-07-08)
The installer for rustup
USAGE:
rustup-init [FLAGS] [OPTIONS]
FLAGS:
-v, --verbose Enable verbose output
-q, --quiet Disable progress output
-y Disable confirmation prompt.
--no-modify-path Don't configure the PATH environment variable
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
--default-host <default-host> Choose a default host triple
--default-toolchain <default-toolchain> Choose a default toolchain to install
--default-toolchain none Do not install any toolchains
--profile [minimal|default|complete] Choose a profile
-c, --component <components>... Component name to also install
-t, --target <targets>... Target name to also install
EOF
}
main() {
downloader --check
need_cmd uname
need_cmd mktemp
need_cmd chmod
need_cmd mkdir
need_cmd rm
need_cmd rmdir
get_architecture || return 1
local _arch="$RETVAL"
assert_nz "$_arch" "arch"
local _ext=""
case "$_arch" in
*windows*)
_ext=".exe"
;;
esac
local _url="${RUSTUP_UPDATE_ROOT}/dist/${_arch}/rustup-init${_ext}"
local _dir
_dir="$(mktemp -d 2>/dev/null || ensure mktemp -d -t rustup)"
local _file="${_dir}/rustup-init${_ext}"
local _ansi_escapes_are_valid=false
if [ -t 2 ]; then
if [ "${TERM+set}" = 'set' ]; then
case "$TERM" in
xterm*|rxvt*|urxvt*|linux*|vt*)
_ansi_escapes_are_valid=true
;;
esac
fi
fi
# check if we have to use /dev/tty to prompt the user
local need_tty=yes
for arg in "$@"; do
case "$arg" in
-h|--help)
usage
exit 0
;;
-y)
# user wants to skip the prompt -- we don't need /dev/tty
need_tty=no
;;
*)
;;
esac
done
if $_ansi_escapes_are_valid; then
printf "\33[1minfo:\33[0m downloading installer\n" 1>&2
else
printf '%s\n' 'info: downloading installer' 1>&2
fi
ensure mkdir -p "$_dir"
ensure downloader "$_url" "$_file" "$_arch"
ensure chmod u+x "$_file"
if [ ! -x "$_file" ]; then
printf '%s\n' "Cannot execute $_file (likely because of mounting /tmp as noexec)." 1>&2
printf '%s\n' "Please copy the file to a location where you can execute binaries and run ./rustup-init${_ext}." 1>&2
exit 1
fi
if [ "$need_tty" = "yes" ]; then
# The installer is going to want to ask for confirmation by
# reading stdin. This script was piped into `sh` though and
# doesn't have stdin to pass to its children. Instead we're going
# to explicitly connect /dev/tty to the installer's stdin.
if [ ! -t 1 ]; then
err "Unable to run interactively. Run with -y to accept defaults, --help for additional options"
fi
ignore "$_file" "$@" < /dev/tty
else
ignore "$_file" "$@"
fi
local _retval=$?
ignore rm "$_file"
ignore rmdir "$_dir"
return "$_retval"
}
get_bitness() {
need_cmd head
# Architecture detection without dependencies beyond coreutils.
# ELF files start out "\x7fELF", and the following byte is
# 0x01 for 32-bit and
# 0x02 for 64-bit.
# The printf builtin on some shells like dash only supports octal
# escape sequences, so we use those.
local _current_exe_head
_current_exe_head=$(head -c 5 /proc/self/exe )
if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then
echo 32
elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then
echo 64
else
err "unknown platform bitness"
fi
}
get_endianness() {
local cputype=$1
local suffix_eb=$2
local suffix_el=$3
# detect endianness without od/hexdump, like get_bitness() does.
need_cmd head
need_cmd tail
local _current_exe_endianness
_current_exe_endianness="$(head -c 6 /proc/self/exe | tail -c 1)"
if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then
echo "${cputype}${suffix_el}"
elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then
echo "${cputype}${suffix_eb}"
else
err "unknown platform endianness"
fi
}
get_architecture() {
local _ostype _cputype _bitness _arch _clibtype
_ostype="$(uname -s)"
_cputype="$(uname -m)"
_clibtype="gnu"
if [ "$_ostype" = Linux ]; then
if [ "$(uname -o)" = Android ]; then
_ostype=Android
fi
if ldd --version 2>&1 | grep -q 'musl'; then
_clibtype="musl"
fi
fi
if [ "$_ostype" = Darwin ] && [ "$_cputype" = i386 ]; then
# Darwin `uname -m` lies
if sysctl hw.optional.x86_64 | grep -q ': 1'; then
_cputype=x86_64
fi
fi
case "$_ostype" in
Android)
_ostype=linux-android
;;
Linux)
_ostype=unknown-linux-$_clibtype
_bitness=$(get_bitness)
;;
FreeBSD)
_ostype=unknown-freebsd
;;
NetBSD)
_ostype=unknown-netbsd
;;
DragonFly)
_ostype=unknown-dragonfly
;;
Darwin)
_ostype=apple-darwin
;;
MINGW* | MSYS* | CYGWIN*)
_ostype=pc-windows-gnu
;;
*)
err "unrecognized OS type: $_ostype"
;;
esac
case "$_cputype" in
i386 | i486 | i686 | i786 | x86)
_cputype=i686
;;
xscale | arm)
_cputype=arm
if [ "$_ostype" = "linux-android" ]; then
_ostype=linux-androideabi
fi
;;
armv6l)
_cputype=arm
if [ "$_ostype" = "linux-android" ]; then
_ostype=linux-androideabi
else
_ostype="${_ostype}eabihf"
fi
;;
armv7l | armv8l)
_cputype=armv7
if [ "$_ostype" = "linux-android" ]; then
_ostype=linux-androideabi
else
_ostype="${_ostype}eabihf"
fi
;;
aarch64)
_cputype=aarch64
;;
x86_64 | x86-64 | x64 | amd64)
_cputype=x86_64
;;
mips)
_cputype=$(get_endianness mips '' el)
;;
mips64)
if [ "$_bitness" -eq 64 ]; then
# only n64 ABI is supported for now
_ostype="${_ostype}abi64"
_cputype=$(get_endianness mips64 '' el)
fi
;;
ppc)
_cputype=powerpc
;;
ppc64)
_cputype=powerpc64
;;
ppc64le)
_cputype=powerpc64le
;;
s390x)
_cputype=s390x
;;
riscv64)
_cputype=riscv64gc
;;
*)
err "unknown CPU type: $_cputype"
esac
# Detect 64-bit linux with 32-bit userland
if [ "${_ostype}" = unknown-linux-gnu ] && [ "${_bitness}" -eq 32 ]; then
case $_cputype in
x86_64)
_cputype=i686
;;
mips64)
_cputype=$(get_endianness mips '' el)
;;
powerpc64)
_cputype=powerpc
;;
aarch64)
_cputype=armv7
if [ "$_ostype" = "linux-android" ]; then
_ostype=linux-androideabi
else
_ostype="${_ostype}eabihf"
fi
;;
riscv64gc)
err "riscv64 with 32-bit userland unsupported"
;;
esac
fi
# Detect armv7 but without the CPU features Rust needs in that build,
# and fall back to arm.
# See https://github.com/rust-lang/rustup.rs/issues/587.
if [ "$_ostype" = "unknown-linux-gnueabihf" ] && [ "$_cputype" = armv7 ]; then
if ensure grep '^Features' /proc/cpuinfo | grep -q -v neon; then
# At least one processor does not have NEON.
_cputype=arm
fi
fi
_arch="${_cputype}-${_ostype}"
RETVAL="$_arch"
}
say() {
printf 'rustup: %s\n' "$1"
}
err() {
say "$1" >&2
exit 1
}
need_cmd() {
if ! check_cmd "$1"; then
err "need '$1' (command not found)"
fi
}
check_cmd() {
command -v "$1" > /dev/null 2>&1
}
assert_nz() {
if [ -z "$1" ]; then err "assert_nz $2"; fi
}
# Run a command that should never fail. If the command fails execution
# will immediately terminate with an error showing the failing
# command.
ensure() {
if ! "$@"; then err "command failed: $*"; fi
}
# This is just for indicating that commands' results are being
# intentionally ignored. Usually, because it's being executed
# as part of error handling.
ignore() {
"$@"
}
# This wraps curl or wget. Try curl first, if not installed,
# use wget instead.
downloader() {
local _dld
local _ciphersuites
if check_cmd curl; then
_dld=curl
elif check_cmd wget; then
_dld=wget
else
_dld='curl or wget' # to be used in error message of need_cmd
fi
if [ "$1" = --check ]; then
need_cmd "$_dld"
elif [ "$_dld" = curl ]; then
get_ciphersuites_for_curl
_ciphersuites="$RETVAL"
if [ -n "$_ciphersuites" ]; then
curl --proto '=https' --tlsv1.2 --ciphers "$_ciphersuites" --silent --show-error --fail --location "$1" --output "$2"
else
echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
if ! check_help_for "$3" curl --proto --tlsv1.2; then
echo "Warning: Not enforcing TLS v1.2, this is potentially less secure"
curl --silent --show-error --fail --location "$1" --output "$2"
else
curl --proto '=https' --tlsv1.2 --silent --show-error --fail --location "$1" --output "$2"
fi
fi
elif [ "$_dld" = wget ]; then
get_ciphersuites_for_wget
_ciphersuites="$RETVAL"
if [ -n "$_ciphersuites" ]; then
wget --https-only --secure-protocol=TLSv1_2 --ciphers "$_ciphersuites" "$1" -O "$2"
else
echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
if ! check_help_for "$3" wget --https-only --secure-protocol; then
echo "Warning: Not enforcing TLS v1.2, this is potentially less secure"
wget "$1" -O "$2"
else
wget --https-only --secure-protocol=TLSv1_2 "$1" -O "$2"
fi
fi
else
err "Unknown downloader" # should not reach here
fi
}
check_help_for() {
local _arch
local _cmd
local _arg
_arch="$1"
shift
_cmd="$1"
shift
case "$_arch" in
# If we're running on OS-X, older than 10.13, then we always
# fail to find these options to force fallback
*darwin*)
if check_cmd sw_vers; then
if [ "$(sw_vers -productVersion | cut -d. -f2)" -lt 13 ]; then
# Older than 10.13
echo "Warning: Detected OS X platform older than 10.13"
return 1
fi
fi
;;
esac
for _arg in "$@"; do
if ! "$_cmd" --help | grep -q -- "$_arg"; then
return 1
fi
done
true # not strictly needed
}
# Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
# if support by local tools is detected. Detection currently supports these curl backends:
# GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
get_ciphersuites_for_curl() {
if [ -n "${RUSTUP_TLS_CIPHERSUITES-}" ]; then
# user specified custom cipher suites, assume they know what they're doing
RETVAL="$RUSTUP_TLS_CIPHERSUITES"
return
fi
local _openssl_syntax="no"
local _gnutls_syntax="no"
local _backend_supported="yes"
if curl -V | grep -q ' OpenSSL/'; then
_openssl_syntax="yes"
elif curl -V | grep -iq ' LibreSSL/'; then
_openssl_syntax="yes"
elif curl -V | grep -iq ' BoringSSL/'; then
_openssl_syntax="yes"
elif curl -V | grep -iq ' GnuTLS/'; then
_gnutls_syntax="yes"
else
_backend_supported="no"
fi
local _args_supported="no"
if [ "$_backend_supported" = "yes" ]; then
# "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
if check_help_for "notspecified" "curl" "--tlsv1.2" "--ciphers" "--proto"; then
_args_supported="yes"
fi
fi
local _cs=""
if [ "$_args_supported" = "yes" ]; then
if [ "$_openssl_syntax" = "yes" ]; then
_cs=$(get_strong_ciphersuites_for "openssl")
elif [ "$_gnutls_syntax" = "yes" ]; then
_cs=$(get_strong_ciphersuites_for "gnutls")
fi
fi
RETVAL="$_cs"
}
# Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
# if support by local tools is detected. Detection currently supports these wget backends:
# GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
get_ciphersuites_for_wget() {
if [ -n "${RUSTUP_TLS_CIPHERSUITES-}" ]; then
# user specified custom cipher suites, assume they know what they're doing
RETVAL="$RUSTUP_TLS_CIPHERSUITES"
return
fi
local _cs=""
if wget -V | grep -q '\-DHAVE_LIBSSL'; then
# "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then
_cs=$(get_strong_ciphersuites_for "openssl")
fi
elif wget -V | grep -q '\-DHAVE_LIBGNUTLS'; then
# "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then
_cs=$(get_strong_ciphersuites_for "gnutls")
fi
fi
RETVAL="$_cs"
}
# Return strong TLS 1.2-1.3 cipher suites in OpenSSL or GnuTLS syntax. TLS 1.2
# excludes non-ECDHE and non-AEAD cipher suites. DHE is excluded due to bad
# DH params often found on servers (see RFC 7919). Sequence matches or is
# similar to Firefox 68 ESR with weak cipher suites disabled via about:config.
# $1 must be openssl or gnutls.
get_strong_ciphersuites_for() {
if [ "$1" = "openssl" ]; then
# OpenSSL is forgiving of unknown values, no problems with TLS 1.3 values on versions that don't support it yet.
echo "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384"
elif [ "$1" = "gnutls" ]; then
# GnuTLS isn't forgiving of unknown values, so this may require a GnuTLS version that supports TLS 1.3 even if wget doesn't.
# Begin with SECURE128 (and higher) then remove/add to build cipher suites. Produces same 9 cipher suites as OpenSSL but in slightly different order.
echo "SECURE128:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-DTLS-ALL:-CIPHER-ALL:-MAC-ALL:-KX-ALL:+AEAD:+ECDHE-ECDSA:+ECDHE-RSA:+AES-128-GCM:+CHACHA20-POLY1305:+AES-256-GCM"
fi
}
main "$@" || exit 1

View File

@ -0,0 +1,61 @@
import { ManagementType, Result } from './types'
import { getCrateLatestVersion, semverLt } from './util'
import getScriptVersion from '../../helpers/get-script-version'
import logger from '../../helpers/logger'
import { sync as spawnSync } from 'cross-spawn'
import inquirer from 'inquirer'
const log = logger('dependency:cargo-commands')
const dependencies = ['tauri-bundler']
async function manageDependencies(managementType: ManagementType): Promise<Result> {
const installedDeps = []
const updatedDeps = []
for (const dependency of dependencies) {
const currentVersion = getScriptVersion('cargo', [dependency])
if (currentVersion === null) {
log(`Installing ${dependency}...`)
spawnSync('cargo', ['install', dependency])
installedDeps.push(dependency)
} else if (managementType === ManagementType.Update) {
const latestVersion = await getCrateLatestVersion(dependency)
if (semverLt(currentVersion, latestVersion)) {
const inquired = await inquirer.prompt([{
type: 'confirm',
name: 'answer',
message: `[CARGO COMMANDS] "${dependency}" latest version is ${latestVersion}. Do you want to update?`,
default: false
}])
if (inquired.answer) {
spawnSync('cargo', ['install', dependency, '--force'])
updatedDeps.push(dependency)
}
} else {
log(`"${dependency}" is up to date`)
}
} else {
log(`"${dependency}" is already installed`)
}
}
const result: Result = new Map<ManagementType, string[]>()
result.set(ManagementType.Install, installedDeps)
result.set(ManagementType.Update, updatedDeps)
return result
}
async function install(): Promise<Result> {
return await manageDependencies(ManagementType.Install)
}
async function update(): Promise<Result> {
return await manageDependencies(ManagementType.Update)
}
export {
install,
update
}

View File

@ -0,0 +1,108 @@
import { spawnSync } from './../../helpers/spawn'
import { CargoManifest, CargoManifestDependency, CargoLock } from './../../types/cargo'
import { ManagementType, Result } from './types'
import { getCrateLatestVersion, semverLt } from './util'
import logger from '../../helpers/logger'
import { resolve as appResolve, tauriDir } from '../../helpers/app-paths'
import { readFileSync, writeFileSync, existsSync } from 'fs'
import toml from '@tauri-apps/toml'
import inquirer from 'inquirer'
const log = logger('dependency:crates')
const dependencies = ['tauri']
function readToml<T>(tomlPath: string): T | null {
if (existsSync(tomlPath)) {
const manifest = readFileSync(tomlPath).toString()
return toml.parse(manifest) as any as T
}
return null
}
function dependencyDefinition(version: string): CargoManifestDependency {
return { version: version.substring(0, version.lastIndexOf('.')) }
}
async function manageDependencies(managementType: ManagementType): Promise<Result> {
const installedDeps = []
const updatedDeps = []
const result: Result = new Map<ManagementType, string[]>()
const manifest = readToml<CargoManifest>(appResolve.tauri('Cargo.toml'))
if (manifest === null) {
log('Cargo.toml not found. Skipping crates check...')
return result
}
const lockPath = appResolve.tauri('Cargo.lock')
if (!existsSync(lockPath)) {
spawnSync('cargo', ['generate-lockfile'], tauriDir)
}
const lock = readToml<CargoLock>(lockPath)
for (const dependency of dependencies) {
const lockPackages = lock ? lock.package.filter(pkg => pkg.name === dependency) : []
// eslint-disable-next-line security/detect-object-injection
const manifestDep = manifest.dependencies[dependency]
const currentVersion = lockPackages.length === 1
? lockPackages[0].version
: (typeof manifestDep === 'string' ? manifestDep : manifestDep?.version)
if (currentVersion === undefined) {
log(`Installing ${dependency}...`)
const latestVersion = await getCrateLatestVersion(dependency)
// eslint-disable-next-line security/detect-object-injection
manifest.dependencies[dependency] = dependencyDefinition(latestVersion)
installedDeps.push(dependency)
} else if (managementType === ManagementType.Update) {
const latestVersion = await getCrateLatestVersion(dependency)
if (semverLt(currentVersion, latestVersion)) {
const inquired = await inquirer.prompt([{
type: 'confirm',
name: 'answer',
message: `[CRATES] "${dependency}" latest version is ${latestVersion}. Do you want to update?`,
default: false
}])
if (inquired.answer) {
log(`Updating ${dependency}...`)
// eslint-disable-next-line security/detect-object-injection
manifest.dependencies[dependency] = dependencyDefinition(latestVersion)
updatedDeps.push(dependency)
}
} else {
log(`"${dependency}" is up to date`)
}
} else {
log(`"${dependency}" is already installed`)
}
}
if (installedDeps.length || updatedDeps.length) {
writeFileSync(appResolve.tauri('Cargo.toml'), toml.stringify(manifest as any))
}
if (updatedDeps.length) {
if (!existsSync(appResolve.tauri('Cargo.lock'))) {
spawnSync('cargo', ['generate-lockfile'], tauriDir)
}
spawnSync('cargo', ['update', ...updatedDeps.reduce<string[]>((initialValue, dep) => [...initialValue, '-p', dep], [])], tauriDir)
}
result.set(ManagementType.Install, installedDeps)
result.set(ManagementType.Update, updatedDeps)
return result
}
async function install(): Promise<Result> {
return await manageDependencies(ManagementType.Install)
}
async function update(): Promise<Result> {
return await manageDependencies(ManagementType.Update)
}
export {
install,
update
}

View File

@ -0,0 +1,24 @@
import logger from '../../helpers/logger'
import * as rust from './rust'
import * as cargoCommands from './cargo-commands'
import * as cargoCrates from './cargo-crates'
import * as npmPackages from './npm-packages'
const log = logger('dependency:manager')
module.exports = {
async installDependencies() {
log('Installing missing dependencies...')
rust.install()
await cargoCommands.install()
await cargoCrates.install()
await npmPackages.install()
},
async updateDependencies() {
log('Updating dependencies...')
rust.update()
await cargoCommands.update()
await cargoCrates.update()
await npmPackages.update()
}
}

View File

@ -0,0 +1,60 @@
import { ManagementType, Result } from './types'
import { getNpmLatestVersion, getNpmPackageVersion, installNpmPackage, updateNpmPackage, semverLt } from './util'
import logger from '../../helpers/logger'
import inquirer from 'inquirer'
const log = logger('dependency:npm-packages')
const dependencies = ['tauri']
async function manageDependencies(managementType: ManagementType): Promise<Result> {
const installedDeps = []
const updatedDeps = []
for (const dependency of dependencies) {
const currentVersion = await getNpmPackageVersion(dependency)
if (currentVersion === null) {
log(`Installing ${dependency}...`)
installNpmPackage(dependency)
installedDeps.push(dependency)
} else if (managementType === ManagementType.Update) {
const latestVersion = getNpmLatestVersion(dependency)
if (semverLt(currentVersion, latestVersion)) {
const inquired = await inquirer.prompt([{
type: 'confirm',
name: 'answer',
message: `[NPM]: "${dependency}" latest version is ${latestVersion}. Do you want to update?`,
default: false
}])
if (inquired.answer) {
log(`Updating ${dependency}...`)
updateNpmPackage(dependency)
updatedDeps.push(dependency)
}
} else {
log(`"${dependency}" is up to date`)
}
} else {
log(`"${dependency}" is already installed`)
}
}
const result: Result = new Map<ManagementType, string[]>()
result.set(ManagementType.Install, installedDeps)
result.set(ManagementType.Update, updatedDeps)
return result
}
async function install(): Promise<Result> {
return await manageDependencies(ManagementType.Install)
}
async function update(): Promise<Result> {
return await manageDependencies(ManagementType.Update)
}
export {
install,
update
}

View File

@ -0,0 +1,57 @@
import { ManagementType } from './types'
import { spawnSync } from '../../helpers/spawn'
import getScriptVersion from '../../helpers/get-script-version'
import logger from '../../helpers/logger'
import { createWriteStream, unlinkSync } from 'fs'
import { resolve } from 'path'
import { platform } from 'os'
import https from 'https'
const log = logger('dependency:rust')
async function download(url: string, dest: string): Promise<void> {
const file = createWriteStream(dest)
return await new Promise((resolve, reject) => {
https.get(url, response => {
response.pipe(file)
file.on('finish', function() {
file.close()
resolve()
})
}).on('error', function(err) {
unlinkSync(dest)
reject(err.message)
})
})
};
function installRustup(): void {
if (platform() === 'win32') {
return spawnSync('powershell', [resolve(__dirname, '../../scripts/rustup-init.exe')], process.cwd())
}
return spawnSync('/bin/sh', [resolve(__dirname, '../../scripts/rustup-init.sh')], process.cwd())
}
function manageDependencies(managementType: ManagementType): void {
if (getScriptVersion('rustup') === null) {
log('Installing rustup...')
installRustup()
}
if (managementType === ManagementType.Update) {
spawnSync('rustup', ['update'], process.cwd())
}
}
function install(): void {
return manageDependencies(ManagementType.Install)
}
function update(): void {
return manageDependencies(ManagementType.Update)
}
export {
install,
update
}

View File

@ -0,0 +1,6 @@
export enum ManagementType {
Install,
Update
}
export type Result = Map<ManagementType, string[]>

View File

@ -0,0 +1,83 @@
import https from 'https'
import { IncomingMessage } from 'http'
import { spawnSync } from '../../helpers/spawn'
import { sync as crossSpawnSync } from 'cross-spawn'
import { appDir, resolve as appResolve } from '../../helpers/app-paths'
import { existsSync } from 'fs'
import semver from 'semver'
const BASE_URL = 'https://docs.rs/crate/'
async function getCrateLatestVersion(crateName: string): Promise<string> {
return await new Promise((resolve, reject) => {
const url = `${BASE_URL}${crateName}`
https.get(url, (res: IncomingMessage) => {
if (res.statusCode !== 302 || !res.headers.location) {
reject(res)
} else {
const version = res.headers.location.replace(url + '/', '')
resolve(version)
}
})
})
}
function getNpmLatestVersion(packageName: string): string {
const child = crossSpawnSync('npm', ['show', packageName, 'version'], { cwd: appDir })
return String(child.output[1]).replace('\n', '')
}
async function getNpmPackageVersion(packageName: string): Promise<string | null> {
return await new Promise((resolve) => {
const child = crossSpawnSync('npm', ['list', packageName, 'version', '--depth', '0'], { cwd: appDir })
const output = String(child.output[1])
// eslint-disable-next-line security/detect-non-literal-regexp
const matches = new RegExp(packageName + '@(\\S+)', 'g').exec(output)
if (matches?.[1]) {
resolve(matches[1])
} else {
resolve(null)
}
})
}
function installNpmPackage(packageName: string): void {
const usesYarn = existsSync(appResolve.app('yarn.lock'))
if (usesYarn) {
spawnSync('yarn', ['add', packageName], appDir)
} else {
spawnSync('npm', ['install', packageName], appDir)
}
}
function updateNpmPackage(packageName: string): void {
const usesYarn = existsSync(appResolve.app('yarn.lock'))
if (usesYarn) {
spawnSync('yarn', ['upgrade', packageName, '--latest'], appDir)
} else {
spawnSync('npm', ['install', `${packageName}@latest`], appDir)
}
}
function padVersion(version: string): string {
let count = (version.match(/\./g) ?? []).length
while (count < 2) {
count++
version += '.0'
}
return version
}
function semverLt(first: string, second: string): boolean {
return semver.lt(padVersion(first), padVersion(second))
}
export {
getCrateLatestVersion,
getNpmLatestVersion,
getNpmPackageVersion,
installNpmPackage,
updateNpmPackage,
padVersion,
semverLt
}

View File

@ -10,6 +10,7 @@ import { TauriConfig } from './../types/config'
import { CargoLock, CargoManifest } from '../types/cargo'
import nonWebpackRequire from '../helpers/non-webpack-require'
import { version } from '../../package.json'
import getScriptVersion from '../helpers/get-script-version'
interface DirInfo {
path: string
@ -45,17 +46,13 @@ function getVersion(
args: string[] = [],
formatter?: (output: string) => string
): string {
try {
const child = spawn(command, [...args, '--version'])
if (child.status === 0) {
const output = String(child.output[1])
return chalk
.green(formatter === undefined ? output : formatter(output))
.replace('\n', '')
}
return chalk.red('Not installed')
} catch (err) {
const version = getScriptVersion(command, args)
if (version === null) {
return chalk.red('Not installed')
} else {
return chalk
.green(formatter === undefined ? version : formatter(version))
.replace('\n', '')
}
}
@ -68,7 +65,7 @@ interface Info {
function printInfo(info: Info): void {
console.log(
`${info.section ? '\n' : ''}${info.key}${
info.value === undefined ? '' : ' - ' + info.value
info.value === undefined ? '' : ' - ' + info.value
}`
)
}
@ -173,7 +170,7 @@ function printAppInfo(tauriDir: string): void {
? chalk.green(config.build.devPath)
: chalk.red('unset')
})
} catch (_) {}
} catch (_) { }
}
module.exports = () => {

View File

@ -0,0 +1,17 @@
import { sync as spawn } from 'cross-spawn'
export default function getVersion(
command: string,
args: string[] = []
): string | null {
try {
const child = spawn(command, [...args, '--version'])
if (child.status === 0) {
const output = String(child.output[1])
return output
}
return null
} catch (err) {
return null
}
}

View File

@ -9,6 +9,7 @@ module.exports = {
'api/init': './src/api/init.ts',
'api/tauricon': './src/api/tauricon.ts',
'api/info': './src/api/info.ts',
'api/dependency-manager': './src/api/dependency-manager/index.ts',
'helpers/tauri-config': './src/helpers/tauri-config.ts',
'helpers/spawn': './src/helpers/spawn.ts'
},

View File

@ -794,14 +794,6 @@
"@babel/helper-plugin-utils" "^7.10.4"
"@babel/plugin-transform-typescript" "^7.10.4"
"@babel/runtime-corejs3@^7.8.3":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.10.4.tgz#f29fc1990307c4c57b10dbd6ce667b27159d9e0d"
integrity sha512-BFlgP2SoLO9HJX9WBwN67gHWMBhDX/eDz64Jajd6mR/UAUzqrNMm99d4qHnVaKscAElZoFiPv+JpR/Siud5lXw==
dependencies:
core-js-pure "^3.0.0"
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.8.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.4.tgz#a6724f1a6b8d2f6ea5236dbfe58c7d7ea9c5eb99"
@ -1305,6 +1297,14 @@
dependencies:
"@types/node" "*"
"@types/inquirer@^6.5.0":
version "6.5.0"
resolved "https://registry.yarnpkg.com/@types/inquirer/-/inquirer-6.5.0.tgz#b83b0bf30b88b8be7246d40e51d32fe9d10e09be"
integrity sha512-rjaYQ9b9y/VFGOpqBEXRavc3jh0a+e6evAbI31tMda8VlPaSy0AZJfXsvmIe3wklc7W6C3zCSfleuMXR7NOyXw==
dependencies:
"@types/through" "*"
rxjs "^6.4.0"
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762"
@ -1365,9 +1365,9 @@
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
"@types/node@*":
version "14.0.22"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.22.tgz#23ea4d88189cec7d58f9e6b66f786b215eb61bdc"
integrity sha512-emeGcJvdiZ4Z3ohbmw93E/64jRzUHAItSHt8nF7M4TGgQTiWqFVGB8KNpLGFmUHmHLvjvBgFwVlqNcq+VuGv9g==
version "14.0.23"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.23.tgz#676fa0883450ed9da0bb24156213636290892806"
integrity sha512-Z4U8yDAl5TFkmYsZdFPdjeMa57NOvnaf1tljHzhouaPEp7LCj2JKkejpI1ODviIAQuW4CcQmxkQ77rnLsOOoKw==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"
@ -1401,6 +1401,13 @@
dependencies:
"@types/node" "*"
"@types/semver@^7.3.1":
version "7.3.1"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.1.tgz#7a9a5d595b6d873f338c867dcef64df289468cfa"
integrity sha512-ooD/FJ8EuwlDKOI6D9HWxgIgJjMg2cuziXm/42npDC8y4NjxplBUn9loewZiBNCt44450lHAU0OSb51/UqXeag==
dependencies:
"@types/node" "*"
"@types/sharp@0.25.0":
version "0.25.0"
resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.25.0.tgz#e21501779b110e26f33cec7fb1969e49e0cdc3c0"
@ -1423,6 +1430,13 @@
resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74"
integrity sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==
"@types/through@*":
version "0.0.30"
resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.30.tgz#e0e42ce77e897bd6aead6f6ea62aeb135b8a3895"
integrity sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==
dependencies:
"@types/node" "*"
"@types/tough-cookie@*":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.0.tgz#fef1904e4668b6e5ecee60c52cc6a078ffa6697d"
@ -1498,7 +1512,18 @@
eslint-scope "^5.0.0"
eslint-utils "^2.0.0"
"@typescript-eslint/parser@3.6.0", "@typescript-eslint/parser@^3.0.1":
"@typescript-eslint/experimental-utils@3.6.1":
version "3.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.6.1.tgz#b5a2738ebbceb3fa90c5b07d50bb1225403c4a54"
integrity sha512-oS+hihzQE5M84ewXrTlVx7eTgc52eu+sVmG7ayLfOhyZmJ8Unvf3osyFQNADHP26yoThFfbxcibbO0d2FjnYhg==
dependencies:
"@types/json-schema" "^7.0.3"
"@typescript-eslint/types" "3.6.1"
"@typescript-eslint/typescript-estree" "3.6.1"
eslint-scope "^5.0.0"
eslint-utils "^2.0.0"
"@typescript-eslint/parser@3.6.0":
version "3.6.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.6.0.tgz#79b5232e1a2d06f1fc745942b690cd87aca7b60e"
integrity sha512-taghDxuLhbDAD1U5Fk8vF+MnR0yiFE9Z3v2/bYScFb0N1I9SK8eKHkdJl1DAD48OGFDMFTeOTX0z7g0W6SYUXw==
@ -1509,11 +1534,27 @@
"@typescript-eslint/typescript-estree" "3.6.0"
eslint-visitor-keys "^1.1.0"
"@typescript-eslint/parser@^3.0.1":
version "3.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.6.1.tgz#216e8adf4ee9c629f77c985476a2ea07fb80e1dc"
integrity sha512-SLihQU8RMe77YJ/jGTqOt0lMq7k3hlPVfp7v/cxMnXA9T0bQYoMDfTsNgHXpwSJM1Iq2aAJ8WqekxUwGv5F67Q==
dependencies:
"@types/eslint-visitor-keys" "^1.0.0"
"@typescript-eslint/experimental-utils" "3.6.1"
"@typescript-eslint/types" "3.6.1"
"@typescript-eslint/typescript-estree" "3.6.1"
eslint-visitor-keys "^1.1.0"
"@typescript-eslint/types@3.6.0":
version "3.6.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.6.0.tgz#4bd6eee55d2f9d35a4b36c4804be1880bf68f7bc"
integrity sha512-JwVj74ohUSt0ZPG+LZ7hb95fW8DFOqBuR6gE7qzq55KDI3BepqsCtHfBIoa0+Xi1AI7fq5nCu2VQL8z4eYftqg==
"@typescript-eslint/types@3.6.1":
version "3.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.6.1.tgz#87600fe79a1874235d3cc1cf5c7e1a12eea69eee"
integrity sha512-NPxd5yXG63gx57WDTW1rp0cF3XlNuuFFB5G+Kc48zZ+51ZnQn9yjDEsjTPQ+aWM+V+Z0I4kuTFKjKvgcT1F7xQ==
"@typescript-eslint/typescript-estree@3.6.0":
version "3.6.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.6.0.tgz#9b4cab43f1192b64ff51530815b8919f166ce177"
@ -1528,6 +1569,20 @@
semver "^7.3.2"
tsutils "^3.17.1"
"@typescript-eslint/typescript-estree@3.6.1":
version "3.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.6.1.tgz#a5c91fcc5497cce7922ff86bc37d5e5891dcdefa"
integrity sha512-G4XRe/ZbCZkL1fy09DPN3U0mR6SayIv1zSeBNquRFRk7CnVLgkC2ZPj8llEMJg5Y8dJ3T76SvTGtceytniaztQ==
dependencies:
"@typescript-eslint/types" "3.6.1"
"@typescript-eslint/visitor-keys" "3.6.1"
debug "^4.1.1"
glob "^7.1.6"
is-glob "^4.0.1"
lodash "^4.17.15"
semver "^7.3.2"
tsutils "^3.17.1"
"@typescript-eslint/visitor-keys@3.6.0":
version "3.6.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.6.0.tgz#44185eb0cc47651034faa95c5e2e8b314ecebb26"
@ -1535,6 +1590,13 @@
dependencies:
eslint-visitor-keys "^1.1.0"
"@typescript-eslint/visitor-keys@3.6.1":
version "3.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.6.1.tgz#5c57a7772f4dd623cfeacc219303e7d46f963b37"
integrity sha512-qC8Olwz5ZyMTZrh4Wl3K4U6tfms0R/mzU4/5W3XeUZptVraGVmbptJbn6h2Ey6Rb3hOs3zWoAUebZk8t47KGiQ==
dependencies:
eslint-visitor-keys "^1.1.0"
"@webassemblyjs/ast@1.9.0":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964"
@ -2418,16 +2480,16 @@ cacache@^12.0.2:
y18n "^4.0.0"
cacache@^15.0.4:
version "15.0.4"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.4.tgz#b2c23cf4ac4f5ead004fb15a0efb0a20340741f1"
integrity sha512-YlnKQqTbD/6iyoJvEY3KJftjrdBYroCbxxYXzhOzsFLWlp6KX4BOlEf4mTx0cMUfVaTS3ENL2QtDWeRYoGLkkw==
version "15.0.5"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.5.tgz#69162833da29170d6732334643c60e005f5f17d0"
integrity sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==
dependencies:
"@npmcli/move-file" "^1.0.1"
chownr "^2.0.0"
fs-minipass "^2.0.0"
glob "^7.1.4"
infer-owner "^1.0.4"
lru-cache "^5.1.1"
lru-cache "^6.0.0"
minipass "^3.1.1"
minipass-collect "^1.0.2"
minipass-flush "^1.0.5"
@ -2510,9 +2572,9 @@ camelcase@^6.0.0:
integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==
caniuse-lite@^1.0.30001093:
version "1.0.30001097"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001097.tgz#1129c40c9f5ee3282158da08fd915d301f4a9bd8"
integrity sha512-TeuSleKt/vWXaPkLVFqGDnbweYfq4IaZ6rUugFf3rWY6dlII8StUZ8Ddin0PkADfgYZ4wRqCdO2ORl4Rn5eZIA==
version "1.0.30001099"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001099.tgz#540118fcc6842d1fde62f4ee5521d1ec6afdb40e"
integrity sha512-sdS9A+sQTk7wKoeuZBN/YMAHVztUfVnjDi4/UV3sDE8xoh7YR12hKW+pIdB3oqKGwr9XaFL2ovfzt9w8eUI5CA==
capture-exit@^2.0.0:
version "2.0.0"
@ -2979,11 +3041,6 @@ core-js-compat@^3.6.2:
browserslist "^4.8.5"
semver "7.0.0"
core-js-pure@^3.0.0:
version "3.6.5"
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813"
integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==
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"
@ -3204,13 +3261,6 @@ decamelize@^1.1.2, decamelize@^1.2.0:
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
decamelize@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-3.2.0.tgz#84b8e8f4f8c579f938e35e2cc7024907e0090851"
integrity sha512-4TgkVUsmmu7oCSyGBm5FvfMoACuoh9EOidm7V5/J2X2djAwwt57qb3F2KMP2ITqODTCSwb+YRV+0Zqrv18k/hw==
dependencies:
xregexp "^4.2.4"
decimal.js@^10.2.0:
version "10.2.0"
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231"
@ -3555,9 +3605,9 @@ ecc-jsbn@~0.1.1:
safer-buffer "^2.1.0"
electron-to-chromium@^1.3.488:
version "1.3.496"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.496.tgz#3f43d32930481d82ad3663d79658e7c59a58af0b"
integrity sha512-TXY4mwoyowwi4Lsrq9vcTUYBThyc1b2hXaTZI13p8/FRhY2CTaq5lK+DVjhYkKiTLsKt569Xes+0J5JsVXFurQ==
version "1.3.497"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.497.tgz#de00f2f2f44c258c4577fbfbd5124b94c18bfa44"
integrity sha512-sPdW5bUDZwiFtoonuZCUwRGzsZmKzcLM0bMVhp6SMCfUG+B3faENLx3cE+o+K0Jl+MPuNA9s9cScyFjOlixZpQ==
elliptic@^6.0.0, elliptic@^6.5.2:
version "6.5.3"
@ -5091,7 +5141,7 @@ inquirer@7.3.0:
cli-width "^3.0.0"
external-editor "^3.0.3"
figures "^3.0.0"
lodash "^4.17.15"
lodash "^4.17.16"
mute-stream "0.0.8"
run-async "^2.4.0"
rxjs "^6.6.0"
@ -6357,7 +6407,7 @@ lodash.sortby@^4.7.0:
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
lodash@4.17.19, lodash@>=4.17.19, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15:
lodash@4.17.19, lodash@>=4.17.19, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.16:
version "4.17.19"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
@ -6447,6 +6497,13 @@ lru-cache@^5.1.1:
dependencies:
yallist "^3.0.2"
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
dependencies:
yallist "^4.0.0"
magic-string@^0.25.2:
version "0.25.7"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
@ -6818,9 +6875,9 @@ node-abi@^2.7.0:
semver "^5.4.1"
node-addon-api@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.0.0.tgz#812446a1001a54f71663bed188314bba07e09247"
integrity sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg==
version "3.0.1"
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.0.1.tgz#990544a2607ec3f538443df4858f8c40089b7783"
integrity sha512-YUpjl57P55u2yUaKX5Bgy4t5s6SCNYMg+62XNg+k41aYbBL1NgWrZfcgljR5MxDxHDjzl0qHDNtH6SkW4DXNCA==
node-int64@^0.4.0:
version "0.4.0"
@ -7193,9 +7250,9 @@ p-limit@^2.0.0, p-limit@^2.2.0:
p-try "^2.0.0"
p-limit@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.1.tgz#584784ac0722d1aed09f19f90ed2999af6ce2839"
integrity sha512-mw/p92EyOzl2MhauKodw54Rx5ZK4624rNfgNaBguFZkHzyUG9WsDzFF5/yQVEJinbJDdP4jEfMN+uBquiGnaLg==
version "3.0.2"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe"
integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==
dependencies:
p-try "^2.0.0"
@ -7945,9 +8002,9 @@ regexpu-core@^4.7.0:
unicode-match-property-value-ecmascript "^1.2.0"
registry-auth-token@^4.0.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.1.1.tgz#40a33be1e82539460f94328b0f7f0f84c16d9479"
integrity sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==
version "4.2.0"
resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.0.tgz#1d37dffda72bbecd0f581e4715540213a65eb7da"
integrity sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w==
dependencies:
rc "^1.2.8"
@ -8219,7 +8276,7 @@ run-queue@^1.0.0, run-queue@^1.0.3:
dependencies:
aproba "^1.1.1"
rxjs@^6.5.5, rxjs@^6.6.0:
rxjs@^6.4.0, rxjs@^6.5.5, rxjs@^6.6.0:
version "6.6.0"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.0.tgz#af2901eedf02e3a83ffa7f886240ff9018bbec84"
integrity sha512-3HMA8z/Oz61DUHe+SdOiQyzIf4tOx5oQHmMir7IZEu6TMqCLHT4LRcmNaUS0NwOz8VLvmmBduMsoaUvMaIiqzg==
@ -8904,9 +8961,9 @@ strip-indent@^1.0.1:
get-stdin "^4.0.1"
strip-json-comments@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.0.tgz#7638d31422129ecf4457440009fba03f9f9ac180"
integrity sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==
version "3.1.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
strip-json-comments@~2.0.1:
version "2.0.1"
@ -9944,13 +10001,6 @@ xmlchars@^2.2.0:
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
xregexp@^4.2.4:
version "4.3.0"
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.3.0.tgz#7e92e73d9174a99a59743f67a4ce879a04b5ae50"
integrity sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g==
dependencies:
"@babel/runtime-corejs3" "^7.8.3"
xtend@^4.0.0, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
@ -10014,12 +10064,12 @@ yargs@^13.2.4, yargs@^13.3.2:
yargs-parser "^13.1.2"
yargs@^15.0.2, yargs@^15.3.1:
version "15.4.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.0.tgz#53949fb768309bac1843de9b17b80051e9805ec2"
integrity sha512-D3fRFnZwLWp8jVAAhPZBsmeIHY8tTsb8ItV9KaAaopmC6wde2u6Yw29JBIZHXw14kgkRnYmDgmQU4FVMDlIsWw==
version "15.4.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
dependencies:
cliui "^6.0.0"
decamelize "^3.2.0"
decamelize "^1.2.0"
find-up "^4.1.0"
get-caller-file "^2.0.1"
require-directory "^2.1.1"