Page MenuHomePhorge

D1636.1775302694.diff
No OneTemporary

Authored By
Unknown
Size
527 KB
Referenced Files
None
Subscribers
None

D1636.1775302694.diff

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/bin/doctum b/bin/doctum
new file mode 100755
--- /dev/null
+++ b/bin/doctum
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+cwd=$(dirname $0)
+
+pushd ${cwd}/../src/
+
+rm -rf cache/store/
+
+php -dmemory_limit=-1 \
+ vendor/bin/doctum.php \
+ update \
+ doctum.config.php \
+ -v
+
+popd
diff --git a/bin/phpunit b/bin/phpunit
--- a/bin/phpunit
+++ b/bin/phpunit
@@ -4,7 +4,9 @@
pushd ${cwd}/../src/
-php -dzend_extension=xdebug.so \
+php \
+ -dmemory_limit=-1 \
+ -dzend_extension=xdebug.so \
vendor/bin/phpunit \
--stop-on-defect \
--stop-on-error \
diff --git a/docker/redis/Dockerfile b/docker/redis/Dockerfile
--- a/docker/redis/Dockerfile
+++ b/docker/redis/Dockerfile
@@ -24,4 +24,4 @@
WORKDIR /root/
-CMD ["/lib/systemd/systemd"]
+CMD ["/usr/bin/redis-server"]
diff --git a/src/app/Auth/LDAPUserProvider.php b/src/app/Auth/LDAPUserProvider.php
--- a/src/app/Auth/LDAPUserProvider.php
+++ b/src/app/Auth/LDAPUserProvider.php
@@ -22,7 +22,7 @@
*/
public function retrieveByCredentials(array $credentials)
{
- $entries = User::where('email', '=', $credentials['email'])->get();
+ $entries = User::where('email', \strtolower($credentials['email']))->get();
$count = $entries->count();
@@ -51,7 +51,7 @@
{
$authenticated = false;
- if ($user->email == $credentials['email']) {
+ if ($user->email === \strtolower($credentials['email'])) {
if (!empty($user->password)) {
if (Hash::check($credentials['password'], $user->password)) {
$authenticated = true;
diff --git a/src/app/Backends/LDAP.php b/src/app/Backends/LDAP.php
--- a/src/app/Backends/LDAP.php
+++ b/src/app/Backends/LDAP.php
@@ -98,7 +98,10 @@
$result = $ldap->add_entry($dn, $entry);
if (!$result) {
- self::throwException($ldap, "Failed to create domain {$domain->namespace} in LDAP");
+ self::throwException(
+ $ldap,
+ "Failed to create domain {$domain->namespace} in LDAP (" . __LINE__ . ")"
+ );
}
}
@@ -144,12 +147,19 @@
);
if (!$ldap->get_entry($domainBaseDN)) {
- $ldap->add_entry($domainBaseDN, $entry);
+ $result = $ldap->add_entry($domainBaseDN, $entry);
+
+ if (!$result) {
+ self::throwException(
+ $ldap,
+ "Failed to create domain {$domain->namespace} in LDAP (" . __LINE__ . ")"
+ );
+ }
}
foreach (['Groups', 'People', 'Resources', 'Shared Folders'] as $item) {
if (!$ldap->get_entry("ou={$item},{$domainBaseDN}")) {
- $ldap->add_entry(
+ $result = $ldap->add_entry(
"ou={$item},{$domainBaseDN}",
[
'ou' => $item,
@@ -160,12 +170,19 @@
]
]
);
+
+ if (!$result) {
+ self::throwException(
+ $ldap,
+ "Failed to create domain {$domain->namespace} in LDAP (" . __LINE__ . ")"
+ );
+ }
}
}
foreach (['kolab-admin'] as $item) {
if (!$ldap->get_entry("cn={$item},{$domainBaseDN}")) {
- $ldap->add_entry(
+ $result = $ldap->add_entry(
"cn={$item},{$domainBaseDN}",
[
'cn' => $item,
@@ -179,6 +196,13 @@
]
]
);
+
+ if (!$result) {
+ self::throwException(
+ $ldap,
+ "Failed to create domain {$domain->namespace} in LDAP (" . __LINE__ . ")"
+ );
+ }
}
}
@@ -230,13 +254,20 @@
'nsroledn' => []
];
- if (!self::getUserEntry($ldap, $user->email, $dn) && $dn) {
+ if (!self::getUserEntry($ldap, $user->email, $dn)) {
+ if (empty($dn)) {
+ self::throwException($ldap, "Failed to create user {$user->email} in LDAP (" . __LINE__ . ")");
+ }
+
self::setUserAttributes($user, $entry);
$result = $ldap->add_entry($dn, $entry);
if (!$result) {
- self::throwException($ldap, "Failed to create user {$user->email} in LDAP");
+ self::throwException(
+ $ldap,
+ "Failed to create user {$user->email} in LDAP (" . __LINE__ . ")"
+ );
}
}
@@ -266,7 +297,10 @@
$result = $ldap->delete_entry_recursive($domainBaseDN);
if (!$result) {
- self::throwException($ldap, "Failed to delete domain {$domain->namespace} from LDAP");
+ self::throwException(
+ $ldap,
+ "Failed to delete domain {$domain->namespace} from LDAP (" . __LINE__ . ")"
+ );
}
}
@@ -275,7 +309,10 @@
$result = $ldap->delete_entry($ldap_domain['dn']);
if (!$result) {
- self::throwException($ldap, "Failed to delete domain {$domain->namespace} from LDAP");
+ self::throwException(
+ $ldap,
+ "Failed to delete domain {$domain->namespace} from LDAP (" . __LINE__ . ")"
+ );
}
}
}
@@ -301,7 +338,10 @@
$result = $ldap->delete_entry($dn);
if (!$result) {
- self::throwException($ldap, "Failed to delete user {$user->email} from LDAP");
+ self::throwException(
+ $ldap,
+ "Failed to delete user {$user->email} from LDAP (" . __LINE__ . ")"
+ );
}
}
@@ -373,7 +413,10 @@
$ldapDomain = $ldap->find_domain($domain->namespace);
if (!$ldapDomain) {
- self::throwException($ldap, "Failed to update domain {$domain->namespace} in LDAP (domain not found)");
+ self::throwException(
+ $ldap,
+ "Failed to update domain {$domain->namespace} in LDAP (domain not found)"
+ );
}
$oldEntry = $ldap->get_entry($ldapDomain['dn']);
@@ -388,7 +431,10 @@
$result = $ldap->modify_entry($ldapDomain['dn'], $oldEntry, $newEntry);
if (!is_array($result)) {
- self::throwException($ldap, "Failed to update domain {$domain->namespace} in LDAP");
+ self::throwException(
+ $ldap,
+ "Failed to update domain {$domain->namespace} in LDAP (" . __LINE__ . ")"
+ );
}
if (empty(self::$ldap)) {
@@ -411,7 +457,10 @@
$newEntry = $oldEntry = self::getUserEntry($ldap, $user->email, $dn, true);
if (!$oldEntry) {
- self::throwException($ldap, "Failed to update user {$user->email} in LDAP (user not found)");
+ self::throwException(
+ $ldap,
+ "Failed to update user {$user->email} in LDAP (user not found)"
+ );
}
self::setUserAttributes($user, $newEntry);
@@ -433,7 +482,10 @@
$result = $ldap->modify_entry($dn, $oldEntry, $newEntry);
if (!is_array($result)) {
- self::throwException($ldap, "Failed to update user {$user->email} in LDAP");
+ self::throwException(
+ $ldap,
+ "Failed to update user {$user->email} in LDAP (" . __LINE__ . ")"
+ );
}
if (empty(self::$ldap)) {
@@ -458,7 +510,10 @@
throw new \Exception("Failed to connect to LDAP");
}
- $bound = $ldap->bind(\config("ldap.{$privilege}.bind_dn"), \config("ldap.{$privilege}.bind_pw"));
+ $bound = $ldap->bind(
+ \config("ldap.{$privilege}.bind_dn"),
+ \config("ldap.{$privilege}.bind_pw")
+ );
if (!$bound) {
throw new \Exception("Failed to bind to LDAP");
diff --git a/src/app/Console/Command.php b/src/app/Console/Command.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Command.php
@@ -0,0 +1,104 @@
+<?php
+
+namespace App\Console;
+
+class Command extends \Illuminate\Console\Command
+{
+ /**
+ * Find the domain.
+ *
+ * @param string $domain Domain ID or namespace
+ *
+ * @return \App\Domain|null
+ */
+ public function getDomain($domain)
+ {
+ return $this->getObject(\App\Domain::class, $domain, 'namespace');
+ }
+
+ /**
+ * Find an object.
+ *
+ * @param string $objectClass The name of the class
+ * @param string $objectIdOrTitle The name of a database field to match.
+ * @param string|null $objectTitle An additional database field to match.
+ *
+ * @return mixed
+ */
+ public function getObject($objectClass, $objectIdOrTitle, $objectTitle)
+ {
+ $object = $objectClass::find($objectIdOrTitle);
+
+ if (!$object && !empty($objectTitle)) {
+ $object = $objectClass::where($objectTitle, $objectIdOrTitle)->first();
+ }
+
+ return $object;
+ }
+
+ /**
+ * Find the user.
+ *
+ * @param string $user User ID or email
+ *
+ * @return \App\User|null
+ */
+ public function getUser($user)
+ {
+ return $this->getObject(\App\User::class, $user, 'email');
+ }
+
+ /**
+ * Find the wallet.
+ *
+ * @param string $wallet Wallet ID
+ *
+ * @return \App\Wallet|null
+ */
+ public function getWallet($wallet)
+ {
+ return $this->getObject(\App\Wallet::class, $wallet, null);
+ }
+
+ /**
+ * Return a string for output, with any additional attributes specified as well.
+ *
+ * @param mixed $entry An object
+ *
+ * @return string
+ */
+ protected function toString($entry)
+ {
+ /**
+ * Haven't figured out yet, how to test if this command implements an option for additional
+ * attributes.
+ if (!in_array('attr', $this->options())) {
+ return $entry->{$entry->getKeyName()};
+ }
+ */
+
+ $str = [
+ $entry->{$entry->getKeyName()}
+ ];
+
+ foreach ($this->option('attr') as $attr) {
+ if ($attr == $entry->getKeyName()) {
+ $this->warn("Specifying {$attr} is not useful.");
+ continue;
+ }
+
+ if (!array_key_exists($attr, $entry->toArray())) {
+ $this->error("Attribute {$attr} isn't available");
+ continue;
+ }
+
+ if (is_numeric($entry->{$attr})) {
+ $str[] = $entry->{$attr};
+ } else {
+ $str[] = !empty($entry->{$attr}) ? $entry->{$attr} : "null";
+ }
+ }
+
+ return implode(" ", $str);
+ }
+}
diff --git a/src/app/Console/Commands/Data/Import/CountriesCommand.php b/src/app/Console/Commands/Data/Import/CountriesCommand.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/Data/Import/CountriesCommand.php
@@ -0,0 +1,114 @@
+<?php
+
+namespace App\Console\Commands\Data\Import;
+
+use App\Console\Command;
+use Carbon\Carbon;
+
+class CountriesCommand extends Command
+{
+ private $currency_fixes = [
+ // Country code => currency
+ 'LT' => 'EUR',
+ ];
+
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'data:import:countries';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Fetches countries map from country.io';
+
+ /**
+ * Execute the console command.
+ *
+ * @return mixed
+ */
+ public function handle()
+ {
+ $today = Carbon::now()->toDateString();
+
+ $countries = [];
+ $currencies = [];
+ $currencySource = 'http://country.io/currency.json';
+ $countrySource = 'http://country.io/names.json';
+
+ //
+ // countries
+ //
+ $file = storage_path("countries-{$today}.json");
+
+ \App\Utils::downloadFile($countrySource, $file);
+
+ $countryJson = file_get_contents($file);
+
+ if (!$countryJson) {
+ $this->error("Failed to fetch countries");
+ return 1;
+ }
+
+ $countries = json_decode($countryJson, true);
+
+ if (!is_array($countries) || empty($countries)) {
+ $this->error("Invalid countries data");
+ return 1;
+ }
+
+ //
+ // currencies
+ //
+ $file = storage_path("currencies-{$today}.json");
+
+ \App\Utils::downloadFile($currencySource, $file);
+
+ // fetch currency table and create an index by country page url
+ $currencyJson = file_get_contents($file);
+
+ if (!$currencyJson) {
+ $this->error("Failed to fetch currencies");
+ return;
+ }
+
+ $currencies = json_decode($currencyJson, true);
+
+ if (!is_array($currencies) || empty($currencies)) {
+ $this->error("Invalid currencies data");
+ return 1;
+ }
+
+ //
+ // export
+ //
+ $file = resource_path('countries.php');
+
+ asort($countries);
+
+ $out = "<?php return [\n";
+
+ foreach ($countries as $code => $name) {
+ $currency = $currencies[$code] ?? null;
+
+ if (!empty($this->currency_fixes[$code])) {
+ $currency = $this->currency_fixes[$code];
+ }
+
+ if (!$currency) {
+ $this->warn("Unknown currency for {$name} ({$code}). Skipped.");
+ continue;
+ }
+
+ $out .= sprintf(" '%s' => ['%s','%s'],\n", $code, $currency, addslashes($name));
+ }
+
+ $out .= "];\n";
+
+ file_put_contents($file, $out);
+ }
+}
diff --git a/src/app/Console/Commands/Data/Import/IP4NetsCommand.php b/src/app/Console/Commands/Data/Import/IP4NetsCommand.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/Data/Import/IP4NetsCommand.php
@@ -0,0 +1,225 @@
+<?php
+
+namespace App\Console\Commands\Data\Import;
+
+use App\Console\Command;
+use Carbon\Carbon;
+
+class IP4NetsCommand extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'data:import:ip4nets';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Update IP4 Networks';
+
+ /**
+ * Create a new command instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return int
+ */
+ public function handle()
+ {
+ $rirs = [
+ 'afrinic' => 'http://ftp.afrinic.net/stats/afrinic/delegated-afrinic-latest',
+ 'apnic' => 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest',
+ 'arin' => 'http://ftp.arin.net/pub/stats/arin/delegated-arin-extended-latest',
+ 'lacnic' => 'http://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-latest',
+ 'ripencc' => 'https://ftp.ripe.net/ripe/stats/delegated-ripencc-latest'
+ ];
+
+ $today = Carbon::now()->toDateString();
+
+ foreach ($rirs as $rir => $url) {
+ $file = storage_path("{$rir}-{$today}");
+
+ \App\Utils::downloadFile($url, $file);
+
+ $serial = $this->serialFromStatsFile($file);
+
+ if (!$serial) {
+ \Log::error("Can not derive serial from {$file}");
+ continue;
+ }
+
+ $numLines = $this->countLines($file);
+
+ if (!$numLines) {
+ \Log::error("No relevant lines could be found in {$file}");
+ continue;
+ }
+
+ $bar = \App\Utils::createProgressBar(
+ $this->output,
+ $numLines,
+ "Importing IPv4 Networks from {$file}"
+ );
+
+ $fp = fopen($file, 'r');
+
+ $nets = [];
+
+ while (!feof($fp)) {
+ $line = trim(fgets($fp));
+
+ if ($line == "") {
+ continue;
+ }
+
+ if ((int)$line) {
+ continue;
+ }
+
+ if ($line[0] == "#") {
+ continue;
+ }
+
+ $items = explode('|', $line);
+
+ if (sizeof($items) < 7) {
+ continue;
+ }
+
+ if ($items[1] == "*") {
+ continue;
+ }
+
+ if ($items[2] != "ipv4") {
+ continue;
+ }
+
+ if ($items[5] == "00000000") {
+ $items[5] = "19700102";
+ }
+
+ if ($items[1] == "" || $items[1] == "ZZ") {
+ continue;
+ }
+
+ $bar->advance();
+
+ $mask = 32 - log($items[4], 2);
+
+ $net = \App\IP4Net::where(
+ [
+ 'net_number' => $items[3],
+ 'net_mask' => $mask,
+ 'net_broadcast' => long2ip((ip2long($items[3]) + 2 ** (32 - $mask)) - 1)
+ ]
+ )->first();
+
+ if ($net) {
+ if ($net->updated_at > Carbon::now()->subDays(1)) {
+ continue;
+ }
+
+ // don't use ->update() method because it doesn't update updated_at which we need for expiry
+ $net->rir_name = $rir;
+ $net->country = $items[1];
+ $net->serial = $serial;
+ $net->updated_at = Carbon::now();
+
+ $net->save();
+
+ continue;
+ }
+
+ $nets[] = [
+ 'rir_name' => $rir,
+ 'net_number' => $items[3],
+ 'net_mask' => $mask,
+ 'net_broadcast' => long2ip((ip2long($items[3]) + 2 ** (32 - $mask)) - 1),
+ 'country' => $items[1],
+ 'serial' => $serial,
+ 'created_at' => Carbon::parse($items[5], 'UTC'),
+ 'updated_at' => Carbon::now()
+ ];
+
+ if (sizeof($nets) >= 100) {
+ \App\IP4Net::insert($nets);
+ $nets = [];
+ }
+ }
+
+ if (sizeof($nets) > 0) {
+ \App\IP4Net::insert($nets);
+ $nets = [];
+ }
+
+ $bar->finish();
+
+ $this->info("DONE");
+ }
+
+ return 0;
+ }
+
+ private function countLines($file)
+ {
+ $numLines = 0;
+
+ $fh = fopen($file, 'r');
+
+ while (!feof($fh)) {
+ $line = trim(fgets($fh));
+
+ $items = explode('|', $line);
+
+ if (sizeof($items) < 3) {
+ continue;
+ }
+
+ if ($items[2] == "ipv4") {
+ $numLines++;
+ }
+ }
+
+ fclose($fh);
+
+ return $numLines;
+ }
+
+ private function serialFromStatsFile($file)
+ {
+ $serial = null;
+
+ $fh = fopen($file, 'r');
+
+ while (!feof($fh)) {
+ $line = trim(fgets($fh));
+
+ $items = explode('|', $line);
+
+ if (sizeof($items) < 2) {
+ continue;
+ }
+
+ if ((int)$items[2]) {
+ $serial = (int)$items[2];
+ break;
+ }
+ }
+
+ fclose($fh);
+
+ return $serial;
+ }
+}
diff --git a/src/app/Console/Commands/Data/Import/IP6NetsCommand.php b/src/app/Console/Commands/Data/Import/IP6NetsCommand.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/Data/Import/IP6NetsCommand.php
@@ -0,0 +1,223 @@
+<?php
+
+namespace App\Console\Commands\Data\Import;
+
+use App\Console\Command;
+use Carbon\Carbon;
+
+class IP6NetsCommand extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'data:import:ip6nets';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Import IP6 Networks.';
+
+ /**
+ * Create a new command instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return mixed
+ */
+ public function handle()
+ {
+ $rirs = [
+ 'afrinic' => 'http://ftp.afrinic.net/stats/afrinic/delegated-afrinic-latest',
+ 'apnic' => 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest',
+ 'arin' => 'http://ftp.arin.net/pub/stats/arin/delegated-arin-extended-latest',
+ 'lacnic' => 'http://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-latest',
+ 'ripencc' => 'https://ftp.ripe.net/ripe/stats/delegated-ripencc-latest'
+ ];
+
+ $today = Carbon::now()->toDateString();
+
+ foreach ($rirs as $rir => $url) {
+ $file = storage_path("{$rir}-{$today}");
+
+ \App\Utils::downloadFile($url, $file);
+
+ $serial = $this->serialFromStatsFile($file);
+
+ if (!$serial) {
+ \Log::error("Can not derive serial from {$file}");
+ continue;
+ }
+
+ $numLines = $this->countLines($file);
+
+ if (!$numLines) {
+ \Log::error("No relevant lines could be found in {$file}");
+ continue;
+ }
+
+ $bar = \App\Utils::createProgressBar(
+ $this->output,
+ $numLines,
+ "Importing IPv6 Networks from {$file}"
+ );
+
+ $fp = fopen($file, 'r');
+
+ $nets = [];
+
+ while (!feof($fp)) {
+ $line = trim(fgets($fp));
+
+ if ($line == "") {
+ continue;
+ }
+
+ if ((int)$line) {
+ continue;
+ }
+
+ if ($line[0] == "#") {
+ continue;
+ }
+
+ $items = explode('|', $line);
+
+ if (sizeof($items) < 7) {
+ continue;
+ }
+
+ if ($items[1] == "*") {
+ continue;
+ }
+
+ if ($items[2] != "ipv6") {
+ continue;
+ }
+
+ if ($items[5] == "00000000") {
+ $items[5] = "19700102";
+ }
+
+ if ($items[1] == "" || $items[1] == "ZZ") {
+ continue;
+ }
+
+ $bar->advance();
+
+ $broadcast = \App\Utils::ip6Broadcast($items[3], (int)$items[4]);
+
+ $net = \App\IP6Net::where(
+ [
+ 'net_number' => $items[3],
+ 'net_mask' => (int)$items[4],
+ 'net_broadcast' => $broadcast
+ ]
+ )->first();
+
+ if ($net) {
+ if ($net->updated_at > Carbon::now()->subDays(1)) {
+ continue;
+ }
+
+ // don't use ->update() method because it doesn't update updated_at which we need for expiry
+ $net->rir_name = $rir;
+ $net->country = $items[1];
+ $net->serial = $serial;
+ $net->updated_at = Carbon::now();
+
+ $net->save();
+
+ continue;
+ }
+
+ $nets[] = [
+ 'rir_name' => $rir,
+ 'net_number' => $items[3],
+ 'net_mask' => (int)$items[4],
+ 'net_broadcast' => $broadcast,
+ 'country' => $items[1],
+ 'serial' => $serial,
+ 'created_at' => Carbon::parse($items[5], 'UTC'),
+ 'updated_at' => Carbon::now()
+ ];
+
+ if (sizeof($nets) >= 100) {
+ \App\IP6Net::insert($nets);
+ $nets = [];
+ }
+ }
+
+ if (sizeof($nets) > 0) {
+ \App\IP6Net::insert($nets);
+ $nets = [];
+ }
+
+ $bar->finish();
+
+ $this->info("DONE");
+ }
+ }
+
+ private function countLines($file)
+ {
+ $numLines = 0;
+
+ $fh = fopen($file, 'r');
+
+ while (!feof($fh)) {
+ $line = trim(fgets($fh));
+
+ $items = explode('|', $line);
+
+ if (sizeof($items) < 3) {
+ continue;
+ }
+
+ if ($items[2] == "ipv6") {
+ $numLines++;
+ }
+ }
+
+ fclose($fh);
+
+ return $numLines;
+ }
+
+ private function serialFromStatsFile($file)
+ {
+ $serial = null;
+
+ $fh = fopen($file, 'r');
+
+ while (!feof($fh)) {
+ $line = trim(fgets($fh));
+
+ $items = explode('|', $line);
+
+ if (sizeof($items) < 2) {
+ continue;
+ }
+
+ if ((int)$items[2]) {
+ $serial = (int)$items[2];
+ break;
+ }
+ }
+
+ fclose($fh);
+
+ return $serial;
+ }
+}
diff --git a/src/app/Console/Commands/Data/ImportCommand.php b/src/app/Console/Commands/Data/ImportCommand.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/Data/ImportCommand.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace App\Console\Commands\Data;
+
+use Illuminate\Console\Command;
+
+class ImportCommand extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'data:import';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Command description';
+
+ /**
+ * Create a new command instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ }
+
+ /**
+ * Execute the console command.
+ *
+ * @return int
+ */
+ public function handle()
+ {
+ $commands = [
+ Import\CountriesCommand::class,
+ Import\IP4NetsCommand::class,
+ Import\IP6NetsCommand::class
+ ];
+
+ foreach ($commands as $command) {
+ $execution = new $command();
+ $execution->output = $this->output;
+ $execution->handle();
+ }
+
+ return 0;
+ }
+}
diff --git a/src/app/Console/Commands/DataCountries.php b/src/app/Console/Commands/DataCountries.php
deleted file mode 100644
--- a/src/app/Console/Commands/DataCountries.php
+++ /dev/null
@@ -1,142 +0,0 @@
-<?php
-
-namespace App\Console\Commands;
-
-use Illuminate\Console\Command;
-
-class DataCountries extends Command
-{
- /**
- * The name and signature of the console command.
- *
- * @var string
- */
- protected $signature = 'data:countries';
-
- /**
- * The console command description.
- *
- * @var string
- */
- protected $description = 'Fetches countries map from wikipedia';
-
- /**
- * Execute the console command.
- *
- * @return mixed
- */
- public function handle()
- {
- $countries = [];
- $currencies = [];
- $currencies_url = 'http://en.wikipedia.org/wiki/ISO_4217';
- $countries_url = 'http://en.wikipedia.org/wiki/ISO_3166-1';
-
- $this->info("Fetching currencies from $currencies_url...");
-
- // fetch currency table and create an index by country page url
- $page = file_get_contents($currencies_url);
-
- if (!$page) {
- $this->error("Failed to fetch currencies");
- return;
- }
-
- $table_regexp = '!<table class="(wikitable|prettytable) sortable".+</table>!ims';
- if (preg_match_all($table_regexp, $page, $matches, PREG_PATTERN_ORDER)) {
- foreach ($matches[0] as $currency_table) {
- preg_match_all('!<tr>\s*<td>(.+)</td>\s*</tr>!Ums', $currency_table, $rows);
-
- foreach ($rows[1] as $row) {
- $cells = preg_split('!</td>\s*<td[^>]*>!', $row);
-
- if (count($cells) == 5) {
- // actual currency table
- $currency = preg_match('/([A-Z]{3})/', $cells[0], $m) ? $m[1] : '';
-
- if (preg_match('/(\d+)/', $cells[1], $m)) {
- $isocode = $m[1];
- $currencies[$m[1]] = $currency;
- }
-
- preg_match_all('!<a[^>]+href="(/wiki/[^"]+)"[^>]*>!', $cells[4], $links, PREG_PATTERN_ORDER);
-
- foreach ($links[1] as $link) {
- $currencies[strtolower($link)] = $currency;
- }
- } elseif (count($cells) == 7) {
- // replacements table
- $currency = preg_match('/([A-Z]{3})/', $cells[6], $m) ? $m[1] : '';
-
- if (preg_match('/(\d+)/', $cells[1], $m)) {
- $currencies[$m[1]] = $currency;
- }
- }
- }
- }
- }
-
- $namecol = 0;
- $codecol = 1;
- $numcol = 3;
- $lang = 'en';
-
- $this->info("Fetching countries from $countries_url...");
-
- $page = file_get_contents($countries_url);
-
- if (!$page) {
- $this->error("Failed to fetch countries");
- return;
- }
-
- if (preg_match($table_regexp, $page, $matches)) {
- preg_match_all('!<tr>\s*<td>(.+)</td>\s*</tr>!Ums', $matches[0], $rows);
-
- foreach ($rows[1] as $row) {
- $cells = preg_split('!</td>\s*<td[^>]*>!', $row);
-
- if (count($cells) < 5) {
- continue;
- }
-
- $regexp = '!<a[^>]+href="(/wiki/[^"]+)"[^>]*>([^>]+)</a>!i';
- $content = preg_match($regexp, $cells[$namecol], $m) ? $m : null;
-
- if (preg_match('/>([A-Z]{2})</', $cells[$codecol], $m)) {
- $code = $m[1];
- } elseif (preg_match('/^([A-Z]{2})/', $cells[$codecol], $m)) {
- $code = $m[1];
- } else {
- continue;
- }
-
- if ($content) {
- $isocode = preg_match('/(\d+)/', $cells[$numcol], $m) ? $m[1] : '';
- list(, $link, $name) = $content;
- $countries[$code][$lang] = $name;
-
- if (!empty($currencies[$isocode])) {
- $countries[$code]['currency'] = $currencies[$isocode];
- } elseif (!empty($currencies[strtolower($link)])) {
- $countries[$code]['currency'] = $currencies[strtolower($link)];
- }
- }
- }
- }
-
- $file = resource_path('countries.php');
-
- $this->info("Generating resource file $file...");
-
- $out = "<?php return [\n";
- foreach ($countries as $code => $names) {
- if (!empty($names['en']) && !empty($names['currency'])) {
- $out .= sprintf(" '%s' => ['%s','%s'],\n", $code, $names['currency'], addslashes($names['en']));
- }
- }
- $out .= "];\n";
-
- file_put_contents($file, $out);
- }
-}
diff --git a/src/app/Console/Commands/DomainStatus.php b/src/app/Console/Commands/DomainStatus.php
--- a/src/app/Console/Commands/DomainStatus.php
+++ b/src/app/Console/Commands/DomainStatus.php
@@ -44,6 +44,21 @@
return 1;
}
- $this->info($domain->status);
+ $statuses = [
+ 'active' => Domain::STATUS_ACTIVE,
+ 'suspended' => Domain::STATUS_SUSPENDED,
+ 'deleted' => Domain::STATUS_DELETED,
+ 'ldapReady' => Domain::STATUS_LDAP_READY,
+ 'verified' => Domain::STATUS_VERIFIED,
+ 'confirmed' => Domain::STATUS_CONFIRMED,
+ ];
+
+ foreach ($statuses as $text => $bit) {
+ $func = 'is' . \ucfirst($text);
+
+ $this->info(sprintf("%d %s: %s", $bit, $text, $domain->$func()));
+ }
+
+ $this->info("In total: {$domain->status}");
}
}
diff --git a/src/app/Console/Commands/Job/DomainCreate.php b/src/app/Console/Commands/Job/DomainCreate.php
--- a/src/app/Console/Commands/Job/DomainCreate.php
+++ b/src/app/Console/Commands/Job/DomainCreate.php
@@ -34,7 +34,7 @@
return 1;
}
- $job = new \App\Jobs\DomainCreate($domain);
+ $job = new \App\Jobs\Domain\CreateJob($domain->id);
$job->handle();
}
}
diff --git a/src/app/Console/Commands/Job/DomainUpdate.php b/src/app/Console/Commands/Job/DomainUpdate.php
--- a/src/app/Console/Commands/Job/DomainUpdate.php
+++ b/src/app/Console/Commands/Job/DomainUpdate.php
@@ -34,7 +34,7 @@
return 1;
}
- $job = new \App\Jobs\DomainUpdate($domain->id);
+ $job = new \App\Jobs\Domain\UpdateJob($domain->id);
$job->handle();
}
}
diff --git a/src/app/Console/Commands/Job/UserCreate.php b/src/app/Console/Commands/Job/UserCreate.php
--- a/src/app/Console/Commands/Job/UserCreate.php
+++ b/src/app/Console/Commands/Job/UserCreate.php
@@ -34,7 +34,7 @@
return 1;
}
- $job = new \App\Jobs\UserCreate($user);
+ $job = new \App\Jobs\User\CreateJob($user->id);
$job->handle();
}
}
diff --git a/src/app/Console/Commands/Job/UserUpdate.php b/src/app/Console/Commands/Job/UserUpdate.php
--- a/src/app/Console/Commands/Job/UserUpdate.php
+++ b/src/app/Console/Commands/Job/UserUpdate.php
@@ -34,7 +34,7 @@
return 1;
}
- $job = new \App\Jobs\UserUpdate($user);
+ $job = new \App\Jobs\User\UpdateJob($user->id);
$job->handle();
}
}
diff --git a/src/app/Console/Commands/MollieInfo.php b/src/app/Console/Commands/MollieInfo.php
--- a/src/app/Console/Commands/MollieInfo.php
+++ b/src/app/Console/Commands/MollieInfo.php
@@ -43,10 +43,21 @@
if ($mandate = $provider->getMandate($wallet)) {
$amount = $wallet->getSetting('mandate_amount');
$balance = $wallet->getSetting('mandate_balance') ?: 0;
+ $status = 'invalid';
+
+ if ($mandate['isPending']) {
+ $status = 'pending';
+ } elseif ($mandate['isValid']) {
+ $status = 'valid';
+ }
+
+ if ($wallet->getSetting('mandate_disabled')) {
+ $status .= ' (disabled)';
+ }
$this->info("Auto-payment: {$mandate['method']}");
$this->info(" id: {$mandate['id']}");
- $this->info(" status: " . ($mandate['isPending'] ? 'pending' : 'valid'));
+ $this->info(" status: {$status}");
$this->info(" amount: {$amount} {$wallet->currency}");
$this->info(" min-balance: {$balance} {$wallet->currency}");
} else {
diff --git a/src/app/Console/Commands/StripeInfo.php b/src/app/Console/Commands/StripeInfo.php
--- a/src/app/Console/Commands/StripeInfo.php
+++ b/src/app/Console/Commands/StripeInfo.php
@@ -45,10 +45,21 @@
if ($mandate = $provider->getMandate($wallet)) {
$amount = $wallet->getSetting('mandate_amount');
$balance = $wallet->getSetting('mandate_balance') ?: 0;
+ $status = 'invalid';
+
+ if ($mandate['isPending']) {
+ $status = 'pending';
+ } elseif ($mandate['isValid']) {
+ $status = 'valid';
+ }
+
+ if ($wallet->getSetting('mandate_disabled')) {
+ $status .= ' (disabled)';
+ }
$this->info("Auto-payment: {$mandate['method']}");
$this->info(" id: {$mandate['id']}");
- $this->info(" status: " . ($mandate['isPending'] ? 'pending' : 'valid'));
+ $this->info(" status: {$status}");
$this->info(" amount: {$amount} {$wallet->currency}");
$this->info(" min-balance: {$balance} {$wallet->currency}");
} else {
diff --git a/src/app/Console/Commands/UserForceDelete.php b/src/app/Console/Commands/UserForceDelete.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/UserForceDelete.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
+
+class UserForceDelete extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'user:force-delete {user}';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Delete a user for realz';
+
+ /**
+ * Execute the console command.
+ *
+ * @return mixed
+ */
+ public function handle()
+ {
+ $user = \App\User::withTrashed()->where('email', $this->argument('user'))->first();
+
+ if (!$user) {
+ return 1;
+ }
+
+ if (!$user->trashed()) {
+ $this->error('The user is not yet deleted');
+ return 1;
+ }
+
+ DB::beginTransaction();
+ $user->forceDelete();
+ DB::commit();
+ }
+}
diff --git a/src/app/Console/Commands/UserStatus.php b/src/app/Console/Commands/UserStatus.php
--- a/src/app/Console/Commands/UserStatus.php
+++ b/src/app/Console/Commands/UserStatus.php
@@ -44,8 +44,20 @@
return 1;
}
- $this->info("Found user: {$user->id}");
+ $statuses = [
+ 'active' => User::STATUS_ACTIVE,
+ 'suspended' => User::STATUS_SUSPENDED,
+ 'deleted' => User::STATUS_DELETED,
+ 'ldapReady' => User::STATUS_LDAP_READY,
+ 'imapReady' => User::STATUS_IMAP_READY,
+ ];
+
+ foreach ($statuses as $text => $bit) {
+ $func = 'is' . \ucfirst($text);
+
+ $this->info(sprintf("%d %s: %s", $bit, $text, $user->$func()));
+ }
- $this->info($user->status);
+ $this->info("In total: {$user->status}");
}
}
diff --git a/src/app/Console/Commands/UserVerify.php b/src/app/Console/Commands/UserVerify.php
--- a/src/app/Console/Commands/UserVerify.php
+++ b/src/app/Console/Commands/UserVerify.php
@@ -45,7 +45,7 @@
$this->info("Found user: {$user->id}");
- $job = new \App\Jobs\UserVerify($user);
+ $job = new \App\Jobs\User\VerifyJob($user->id);
$job->handle();
}
}
diff --git a/src/app/Console/Kernel.php b/src/app/Console/Kernel.php
--- a/src/app/Console/Kernel.php
+++ b/src/app/Console/Kernel.php
@@ -25,8 +25,18 @@
*/
protected function schedule(Schedule $schedule)
{
- // $schedule->command('inspire')
- // ->hourly();
+ // This command imports countries and the current set of IPv4 and IPv6 networks allocated to countries.
+ $schedule->command('data:import')->dailyAt('05:00');
+
+ $schedule->command('wallet:charge')->dailyAt('00:00');
+ $schedule->command('wallet:charge')->dailyAt('04:00');
+ $schedule->command('wallet:charge')->dailyAt('08:00');
+ $schedule->command('wallet:charge')->dailyAt('12:00');
+ $schedule->command('wallet:charge')->dailyAt('16:00');
+ $schedule->command('wallet:charge')->dailyAt('20:00');
+
+ // this is a laravel 8-ism
+ //$schedule->command('wallet:charge')->everyFourHours();
}
/**
diff --git a/src/app/Documents/Receipt.php b/src/app/Documents/Receipt.php
--- a/src/app/Documents/Receipt.php
+++ b/src/app/Documents/Receipt.php
@@ -160,7 +160,7 @@
->where('status', PaymentProvider::STATUS_PAID)
->where('updated_at', '>=', $start)
->where('updated_at', '<', $end)
- ->where('amount', '>', 0)
+ ->where('amount', '<>', 0)
->orderBy('updated_at')
->get();
}
@@ -185,9 +185,17 @@
$total += $amount;
+ if ($item->type == PaymentProvider::TYPE_REFUND) {
+ $description = \trans('documents.receipt-refund');
+ } elseif ($item->type == PaymentProvider::TYPE_CHARGEBACK) {
+ $description = \trans('documents.receipt-chargeback');
+ } else {
+ $description = \trans('documents.receipt-item-desc', ['site' => $appName]);
+ }
+
return [
'amount' => $this->wallet->money($amount),
- 'description' => \trans('documents.receipt-item-desc', ['site' => $appName]),
+ 'description' => $description,
'date' => $item->updated_at->toDateString(),
];
});
diff --git a/src/app/Domain.php b/src/app/Domain.php
--- a/src/app/Domain.php
+++ b/src/app/Domain.php
@@ -232,11 +232,11 @@
$allowed_values = [
self::STATUS_NEW,
self::STATUS_ACTIVE,
- self::STATUS_CONFIRMED,
self::STATUS_SUSPENDED,
self::STATUS_DELETED,
- self::STATUS_LDAP_READY,
+ self::STATUS_CONFIRMED,
self::STATUS_VERIFIED,
+ self::STATUS_LDAP_READY,
];
foreach ($allowed_values as $value) {
@@ -250,6 +250,31 @@
throw new \Exception("Invalid domain status: {$status}");
}
+ if ($this->isPublic()) {
+ $this->attributes['status'] = $new_status;
+ return;
+ }
+
+ if ($new_status & self::STATUS_CONFIRMED) {
+ // if we have confirmed ownership of or management access to the domain, then we have
+ // also confirmed the domain exists in DNS.
+ $new_status |= self::STATUS_VERIFIED;
+ $new_status |= self::STATUS_ACTIVE;
+ }
+
+ if ($new_status & self::STATUS_DELETED && $new_status & self::STATUS_ACTIVE) {
+ $new_status ^= self::STATUS_ACTIVE;
+ }
+
+ if ($new_status & self::STATUS_SUSPENDED && $new_status & self::STATUS_ACTIVE) {
+ $new_status ^= self::STATUS_ACTIVE;
+ }
+
+ // if the domain is now active, it is not new anymore.
+ if ($new_status & self::STATUS_ACTIVE && $new_status & self::STATUS_NEW) {
+ $new_status ^= self::STATUS_NEW;
+ }
+
$this->attributes['status'] = $new_status;
}
@@ -349,6 +374,15 @@
/**
* Unsuspend this domain.
*
+ * The domain is unsuspended through either of the following courses of actions;
+ *
+ * * The account balance has been topped up, or
+ * * a suspected spammer has resolved their issues, or
+ * * the command-line is triggered.
+ *
+ * Therefore, we can also confidently set the domain status to 'active' should the ownership of or management
+ * access to have been confirmed before.
+ *
* @return void
*/
public function unsuspend(): void
@@ -358,6 +392,11 @@
}
$this->status ^= Domain::STATUS_SUSPENDED;
+
+ if ($this->isConfirmed() && $this->isVerified()) {
+ $this->status |= Domain::STATUS_ACTIVE;
+ }
+
$this->save();
}
@@ -399,7 +438,7 @@
public function wallet(): ?Wallet
{
// Note: Not all domains have a entitlement/wallet
- $entitlement = $this->entitlement()->first();
+ $entitlement = $this->entitlement()->withTrashed()->first();
return $entitlement ? $entitlement->wallet : null;
}
diff --git a/src/app/Http/Controllers/API/AuthController.php b/src/app/Http/Controllers/API/AuthController.php
--- a/src/app/Http/Controllers/API/AuthController.php
+++ b/src/app/Http/Controllers/API/AuthController.php
@@ -38,8 +38,10 @@
{
// @phpstan-ignore-next-line
$token = Auth::guard()->login($user);
+ $response = V4\UsersController::userResponse($user);
+ $response['status'] = 'success';
- return self::respondWithToken($token, ['status' => 'success']);
+ return self::respondWithToken($token, $response);
}
/**
@@ -67,13 +69,16 @@
$credentials = $request->only('email', 'password');
if ($token = Auth::guard()->attempt($credentials)) {
- $sf = new \App\Auth\SecondFactor(Auth::guard()->user());
+ $user = Auth::guard()->user();
+ $sf = new \App\Auth\SecondFactor($user);
if ($response = $sf->requestHandler($request)) {
return $response;
}
- return $this->respondWithToken($token);
+ $response = V4\UsersController::userResponse($user);
+
+ return $this->respondWithToken($token, $response);
}
return response()->json(['status' => 'error', 'message' => __('auth.failed')], 401);
diff --git a/src/app/Http/Controllers/API/SignupController.php b/src/app/Http/Controllers/API/SignupController.php
--- a/src/app/Http/Controllers/API/SignupController.php
+++ b/src/app/Http/Controllers/API/SignupController.php
@@ -211,11 +211,11 @@
$plan = $this->getPlan();
$is_domain = $plan->hasDomain();
- $login = $request->login;
- $domain = $request->domain;
+ $login = $request->login;
+ $domain_name = $request->domain;
// Validate login
- if ($errors = self::validateLogin($login, $domain, $is_domain)) {
+ if ($errors = self::validateLogin($login, $domain_name, $is_domain)) {
return response()->json(['status' => 'error', 'errors' => $errors], 422);
}
@@ -225,26 +225,26 @@
// We allow only ASCII, so we can safely lower-case the email address
$login = Str::lower($login);
- $domain = Str::lower($domain);
+ $domain_name = Str::lower($domain_name);
+ $domain = null;
DB::beginTransaction();
- // Create user record
- $user = User::create([
- 'email' => $login . '@' . $domain,
- 'password' => $request->password,
- ]);
-
// Create domain record
- // FIXME: Should we do this in UserObserver::created()?
if ($is_domain) {
$domain = Domain::create([
- 'namespace' => $domain,
+ 'namespace' => $domain_name,
'status' => Domain::STATUS_NEW,
'type' => Domain::TYPE_EXTERNAL,
]);
}
+ // Create user record
+ $user = User::create([
+ 'email' => $login . '@' . $domain_name,
+ 'password' => $request->password,
+ ]);
+
if (!empty($discount)) {
$wallet = $user->wallets()->first();
$wallet->discount()->associate($discount);
diff --git a/src/app/Http/Controllers/API/V4/Admin/DomainsController.php b/src/app/Http/Controllers/API/V4/Admin/DomainsController.php
--- a/src/app/Http/Controllers/API/V4/Admin/DomainsController.php
+++ b/src/app/Http/Controllers/API/V4/Admin/DomainsController.php
@@ -58,7 +58,7 @@
* Suspend the domain
*
* @param \Illuminate\Http\Request $request The API request.
- * @params string $id Domain identifier
+ * @param string $id Domain identifier
*
* @return \Illuminate\Http\JsonResponse The response
*/
@@ -82,7 +82,7 @@
* Un-Suspend the domain
*
* @param \Illuminate\Http\Request $request The API request.
- * @params string $id Domain identifier
+ * @param string $id Domain identifier
*
* @return \Illuminate\Http\JsonResponse The response
*/
diff --git a/src/app/Http/Controllers/API/V4/Admin/UsersController.php b/src/app/Http/Controllers/API/V4/Admin/UsersController.php
--- a/src/app/Http/Controllers/API/V4/Admin/UsersController.php
+++ b/src/app/Http/Controllers/API/V4/Admin/UsersController.php
@@ -29,32 +29,34 @@
}
} elseif (strpos($search, '@')) {
// Search by email
- $user = User::where('email', $search)->first();
- if ($user) {
- $result->push($user);
- } else {
+ $result = User::withTrashed()->where('email', $search)
+ ->orderBy('email')->get();
+
+ if ($result->isEmpty()) {
// Search by an alias
$user_ids = UserAlias::where('alias', $search)->get()->pluck('user_id');
- if ($user_ids->isEmpty()) {
- // Search by an external email
- $user_ids = UserSetting::where('key', 'external_email')
- ->where('value', $search)->get()->pluck('user_id');
- }
+
+ // Search by an external email
+ $ext_user_ids = UserSetting::where('key', 'external_email')
+ ->where('value', $search)->get()->pluck('user_id');
+
+ $user_ids = $user_ids->merge($ext_user_ids)->unique();
if (!$user_ids->isEmpty()) {
- $result = User::whereIn('id', $user_ids)->orderBy('email')->get();
+ $result = User::withTrashed()->whereIn('id', $user_ids)
+ ->orderBy('email')->get();
}
}
} elseif (is_numeric($search)) {
// Search by user ID
- if ($user = User::find($search)) {
+ if ($user = User::withTrashed()->find($search)) {
$result->push($user);
}
} elseif (!empty($search)) {
// Search by domain
- if ($domain = Domain::where('namespace', $search)->first()) {
+ if ($domain = Domain::withTrashed()->where('namespace', $search)->first()) {
if ($wallet = $domain->wallet()) {
- $result->push($wallet->owner);
+ $result->push($wallet->owner()->withTrashed()->first());
}
}
}
@@ -79,7 +81,7 @@
* Reset 2-Factor Authentication for the user
*
* @param \Illuminate\Http\Request $request The API request.
- * @params string $id User identifier
+ * @param string $id User identifier
*
* @return \Illuminate\Http\JsonResponse The response
*/
@@ -109,7 +111,7 @@
* Suspend the user
*
* @param \Illuminate\Http\Request $request The API request.
- * @params string $id User identifier
+ * @param string $id User identifier
*
* @return \Illuminate\Http\JsonResponse The response
*/
@@ -133,7 +135,7 @@
* Un-Suspend the user
*
* @param \Illuminate\Http\Request $request The API request.
- * @params string $id User identifier
+ * @param string $id User identifier
*
* @return \Illuminate\Http\JsonResponse The response
*/
@@ -157,7 +159,7 @@
* Update user data.
*
* @param \Illuminate\Http\Request $request The API request.
- * @params string $id User identifier
+ * @param string $id User identifier
*
* @return \Illuminate\Http\JsonResponse The response
*/
diff --git a/src/app/Http/Controllers/API/V4/Admin/WalletsController.php b/src/app/Http/Controllers/API/V4/Admin/WalletsController.php
--- a/src/app/Http/Controllers/API/V4/Admin/WalletsController.php
+++ b/src/app/Http/Controllers/API/V4/Admin/WalletsController.php
@@ -52,7 +52,7 @@
* Award/penalize a wallet.
*
* @param \Illuminate\Http\Request $request The API request.
- * @params string $id Wallet identifier
+ * @param string $id Wallet identifier
*
* @return \Illuminate\Http\JsonResponse The response
*/
@@ -111,7 +111,7 @@
* Update wallet data.
*
* @param \Illuminate\Http\Request $request The API request.
- * @params string $id Wallet identifier
+ * @param string $id Wallet identifier
*
* @return \Illuminate\Http\JsonResponse The response
*/
diff --git a/src/app/Http/Controllers/API/V4/UsersController.php b/src/app/Http/Controllers/API/V4/UsersController.php
--- a/src/app/Http/Controllers/API/V4/UsersController.php
+++ b/src/app/Http/Controllers/API/V4/UsersController.php
@@ -291,7 +291,7 @@
* Update user data.
*
* @param \Illuminate\Http\Request $request The API request.
- * @params string $id User identifier
+ * @param string $id User identifier
*
* @return \Illuminate\Http\JsonResponse The response
*/
@@ -592,14 +592,20 @@
switch ($step) {
case 'user-ldap-ready':
// User not in LDAP, create it
- $job = new \App\Jobs\UserCreate($user);
+ $job = new \App\Jobs\User\CreateJob($user->id);
$job->handle();
+
+ $user->refresh();
+
return $user->isLdapReady();
case 'user-imap-ready':
// User not in IMAP? Verify again
- $job = new \App\Jobs\UserVerify($user);
+ $job = new \App\Jobs\User\VerifyJob($user->id);
$job->handle();
+
+ $user->refresh();
+
return $user->isImapReady();
}
} catch (\Exception $e) {
@@ -629,14 +635,14 @@
return \trans('validation.entryinvalid', ['attribute' => $attribute]);
}
- list($login, $domain) = explode('@', $email);
+ list($login, $domain) = explode('@', Str::lower($email));
if (strlen($login) === 0 || strlen($domain) === 0) {
return \trans('validation.entryinvalid', ['attribute' => $attribute]);
}
// Check if domain exists
- $domain = Domain::where('namespace', Str::lower($domain))->first();
+ $domain = Domain::where('namespace', $domain)->first();
if (empty($domain)) {
return \trans('validation.domaininvalid');
diff --git a/src/app/Http/Controllers/API/V4/WalletsController.php b/src/app/Http/Controllers/API/V4/WalletsController.php
--- a/src/app/Http/Controllers/API/V4/WalletsController.php
+++ b/src/app/Http/Controllers/API/V4/WalletsController.php
@@ -93,7 +93,7 @@
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
- * @param int $id
+ * @param string $id
*
* @return \Illuminate\Http\JsonResponse
*/
@@ -179,7 +179,7 @@
$result = $wallet->payments()
->selectRaw('distinct date_format(updated_at, "%Y-%m") as ident')
->where('status', PaymentProvider::STATUS_PAID)
- ->where('amount', '>', 0)
+ ->where('amount', '<>', 0)
->orderBy('ident', 'desc')
->get()
->whereNotIn('ident', [date('Y-m')]) // exclude current month
@@ -284,24 +284,28 @@
*/
protected function getWalletNotice(Wallet $wallet): ?string
{
+ // there is no credit
if ($wallet->balance < 0) {
return \trans('app.wallet-notice-nocredit');
}
+ // the discount is 100%, no credit is needed
if ($wallet->discount && $wallet->discount->discount == 100) {
return null;
}
- if ($wallet->owner->created_at > Carbon::now()->subDays(14)) {
+ // the owner was created less than a month ago
+ if ($wallet->owner->created_at > Carbon::now()->subMonthsWithoutOverflow(1)) {
+ // but more than two weeks ago, notice of trial ending
+ if ($wallet->owner->created_at <= Carbon::now()->subWeeks(2)) {
+ return \trans('app.wallet-notice-trial-end');
+ }
+
return \trans('app.wallet-notice-trial');
}
if ($until = $wallet->balanceLastsUntil()) {
if ($until->isToday()) {
- if ($wallet->owner->created_at > Carbon::now()->subDays(30)) {
- return \trans('app.wallet-notice-trial-end');
- }
-
return \trans('app.wallet-notice-today');
}
diff --git a/src/app/IP4Net.php b/src/app/IP4Net.php
new file mode 100644
--- /dev/null
+++ b/src/app/IP4Net.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Facades\DB;
+
+class IP4Net extends Model
+{
+ protected $table = "ip4nets";
+
+ protected $fillable = [
+ 'net_number',
+ 'net_mask',
+ 'net_broadcast',
+ 'country',
+ 'serial'
+ ];
+}
diff --git a/src/app/IP6Net.php b/src/app/IP6Net.php
new file mode 100644
--- /dev/null
+++ b/src/app/IP6Net.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Facades\DB;
+
+class IP6Net extends Model
+{
+ protected $table = "ip6nets";
+
+ protected $fillable = [
+ 'rir_name',
+ 'net_number',
+ 'net_mask',
+ 'net_broadcast',
+ 'country',
+ 'serial',
+ 'created_at',
+ 'updated_at'
+ ];
+
+ public static function getNet($ip, $mask = 128)
+ {
+ $query = "
+ SELECT id FROM ip6nets
+ WHERE INET6_ATON(net_number) <= INET6_ATON(?)
+ AND INET6_ATON(net_broadcast) >= INET6_ATON(?)
+ ORDER BY INET6_ATON(net_number), net_mask DESC LIMIT 1
+ ";
+
+ $results = DB::select($query, [$ip, $ip]);
+
+ if (sizeof($results) == 0) {
+ return null;
+ }
+
+ return \App\IP6Net::find($results[0]->id);
+ }
+}
diff --git a/src/app/Jobs/CommonJob.php b/src/app/Jobs/CommonJob.php
new file mode 100644
--- /dev/null
+++ b/src/app/Jobs/CommonJob.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace App\Jobs;
+
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+
+/**
+ * The abstract \App\Jobs\DomainJob implements the logic needed for all dispatchable Jobs related to
+ * \App\Domain objects.
+ *
+ * ```php
+ * $job = new \App\Jobs\Domain\CreateJob($domainId);
+ * $job->handle();
+ * ```
+ */
+abstract class CommonJob implements ShouldQueue
+{
+ use Dispatchable;
+ use InteractsWithQueue;
+ use Queueable;
+
+ /**
+ * The failure message.
+ *
+ * @var string
+ */
+ public $failureMessage;
+
+ /**
+ * The number of tries for this Job.
+ *
+ * @var int
+ */
+ public $tries = 5;
+
+ /**
+ * Execute the job.
+ *
+ * @return void
+ */
+ abstract public function handle();
+
+ /**
+ * Delete the job, call the "failed" method, and raise the failed job event.
+ *
+ * @param \Throwable|null $e An Exception
+ *
+ * @return void
+ */
+ public function fail($e = null)
+ {
+ // Save the message, for testing purposes
+ $this->failureMessage = $e->getMessage();
+
+ // @phpstan-ignore-next-line
+ if ($this->job) {
+ $this->job->fail($e);
+ }
+ }
+
+ /**
+ * Check if the job has failed
+ *
+ * @return bool
+ */
+ public function hasFailed(): bool
+ {
+ return $this->failureMessage !== null;
+ }
+}
diff --git a/src/app/Jobs/Domain/CreateJob.php b/src/app/Jobs/Domain/CreateJob.php
new file mode 100644
--- /dev/null
+++ b/src/app/Jobs/Domain/CreateJob.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace App\Jobs\Domain;
+
+use App\Jobs\DomainJob;
+
+class CreateJob extends DomainJob
+{
+ /**
+ * Execute the job.
+ *
+ * @return void
+ */
+ public function handle()
+ {
+ $domain = $this->getDomain();
+
+ if (!$domain->isLdapReady()) {
+ \App\Backends\LDAP::createDomain($domain);
+
+ $domain->status |= \App\Domain::STATUS_LDAP_READY;
+ $domain->save();
+
+ \App\Jobs\Domain\VerifyJob::dispatch($domain->id);
+ }
+ }
+}
diff --git a/src/app/Jobs/Domain/DeleteJob.php b/src/app/Jobs/Domain/DeleteJob.php
new file mode 100644
--- /dev/null
+++ b/src/app/Jobs/Domain/DeleteJob.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Jobs\Domain;
+
+use App\Jobs\DomainJob;
+
+class DeleteJob extends DomainJob
+{
+ /**
+ * Execute the job.
+ *
+ * @return void
+ */
+ public function handle()
+ {
+ $domain = $this->getDomain();
+
+ // sanity checks
+ if ($domain->isDeleted()) {
+ $this->fail(new \Exception("Domain {$this->domainId} is already marked as deleted."));
+ return;
+ }
+
+ \App\Backends\LDAP::deleteDomain($domain);
+
+ $domain->status |= \App\Domain::STATUS_DELETED;
+ $domain->save();
+ }
+}
diff --git a/src/app/Jobs/Domain/UpdateJob.php b/src/app/Jobs/Domain/UpdateJob.php
new file mode 100644
--- /dev/null
+++ b/src/app/Jobs/Domain/UpdateJob.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace App\Jobs\Domain;
+
+use App\Jobs\DomainJob;
+
+class UpdateJob extends DomainJob
+{
+ /**
+ * Execute the job.
+ *
+ * @return void
+ */
+ public function handle()
+ {
+ $domain = $this->getDomain();
+
+ if (!$domain->isLdapReady()) {
+ $this->delete();
+ return;
+ }
+
+ \App\Backends\LDAP::updateDomain($domain);
+ }
+}
diff --git a/src/app/Jobs/Domain/VerifyJob.php b/src/app/Jobs/Domain/VerifyJob.php
new file mode 100644
--- /dev/null
+++ b/src/app/Jobs/Domain/VerifyJob.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Jobs\Domain;
+
+use App\Jobs\DomainJob;
+
+class VerifyJob extends DomainJob
+{
+ /**
+ * Execute the job.
+ *
+ * @return void
+ */
+ public function handle()
+ {
+ $domain = $this->getDomain();
+
+ $domain->verify();
+
+ // TODO: What should happen if the domain is not registered yet?
+ // Should we start a new job with some specified delay?
+ // Or we just give the user a button to start verification again?
+ }
+}
diff --git a/src/app/Jobs/DomainCreate.php b/src/app/Jobs/DomainCreate.php
deleted file mode 100644
--- a/src/app/Jobs/DomainCreate.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-
-namespace App\Jobs;
-
-use App\Backends\LDAP;
-use App\Domain;
-use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Foundation\Bus\Dispatchable;
-use Illuminate\Queue\SerializesModels;
-use Illuminate\Queue\InteractsWithQueue;
-
-class DomainCreate implements ShouldQueue
-{
- use Dispatchable;
- use InteractsWithQueue;
- use Queueable;
- use SerializesModels;
-
- protected $domain;
-
- public $tries = 5;
-
- /** @var bool Delete the job if its models no longer exist. */
- public $deleteWhenMissingModels = true;
-
- /**
- * Create a new job instance.
- *
- * @param Domain $domain The domain to create.
- *
- * @return void
- */
- public function __construct(Domain $domain)
- {
- $this->domain = $domain;
- }
-
- /**
- * Execute the job.
- *
- * @return void
- */
- public function handle()
- {
- if (!$this->domain->isLdapReady()) {
- LDAP::createDomain($this->domain);
-
- $this->domain->status |= Domain::STATUS_LDAP_READY;
- $this->domain->save();
-
- DomainVerify::dispatch($this->domain);
- }
- }
-}
diff --git a/src/app/Jobs/DomainDelete.php b/src/app/Jobs/DomainDelete.php
deleted file mode 100644
--- a/src/app/Jobs/DomainDelete.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-namespace App\Jobs;
-
-use App\Backends\LDAP;
-use App\Domain;
-use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Foundation\Bus\Dispatchable;
-use Illuminate\Queue\SerializesModels;
-use Illuminate\Queue\InteractsWithQueue;
-
-class DomainDelete implements ShouldQueue
-{
- use Dispatchable;
- use InteractsWithQueue;
- use Queueable;
- use SerializesModels;
-
- protected $domain;
-
- public $tries = 5;
-
- /** @var bool Delete the job if its models no longer exist. */
- public $deleteWhenMissingModels = true;
-
- /**
- * Create a new job instance.
- *
- * @param int $domain_id The ID of the domain to delete.
- *
- * @return void
- */
- public function __construct(int $domain_id)
- {
- $this->domain = Domain::withTrashed()->find($domain_id);
- }
-
- /**
- * Execute the job.
- *
- * @return void
- */
- public function handle()
- {
- if (!$this->domain->isDeleted()) {
- LDAP::deleteDomain($this->domain);
-
- $this->domain->status |= Domain::STATUS_DELETED;
- $this->domain->save();
- }
- }
-}
diff --git a/src/app/Jobs/DomainJob.php b/src/app/Jobs/DomainJob.php
new file mode 100644
--- /dev/null
+++ b/src/app/Jobs/DomainJob.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace App\Jobs;
+
+/**
+ * The abstract \App\Jobs\DomainJob implements the logic needed for all dispatchable Jobs related to
+ * \App\Domain objects.
+ *
+ * ```php
+ * $job = new \App\Jobs\Domain\CreateJob($domainId);
+ * $job->handle();
+ * ```
+ */
+abstract class DomainJob extends CommonJob
+{
+ /**
+ * The ID for the \App\Domain. This is the shortest globally unique identifier and saves Redis space
+ * compared to a serialized version of the complete \App\Domain object.
+ *
+ * @var int
+ */
+ protected $domainId;
+
+ /**
+ * The \App\Domain namespace property, for legibility in the queue management.
+ *
+ * @var string
+ */
+ protected $domainNamespace;
+
+ /**
+ * Create a new job instance.
+ *
+ * @param int $domainId The ID for the user to create.
+ *
+ * @return void
+ */
+ public function __construct(int $domainId)
+ {
+ $this->domainId = $domainId;
+
+ $domain = $this->getDomain();
+
+ if ($domain) {
+ $this->domainNamespace = $domain->namespace;
+ }
+ }
+
+ /**
+ * Get the \App\Domain entry associated with this job.
+ *
+ * @return \App\Domain|null
+ *
+ * @throws \Exception
+ */
+ protected function getDomain()
+ {
+ $domain = \App\Domain::withTrashed()->find($this->domainId);
+
+ if (!$domain) {
+ $this->fail(new \Exception("Domain {$this->domainId} could not be found in the database."));
+ }
+
+ return $domain;
+ }
+}
diff --git a/src/app/Jobs/DomainUpdate.php b/src/app/Jobs/DomainUpdate.php
deleted file mode 100644
--- a/src/app/Jobs/DomainUpdate.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-namespace App\Jobs;
-
-use App\Backends\LDAP;
-use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Foundation\Bus\Dispatchable;
-use Illuminate\Queue\InteractsWithQueue;
-use Illuminate\Queue\SerializesModels;
-
-class DomainUpdate implements ShouldQueue
-{
- use Dispatchable;
- use InteractsWithQueue;
- use Queueable;
- use SerializesModels;
-
- protected $domain_id;
-
- /**
- * Create a new job instance.
- *
- * @param int $domain_id
- *
- * @return void
- */
- public function __construct($domain_id)
- {
- $this->domain_id = $domain_id;
- }
-
- /**
- * Execute the job.
- *
- * @return void
- */
- public function handle()
- {
- $domain = \App\Domain::find($this->domain_id);
-
- LDAP::updateDomain($domain);
- }
-}
diff --git a/src/app/Jobs/DomainVerify.php b/src/app/Jobs/DomainVerify.php
deleted file mode 100644
--- a/src/app/Jobs/DomainVerify.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-
-namespace App\Jobs;
-
-use App\Domain;
-use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Foundation\Bus\Dispatchable;
-use Illuminate\Queue\InteractsWithQueue;
-use Illuminate\Queue\SerializesModels;
-
-class DomainVerify implements ShouldQueue
-{
- use Dispatchable;
- use InteractsWithQueue;
- use Queueable;
- use SerializesModels;
-
- protected $domain;
-
- public $tries = 5;
-
- /** @var bool Delete the job if its models no longer exist. */
- public $deleteWhenMissingModels = true;
-
- /**
- * Create a new job instance.
- *
- * @param Domain $domain The domain to create.
- *
- * @return void
- */
- public function __construct(Domain $domain)
- {
- $this->domain = $domain;
- }
-
- /**
- * Execute the job.
- *
- * @return void
- */
- public function handle()
- {
- $this->domain->verify();
-
- // TODO: What should happen if the domain is not registered yet?
- // Should we start a new job with some specified delay?
- // Or we just give the user a button to start verification again?
- }
-}
diff --git a/src/app/Jobs/PaymentEmail.php b/src/app/Jobs/PaymentEmail.php
--- a/src/app/Jobs/PaymentEmail.php
+++ b/src/app/Jobs/PaymentEmail.php
@@ -62,25 +62,49 @@
$this->controller = $wallet->owner;
}
- $ext_email = $this->controller->getSetting('external_email');
- $cc = [];
-
- if ($ext_email && $ext_email != $this->controller->email) {
- $cc[] = $ext_email;
+ if (empty($this->controller)) {
+ return;
}
if ($this->payment->status == PaymentProvider::STATUS_PAID) {
$mail = new \App\Mail\PaymentSuccess($this->payment, $this->controller);
+ $label = "Success";
} elseif (
$this->payment->status == PaymentProvider::STATUS_EXPIRED
|| $this->payment->status == PaymentProvider::STATUS_FAILED
) {
$mail = new \App\Mail\PaymentFailure($this->payment, $this->controller);
+ $label = "Failure";
} else {
return;
}
- Mail::to($this->controller->email)->cc($cc)->send($mail);
+ list($to, $cc) = \App\Mail\Helper::userEmails($this->controller);
+
+ if (!empty($to)) {
+ try {
+ Mail::to($to)->cc($cc)->send($mail);
+
+ $msg = sprintf(
+ "[Payment] %s mail sent for %s (%s)",
+ $label,
+ $wallet->id,
+ empty($cc) ? $to : implode(', ', array_merge([$to], $cc))
+ );
+
+ \Log::info($msg);
+ } catch (\Exception $e) {
+ $msg = sprintf(
+ "[Payment] Failed to send mail for wallet %s (%s): %s",
+ $wallet->id,
+ empty($cc) ? $to : implode(', ', array_merge([$to], $cc)),
+ $e->getMessage()
+ );
+
+ \Log::error($msg);
+ throw $e;
+ }
+ }
/*
// Send the email to all wallet controllers too
diff --git a/src/app/Jobs/PaymentMandateDisabledEmail.php b/src/app/Jobs/PaymentMandateDisabledEmail.php
--- a/src/app/Jobs/PaymentMandateDisabledEmail.php
+++ b/src/app/Jobs/PaymentMandateDisabledEmail.php
@@ -60,16 +60,37 @@
$this->controller = $this->wallet->owner;
}
- $ext_email = $this->controller->getSetting('external_email');
- $cc = [];
-
- if ($ext_email && $ext_email != $this->controller->email) {
- $cc[] = $ext_email;
+ if (empty($this->controller)) {
+ return;
}
$mail = new PaymentMandateDisabled($this->wallet, $this->controller);
- Mail::to($this->controller->email)->cc($cc)->send($mail);
+ list($to, $cc) = \App\Mail\Helper::userEmails($this->controller);
+
+ if (!empty($to)) {
+ try {
+ Mail::to($to)->cc($cc)->send($mail);
+
+ $msg = sprintf(
+ "[PaymentMandateDisabled] Sent mail for %s (%s)",
+ $this->wallet->id,
+ empty($cc) ? $to : implode(', ', array_merge([$to], $cc))
+ );
+
+ \Log::info($msg);
+ } catch (\Exception $e) {
+ $msg = sprintf(
+ "[PaymentMandateDisabled] Failed to send mail for wallet %s (%s): %s",
+ $this->wallet->id,
+ empty($cc) ? $to : implode(', ', array_merge([$to], $cc)),
+ $e->getMessage()
+ );
+
+ \Log::error($msg);
+ throw $e;
+ }
+ }
/*
// Send the email to all controllers too
diff --git a/src/app/Jobs/User/CreateJob.php b/src/app/Jobs/User/CreateJob.php
new file mode 100644
--- /dev/null
+++ b/src/app/Jobs/User/CreateJob.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace App\Jobs\User;
+
+use App\Jobs\UserJob;
+
+/**
+ * Create the \App\User in LDAP.
+ *
+ * Throws exceptions for the following reasons:
+ *
+ * * The user is marked as deleted (`$user->isDeleted()`), or
+ * * the user is actually deleted (`$user->deleted_at`), or
+ * * the user is already marked as ready in LDAP (`$user->isLdapReady()`).
+ *
+ */
+class CreateJob extends UserJob
+{
+ /**
+ * Execute the job.
+ *
+ * @return void
+ *
+ * @throws \Exception
+ */
+ public function handle()
+ {
+ $user = $this->getUser();
+
+ if (!$user) {
+ return;
+ }
+
+ // sanity checks
+ if ($user->isDeleted()) {
+ $this->fail(new \Exception("User {$this->userId} is marked as deleted."));
+ return;
+ }
+
+ if ($user->deleted_at) {
+ $this->fail(new \Exception("User {$this->userId} is actually deleted."));
+ return;
+ }
+
+ if ($user->isLdapReady()) {
+ $this->fail(new \Exception("User {$this->userId} is already marked as ldap-ready."));
+ return;
+ }
+
+ // see if the domain is ready
+ $domain = $user->domain();
+
+ if (!$domain) {
+ $this->fail(new \Exception("The domain for {$this->userId} does not exist."));
+ return;
+ }
+
+ if ($domain->isDeleted()) {
+ $this->fail(new \Exception("The domain for {$this->userId} is marked as deleted."));
+ return;
+ }
+
+ if (!$domain->isLdapReady()) {
+ $this->release(60);
+ return;
+ }
+
+ \App\Backends\LDAP::createUser($user);
+
+ $user->status |= \App\User::STATUS_LDAP_READY;
+ $user->save();
+ }
+}
diff --git a/src/app/Jobs/User/DeleteJob.php b/src/app/Jobs/User/DeleteJob.php
new file mode 100644
--- /dev/null
+++ b/src/app/Jobs/User/DeleteJob.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace App\Jobs\User;
+
+use App\Jobs\UserJob;
+
+class DeleteJob extends UserJob
+{
+ /**
+ * Execute the job.
+ *
+ * @return void
+ */
+ public function handle()
+ {
+ $user = $this->getUser();
+
+ if (!$user) {
+ return;
+ }
+
+ // sanity checks
+ if ($user->isDeleted()) {
+ $this->fail(new \Exception("User {$this->userId} is already marked as deleted."));
+ return;
+ }
+
+ \App\Backends\LDAP::deleteUser($user);
+
+ $user->status |= \App\User::STATUS_DELETED;
+ $user->save();
+ }
+}
diff --git a/src/app/Jobs/User/UpdateJob.php b/src/app/Jobs/User/UpdateJob.php
new file mode 100644
--- /dev/null
+++ b/src/app/Jobs/User/UpdateJob.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace App\Jobs\User;
+
+use App\Jobs\UserJob;
+
+class UpdateJob extends UserJob
+{
+ /**
+ * Execute the job.
+ *
+ * @return void
+ */
+ public function handle()
+ {
+ $user = $this->getUser();
+
+ if (!$user->isLdapReady()) {
+ $this->delete();
+ return;
+ }
+
+ \App\Backends\LDAP::updateUser($user);
+ }
+}
diff --git a/src/app/Jobs/User/VerifyJob.php b/src/app/Jobs/User/VerifyJob.php
new file mode 100644
--- /dev/null
+++ b/src/app/Jobs/User/VerifyJob.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace App\Jobs\User;
+
+use App\Jobs\UserJob;
+
+class VerifyJob extends UserJob
+{
+ /**
+ * Execute the job.
+ *
+ * @return void
+ */
+ public function handle()
+ {
+ $user = $this->getUser();
+
+ if (!$user) {
+ return;
+ }
+
+ // sanity checks
+ if (!$user->hasSku('mailbox')) {
+ $this->fail(new \Exception("User {$this->userId} has no mailbox SKU."));
+ return;
+ }
+
+ // the user has a mailbox (or is marked as such)
+ if ($user->isImapReady()) {
+ $this->fail(new \Exception("User {$this->userId} is already verified."));
+ return;
+ }
+
+ if (\App\Backends\IMAP::verifyAccount($user->email)) {
+ $user->status |= \App\User::STATUS_IMAP_READY;
+ $user->status |= \App\User::STATUS_ACTIVE;
+ $user->save();
+ }
+ }
+}
diff --git a/src/app/Jobs/UserCreate.php b/src/app/Jobs/UserCreate.php
deleted file mode 100644
--- a/src/app/Jobs/UserCreate.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-
-namespace App\Jobs;
-
-use App\Backends\LDAP;
-use App\User;
-use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Foundation\Bus\Dispatchable;
-use Illuminate\Queue\InteractsWithQueue;
-use Illuminate\Queue\SerializesModels;
-
-class UserCreate implements ShouldQueue
-{
- use Dispatchable;
- use InteractsWithQueue;
- use Queueable;
- use SerializesModels;
-
- protected $user;
-
- public $tries = 5;
-
- /** @var bool Delete the job if its models no longer exist. */
- public $deleteWhenMissingModels = true;
-
-
- /**
- * Create a new job instance.
- *
- * @param User $user The user to create.
- *
- * @return void
- */
- public function __construct(User $user)
- {
- $this->user = $user;
- }
-
- /**
- * Execute the job.
- *
- * @return void
- */
- public function handle()
- {
- if (!$this->user->isLdapReady()) {
- LDAP::createUser($this->user);
-
- $this->user->status |= User::STATUS_LDAP_READY;
- $this->user->save();
- }
- }
-}
diff --git a/src/app/Jobs/UserDelete.php b/src/app/Jobs/UserDelete.php
deleted file mode 100644
--- a/src/app/Jobs/UserDelete.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-namespace App\Jobs;
-
-use App\Backends\LDAP;
-use App\User;
-use Illuminate\Bus\Queueable;
-use Illuminate\Queue\SerializesModels;
-use Illuminate\Queue\InteractsWithQueue;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Foundation\Bus\Dispatchable;
-
-class UserDelete implements ShouldQueue
-{
- use Dispatchable;
- use InteractsWithQueue;
- use Queueable;
- use SerializesModels;
-
- protected $user;
-
- public $tries = 5;
-
- /** @var bool Delete the job if its models no longer exist. */
- public $deleteWhenMissingModels = true;
-
- /**
- * Create a new job instance.
- *
- * @param int $user_id The ID of the user to delete.
- *
- * @return void
- */
- public function __construct(int $user_id)
- {
- $this->user = User::withTrashed()->find($user_id);
- }
-
- /**
- * Execute the job.
- *
- * @return void
- */
- public function handle()
- {
- if (!$this->user->isDeleted()) {
- LDAP::deleteUser($this->user);
-
- $this->user->status |= User::STATUS_DELETED;
- $this->user->save();
- }
- }
-}
diff --git a/src/app/Jobs/UserJob.php b/src/app/Jobs/UserJob.php
new file mode 100644
--- /dev/null
+++ b/src/app/Jobs/UserJob.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace App\Jobs;
+
+/**
+ * The abstract \App\Jobs\UserJob implements the logic needed for all dispatchable Jobs related to
+ * \App\User objects.
+ *
+ * ```php
+ * $job = new \App\Jobs\User\CreateJob($userId);
+ * $job->handle();
+ * ```
+ */
+abstract class UserJob extends CommonJob
+{
+ /**
+ * The ID for the \App\User. This is the shortest globally unique identifier and saves Redis space
+ * compared to a serialized version of the complete \App\User object.
+ *
+ * @var int
+ */
+ protected $userId;
+
+ /**
+ * The \App\User email property, for legibility in the queue management.
+ *
+ * @var string
+ */
+ protected $userEmail;
+
+ /**
+ * Create a new job instance.
+ *
+ * @param int $userId The ID for the user to create.
+ *
+ * @return void
+ */
+ public function __construct(int $userId)
+ {
+ $this->userId = $userId;
+
+ $user = $this->getUser();
+
+ if ($user) {
+ $this->userEmail = $user->email;
+ }
+ }
+
+ /**
+ * Get the \App\User entry associated with this job.
+ *
+ * @return \App\User|null
+ *
+ * @throws \Exception
+ */
+ protected function getUser()
+ {
+ $user = \App\User::withTrashed()->find($this->userId);
+
+ if (!$user) {
+ $this->fail(new \Exception("User {$this->userId} could not be found in the database."));
+ }
+
+ return $user;
+ }
+}
diff --git a/src/app/Jobs/UserUpdate.php b/src/app/Jobs/UserUpdate.php
deleted file mode 100644
--- a/src/app/Jobs/UserUpdate.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-namespace App\Jobs;
-
-use App\Backends\LDAP;
-use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Foundation\Bus\Dispatchable;
-use Illuminate\Queue\SerializesModels;
-use Illuminate\Queue\InteractsWithQueue;
-
-class UserUpdate implements ShouldQueue
-{
- use Dispatchable;
- use InteractsWithQueue;
- use Queueable;
- use SerializesModels;
-
- protected $user;
-
- public $tries = 5;
-
- /** @var bool Delete the job if its models no longer exist. */
- public $deleteWhenMissingModels = true;
-
- /**
- * Create a new job instance.
- *
- * @param \App\User $user The user for which to process the update.
- *
- * @return void
- */
- public function __construct(\App\User $user)
- {
- $this->user = $user;
- }
-
- /**
- * Execute the job.
- *
- * @return void
- */
- public function handle()
- {
- LDAP::updateUser($this->user);
- }
-}
diff --git a/src/app/Jobs/UserVerify.php b/src/app/Jobs/UserVerify.php
deleted file mode 100644
--- a/src/app/Jobs/UserVerify.php
+++ /dev/null
@@ -1,60 +0,0 @@
-<?php
-
-namespace App\Jobs;
-
-use App\Backends\IMAP;
-use App\User;
-use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Foundation\Bus\Dispatchable;
-use Illuminate\Queue\InteractsWithQueue;
-use Illuminate\Queue\SerializesModels;
-
-class UserVerify implements ShouldQueue
-{
- use Dispatchable;
- use InteractsWithQueue;
- use Queueable;
- use SerializesModels;
-
- protected $user;
-
- public $tries = 5;
-
- /** @var bool Delete the job if its models no longer exist. */
- public $deleteWhenMissingModels = true;
-
-
- /**
- * Create a new job instance.
- *
- * @param User $user The user to create.
- *
- * @return void
- */
- public function __construct(User $user)
- {
- $this->user = $user;
- }
-
- /**
- * Execute the job.
- *
- * @return void
- */
- public function handle()
- {
- if (!$this->user->hasSku('mailbox')) {
- return;
- }
-
- // The user has a mailbox
- if (!$this->user->isImapReady()) {
- if (IMAP::verifyAccount($this->user->email)) {
- $this->user->status |= User::STATUS_IMAP_READY;
- $this->user->status |= User::STATUS_ACTIVE;
- $this->user->save();
- }
- }
- }
-}
diff --git a/src/app/Jobs/WalletCheck.php b/src/app/Jobs/WalletCheck.php
--- a/src/app/Jobs/WalletCheck.php
+++ b/src/app/Jobs/WalletCheck.php
@@ -2,6 +2,7 @@
namespace App\Jobs;
+use App\Http\Controllers\API\V4\PaymentsController;
use App\Wallet;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
@@ -21,7 +22,9 @@
public const THRESHOLD_DELETE = 'delete';
public const THRESHOLD_BEFORE_DELETE = 'before_delete';
public const THRESHOLD_SUSPEND = 'suspend';
+ public const THRESHOLD_BEFORE_SUSPEND = 'before_suspend';
public const THRESHOLD_REMINDER = 'reminder';
+ public const THRESHOLD_BEFORE_REMINDER = 'before_reminder';
public const THRESHOLD_INITIAL = 'initial';
/** @var int The number of seconds to wait before retrying the job. */
@@ -52,12 +55,12 @@
/**
* Execute the job.
*
- * @return void
+ * @return ?string Executed action (THRESHOLD_*)
*/
public function handle()
{
if ($this->wallet->balance >= 0) {
- return;
+ return null;
}
$now = Carbon::now();
@@ -65,32 +68,46 @@
// Delete the account
if (self::threshold($this->wallet, self::THRESHOLD_DELETE) < $now) {
$this->deleteAccount();
- return;
+ return self::THRESHOLD_DELETE;
}
// Warn about the upcomming account deletion
if (self::threshold($this->wallet, self::THRESHOLD_BEFORE_DELETE) < $now) {
$this->warnBeforeDelete();
- return;
+ return self::THRESHOLD_BEFORE_DELETE;
}
// Suspend the account
if (self::threshold($this->wallet, self::THRESHOLD_SUSPEND) < $now) {
$this->suspendAccount();
- return;
+ return self::THRESHOLD_SUSPEND;
+ }
+
+ // Try to top-up the wallet before suspending the account
+ if (self::threshold($this->wallet, self::THRESHOLD_BEFORE_SUSPEND) < $now) {
+ PaymentsController::topUpWallet($this->wallet);
+ return self::THRESHOLD_BEFORE_SUSPEND;
}
// Send the second reminder
if (self::threshold($this->wallet, self::THRESHOLD_REMINDER) < $now) {
$this->secondReminder();
- return;
+ return self::THRESHOLD_REMINDER;
+ }
+
+ // Try to top-up the wallet before the second reminder
+ if (self::threshold($this->wallet, self::THRESHOLD_BEFORE_REMINDER) < $now) {
+ PaymentsController::topUpWallet($this->wallet);
+ return self::THRESHOLD_BEFORE_REMINDER;
}
// Send the initial reminder
if (self::threshold($this->wallet, self::THRESHOLD_INITIAL) < $now) {
$this->initialReminder();
- return;
+ return self::THRESHOLD_INITIAL;
}
+
+ return null;
}
/**
@@ -104,12 +121,12 @@
// TODO: Should we check if the account is already suspended?
- $this->sendMail(\App\Mail\NegativeBalance::class);
+ $label = "Notification sent for";
+
+ $this->sendMail(\App\Mail\NegativeBalance::class, false, $label);
$now = \Carbon\Carbon::now()->toDateTimeString();
$this->wallet->setSetting('balance_warning_initial', $now);
-
- \Log::info("[WalletCheck] Notification sent for {$this->wallet->owner->email}");
}
/**
@@ -123,12 +140,12 @@
// TODO: Should we check if the account is already suspended?
- $this->sendMail(\App\Mail\NegativeBalanceReminder::class);
+ $label = "Reminder sent for";
+
+ $this->sendMail(\App\Mail\NegativeBalanceReminder::class, false, $label);
$now = \Carbon\Carbon::now()->toDateTimeString();
$this->wallet->setSetting('balance_warning_reminder', $now);
-
- \Log::info("[WalletCheck] Reminder sent for {$this->wallet->owner->email}");
}
/**
@@ -145,8 +162,6 @@
return;
}
- \Log::info("[WalletCheck] Suspend account {$this->wallet->owner->email}");
-
// Suspend the account
$this->wallet->owner->suspend();
foreach ($this->wallet->entitlements as $entitlement) {
@@ -158,7 +173,9 @@
}
}
- $this->sendMail(\App\Mail\NegativeBalanceSuspended::class);
+ $label = "Account suspended";
+
+ $this->sendMail(\App\Mail\NegativeBalanceSuspended::class, false, $label);
$now = \Carbon\Carbon::now()->toDateTimeString();
$this->wallet->setSetting('balance_warning_suspended', $now);
@@ -178,12 +195,12 @@
return;
}
- $this->sendMail(\App\Mail\NegativeBalanceBeforeDelete::class, true);
+ $label = "Last warning sent for";
+
+ $this->sendMail(\App\Mail\NegativeBalanceBeforeDelete::class, true, $label);
$now = \Carbon\Carbon::now()->toDateTimeString();
$this->wallet->setSetting('balance_warning_before_delete', $now);
-
- \Log::info("[WalletCheck] Last warning sent for {$this->wallet->owner->email}");
}
/**
@@ -196,18 +213,28 @@
// and calculate summarized balance from all wallets.
// The dirty work will be done by UserObserver
if ($this->wallet->owner) {
- \Log::info("[WalletCheck] Delete account {$this->wallet->owner->email}");
+ $email = $this->wallet->owner->email;
+
$this->wallet->owner->delete();
+
+ \Log::info(
+ sprintf(
+ "[WalletCheck] Account deleted %s (%s)",
+ $this->wallet->id,
+ $email
+ )
+ );
}
}
/**
* Send the email
*
- * @param string $class Mailable class name
- * @param bool $with_external Use users's external email
+ * @param string $class Mailable class name
+ * @param bool $with_external Use users's external email
+ * @param ?string $log_label Log label
*/
- protected function sendMail($class, $with_external = false): void
+ protected function sendMail($class, $with_external = false, $log_label = null): void
{
// TODO: Send the email to all wallet controllers?
@@ -218,11 +245,22 @@
if (!empty($to) || !empty($cc)) {
try {
Mail::to($to)->cc($cc)->send($mail);
+
+ if ($log_label) {
+ $msg = sprintf(
+ "[WalletCheck] %s %s (%s)",
+ $log_label,
+ $this->wallet->id,
+ empty($cc) ? $to : implode(', ', array_merge([$to], $cc)),
+ );
+
+ \Log::info($msg);
+ }
} catch (\Exception $e) {
$msg = sprintf(
- "[WalletCheck] Failed to send mail for wallet %s (%s): %s",
+ "[WalletCheck] Failed to send mail for %s (%s): %s",
$this->wallet->id,
- json_encode(array_merge([$to], $cc)),
+ empty($cc) ? $to : implode(', ', array_merge([$to], $cc)),
$e->getMessage()
);
@@ -274,11 +312,21 @@
return $negative_since->addDays($suspend + $remind);
}
+ // A day before account suspension
+ if ($type == self::THRESHOLD_BEFORE_SUSPEND) {
+ return $negative_since->addDays($suspend + $remind - 1);
+ }
+
// Second notification
if ($type == self::THRESHOLD_REMINDER) {
return $negative_since->addDays($remind);
}
+ // A day before the second reminder
+ if ($type == self::THRESHOLD_BEFORE_REMINDER) {
+ return $negative_since->addDays($remind - 1);
+ }
+
// Initial notification
// Give it an hour so the async recurring payment has a chance to be finished
if ($type == self::THRESHOLD_INITIAL) {
diff --git a/src/app/Observers/DomainObserver.php b/src/app/Observers/DomainObserver.php
--- a/src/app/Observers/DomainObserver.php
+++ b/src/app/Observers/DomainObserver.php
@@ -24,7 +24,9 @@
}
}
- $domain->status |= Domain::STATUS_NEW | Domain::STATUS_ACTIVE;
+ $domain->namespace = \strtolower($domain->namespace);
+
+ $domain->status |= Domain::STATUS_NEW;
}
/**
@@ -38,7 +40,7 @@
{
// Create domain record in LDAP
// Note: DomainCreate job will dispatch DomainVerify job
- \App\Jobs\DomainCreate::dispatch($domain);
+ \App\Jobs\Domain\CreateJob::dispatch($domain->id);
}
/**
@@ -66,7 +68,7 @@
*/
public function deleted(Domain $domain)
{
- \App\Jobs\DomainDelete::dispatch($domain->id);
+ \App\Jobs\Domain\DeleteJob::dispatch($domain->id);
}
/**
@@ -78,7 +80,7 @@
*/
public function updated(Domain $domain)
{
- \App\Jobs\DomainUpdate::dispatch($domain->id);
+ \App\Jobs\Domain\UpdateJob::dispatch($domain->id);
}
/**
diff --git a/src/app/Observers/EntitlementObserver.php b/src/app/Observers/EntitlementObserver.php
--- a/src/app/Observers/EntitlementObserver.php
+++ b/src/app/Observers/EntitlementObserver.php
@@ -93,22 +93,44 @@
$entitlement->createTransaction(\App\Transaction::ENTITLEMENT_DELETED);
}
+ /**
+ * Handle the entitlement "deleting" event.
+ *
+ * @param \App\Entitlement $entitlement The entitlement.
+ *
+ * @return void
+ */
public function deleting(Entitlement $entitlement)
{
+ if ($entitlement->trashed()) {
+ return;
+ }
+
// Start calculating the costs for the consumption of this entitlement if the
// existing consumption spans >= 14 days.
- // anything's free for 14 days
+ //
+ // Effect is that anything's free for the first 14 days
if ($entitlement->created_at >= Carbon::now()->subDays(14)) {
return;
}
+ $owner = $entitlement->wallet->owner;
+
+ // Determine if we're still within the free first month
+ $freeMonthEnds = $owner->created_at->copy()->addMonthsWithoutOverflow(1);
+
+ if ($freeMonthEnds >= Carbon::now()) {
+ return;
+ }
+
$cost = 0;
+ $now = Carbon::now();
// get the discount rate applied to the wallet.
$discount = $entitlement->wallet->getDiscountRate();
// just in case this had not been billed yet, ever
- $diffInMonths = $entitlement->updated_at->diffInMonths(Carbon::now());
+ $diffInMonths = $entitlement->updated_at->diffInMonths($now);
$cost += (int) ($entitlement->cost * $discount * $diffInMonths);
// this moves the hypothetical updated at forward to however many months past the original
@@ -116,24 +138,21 @@
// now we have the diff in days since the last "billed" period end.
// This may be an entitlement paid up until February 28th, 2020, with today being March
- // 12th 2020. Calculating the costs for the entitlement is based on the daily price for the
- // past month -- i.e. $price/29 in the case at hand -- times the number of (full) days in
- // between the period end and now.
- //
- // a) The number of days left in the past month, 1
- // b) The cost divided by the number of days in the past month, for example, 555/29,
- // c) a) + Todays day-of-month, 12, so 13.
- //
+ // 12th 2020. Calculating the costs for the entitlement is based on the daily price
- $diffInDays = $updatedAt->diffInDays(Carbon::now());
+ // the price per day is based on the number of days in the last month
+ // or the current month if the period does not overlap with the previous month
+ // FIXME: This really should be simplified to $daysInMonth=30
- $dayOfThisMonth = Carbon::now()->day;
+ $diffInDays = $updatedAt->diffInDays($now);
- // days in the month for the month prior to this one.
- // the price per day is based on the number of days left in the last month
- $daysInLastMonth = \App\Utils::daysInLastMonth();
+ if ($now->day >= $diffInDays) {
+ $daysInMonth = $now->daysInMonth;
+ } else {
+ $daysInMonth = \App\Utils::daysInLastMonth();
+ }
- $pricePerDay = (float)$entitlement->cost / $daysInLastMonth;
+ $pricePerDay = $entitlement->cost / $daysInMonth;
$cost += (int) (round($pricePerDay * $discount * $diffInDays, 0));
diff --git a/src/app/Observers/UserAliasObserver.php b/src/app/Observers/UserAliasObserver.php
--- a/src/app/Observers/UserAliasObserver.php
+++ b/src/app/Observers/UserAliasObserver.php
@@ -60,7 +60,7 @@
public function created(UserAlias $alias)
{
if ($alias->user) {
- \App\Jobs\UserUpdate::dispatch($alias->user);
+ \App\Jobs\User\UpdateJob::dispatch($alias->user_id);
}
}
@@ -74,7 +74,7 @@
public function updated(UserAlias $alias)
{
if ($alias->user) {
- \App\Jobs\UserUpdate::dispatch($alias->user);
+ \App\Jobs\User\UpdateJob::dispatch($alias->user_id);
}
}
@@ -88,7 +88,7 @@
public function deleted(UserAlias $alias)
{
if ($alias->user) {
- \App\Jobs\UserUpdate::dispatch($alias->user);
+ \App\Jobs\User\UpdateJob::dispatch($alias->user_id);
}
}
}
diff --git a/src/app/Observers/UserObserver.php b/src/app/Observers/UserObserver.php
--- a/src/app/Observers/UserObserver.php
+++ b/src/app/Observers/UserObserver.php
@@ -4,7 +4,9 @@
use App\Entitlement;
use App\Domain;
+use App\Transaction;
use App\User;
+use App\Wallet;
use Illuminate\Support\Facades\DB;
class UserObserver
@@ -30,6 +32,8 @@
}
}
+ $user->email = \strtolower($user->email);
+
// only users that are not imported get the benefit of the doubt.
$user->status |= User::STATUS_NEW | User::STATUS_ACTIVE;
@@ -50,7 +54,7 @@
public function created(User $user)
{
$settings = [
- 'country' => 'CH',
+ 'country' => \App\Utils::countryForRequest(),
'currency' => 'CHF',
/*
'first_name' => '',
@@ -78,10 +82,10 @@
// Create user record in LDAP, then check if the account is created in IMAP
$chain = [
- new \App\Jobs\UserVerify($user),
+ new \App\Jobs\User\VerifyJob($user->id),
];
- \App\Jobs\UserCreate::withChain($chain)->dispatch($user);
+ \App\Jobs\User\CreateJob::withChain($chain)->dispatch($user->id);
}
/**
@@ -105,6 +109,11 @@
*/
public function deleting(User $user)
{
+ if ($user->isForceDeleting()) {
+ $this->forceDeleting($user);
+ return;
+ }
+
// TODO: Especially in tests we're doing delete() on a already deleted user.
// Should we escape here - for performance reasons?
// TODO: I think all of this should use database transactions
@@ -138,9 +147,8 @@
$users = array_unique($users);
$domains = array_unique($domains);
- // Note: Domains/users need to be deleted one by one to make sure
- // events are fired and observers can do the proper cleanup.
- // Entitlements have no delete event handlers as for now.
+ // Domains/users/entitlements need to be deleted one by one to make sure
+ // events are fired and observers can do the proper cleanup.
if (!empty($users)) {
foreach (User::whereIn('id', $users)->get() as $_user) {
$_user->delete();
@@ -159,7 +167,70 @@
// FIXME: What do we do with user wallets?
- \App\Jobs\UserDelete::dispatch($user->id);
+ \App\Jobs\User\DeleteJob::dispatch($user->id);
+ }
+
+ /**
+ * Handle the "deleting" event on forceDelete() call.
+ *
+ * @param User $user The user that is being deleted.
+ *
+ * @return void
+ */
+ public function forceDeleting(User $user)
+ {
+ // TODO: We assume that at this moment all belongings are already soft-deleted.
+
+ // Remove owned users/domains
+ $wallets = $user->wallets()->pluck('id')->all();
+ $assignments = Entitlement::withTrashed()->whereIn('wallet_id', $wallets)->get();
+ $entitlements = [];
+ $domains = [];
+ $users = [];
+
+ foreach ($assignments as $entitlement) {
+ $entitlements[] = $entitlement->id;
+
+ if ($entitlement->entitleable_type == Domain::class) {
+ $domains[] = $entitlement->entitleable_id;
+ } elseif (
+ $entitlement->entitleable_type == User::class
+ && $entitlement->entitleable_id != $user->id
+ ) {
+ $users[] = $entitlement->entitleable_id;
+ }
+ }
+
+ $users = array_unique($users);
+ $domains = array_unique($domains);
+
+ // Remove the user "direct" entitlements explicitely, if they belong to another
+ // user's wallet they will not be removed by the wallets foreign key cascade
+ Entitlement::withTrashed()
+ ->where('entitleable_id', $user->id)
+ ->where('entitleable_type', User::class)
+ ->forceDelete();
+
+ // Users need to be deleted one by one to make sure observers can do the proper cleanup.
+ if (!empty($users)) {
+ foreach (User::withTrashed()->whereIn('id', $users)->get() as $_user) {
+ $_user->forceDelete();
+ }
+ }
+
+ // Domains can be just removed
+ if (!empty($domains)) {
+ Domain::withTrashed()->whereIn('id', $domains)->forceDelete();
+ }
+
+ // Remove transactions, they also have no foreign key constraint
+ Transaction::where('object_type', Entitlement::class)
+ ->whereIn('object_id', $entitlements)
+ ->delete();
+
+ Transaction::where('object_type', Wallet::class)
+ ->whereIn('object_id', $wallets)
+ ->delete();
}
/**
@@ -173,7 +244,7 @@
*/
public function retrieving(User $user)
{
- // TODO \App\Jobs\UserRead::dispatch($user);
+ // TODO \App\Jobs\User\ReadJob::dispatch($user->id);
}
/**
@@ -185,6 +256,6 @@
*/
public function updating(User $user)
{
- \App\Jobs\UserUpdate::dispatch($user);
+ \App\Jobs\User\UpdateJob::dispatch($user->id);
}
}
diff --git a/src/app/Observers/UserSettingObserver.php b/src/app/Observers/UserSettingObserver.php
--- a/src/app/Observers/UserSettingObserver.php
+++ b/src/app/Observers/UserSettingObserver.php
@@ -17,7 +17,7 @@
public function created(UserSetting $userSetting)
{
if (in_array($userSetting->key, LDAP::USER_SETTINGS)) {
- \App\Jobs\UserUpdate::dispatch($userSetting->user);
+ \App\Jobs\User\UpdateJob::dispatch($userSetting->user_id);
}
}
@@ -31,7 +31,7 @@
public function updated(UserSetting $userSetting)
{
if (in_array($userSetting->key, LDAP::USER_SETTINGS)) {
- \App\Jobs\UserUpdate::dispatch($userSetting->user);
+ \App\Jobs\User\UpdateJob::dispatch($userSetting->user_id);
}
}
@@ -45,7 +45,7 @@
public function deleted(UserSetting $userSetting)
{
if (in_array($userSetting->key, LDAP::USER_SETTINGS)) {
- \App\Jobs\UserUpdate::dispatch($userSetting->user);
+ \App\Jobs\User\UpdateJob::dispatch($userSetting->user_id);
}
}
}
diff --git a/src/app/Providers/Payment/Mollie.php b/src/app/Providers/Payment/Mollie.php
--- a/src/app/Providers/Payment/Mollie.php
+++ b/src/app/Providers/Payment/Mollie.php
@@ -293,6 +293,7 @@
}
// Get the payment details from Mollie
+ // TODO: Consider https://github.com/mollie/mollie-api-php/issues/502 when it's fixed
$mollie_payment = mollie()->payments()->get($payment_id);
if (empty($mollie_payment)) {
@@ -300,22 +301,44 @@
return 200;
}
+ $refunds = [];
+
if ($mollie_payment->isPaid()) {
- if (!$mollie_payment->hasRefunds() && !$mollie_payment->hasChargebacks()) {
- // The payment is paid and isn't refunded or charged back.
- // Update the balance, if it wasn't already
- if ($payment->status != self::STATUS_PAID && $payment->amount > 0) {
- $credit = true;
- $notify = $payment->type == self::TYPE_RECURRING;
+ // The payment is paid. Update the balance, and notify the user
+ if ($payment->status != self::STATUS_PAID && $payment->amount > 0) {
+ $credit = true;
+ $notify = $payment->type == self::TYPE_RECURRING;
+ }
+
+ // The payment has been (partially) refunded.
+ // Let's process refunds with status "refunded".
+ if ($mollie_payment->hasRefunds()) {
+ foreach ($mollie_payment->refunds() as $refund) {
+ if ($refund->isTransferred() && $refund->amount->value) {
+ $refunds[] = [
+ 'id' => $refund->id,
+ 'description' => $refund->description,
+ 'amount' => round(floatval($refund->amount->value) * 100),
+ 'type' => self::TYPE_REFUND,
+ // Note: we assume this is the original payment/wallet currency
+ ];
+ }
+ }
+ }
+
+ // The payment has been (partially) charged back.
+ // Let's process chargebacks (they have no states as refunds)
+ if ($mollie_payment->hasChargebacks()) {
+ foreach ($mollie_payment->chargebacks() as $chargeback) {
+ if ($chargeback->amount->value) {
+ $refunds[] = [
+ 'id' => $chargeback->id,
+ 'amount' => round(floatval($chargeback->amount->value) * 100),
+ 'type' => self::TYPE_CHARGEBACK,
+ // Note: we assume this is the original payment/wallet currency
+ ];
+ }
}
- } elseif ($mollie_payment->hasRefunds()) {
- // The payment has been (partially) refunded.
- // The status of the payment is still "paid"
- // TODO: Update balance
- } elseif ($mollie_payment->hasChargebacks()) {
- // The payment has been (partially) charged back.
- // The status of the payment is still "paid"
- // TODO: Update balance
}
} elseif ($mollie_payment->isFailed()) {
// Note: I didn't find a way to get any description of the problem with a payment
@@ -343,6 +366,10 @@
self::creditPayment($payment, $mollie_payment);
}
+ foreach ($refunds as $refund) {
+ $this->storeRefund($payment->wallet, $refund);
+ }
+
DB::commit();
if (!empty($notify)) {
diff --git a/src/app/Providers/Payment/Stripe.php b/src/app/Providers/Payment/Stripe.php
--- a/src/app/Providers/Payment/Stripe.php
+++ b/src/app/Providers/Payment/Stripe.php
@@ -70,8 +70,8 @@
$request = [
'customer' => $customer_id,
- 'cancel_url' => \url('/wallet'), // required
- 'success_url' => \url('/wallet'), // required
+ 'cancel_url' => Utils::serviceUrl('/wallet'), // required
+ 'success_url' => Utils::serviceUrl('/wallet'), // required
'payment_method_types' => ['card'], // required
'locale' => 'en',
'mode' => 'setup',
@@ -181,8 +181,8 @@
$request = [
'customer' => $customer_id,
- 'cancel_url' => \url('/wallet'), // required
- 'success_url' => \url('/wallet'), // required
+ 'cancel_url' => Utils::serviceUrl('/wallet'), // required
+ 'success_url' => Utils::serviceUrl('/wallet'), // required
'payment_method_types' => ['card'], // required
'locale' => 'en',
'line_items' => [
diff --git a/src/app/Providers/PaymentProvider.php b/src/app/Providers/PaymentProvider.php
--- a/src/app/Providers/PaymentProvider.php
+++ b/src/app/Providers/PaymentProvider.php
@@ -2,6 +2,7 @@
namespace App\Providers;
+use App\Transaction;
use App\Payment;
use App\Wallet;
@@ -18,6 +19,8 @@
public const TYPE_ONEOFF = 'oneoff';
public const TYPE_RECURRING = 'recurring';
public const TYPE_MANDATE = 'mandate';
+ public const TYPE_REFUND = 'refund';
+ public const TYPE_CHARGEBACK = 'chargeback';
/** const int Minimum amount of money in a single payment (in cents) */
public const MIN_AMOUNT = 1000;
@@ -153,4 +156,42 @@
return $db_payment;
}
+
+ /**
+ * Deduct an amount of pecunia from the wallet.
+ * Creates a payment and transaction records for the refund/chargeback operation.
+ *
+ * @param \App\Wallet $wallet A wallet object
+ * @param array $refund A refund or chargeback data (id, type, amount, description)
+ *
+ * @return void
+ */
+ protected function storeRefund(Wallet $wallet, array $refund): void
+ {
+ if (empty($refund) || empty($refund['amount'])) {
+ return;
+ }
+
+ $wallet->balance -= $refund['amount'];
+ $wallet->save();
+
+ if ($refund['type'] == self::TYPE_CHARGEBACK) {
+ $transaction_type = Transaction::WALLET_CHARGEBACK;
+ } else {
+ $transaction_type = Transaction::WALLET_REFUND;
+ }
+
+ Transaction::create([
+ 'object_id' => $wallet->id,
+ 'object_type' => Wallet::class,
+ 'type' => $transaction_type,
+ 'amount' => $refund['amount'],
+ 'description' => $refund['description'] ?? '',
+ ]);
+
+ $refund['status'] = self::STATUS_PAID;
+ $refund['amount'] *= -1;
+
+ $this->storePayment($refund, $wallet->id);
+ }
}
diff --git a/src/app/Transaction.php b/src/app/Transaction.php
--- a/src/app/Transaction.php
+++ b/src/app/Transaction.php
@@ -28,6 +28,8 @@
public const WALLET_CREDIT = 'credit';
public const WALLET_DEBIT = 'debit';
public const WALLET_PENALTY = 'penalty';
+ public const WALLET_REFUND = 'refund';
+ public const WALLET_CHARGEBACK = 'chback';
protected $fillable = [
// actor, if any
@@ -94,6 +96,8 @@
case self::WALLET_CREDIT:
case self::WALLET_DEBIT:
case self::WALLET_PENALTY:
+ case self::WALLET_REFUND:
+ case self::WALLET_CHARGEBACK:
// TODO: This must be a wallet.
$this->attributes['type'] = $value;
break;
@@ -112,7 +116,9 @@
{
$label = $this->objectTypeToLabelString() . '-' . $this->{'type'} . '-short';
- return \trans("transactions.{$label}", $this->descriptionParams());
+ $result = \trans("transactions.{$label}", $this->descriptionParams());
+
+ return trim($result, ': ');
}
/**
diff --git a/src/app/User.php b/src/app/User.php
--- a/src/app/User.php
+++ b/src/app/User.php
@@ -268,6 +268,20 @@
return $this->canDelete($object);
}
+ /**
+ * Return the \App\Domain for this user.
+ *
+ * @return \App\Domain|null
+ */
+ public function domain()
+ {
+ list($local, $domainName) = explode('@', $this->email);
+
+ $domain = \App\Domain::withTrashed()->where('namespace', $domainName)->first();
+
+ return $domain;
+ }
+
/**
* List the domains to which this user is entitled.
*
diff --git a/src/app/Utils.php b/src/app/Utils.php
--- a/src/app/Utils.php
+++ b/src/app/Utils.php
@@ -11,6 +11,98 @@
*/
class Utils
{
+ /**
+ * Count the number of lines in a file.
+ *
+ * Useful for progress bars.
+ *
+ * @param string $file The filepath to count the lines of.
+ *
+ * @return int
+ */
+ public static function countLines($file)
+ {
+ $fh = fopen($file, 'rb');
+ $numLines = 0;
+
+ while (!feof($fh)) {
+ $numLines += substr_count(fread($fh, 8192), "\n");
+ }
+
+ fclose($fh);
+
+ return $numLines;
+ }
+
+ /**
+ * Return the country ISO code for an IP address.
+ *
+ * @return string
+ */
+ public static function countryForIP($ip)
+ {
+ if (strpos(':', $ip) === false) {
+ $query = "
+ SELECT country FROM ip4nets
+ WHERE INET_ATON(net_number) <= INET_ATON(?)
+ AND INET_ATON(net_broadcast) >= INET_ATON(?)
+ ORDER BY INET_ATON(net_number), net_mask DESC LIMIT 1
+ ";
+ } else {
+ $query = "
+ SELECT id FROM ip6nets
+ WHERE INET6_ATON(net_number) <= INET6_ATON(?)
+ AND INET6_ATON(net_broadcast) >= INET6_ATON(?)
+ ORDER BY INET6_ATON(net_number), net_mask DESC LIMIT 1
+ ";
+ }
+
+ $nets = \Illuminate\Support\Facades\DB::select($query, [$ip, $ip]);
+
+ if (sizeof($nets) > 0) {
+ return $nets[0]->country;
+ }
+
+ return 'CH';
+ }
+
+ /**
+ * Return the country ISO code for the current request.
+ */
+ public static function countryForRequest()
+ {
+ $request = \request();
+ $ip = $request->ip();
+
+ return self::countryForIP($ip);
+ }
+
+ /**
+ * Shortcut to creating a progress bar of a particular format with a particular message.
+ *
+ * @param \Illuminate\Console\OutputStyle $output Console output object
+ * @param int $count Number of progress steps
+ * @param string $message The description
+ *
+ * @return \Symfony\Component\Console\Helper\ProgressBar
+ */
+ public static function createProgressBar($output, $count, $message = null)
+ {
+ $bar = $output->createProgressBar($count);
+
+ $bar->setFormat(
+ '%current:7s%/%max:7s% [%bar%] %percent:3s%% %elapsed:7s%/%estimated:-7s% %message% '
+ );
+
+ if ($message) {
+ $bar->setMessage($message . " ...");
+ }
+
+ $bar->start();
+
+ return $bar;
+ }
+
/**
* Return the number of days in the month prior to this one.
*
@@ -24,6 +116,100 @@
return $start->diffInDays($end) + 1;
}
+ /**
+ * Download a file from the interwebz and store it locally.
+ *
+ * @param string $source The source location
+ * @param string $target The target location
+ * @param bool $force Force the download (and overwrite target)
+ *
+ * @return void
+ */
+ public static function downloadFile($source, $target, $force = false)
+ {
+ if (is_file($target) && !$force) {
+ return;
+ }
+
+ \Log::info("Retrieving {$source}");
+
+ $fp = fopen($target, 'w');
+
+ $curl = curl_init();
+ curl_setopt($curl, CURLOPT_URL, $source);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_FILE, $fp);
+ curl_exec($curl);
+
+ if (curl_errno($curl)) {
+ \Log::error("Request error on {$source}: " . curl_error($curl));
+
+ curl_close($curl);
+ fclose($fp);
+
+ unlink($target);
+ return;
+ }
+
+ curl_close($curl);
+ fclose($fp);
+ }
+
+ /**
+ * Calculate the broadcast address provided a net number and a prefix.
+ *
+ * @param string $net A valid IPv6 network number.
+ * @param int $prefix The network prefix.
+ *
+ * @return string
+ */
+ public static function ip6Broadcast($net, $prefix)
+ {
+ $netHex = bin2hex(inet_pton($net));
+
+ // Overwriting first address string to make sure notation is optimal
+ $net = inet_ntop(hex2bin($netHex));
+
+ // Calculate the number of 'flexible' bits
+ $flexbits = 128 - $prefix;
+
+ // Build the hexadecimal string of the last address
+ $lastAddrHex = $netHex;
+
+ // We start at the end of the string (which is always 32 characters long)
+ $pos = 31;
+ while ($flexbits > 0) {
+ // Get the character at this position
+ $orig = substr($lastAddrHex, $pos, 1);
+
+ // Convert it to an integer
+ $origval = hexdec($orig);
+
+ // OR it with (2^flexbits)-1, with flexbits limited to 4 at a time
+ $newval = $origval | (pow(2, min(4, $flexbits)) - 1);
+
+ // Convert it back to a hexadecimal character
+ $new = dechex($newval);
+
+ // And put that character back in the string
+ $lastAddrHex = substr_replace($lastAddrHex, $new, $pos, 1);
+
+ // We processed one nibble, move to previous position
+ $flexbits -= 4;
+ $pos -= 1;
+ }
+
+ // Convert the hexadecimal string to a binary string
+ # Using pack() here
+ # Newer PHP version can use hex2bin()
+ $lastaddrbin = pack('H*', $lastAddrHex);
+
+ // And create an IPv6 address from the binary string
+ $lastaddrstr = inet_ntop($lastaddrbin);
+
+ return $lastaddrstr;
+ }
+
/**
* Provide all unique combinations of elements in $input, with order and duplicates irrelevant.
*
@@ -116,20 +302,13 @@
*/
public static function serviceUrl(string $route): string
{
- return trim(\config('app.public_url'), '/') . '/' . ltrim($route, '/');
-
- // TODO: Investigate why it does not work
-
- $url = \secure_url($route);
-
- $app_url = trim(\config('app.url'), '/');
- $pub_url = trim(\config('app.public_url'), '/');
+ $url = \config('app.public_url');
- if ($pub_url != $app_url) {
- $url = str_replace($app_url, $pub_url, $url);
+ if (!$url) {
+ $url = \config('app.url');
}
- return $url;
+ return rtrim(trim($url, '/') . '/' . ltrim($route, '/'), '/');
}
/**
diff --git a/src/app/Wallet.php b/src/app/Wallet.php
--- a/src/app/Wallet.php
+++ b/src/app/Wallet.php
@@ -60,6 +60,22 @@
public function chargeEntitlements($apply = true)
{
+ // This wallet has been created less than a month ago, this is the trial period
+ if ($this->owner->created_at >= Carbon::now()->subMonthsWithoutOverflow(1)) {
+ // Move all the current entitlement's updated_at timestamps forward to one month after
+ // this wallet was created.
+ $freeMonthEnds = $this->owner->created_at->copy()->addMonthsWithoutOverflow(1);
+
+ foreach ($this->entitlements()->get()->fresh() as $entitlement) {
+ if ($entitlement->updated_at < $freeMonthEnds) {
+ $entitlement->updated_at = $freeMonthEnds;
+ $entitlement->save();
+ }
+ }
+
+ return 0;
+ }
+
$charges = 0;
$discount = $this->getDiscountRate();
@@ -80,7 +96,7 @@
continue;
}
- // created more than a month ago -- was it billed?
+ // updated last more than a month ago -- was it billed?
if ($entitlement->updated_at <= Carbon::now()->subMonthsWithoutOverflow(1)) {
$diff = $entitlement->updated_at->diffInMonths(Carbon::now());
@@ -93,7 +109,9 @@
continue;
}
- $entitlement->updated_at = $entitlement->updated_at->copy()->addMonthsWithoutOverflow($diff);
+ $entitlement->updated_at = $entitlement->updated_at->copy()
+ ->addMonthsWithoutOverflow($diff);
+
$entitlement->save();
if ($cost == 0) {
diff --git a/src/composer.json b/src/composer.json
--- a/src/composer.json
+++ b/src/composer.json
@@ -16,27 +16,24 @@
"require": {
"php": "^7.1.3",
"barryvdh/laravel-dompdf": "^0.8.6",
- "doctrine/dbal": "^2.9",
+ "dyrynda/laravel-nullable-fields": "*",
"fideloper/proxy": "^4.0",
- "geoip2/geoip2": "^2.9",
- "iatstuti/laravel-nullable-fields": "*",
"kolab/net_ldap3": "dev-master",
"laravel/framework": "6.*",
"laravel/tinker": "^2.4",
"mollie/laravel-mollie": "^2.9",
"morrislaptop/laravel-queue-clear": "^1.2",
- "silviolleite/laravelpwa": "^1.0",
+ "silviolleite/laravelpwa": "^2.0",
"spatie/laravel-translatable": "^4.2",
"spomky-labs/otphp": "~4.0.0",
"stripe/stripe-php": "^7.29",
"swooletw/laravel-swoole": "^2.6",
- "torann/currency": "^1.0",
- "torann/geoip": "^1.0",
"tymon/jwt-auth": "^1.0"
},
"require-dev": {
"beyondcode/laravel-dump-server": "^1.0",
"beyondcode/laravel-er-diagram-generator": "^1.3",
+ "code-lts/doctum": "^5.1",
"filp/whoops": "^2.0",
"fzaninotto/faker": "^1.4",
"kirschbaum-development/mail-intercept": "^0.2.4",
diff --git a/src/config/geoip.php b/src/config/geoip.php
deleted file mode 100644
--- a/src/config/geoip.php
+++ /dev/null
@@ -1,165 +0,0 @@
-<?php
-
-return [
-
- /*
- |--------------------------------------------------------------------------
- | Logging Configuration
- |--------------------------------------------------------------------------
- |
- | Here you may configure the log settings for when a location is not found
- | for the IP provided.
- |
- */
-
- 'log_failures' => true,
-
- /*
- |--------------------------------------------------------------------------
- | Include Currency in Results
- |--------------------------------------------------------------------------
- |
- | When enabled the system will do it's best in deciding the user's currency
- | by matching their ISO code to a preset list of currencies.
- |
- */
-
- 'include_currency' => true,
-
- /*
- |--------------------------------------------------------------------------
- | Default Service
- |--------------------------------------------------------------------------
- |
- | Here you may specify the default storage driver that should be used
- | by the framework.
- |
- | Supported: "maxmind_database", "maxmind_api", "ipapi"
- |
- */
-
- 'service' => 'maxmind_database',
-
- /*
- |--------------------------------------------------------------------------
- | Storage Specific Configuration
- |--------------------------------------------------------------------------
- |
- | Here you may configure as many storage drivers as you wish.
- |
- */
-
- 'services' => [
-
- 'maxmind_database' => [
- 'class' => \Torann\GeoIP\Services\MaxMindDatabase::class,
- 'database_path' => storage_path('app/geoip.mmdb'),
- 'update_url' => 'https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz',
- 'locales' => ['en'],
- ],
-
- 'maxmind_api' => [
- 'class' => \Torann\GeoIP\Services\MaxMindWebService::class,
- 'user_id' => env('MAXMIND_USER_ID'),
- 'license_key' => env('MAXMIND_LICENSE_KEY'),
- 'locales' => ['en'],
- ],
-
- 'ipapi' => [
- 'class' => \Torann\GeoIP\Services\IPApi::class,
- 'secure' => true,
- 'key' => env('IPAPI_KEY'),
- 'continent_path' => storage_path('app/continents.json'),
- 'lang' => 'en',
- ],
-
- 'ipgeolocation' => [
- 'class' => \Torann\GeoIP\Services\IPGeoLocation::class,
- 'secure' => true,
- 'key' => env('IPGEOLOCATION_KEY'),
- 'continent_path' => storage_path('app/continents.json'),
- 'lang' => 'en',
- ],
-
- 'ipdata' => [
- 'class' => \Torann\GeoIP\Services\IPData::class,
- 'key' => env('IPDATA_API_KEY'),
- 'secure' => true,
- ],
-
- 'ipfinder' => [
- 'class' => \Torann\GeoIP\Services\IPFinder::class,
- 'key' => env('IPFINDER_API_KEY'),
- 'secure' => true,
- 'locales' => ['en'],
- ],
-
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Default Cache Driver
- |--------------------------------------------------------------------------
- |
- | Here you may specify the type of caching that should be used
- | by the package.
- |
- | Options:
- |
- | all - All location are cached
- | some - Cache only the requesting user
- | none - Disable cached
- |
- */
-
- 'cache' => 'all',
-
- /*
- |--------------------------------------------------------------------------
- | Cache Tags
- |--------------------------------------------------------------------------
- |
- | Cache tags are not supported when using the file or database cache
- | drivers in Laravel. This is done so that only locations can be cleared.
- |
- */
-
- 'cache_tags' => false,
-
- /*
- |--------------------------------------------------------------------------
- | Cache Expiration
- |--------------------------------------------------------------------------
- |
- | Define how long cached location are valid.
- |
- */
-
- 'cache_expires' => 30,
-
- /*
- |--------------------------------------------------------------------------
- | Default Location
- |--------------------------------------------------------------------------
- |
- | Return when a location is not found.
- |
- */
-
- 'default_location' => [
- 'ip' => '127.0.0.0',
- 'iso_code' => 'CH',
- 'country' => 'Switzerland',
- 'city' => 'Zurich',
- 'state' => 'ZH',
- 'state_name' => 'Zurich',
- 'postal_code' => '8703',
- 'lat' => 47.30,
- 'lon' => 8.59,
- 'timezone' => 'Europe/Zurich',
- 'continent' => 'EU',
- 'default' => true,
- 'currency' => 'CHF',
- ],
-
-];
diff --git a/src/database/migrations/2020_06_04_140800_create_ip4nets_table.php b/src/database/migrations/2020_06_04_140800_create_ip4nets_table.php
new file mode 100644
--- /dev/null
+++ b/src/database/migrations/2020_06_04_140800_create_ip4nets_table.php
@@ -0,0 +1,43 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+// phpcs:ignore
+class CreateIp4netsTable extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::create(
+ 'ip4nets',
+ function (Blueprint $table) {
+ $table->bigIncrements('id');
+ $table->string('rir_name', 8);
+ $table->string('net_number', 15)->index();
+ $table->tinyInteger('net_mask')->unsigned();
+ $table->string('net_broadcast', 15)->index();
+ $table->string('country', 2)->nullable();
+ $table->bigInteger('serial')->unsigned();
+ $table->timestamps();
+
+ $table->index(['net_number', 'net_mask', 'net_broadcast']);
+ }
+ );
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('ip4nets');
+ }
+}
diff --git a/src/database/migrations/2020_06_04_140800_create_ip6nets_table.php b/src/database/migrations/2020_06_04_140800_create_ip6nets_table.php
new file mode 100644
--- /dev/null
+++ b/src/database/migrations/2020_06_04_140800_create_ip6nets_table.php
@@ -0,0 +1,43 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+// phpcs:ignore
+class CreateIp6netsTable extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::create(
+ 'ip6nets',
+ function (Blueprint $table) {
+ $table->bigIncrements('id');
+ $table->string('rir_name', 8);
+ $table->string('net_number', 39)->index();
+ $table->tinyInteger('net_mask')->unsigned();
+ $table->string('net_broadcast', 39)->index();
+ $table->string('country', 2)->nullable();
+ $table->bigInteger('serial')->unsigned();
+ $table->timestamps();
+
+ $table->index(['net_number', 'net_mask', 'net_broadcast']);
+ }
+ );
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('ip6nets');
+ }
+}
diff --git a/src/database/seeds/local/UserSeeder.php b/src/database/seeds/local/UserSeeder.php
--- a/src/database/seeds/local/UserSeeder.php
+++ b/src/database/seeds/local/UserSeeder.php
@@ -127,7 +127,7 @@
$joe->setAliases(['joe.monster@kolab.org']);
- factory(User::class, 10)->create();
+ // factory(User::class, 10)->create();
$jeroen = User::create(
[
@@ -136,8 +136,7 @@
]
);
- $jeroen->role = "admin";
-
+ $jeroen->role = 'admin';
$jeroen->save();
}
}
diff --git a/src/database/seeds/production/PackageSeeder.php b/src/database/seeds/production/PackageSeeder.php
--- a/src/database/seeds/production/PackageSeeder.php
+++ b/src/database/seeds/production/PackageSeeder.php
@@ -15,6 +15,7 @@
*/
public function run()
{
+ $skuActiveSync = Sku::firstOrCreate(['title' => 'activesync']);
$skuGroupware = Sku::firstOrCreate(['title' => 'groupware']);
$skuMailbox = Sku::firstOrCreate(['title' => 'mailbox']);
$skuStorage = Sku::firstOrCreate(['title' => 'storage']);
@@ -31,7 +32,8 @@
$skus = [
$skuMailbox,
$skuGroupware,
- $skuStorage
+ $skuStorage,
+ $skuActiveSync
];
$package->skus()->saveMany($skus);
diff --git a/src/doctum b/src/doctum
new file mode 120000
--- /dev/null
+++ b/src/doctum
@@ -0,0 +1 @@
+../bin/doctum
\ No newline at end of file
diff --git a/src/doctum.config.php b/src/doctum.config.php
new file mode 100644
--- /dev/null
+++ b/src/doctum.config.php
@@ -0,0 +1,26 @@
+<?php
+
+use Doctum\Doctum;
+use Symfony\Component\Finder\Finder;
+
+$iterator = Finder::create()
+ ->files()
+ ->name('*.php')
+ ->exclude('bootstrap')
+ ->exclude('cache')
+ ->exclude('database')
+ ->exclude('include')
+ ->exclude('node_modules')
+ ->exclude('tests')
+ ->exclude('vendor')
+ ->in(__DIR__);
+
+return new Doctum(
+ $iterator,
+ [
+ 'build_dir' => __DIR__ . '/../docs/build/%version%/',
+ 'cache_dir' => __DIR__ . '/cache/',
+ 'default_opened_level' => 1,
+ //'include_parent_data' => false,
+ ]
+);
diff --git a/src/package-lock.json b/src/package-lock.json
--- a/src/package-lock.json
+++ b/src/package-lock.json
@@ -12,9 +12,9 @@
}
},
"@babel/compat-data": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.10.3.tgz",
- "integrity": "sha512-BDIfJ9uNZuI0LajPfoYV28lX8kyCPMHY6uY4WH1lJdcicmAfxCK5ASzaeV0D/wsUaRH/cLk+amuxtC37sZ8TUg==",
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz",
+ "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==",
"dev": true,
"requires": {
"browserslist": "^4.12.0",
@@ -99,31 +99,69 @@
}
},
"@babel/helper-annotate-as-pure": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.1.tgz",
- "integrity": "sha512-ewp3rvJEwLaHgyWGe4wQssC2vjks3E80WiUe2BpMb0KhreTjMROCbxXcEovTrbeGVdQct5VjQfrv9EgC+xMzCw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz",
+ "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==",
"dev": true,
"requires": {
- "@babel/types": "^7.10.1"
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/helper-builder-binary-assignment-operator-visitor": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.3.tgz",
- "integrity": "sha512-lo4XXRnBlU6eRM92FkiZxpo1xFLmv3VsPFk61zJKMm7XYJfwqXHsYJTY6agoc4a3L8QPw1HqWehO18coZgbT6A==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz",
+ "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==",
"dev": true,
"requires": {
- "@babel/helper-explode-assignable-expression": "^7.10.3",
- "@babel/types": "^7.10.3"
+ "@babel/helper-explode-assignable-expression": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/helper-compilation-targets": {
- "version": "7.10.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.2.tgz",
- "integrity": "sha512-hYgOhF4To2UTB4LTaZepN/4Pl9LD4gfbJx8A34mqoluT8TLbof1mhUlYuNWTEebONa8+UlCC4X0TEXu7AOUyGA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz",
+ "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==",
"dev": true,
"requires": {
- "@babel/compat-data": "^7.10.1",
+ "@babel/compat-data": "^7.10.4",
"browserslist": "^4.12.0",
"invariant": "^2.2.4",
"levenary": "^1.1.1",
@@ -139,49 +177,329 @@
}
},
"@babel/helper-create-class-features-plugin": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.3.tgz",
- "integrity": "sha512-iRT9VwqtdFmv7UheJWthGc/h2s7MqoweBF9RUj77NFZsg9VfISvBTum3k6coAhJ8RWv2tj3yUjA03HxPd0vfpQ==",
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz",
+ "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==",
"dev": true,
"requires": {
- "@babel/helper-function-name": "^7.10.3",
- "@babel/helper-member-expression-to-functions": "^7.10.3",
- "@babel/helper-optimise-call-expression": "^7.10.3",
- "@babel/helper-plugin-utils": "^7.10.3",
- "@babel/helper-replace-supers": "^7.10.1",
- "@babel/helper-split-export-declaration": "^7.10.1"
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-member-expression-to-functions": "^7.10.5",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.11.6",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz",
+ "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.5",
+ "jsesc": "^2.5.1",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz",
+ "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz",
+ "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz",
+ "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+ "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+ "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz",
+ "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.11.5",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/parser": "^7.11.5",
+ "@babel/types": "^7.11.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "debug": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+ "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
}
},
"@babel/helper-create-regexp-features-plugin": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.1.tgz",
- "integrity": "sha512-Rx4rHS0pVuJn5pJOqaqcZR4XSgeF9G/pO/79t+4r7380tXFJdzImFnxMU19f83wjSrmKHq6myrM10pFHTGzkUA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz",
+ "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==",
"dev": true,
"requires": {
- "@babel/helper-annotate-as-pure": "^7.10.1",
- "@babel/helper-regex": "^7.10.1",
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-regex": "^7.10.4",
"regexpu-core": "^4.7.0"
}
},
"@babel/helper-define-map": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.3.tgz",
- "integrity": "sha512-bxRzDi4Sin/k0drWCczppOhov1sBSdBvXJObM1NLHQzjhXhwRtn7aRWGvLJWCYbuu2qUk3EKs6Ci9C9ps8XokQ==",
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz",
+ "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==",
"dev": true,
"requires": {
- "@babel/helper-function-name": "^7.10.3",
- "@babel/types": "^7.10.3",
- "lodash": "^4.17.13"
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/types": "^7.10.5",
+ "lodash": "^4.17.19"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+ "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ }
}
},
"@babel/helper-explode-assignable-expression": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.3.tgz",
- "integrity": "sha512-0nKcR64XrOC3lsl+uhD15cwxPvaB6QKUDlD84OT9C3myRbhJqTMYir69/RWItUvHpharv0eJ/wk7fl34ONSwZw==",
+ "version": "7.11.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz",
+ "integrity": "sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==",
"dev": true,
"requires": {
- "@babel/traverse": "^7.10.3",
- "@babel/types": "^7.10.3"
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/helper-function-name": {
@@ -205,12 +523,31 @@
}
},
"@babel/helper-hoist-variables": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.3.tgz",
- "integrity": "sha512-9JyafKoBt5h20Yv1+BXQMdcXXavozI1vt401KBiRc2qzUepbVnd7ogVNymY1xkQN9fekGwfxtotH2Yf5xsGzgg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz",
+ "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==",
"dev": true,
"requires": {
- "@babel/types": "^7.10.3"
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/helper-member-expression-to-functions": {
@@ -256,31 +593,97 @@
}
},
"@babel/helper-plugin-utils": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.3.tgz",
- "integrity": "sha512-j/+j8NAWUTxOtx4LKHybpSClxHoq6I91DQ/mKgAXn5oNUPIUiGppjPIX3TDtJWPrdfP9Kfl7e4fgVMiQR9VE/g==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
"dev": true
},
"@babel/helper-regex": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.1.tgz",
- "integrity": "sha512-7isHr19RsIJWWLLFn21ubFt223PjQyg1HY7CZEMRr820HttHPpVvrsIN3bUOo44DEfFV4kBXO7Abbn9KTUZV7g==",
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz",
+ "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==",
"dev": true,
"requires": {
- "lodash": "^4.17.13"
+ "lodash": "^4.17.19"
}
},
"@babel/helper-remap-async-to-generator": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.3.tgz",
- "integrity": "sha512-sLB7666ARbJUGDO60ZormmhQOyqMX/shKBXZ7fy937s+3ID8gSrneMvKSSb+8xIM5V7Vn6uNVtOY1vIm26XLtA==",
+ "version": "7.11.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz",
+ "integrity": "sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA==",
"dev": true,
"requires": {
- "@babel/helper-annotate-as-pure": "^7.10.1",
- "@babel/helper-wrap-function": "^7.10.1",
- "@babel/template": "^7.10.3",
- "@babel/traverse": "^7.10.3",
- "@babel/types": "^7.10.3"
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-wrap-function": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+ "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ }
}
},
"@babel/helper-replace-supers": {
@@ -305,6 +708,34 @@
"@babel/types": "^7.10.1"
}
},
+ "@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz",
+ "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ },
+ "dependencies": {
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
+ }
+ },
"@babel/helper-split-export-declaration": {
"version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz",
@@ -321,43 +752,188 @@
"dev": true
},
"@babel/helper-wrap-function": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.1.tgz",
- "integrity": "sha512-C0MzRGteVDn+H32/ZgbAv5r56f2o1fZSA/rj/TYo8JEJNHg+9BdSmKBUND0shxWRztWhjlT2cvHYuynpPsVJwQ==",
- "dev": true,
- "requires": {
- "@babel/helper-function-name": "^7.10.1",
- "@babel/template": "^7.10.1",
- "@babel/traverse": "^7.10.1",
- "@babel/types": "^7.10.1"
- }
- },
- "@babel/helpers": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.1.tgz",
- "integrity": "sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==",
- "dev": true,
- "requires": {
- "@babel/template": "^7.10.1",
- "@babel/traverse": "^7.10.1",
- "@babel/types": "^7.10.1"
- }
- },
- "@babel/highlight": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.3.tgz",
- "integrity": "sha512-Ih9B/u7AtgEnySE2L2F0Xm0GaM729XqqLfHkalTsbjXGyqmf/6M0Cu0WpvqueUlW+xk88BHw9Nkpj49naU+vWw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz",
+ "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==",
"dev": true,
"requires": {
- "@babel/helper-validator-identifier": "^7.10.3",
- "chalk": "^2.0.0",
- "js-tokens": "^4.0.0"
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
},
"dependencies": {
- "chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.11.6",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz",
+ "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.5",
+ "jsesc": "^2.5.1",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+ "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+ "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz",
+ "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.11.5",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/parser": "^7.11.5",
+ "@babel/types": "^7.11.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "debug": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+ "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helpers": {
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.1.tgz",
+ "integrity": "sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.10.1",
+ "@babel/traverse": "^7.10.1",
+ "@babel/types": "^7.10.1"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.10.3",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.3.tgz",
+ "integrity": "sha512-Ih9B/u7AtgEnySE2L2F0Xm0GaM729XqqLfHkalTsbjXGyqmf/6M0Cu0WpvqueUlW+xk88BHw9Nkpj49naU+vWw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.3",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
@@ -374,115 +950,136 @@
"dev": true
},
"@babel/plugin-proposal-async-generator-functions": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.3.tgz",
- "integrity": "sha512-WUUWM7YTOudF4jZBAJIW9D7aViYC/Fn0Pln4RIHlQALyno3sXSjqmTA4Zy1TKC2D49RCR8Y/Pn4OIUtEypK3CA==",
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz",
+ "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.3",
- "@babel/helper-remap-async-to-generator": "^7.10.3",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-remap-async-to-generator": "^7.10.4",
"@babel/plugin-syntax-async-generators": "^7.8.0"
}
},
"@babel/plugin-proposal-class-properties": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.1.tgz",
- "integrity": "sha512-sqdGWgoXlnOdgMXU+9MbhzwFRgxVLeiGBqTrnuS7LC2IBU31wSsESbTUreT2O418obpfPdGUR2GbEufZF1bpqw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz",
+ "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==",
"dev": true,
"requires": {
- "@babel/helper-create-class-features-plugin": "^7.10.1",
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-create-class-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-proposal-dynamic-import": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.1.tgz",
- "integrity": "sha512-Cpc2yUVHTEGPlmiQzXj026kqwjEQAD9I4ZC16uzdbgWgitg/UHKHLffKNCQZ5+y8jpIZPJcKcwsr2HwPh+w3XA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz",
+ "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.4",
"@babel/plugin-syntax-dynamic-import": "^7.8.0"
}
},
+ "@babel/plugin-proposal-export-namespace-from": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz",
+ "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+ }
+ },
"@babel/plugin-proposal-json-strings": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.1.tgz",
- "integrity": "sha512-m8r5BmV+ZLpWPtMY2mOKN7wre6HIO4gfIiV+eOmsnZABNenrt/kzYBwrh+KOfgumSWpnlGs5F70J8afYMSJMBg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz",
+ "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.4",
"@babel/plugin-syntax-json-strings": "^7.8.0"
}
},
+ "@babel/plugin-proposal-logical-assignment-operators": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz",
+ "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+ }
+ },
"@babel/plugin-proposal-nullish-coalescing-operator": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.1.tgz",
- "integrity": "sha512-56cI/uHYgL2C8HVuHOuvVowihhX0sxb3nnfVRzUeVHTWmRHTZrKuAh/OBIMggGU/S1g/1D2CRCXqP+3u7vX7iA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz",
+ "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.4",
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0"
}
},
"@babel/plugin-proposal-numeric-separator": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.1.tgz",
- "integrity": "sha512-jjfym4N9HtCiNfyyLAVD8WqPYeHUrw4ihxuAynWj6zzp2gf9Ey2f7ImhFm6ikB3CLf5Z/zmcJDri6B4+9j9RsA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1",
- "@babel/plugin-syntax-numeric-separator": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4"
}
},
"@babel/plugin-proposal-object-rest-spread": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.3.tgz",
- "integrity": "sha512-ZZh5leCIlH9lni5bU/wB/UcjtcVLgR8gc+FAgW2OOY+m9h1II3ItTO1/cewNUcsIDZSYcSaz/rYVls+Fb0ExVQ==",
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz",
+ "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.3",
+ "@babel/helper-plugin-utils": "^7.10.4",
"@babel/plugin-syntax-object-rest-spread": "^7.8.0",
- "@babel/plugin-transform-parameters": "^7.10.1"
+ "@babel/plugin-transform-parameters": "^7.10.4"
}
},
"@babel/plugin-proposal-optional-catch-binding": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.1.tgz",
- "integrity": "sha512-VqExgeE62YBqI3ogkGoOJp1R6u12DFZjqwJhqtKc2o5m1YTUuUWnos7bZQFBhwkxIFpWYJ7uB75U7VAPPiKETA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz",
+ "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1",
+ "@babel/helper-plugin-utils": "^7.10.4",
"@babel/plugin-syntax-optional-catch-binding": "^7.8.0"
}
},
"@babel/plugin-proposal-optional-chaining": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.3.tgz",
- "integrity": "sha512-yyG3n9dJ1vZ6v5sfmIlMMZ8azQoqx/5/nZTSWX1td6L1H1bsjzA8TInDChpafCZiJkeOFzp/PtrfigAQXxI1Ng==",
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz",
+ "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.3",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0",
"@babel/plugin-syntax-optional-chaining": "^7.8.0"
}
},
"@babel/plugin-proposal-private-methods": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.1.tgz",
- "integrity": "sha512-RZecFFJjDiQ2z6maFprLgrdnm0OzoC23Mx89xf1CcEsxmHuzuXOdniEuI+S3v7vjQG4F5sa6YtUp+19sZuSxHg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz",
+ "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==",
"dev": true,
"requires": {
- "@babel/helper-create-class-features-plugin": "^7.10.1",
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-create-class-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-proposal-unicode-property-regex": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.1.tgz",
- "integrity": "sha512-JjfngYRvwmPwmnbRZyNiPFI8zxCZb8euzbCG/LxyKdeTb59tVciKo9GK9bi6JYKInk1H11Dq9j/zRqIH4KigfQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz",
+ "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==",
"dev": true,
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.10.1",
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-syntax-async-generators": {
@@ -495,12 +1092,12 @@
}
},
"@babel/plugin-syntax-class-properties": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.1.tgz",
- "integrity": "sha512-Gf2Yx/iRs1JREDtVZ56OrjjgFHCaldpTnuy9BHla10qyVT3YkIIGEtoDWhyop0ksu1GvNjHIoYRBqm3zoR1jyQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz",
+ "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-syntax-dynamic-import": {
@@ -512,6 +1109,15 @@
"@babel/helper-plugin-utils": "^7.8.0"
}
},
+ "@babel/plugin-syntax-export-namespace-from": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
+ "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
"@babel/plugin-syntax-json-strings": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
@@ -521,6 +1127,15 @@
"@babel/helper-plugin-utils": "^7.8.0"
}
},
+ "@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
"@babel/plugin-syntax-nullish-coalescing-operator": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
@@ -531,12 +1146,12 @@
}
},
"@babel/plugin-syntax-numeric-separator": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.1.tgz",
- "integrity": "sha512-uTd0OsHrpe3tH5gRPTxG8Voh99/WCU78vIm5NMRYPAqC8lR4vajt6KkCAknCHrx24vkPdd/05yfdGSB4EIY2mg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-syntax-object-rest-spread": {
@@ -567,283 +1182,1629 @@
}
},
"@babel/plugin-syntax-top-level-await": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.1.tgz",
- "integrity": "sha512-hgA5RYkmZm8FTFT3yu2N9Bx7yVVOKYT6yEdXXo6j2JTm0wNxgqaGeQVaSHRjhfnQbX91DtjFB6McRFSlcJH3xQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz",
+ "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-arrow-functions": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.1.tgz",
- "integrity": "sha512-6AZHgFJKP3DJX0eCNJj01RpytUa3SOGawIxweHkNX2L6PYikOZmoh5B0d7hIHaIgveMjX990IAa/xK7jRTN8OA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz",
+ "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-async-to-generator": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.1.tgz",
- "integrity": "sha512-XCgYjJ8TY2slj6SReBUyamJn3k2JLUIiiR5b6t1mNCMSvv7yx+jJpaewakikp0uWFQSF7ChPPoe3dHmXLpISkg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz",
+ "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==",
"dev": true,
"requires": {
- "@babel/helper-module-imports": "^7.10.1",
- "@babel/helper-plugin-utils": "^7.10.1",
- "@babel/helper-remap-async-to-generator": "^7.10.1"
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-remap-async-to-generator": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-module-imports": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz",
+ "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/plugin-transform-block-scoped-functions": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.1.tgz",
- "integrity": "sha512-B7K15Xp8lv0sOJrdVAoukKlxP9N59HS48V1J3U/JGj+Ad+MHq+am6xJVs85AgXrQn4LV8vaYFOB+pr/yIuzW8Q==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz",
+ "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-block-scoping": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.1.tgz",
- "integrity": "sha512-8bpWG6TtF5akdhIm/uWTyjHqENpy13Fx8chg7pFH875aNLwX8JxIxqm08gmAT+Whe6AOmaTeLPe7dpLbXt+xUw==",
+ "version": "7.11.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz",
+ "integrity": "sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1",
- "lodash": "^4.17.13"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-classes": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.3.tgz",
- "integrity": "sha512-irEX0ChJLaZVC7FvvRoSIxJlmk0IczFLcwaRXUArBKYHCHbOhe57aG8q3uw/fJsoSXvZhjRX960hyeAGlVBXZw==",
- "dev": true,
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.10.1",
- "@babel/helper-define-map": "^7.10.3",
- "@babel/helper-function-name": "^7.10.3",
- "@babel/helper-optimise-call-expression": "^7.10.3",
- "@babel/helper-plugin-utils": "^7.10.3",
- "@babel/helper-replace-supers": "^7.10.1",
- "@babel/helper-split-export-declaration": "^7.10.1",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz",
+ "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-define-map": "^7.10.4",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.10.4",
"globals": "^11.1.0"
},
"dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.11.6",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz",
+ "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.5",
+ "jsesc": "^2.5.1",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz",
+ "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz",
+ "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz",
+ "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+ "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+ "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz",
+ "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.11.5",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/parser": "^7.11.5",
+ "@babel/types": "^7.11.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "debug": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+ "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
"globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
}
}
},
"@babel/plugin-transform-computed-properties": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.3.tgz",
- "integrity": "sha512-GWzhaBOsdbjVFav96drOz7FzrcEW6AP5nax0gLIpstiFaI3LOb2tAg06TimaWU6YKOfUACK3FVrxPJ4GSc5TgA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz",
+ "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.3"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-destructuring": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.1.tgz",
- "integrity": "sha512-V/nUc4yGWG71OhaTH705pU8ZSdM6c1KmmLP8ys59oOYbT7RpMYAR3MsVOt6OHL0WzG7BlTU076va9fjJyYzJMA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz",
+ "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-dotall-regex": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.1.tgz",
- "integrity": "sha512-19VIMsD1dp02RvduFUmfzj8uknaO3uiHHF0s3E1OHnVsNj8oge8EQ5RzHRbJjGSetRnkEuBYO7TG1M5kKjGLOA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz",
+ "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==",
"dev": true,
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.10.1",
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-duplicate-keys": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.1.tgz",
- "integrity": "sha512-wIEpkX4QvX8Mo9W6XF3EdGttrIPZWozHfEaDTU0WJD/TDnXMvdDh30mzUl/9qWhnf7naicYartcEfUghTCSNpA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz",
+ "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-exponentiation-operator": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.1.tgz",
- "integrity": "sha512-lr/przdAbpEA2BUzRvjXdEDLrArGRRPwbaF9rvayuHRvdQ7lUTTkZnhZrJ4LE2jvgMRFF4f0YuPQ20vhiPYxtA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz",
+ "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==",
"dev": true,
"requires": {
- "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.1",
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-for-of": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.1.tgz",
- "integrity": "sha512-US8KCuxfQcn0LwSCMWMma8M2R5mAjJGsmoCBVwlMygvmDUMkTCykc84IqN1M7t+agSfOmLYTInLCHJM+RUoz+w==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz",
+ "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-function-name": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.1.tgz",
- "integrity": "sha512-//bsKsKFBJfGd65qSNNh1exBy5Y9gD9ZN+DvrJ8f7HXr4avE5POW6zB7Rj6VnqHV33+0vXWUwJT0wSHubiAQkw==",
- "dev": true,
- "requires": {
- "@babel/helper-function-name": "^7.10.1",
- "@babel/helper-plugin-utils": "^7.10.1"
- }
- },
- "@babel/plugin-transform-literals": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.1.tgz",
- "integrity": "sha512-qi0+5qgevz1NHLZroObRm5A+8JJtibb7vdcPQF1KQE12+Y/xxl8coJ+TpPW9iRq+Mhw/NKLjm+5SHtAHCC7lAw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz",
+ "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
- }
- },
- "@babel/plugin-transform-member-expression-literals": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.1.tgz",
- "integrity": "sha512-UmaWhDokOFT2GcgU6MkHC11i0NQcL63iqeufXWfRy6pUOGYeCGEKhvfFO6Vz70UfYJYHwveg62GS83Rvpxn+NA==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
- }
- },
- "@babel/plugin-transform-modules-amd": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.1.tgz",
- "integrity": "sha512-31+hnWSFRI4/ACFr1qkboBbrTxoBIzj7qA69qlq8HY8p7+YCzkCT6/TvQ1a4B0z27VeWtAeJd6pr5G04dc1iHw==",
- "dev": true,
- "requires": {
- "@babel/helper-module-transforms": "^7.10.1",
- "@babel/helper-plugin-utils": "^7.10.1",
- "babel-plugin-dynamic-import-node": "^2.3.3"
- }
- },
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+ "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ }
+ }
+ },
+ "@babel/plugin-transform-literals": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz",
+ "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
+ "@babel/plugin-transform-member-expression-literals": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz",
+ "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
+ "@babel/plugin-transform-modules-amd": {
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz",
+ "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-transforms": "^7.10.5",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.11.6",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz",
+ "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.5",
+ "jsesc": "^2.5.1",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz",
+ "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz",
+ "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz",
+ "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-simple-access": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.11.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz",
+ "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz",
+ "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz",
+ "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+ "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+ "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz",
+ "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.11.5",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/parser": "^7.11.5",
+ "@babel/types": "^7.11.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "debug": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+ "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
"@babel/plugin-transform-modules-commonjs": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.1.tgz",
- "integrity": "sha512-AQG4fc3KOah0vdITwt7Gi6hD9BtQP/8bhem7OjbaMoRNCH5Djx42O2vYMfau7QnAzQCa+RJnhJBmFFMGpQEzrg==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz",
+ "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==",
"dev": true,
"requires": {
- "@babel/helper-module-transforms": "^7.10.1",
- "@babel/helper-plugin-utils": "^7.10.1",
- "@babel/helper-simple-access": "^7.10.1",
+ "@babel/helper-module-transforms": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-simple-access": "^7.10.4",
"babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.11.6",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz",
+ "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.5",
+ "jsesc": "^2.5.1",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz",
+ "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz",
+ "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz",
+ "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-simple-access": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.11.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz",
+ "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz",
+ "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz",
+ "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+ "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+ "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz",
+ "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.11.5",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/parser": "^7.11.5",
+ "@babel/types": "^7.11.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "debug": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+ "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-modules-systemjs": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.3.tgz",
- "integrity": "sha512-GWXWQMmE1GH4ALc7YXW56BTh/AlzvDWhUNn9ArFF0+Cz5G8esYlVbXfdyHa1xaD1j+GnBoCeoQNlwtZTVdiG/A==",
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz",
+ "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==",
"dev": true,
"requires": {
- "@babel/helper-hoist-variables": "^7.10.3",
- "@babel/helper-module-transforms": "^7.10.1",
- "@babel/helper-plugin-utils": "^7.10.3",
+ "@babel/helper-hoist-variables": "^7.10.4",
+ "@babel/helper-module-transforms": "^7.10.5",
+ "@babel/helper-plugin-utils": "^7.10.4",
"babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.11.6",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz",
+ "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.5",
+ "jsesc": "^2.5.1",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz",
+ "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz",
+ "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz",
+ "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-simple-access": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.11.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz",
+ "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz",
+ "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz",
+ "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+ "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+ "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz",
+ "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.11.5",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/parser": "^7.11.5",
+ "@babel/types": "^7.11.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "debug": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+ "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-modules-umd": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.1.tgz",
- "integrity": "sha512-EIuiRNMd6GB6ulcYlETnYYfgv4AxqrswghmBRQbWLHZxN4s7mupxzglnHqk9ZiUpDI4eRWewedJJNj67PWOXKA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz",
+ "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==",
"dev": true,
"requires": {
- "@babel/helper-module-transforms": "^7.10.1",
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-module-transforms": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.11.6",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz",
+ "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.5",
+ "jsesc": "^2.5.1",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz",
+ "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz",
+ "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz",
+ "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4",
+ "@babel/helper-simple-access": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.11.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz",
+ "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz",
+ "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz",
+ "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+ "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+ "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz",
+ "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.11.5",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/parser": "^7.11.5",
+ "@babel/types": "^7.11.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "debug": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+ "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-named-capturing-groups-regex": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.3.tgz",
- "integrity": "sha512-I3EH+RMFyVi8Iy/LekQm948Z4Lz4yKT7rK+vuCAeRm0kTa6Z5W7xuhRxDNJv0FPya/her6AUgrDITb70YHtTvA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz",
+ "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==",
"dev": true,
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.8.3"
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4"
}
},
"@babel/plugin-transform-new-target": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.1.tgz",
- "integrity": "sha512-MBlzPc1nJvbmO9rPr1fQwXOM2iGut+JC92ku6PbiJMMK7SnQc1rytgpopveE3Evn47gzvGYeCdgfCDbZo0ecUw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz",
+ "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-object-super": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.1.tgz",
- "integrity": "sha512-WnnStUDN5GL+wGQrJylrnnVlFhFmeArINIR9gjhSeYyvroGhBrSAXYg/RHsnfzmsa+onJrTJrEClPzgNmmQ4Gw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz",
+ "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1",
- "@babel/helper-replace-supers": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-replace-supers": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+ "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.11.6",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz",
+ "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.5",
+ "jsesc": "^2.5.1",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+ "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/template": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz",
+ "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz",
+ "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz",
+ "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.10.4",
+ "@babel/helper-optimise-call-expression": "^7.10.4",
+ "@babel/traverse": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+ "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.11.0"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+ "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+ "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
+ "dev": true
+ },
+ "@babel/template": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+ "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/parser": "^7.10.4",
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz",
+ "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.11.5",
+ "@babel/helper-function-name": "^7.10.4",
+ "@babel/helper-split-export-declaration": "^7.11.0",
+ "@babel/parser": "^7.11.5",
+ "@babel/types": "^7.11.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.19"
+ }
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "debug": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+ "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
}
},
"@babel/plugin-transform-parameters": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.1.tgz",
- "integrity": "sha512-tJ1T0n6g4dXMsL45YsSzzSDZCxiHXAQp/qHrucOq5gEHncTA3xDxnd5+sZcoQp+N1ZbieAaB8r/VUCG0gqseOg==",
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz",
+ "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==",
"dev": true,
"requires": {
- "@babel/helper-get-function-arity": "^7.10.1",
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-get-function-arity": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "dependencies": {
+ "@babel/helper-get-function-arity": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+ "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ }
}
},
"@babel/plugin-transform-property-literals": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.1.tgz",
- "integrity": "sha512-Kr6+mgag8auNrgEpbfIWzdXYOvqDHZOF0+Bx2xh4H2EDNwcbRb9lY6nkZg8oSjsX+DH9Ebxm9hOqtKW+gRDeNA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz",
+ "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-regenerator": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.3.tgz",
- "integrity": "sha512-H5kNeW0u8mbk0qa1jVIVTeJJL6/TJ81ltD4oyPx0P499DhMJrTmmIFCmJ3QloGpQG8K9symccB7S7SJpCKLwtw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz",
+ "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==",
"dev": true,
"requires": {
"regenerator-transform": "^0.14.2"
}
},
"@babel/plugin-transform-reserved-words": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.1.tgz",
- "integrity": "sha512-qN1OMoE2nuqSPmpTqEM7OvJ1FkMEV+BjVeZZm9V9mq/x1JLKQ4pcv8riZJMNN3u2AUGl0ouOMjRr2siecvHqUQ==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz",
+ "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-runtime": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.10.3.tgz",
- "integrity": "sha512-b5OzMD1Hi8BBzgQdRHyVVaYrk9zG0wset1it2o3BgonkPadXfOv0aXRqd7864DeOIu3FGKP/h6lr15FE5mahVw==",
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.5.tgz",
+ "integrity": "sha512-9aIoee+EhjySZ6vY5hnLjigHzunBlscx9ANKutkeWTJTx6m5Rbq6Ic01tLvO54lSusR+BxV7u4UDdCmXv5aagg==",
"dev": true,
"requires": {
- "@babel/helper-module-imports": "^7.10.3",
- "@babel/helper-plugin-utils": "^7.10.3",
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
"resolve": "^1.8.1",
"semver": "^5.5.1"
},
"dependencies": {
+ "@babel/helper-module-imports": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz",
+ "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
@@ -853,136 +2814,141 @@
}
},
"@babel/plugin-transform-shorthand-properties": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.1.tgz",
- "integrity": "sha512-AR0E/lZMfLstScFwztApGeyTHJ5u3JUKMjneqRItWeEqDdHWZwAOKycvQNCasCK/3r5YXsuNG25funcJDu7Y2g==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz",
+ "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-spread": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.1.tgz",
- "integrity": "sha512-8wTPym6edIrClW8FI2IoaePB91ETOtg36dOkj3bYcNe7aDMN2FXEoUa+WrmPc4xa1u2PQK46fUX2aCb+zo9rfw==",
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz",
+ "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0"
}
},
"@babel/plugin-transform-sticky-regex": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.1.tgz",
- "integrity": "sha512-j17ojftKjrL7ufX8ajKvwRilwqTok4q+BjkknmQw9VNHnItTyMP5anPFzxFJdCQs7clLcWpCV3ma+6qZWLnGMA==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz",
+ "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1",
- "@babel/helper-regex": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/helper-regex": "^7.10.4"
}
},
"@babel/plugin-transform-template-literals": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.3.tgz",
- "integrity": "sha512-yaBn9OpxQra/bk0/CaA4wr41O0/Whkg6nqjqApcinxM7pro51ojhX6fv1pimAnVjVfDy14K0ULoRL70CA9jWWA==",
+ "version": "7.10.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz",
+ "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==",
"dev": true,
"requires": {
- "@babel/helper-annotate-as-pure": "^7.10.1",
- "@babel/helper-plugin-utils": "^7.10.3"
+ "@babel/helper-annotate-as-pure": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-typeof-symbol": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.1.tgz",
- "integrity": "sha512-qX8KZcmbvA23zDi+lk9s6hC1FM7jgLHYIjuLgULgc8QtYnmB3tAVIYkNoKRQ75qWBeyzcoMoK8ZQmogGtC/w0g==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz",
+ "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-unicode-escapes": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.1.tgz",
- "integrity": "sha512-zZ0Poh/yy1d4jeDWpx/mNwbKJVwUYJX73q+gyh4bwtG0/iUlzdEu0sLMda8yuDFS6LBQlT/ST1SJAR6zYwXWgw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz",
+ "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==",
"dev": true,
"requires": {
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-transform-unicode-regex": {
- "version": "7.10.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.1.tgz",
- "integrity": "sha512-Y/2a2W299k0VIUdbqYm9X2qS6fE0CUBhhiPpimK6byy7OJ/kORLlIX+J6UrjgNu5awvs62k+6RSslxhcvVw2Tw==",
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz",
+ "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==",
"dev": true,
"requires": {
- "@babel/helper-create-regexp-features-plugin": "^7.10.1",
- "@babel/helper-plugin-utils": "^7.10.1"
+ "@babel/helper-create-regexp-features-plugin": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/preset-env": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.10.3.tgz",
- "integrity": "sha512-jHaSUgiewTmly88bJtMHbOd1bJf2ocYxb5BWKSDQIP5tmgFuS/n0gl+nhSrYDhT33m0vPxp+rP8oYYgPgMNQlg==",
- "dev": true,
- "requires": {
- "@babel/compat-data": "^7.10.3",
- "@babel/helper-compilation-targets": "^7.10.2",
- "@babel/helper-module-imports": "^7.10.3",
- "@babel/helper-plugin-utils": "^7.10.3",
- "@babel/plugin-proposal-async-generator-functions": "^7.10.3",
- "@babel/plugin-proposal-class-properties": "^7.10.1",
- "@babel/plugin-proposal-dynamic-import": "^7.10.1",
- "@babel/plugin-proposal-json-strings": "^7.10.1",
- "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.1",
- "@babel/plugin-proposal-numeric-separator": "^7.10.1",
- "@babel/plugin-proposal-object-rest-spread": "^7.10.3",
- "@babel/plugin-proposal-optional-catch-binding": "^7.10.1",
- "@babel/plugin-proposal-optional-chaining": "^7.10.3",
- "@babel/plugin-proposal-private-methods": "^7.10.1",
- "@babel/plugin-proposal-unicode-property-regex": "^7.10.1",
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.5.tgz",
+ "integrity": "sha512-kXqmW1jVcnB2cdueV+fyBM8estd5mlNfaQi6lwLgRwCby4edpavgbFhiBNjmWA3JpB/yZGSISa7Srf+TwxDQoA==",
+ "dev": true,
+ "requires": {
+ "@babel/compat-data": "^7.11.0",
+ "@babel/helper-compilation-targets": "^7.10.4",
+ "@babel/helper-module-imports": "^7.10.4",
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-proposal-async-generator-functions": "^7.10.4",
+ "@babel/plugin-proposal-class-properties": "^7.10.4",
+ "@babel/plugin-proposal-dynamic-import": "^7.10.4",
+ "@babel/plugin-proposal-export-namespace-from": "^7.10.4",
+ "@babel/plugin-proposal-json-strings": "^7.10.4",
+ "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
+ "@babel/plugin-proposal-numeric-separator": "^7.10.4",
+ "@babel/plugin-proposal-object-rest-spread": "^7.11.0",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.10.4",
+ "@babel/plugin-proposal-optional-chaining": "^7.11.0",
+ "@babel/plugin-proposal-private-methods": "^7.10.4",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.10.4",
"@babel/plugin-syntax-async-generators": "^7.8.0",
- "@babel/plugin-syntax-class-properties": "^7.10.1",
+ "@babel/plugin-syntax-class-properties": "^7.10.4",
"@babel/plugin-syntax-dynamic-import": "^7.8.0",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
"@babel/plugin-syntax-json-strings": "^7.8.0",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0",
- "@babel/plugin-syntax-numeric-separator": "^7.10.1",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
"@babel/plugin-syntax-object-rest-spread": "^7.8.0",
"@babel/plugin-syntax-optional-catch-binding": "^7.8.0",
"@babel/plugin-syntax-optional-chaining": "^7.8.0",
- "@babel/plugin-syntax-top-level-await": "^7.10.1",
- "@babel/plugin-transform-arrow-functions": "^7.10.1",
- "@babel/plugin-transform-async-to-generator": "^7.10.1",
- "@babel/plugin-transform-block-scoped-functions": "^7.10.1",
- "@babel/plugin-transform-block-scoping": "^7.10.1",
- "@babel/plugin-transform-classes": "^7.10.3",
- "@babel/plugin-transform-computed-properties": "^7.10.3",
- "@babel/plugin-transform-destructuring": "^7.10.1",
- "@babel/plugin-transform-dotall-regex": "^7.10.1",
- "@babel/plugin-transform-duplicate-keys": "^7.10.1",
- "@babel/plugin-transform-exponentiation-operator": "^7.10.1",
- "@babel/plugin-transform-for-of": "^7.10.1",
- "@babel/plugin-transform-function-name": "^7.10.1",
- "@babel/plugin-transform-literals": "^7.10.1",
- "@babel/plugin-transform-member-expression-literals": "^7.10.1",
- "@babel/plugin-transform-modules-amd": "^7.10.1",
- "@babel/plugin-transform-modules-commonjs": "^7.10.1",
- "@babel/plugin-transform-modules-systemjs": "^7.10.3",
- "@babel/plugin-transform-modules-umd": "^7.10.1",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.3",
- "@babel/plugin-transform-new-target": "^7.10.1",
- "@babel/plugin-transform-object-super": "^7.10.1",
- "@babel/plugin-transform-parameters": "^7.10.1",
- "@babel/plugin-transform-property-literals": "^7.10.1",
- "@babel/plugin-transform-regenerator": "^7.10.3",
- "@babel/plugin-transform-reserved-words": "^7.10.1",
- "@babel/plugin-transform-shorthand-properties": "^7.10.1",
- "@babel/plugin-transform-spread": "^7.10.1",
- "@babel/plugin-transform-sticky-regex": "^7.10.1",
- "@babel/plugin-transform-template-literals": "^7.10.3",
- "@babel/plugin-transform-typeof-symbol": "^7.10.1",
- "@babel/plugin-transform-unicode-escapes": "^7.10.1",
- "@babel/plugin-transform-unicode-regex": "^7.10.1",
+ "@babel/plugin-syntax-top-level-await": "^7.10.4",
+ "@babel/plugin-transform-arrow-functions": "^7.10.4",
+ "@babel/plugin-transform-async-to-generator": "^7.10.4",
+ "@babel/plugin-transform-block-scoped-functions": "^7.10.4",
+ "@babel/plugin-transform-block-scoping": "^7.10.4",
+ "@babel/plugin-transform-classes": "^7.10.4",
+ "@babel/plugin-transform-computed-properties": "^7.10.4",
+ "@babel/plugin-transform-destructuring": "^7.10.4",
+ "@babel/plugin-transform-dotall-regex": "^7.10.4",
+ "@babel/plugin-transform-duplicate-keys": "^7.10.4",
+ "@babel/plugin-transform-exponentiation-operator": "^7.10.4",
+ "@babel/plugin-transform-for-of": "^7.10.4",
+ "@babel/plugin-transform-function-name": "^7.10.4",
+ "@babel/plugin-transform-literals": "^7.10.4",
+ "@babel/plugin-transform-member-expression-literals": "^7.10.4",
+ "@babel/plugin-transform-modules-amd": "^7.10.4",
+ "@babel/plugin-transform-modules-commonjs": "^7.10.4",
+ "@babel/plugin-transform-modules-systemjs": "^7.10.4",
+ "@babel/plugin-transform-modules-umd": "^7.10.4",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4",
+ "@babel/plugin-transform-new-target": "^7.10.4",
+ "@babel/plugin-transform-object-super": "^7.10.4",
+ "@babel/plugin-transform-parameters": "^7.10.4",
+ "@babel/plugin-transform-property-literals": "^7.10.4",
+ "@babel/plugin-transform-regenerator": "^7.10.4",
+ "@babel/plugin-transform-reserved-words": "^7.10.4",
+ "@babel/plugin-transform-shorthand-properties": "^7.10.4",
+ "@babel/plugin-transform-spread": "^7.11.0",
+ "@babel/plugin-transform-sticky-regex": "^7.10.4",
+ "@babel/plugin-transform-template-literals": "^7.10.4",
+ "@babel/plugin-transform-typeof-symbol": "^7.10.4",
+ "@babel/plugin-transform-unicode-escapes": "^7.10.4",
+ "@babel/plugin-transform-unicode-regex": "^7.10.4",
"@babel/preset-modules": "^0.1.3",
- "@babel/types": "^7.10.3",
+ "@babel/types": "^7.11.5",
"browserslist": "^4.12.0",
"core-js-compat": "^3.6.2",
"invariant": "^2.2.2",
@@ -990,6 +2956,32 @@
"semver": "^5.5.0"
},
"dependencies": {
+ "@babel/helper-module-imports": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz",
+ "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.10.4"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+ "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+ "dev": true
+ },
+ "@babel/types": {
+ "version": "7.11.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+ "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.10.4",
+ "lodash": "^4.17.19",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
@@ -999,9 +2991,9 @@
}
},
"@babel/preset-modules": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz",
- "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==",
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz",
+ "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
@@ -1012,9 +3004,9 @@
}
},
"@babel/runtime": {
- "version": "7.10.3",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.3.tgz",
- "integrity": "sha512-RzGO0RLSdokm9Ipe/YD+7ww8X2Ro79qiXZF3HU9ljrM+qnJmH1Vqth+hbiQZy761LnMJTMitHDuKVYTk3k4dLw==",
+ "version": "7.11.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz",
+ "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==",
"dev": true,
"requires": {
"regenerator-runtime": "^0.13.4"
@@ -1083,45 +3075,45 @@
}
},
"@fortawesome/fontawesome-common-types": {
- "version": "0.2.30",
- "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.30.tgz",
- "integrity": "sha512-TsRwpTuKwFNiPhk1UfKgw7zNPeV5RhNp2Uw3pws+9gDAkPGKrtjR1y2lI3SYn7+YzyfuNknflpBA1LRKjt7hMg==",
+ "version": "0.2.32",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.32.tgz",
+ "integrity": "sha512-ux2EDjKMpcdHBVLi/eWZynnPxs0BtFVXJkgHIxXRl+9ZFaHPvYamAfCzeeQFqHRjuJtX90wVnMRaMQAAlctz3w==",
"dev": true
},
"@fortawesome/fontawesome-svg-core": {
- "version": "1.2.30",
- "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.30.tgz",
- "integrity": "sha512-E3sAXATKCSVnT17HYmZjjbcmwihrNOCkoU7dVMlasrcwiJAHxSKeZ+4WN5O+ElgO/FaYgJmASl8p9N7/B/RttA==",
+ "version": "1.2.32",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.32.tgz",
+ "integrity": "sha512-XjqyeLCsR/c/usUpdWcOdVtWFVjPbDFBTQkn2fQRrWhhUoxriQohO2RWDxLyUM8XpD+Zzg5xwJ8gqTYGDLeGaQ==",
"dev": true,
"requires": {
- "@fortawesome/fontawesome-common-types": "^0.2.30"
+ "@fortawesome/fontawesome-common-types": "^0.2.32"
}
},
"@fortawesome/free-brands-svg-icons": {
- "version": "5.14.0",
- "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.14.0.tgz",
- "integrity": "sha512-WsqPFTvJFI7MYkcy0jeFE2zY+blC4OrnB9MJOcn1NxRXT/sSfEEhrI7CwzIkiYajLiVDBKWeErYOvpsMeodmCQ==",
+ "version": "5.15.1",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.1.tgz",
+ "integrity": "sha512-pkTZIWn7iuliCCgV+huDfZmZb2UjslalXGDA2PcqOVUYJmYL11y6ooFiMJkJvUZu+xgAc1gZgQe+Px12mZF0CA==",
"dev": true,
"requires": {
- "@fortawesome/fontawesome-common-types": "^0.2.30"
+ "@fortawesome/fontawesome-common-types": "^0.2.32"
}
},
"@fortawesome/free-regular-svg-icons": {
- "version": "5.14.0",
- "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.14.0.tgz",
- "integrity": "sha512-6LCFvjGSMPoUQbn3NVlgiG4CY5iIY8fOm+to/D6QS/GvdqhDt+xZklQeERdCvVRbnFa1ITc1rJHPRXqkX5wztQ==",
+ "version": "5.15.1",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.1.tgz",
+ "integrity": "sha512-eD9NWFy89e7SVVtrLedJUxIpCBGhd4x7s7dhesokjyo1Tw62daqN5UcuAGu1NrepLLq1IeAYUVfWwnOjZ/j3HA==",
"dev": true,
"requires": {
- "@fortawesome/fontawesome-common-types": "^0.2.30"
+ "@fortawesome/fontawesome-common-types": "^0.2.32"
}
},
"@fortawesome/free-solid-svg-icons": {
- "version": "5.14.0",
- "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.14.0.tgz",
- "integrity": "sha512-M933RDM8cecaKMWDSk3FRYdnzWGW7kBBlGNGfvqLVwcwhUPNj9gcw+xZMrqBdRqxnSXdl3zWzTCNNGEtFUq67Q==",
+ "version": "5.15.1",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.1.tgz",
+ "integrity": "sha512-EFMuKtzRMNbvjab/SvJBaOOpaqJfdSap/Nl6hst7CgrJxwfORR1drdTV6q1Ib/JVzq4xObdTDcT6sqTaXMqfdg==",
"dev": true,
"requires": {
- "@fortawesome/fontawesome-common-types": "^0.2.30"
+ "@fortawesome/fontawesome-common-types": "^0.2.32"
}
},
"@fortawesome/vue-fontawesome": {
@@ -1175,9 +3167,9 @@
}
},
"@stylelint/postcss-css-in-js": {
- "version": "0.37.1",
- "resolved": "https://registry.npmjs.org/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.1.tgz",
- "integrity": "sha512-UMf2Rni3JGKi3ZwYRGMYJ5ipOA5ENJSKMtYA/pE1ZLURwdh7B5+z2r73RmWvub+N0UuH1Lo+TGfCgYwPvqpXNw==",
+ "version": "0.37.2",
+ "resolved": "https://registry.npmjs.org/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.2.tgz",
+ "integrity": "sha512-nEhsFoJurt8oUmieT8qy4nk81WRHmJynmVwn/Vts08PL9fhgIsMhk1GId5yAN643OzqEEb5S/6At2TZW7pqPDA==",
"dev": true,
"requires": {
"@babel/core": ">=7.9.0"
@@ -1200,9 +3192,9 @@
"dev": true
},
"@types/glob": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.2.tgz",
- "integrity": "sha512-VgNIkxK+j7Nz5P7jvUZlRvhuPSmsEfS03b0alKcq5V/STUKAa3Plemsn5mrQUO7am6OErJ4rhGEGJbACclrtRA==",
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
+ "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==",
"dev": true,
"requires": {
"@types/minimatch": "*",
@@ -1228,9 +3220,9 @@
"dev": true
},
"@types/node": {
- "version": "14.0.14",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.14.tgz",
- "integrity": "sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ==",
+ "version": "14.11.8",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.8.tgz",
+ "integrity": "sha512-KPcKqKm5UKDkaYPTuXSx8wEP7vE9GnuaXIZKijwRYcePpZFDVuy2a57LarFKiORbHOuTOOwYzxVxcUzsh2P2Pw==",
"dev": true
},
"@types/normalize-package-data": {
@@ -1258,9 +3250,9 @@
"dev": true
},
"@vue/component-compiler-utils": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.1.2.tgz",
- "integrity": "sha512-QLq9z8m79mCinpaEeSURhnNCN6djxpHw0lpP/bodMlt5kALfONpryMthvnrQOlTcIKoF+VoPi+lPHUYeDFPXug==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.2.0.tgz",
+ "integrity": "sha512-lejBLa7xAMsfiZfNp7Kv51zOzifnb29FwdnMLa96z26kXErPFioSf9BMcePVIQ6/Gc6/mC0UrPpxAWIHyae0vw==",
"dev": true,
"requires": {
"consolidate": "^0.15.1",
@@ -1554,9 +3546,9 @@
}
},
"aggregate-error": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz",
- "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
"dev": true,
"requires": {
"clean-stack": "^2.0.0",
@@ -1725,14 +3717,15 @@
"dev": true
},
"asn1.js": {
- "version": "4.10.1",
- "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
- "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
+ "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
"dev": true,
"requires": {
"bn.js": "^4.0.0",
"inherits": "^2.0.1",
- "minimalistic-assert": "^1.0.0"
+ "minimalistic-assert": "^1.0.0",
+ "safer-buffer": "^2.1.0"
},
"dependencies": {
"bn.js": {
@@ -2068,9 +4061,9 @@
"dev": true
},
"bn.js": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz",
- "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==",
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz",
+ "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==",
"dev": true
},
"body-parser": {
@@ -2129,9 +4122,9 @@
"dev": true
},
"bootstrap": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.5.0.tgz",
- "integrity": "sha1-l9nby1qJcvhyLJliSDVDuQfZuew=",
+ "version": "4.5.3",
+ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.5.3.tgz",
+ "integrity": "sha512-o9ppKQioXGqhw8Z7mah6KdTYpNQY//tipnkxppWhPbiSWdD+1raYsnhwEZjkTHYbGee4cVQ0Rx65EhOY/HNLcQ==",
"dev": true
},
"brace-expansion": {
@@ -2241,16 +4234,16 @@
}
},
"browserify-sign": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.0.tgz",
- "integrity": "sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA==",
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz",
+ "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==",
"dev": true,
"requires": {
"bn.js": "^5.1.1",
"browserify-rsa": "^4.0.1",
"create-hash": "^1.2.0",
"create-hmac": "^1.1.7",
- "elliptic": "^6.5.2",
+ "elliptic": "^6.5.3",
"inherits": "^2.0.4",
"parse-asn1": "^5.1.5",
"readable-stream": "^3.6.0",
@@ -2492,12 +4485,11 @@
},
"dependencies": {
"ansi-styles": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
- "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
- "@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
}
},
@@ -2523,9 +4515,9 @@
"dev": true
},
"supports-color": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
- "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
@@ -2570,9 +4562,9 @@
"dev": true
},
"chokidar": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz",
- "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==",
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz",
+ "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==",
"dev": true,
"requires": {
"anymatch": "~3.1.1",
@@ -2582,7 +4574,7 @@
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
- "readdirp": "~3.4.0"
+ "readdirp": "~3.5.0"
},
"dependencies": {
"anymatch": {
@@ -2626,15 +4618,6 @@
"dev": true,
"optional": true
},
- "glob-parent": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
- "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
- "dev": true,
- "requires": {
- "is-glob": "^4.0.1"
- }
- },
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@@ -2651,9 +4634,9 @@
"dev": true
},
"readdirp": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
- "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
+ "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
"dev": true,
"requires": {
"picomatch": "^2.2.1"
@@ -2828,12 +4811,6 @@
}
}
},
- "code-point-at": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
- "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
- "dev": true
- },
"collapse-white-space": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz",
@@ -2841,9 +4818,9 @@
"dev": true
},
"collect.js": {
- "version": "4.27.3",
- "resolved": "https://registry.npmjs.org/collect.js/-/collect.js-4.27.3.tgz",
- "integrity": "sha512-2nmoyhUJbhjVVE0W9W0cSBeg8/PL3ObGe1ijj9WDlLG3RrpvePsBZd6p3uTm1dTAUKJVd3qT8mnH6iXCdENEHQ==",
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/collect.js/-/collect.js-4.28.2.tgz",
+ "integrity": "sha512-Ok2z0kuyywWJ4AtkeUI61pbSxCmaN5XYr/fkUYJP4bYk6Dz3NKH2FA8RhF7i3Do9Iq80MLRFWasSOpyE9X7hDA==",
"dev": true
},
"collection-visit": {
@@ -2857,13 +4834,13 @@
}
},
"color": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz",
- "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz",
+ "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==",
"dev": true,
"requires": {
"color-convert": "^1.9.1",
- "color-string": "^1.5.2"
+ "color-string": "^1.5.4"
}
},
"color-convert": {
@@ -2882,9 +4859,9 @@
"dev": true
},
"color-string": {
- "version": "1.5.3",
- "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
- "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz",
+ "integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==",
"dev": true,
"requires": {
"color-name": "^1.0.0",
@@ -2898,9 +4875,9 @@
"dev": true
},
"commander": {
- "version": "2.17.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
- "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"commondir": {
@@ -2950,6 +4927,15 @@
}
}
},
+ "concat": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/concat/-/concat-1.0.3.tgz",
+ "integrity": "sha1-QPM1MInWVGdpXLGIa0Xt1jfYzKg=",
+ "dev": true,
+ "requires": {
+ "commander": "^2.9.0"
+ }
+ },
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -2968,15 +4954,6 @@
"typedarray": "^0.0.6"
}
},
- "concatenate": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/concatenate/-/concatenate-0.0.2.tgz",
- "integrity": "sha1-C0nW6MQQR9dyjNyNYqCGYjOXtJ8=",
- "dev": true,
- "requires": {
- "globs": "^0.1.2"
- }
- },
"connect-history-api-fallback": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
@@ -3115,13 +5092,13 @@
}
},
"create-ecdh": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
- "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
+ "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==",
"dev": true,
"requires": {
"bn.js": "^4.1.0",
- "elliptic": "^6.0.0"
+ "elliptic": "^6.5.3"
},
"dependencies": {
"bn.js": {
@@ -3315,14 +5292,13 @@
"dev": true
},
"css-selector-tokenizer": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.2.tgz",
- "integrity": "sha512-yj856NGuAymN6r8bn8/Jl46pR+OC3eEvAhfGYDUe7YPtTPAYrSSw4oAniZ9Y8T5B92hjhwTBLUen0/vKPxf6pw==",
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz",
+ "integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==",
"dev": true,
"requires": {
"cssesc": "^3.0.0",
- "fastparse": "^1.1.2",
- "regexpu-core": "^4.6.0"
+ "fastparse": "^1.1.2"
}
},
"css-tree": {
@@ -3344,9 +5320,9 @@
}
},
"css-what": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.3.0.tgz",
- "integrity": "sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg==",
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.1.tgz",
+ "integrity": "sha512-wHOppVDKl4vTAOWzJt5Ek37Sgd9qq1Bmj/T1OjvicWbU5W7ru7Pqbn0Jdqii3Drx/h+dixHKXNhZYx7blthL7g==",
"dev": true
},
"cssesc": {
@@ -3793,9 +5769,9 @@
}
},
"dot-prop": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz",
- "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==",
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
+ "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
"dev": true,
"requires": {
"is-obj": "^2.0.0"
@@ -3888,9 +5864,9 @@
}
},
"enhanced-resolve": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.2.0.tgz",
- "integrity": "sha512-S7eiFb/erugyd1rLb6mQ3Vuq+EXHv5cpCkNqqIkYkBgN2QdFnyCZzFBleqwGEx4lgNGYij81BWnCrFNK7vxvjQ==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz",
+ "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.2",
@@ -3944,20 +5920,21 @@
}
},
"es-abstract": {
- "version": "1.17.6",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
- "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
+ "version": "1.18.0-next.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz",
+ "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==",
"dev": true,
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
- "is-callable": "^1.2.0",
- "is-regex": "^1.1.0",
- "object-inspect": "^1.7.0",
+ "is-callable": "^1.2.2",
+ "is-negative-zero": "^2.0.0",
+ "is-regex": "^1.1.1",
+ "object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
+ "object.assign": "^4.1.1",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
}
@@ -4246,15 +6223,15 @@
"dev": true
},
"eventemitter3": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz",
- "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==",
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
"dev": true
},
"events": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz",
- "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz",
+ "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==",
"dev": true
},
"eventsource": {
@@ -4642,6 +6619,12 @@
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
"dev": true
},
+ "fastest-levenshtein": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz",
+ "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==",
+ "dev": true
+ },
"fastparse": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
@@ -5188,15 +7171,6 @@
"integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=",
"dev": true
},
- "globs": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/globs/-/globs-0.1.4.tgz",
- "integrity": "sha512-D23dWbOq48vlOraoSigbcQV4tWrnhwk+E/Um2cMuDS3/5dwGmdFeA7L/vAvDhLFlQOTDqHcXh35m/71g2A2WzQ==",
- "dev": true,
- "requires": {
- "glob": "^7.1.1"
- }
- },
"gonzales-pe": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz",
@@ -5452,6 +7426,14 @@
"param-case": "2.1.x",
"relateurl": "0.2.x",
"uglify-js": "3.4.x"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.17.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
+ "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
+ "dev": true
+ }
}
},
"html-tags": {
@@ -5655,9 +7637,9 @@
}
},
"img-loader": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/img-loader/-/img-loader-3.0.1.tgz",
- "integrity": "sha512-0jDJqexgzOuq3zlXwFTBKJlMcaP1uXyl5t4Qu6b1IgXb3IwBDjPfVylBC8vHFIIESDw/S+5QkBbtBrt4T8wESA==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/img-loader/-/img-loader-3.0.2.tgz",
+ "integrity": "sha512-rSriLKgvi85Km7ppSF+AEAM3nU4fxpvCkaXtC/IoCEU7jfks55bEANFs0bB9YXYkxY9JurZQIZFtXh5Gue3upw==",
"dev": true,
"requires": {
"loader-utils": "^1.1.0"
@@ -5882,12 +7864,6 @@
"loose-envify": "^1.0.0"
}
},
- "invert-kv": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
- "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
- "dev": true
- },
"ip": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
@@ -5988,9 +7964,9 @@
"dev": true
},
"is-callable": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
- "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz",
+ "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==",
"dev": true
},
"is-color-stop": {
@@ -6106,6 +8082,12 @@
"integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
"dev": true
},
+ "is-negative-zero": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz",
+ "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=",
+ "dev": true
+ },
"is-number": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
@@ -6178,9 +8160,9 @@
}
},
"is-regex": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz",
- "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
+ "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
"dev": true,
"requires": {
"has-symbols": "^1.0.1"
@@ -6287,9 +8269,9 @@
"dev": true
},
"supports-color": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
- "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
@@ -6331,6 +8313,12 @@
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
"dev": true
},
+ "json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true
+ },
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -6386,9 +8374,9 @@
"dev": true
},
"laravel-mix": {
- "version": "5.0.4",
- "resolved": "https://registry.npmjs.org/laravel-mix/-/laravel-mix-5.0.4.tgz",
- "integrity": "sha512-/fkcMdlxhGDBcH+kFDqKONlAfhJinMAWd+fjQ+VLii4UzIeXUF5Q8FbS4+ZrZs9JO3Y1E4KoNq3hMw0t/soahA==",
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/laravel-mix/-/laravel-mix-5.0.6.tgz",
+ "integrity": "sha512-yeX23rnpUUs7LXZlDMQMh2yg5nOkizlvUjwir8d54yhIqDec7Btnkg935Pxeo81kq/JONssHEaVPrwp1/TsPsQ==",
"dev": true,
"requires": {
"@babel/core": "^7.2.0",
@@ -6403,7 +8391,7 @@
"chokidar": "^2.0.3",
"clean-css": "^4.1.3",
"collect.js": "^4.12.8",
- "concatenate": "0.0.2",
+ "concat": "^1.0.3",
"css-loader": "^1.0.1",
"dotenv": "^6.2.0",
"dotenv-expand": "^4.2.0",
@@ -6428,7 +8416,7 @@
"webpack-dev-server": "^3.1.14",
"webpack-merge": "^4.1.0",
"webpack-notifier": "^1.5.1",
- "yargs": "^12.0.5"
+ "yargs": "^15.4.1"
},
"dependencies": {
"chokidar": {
@@ -6484,15 +8472,6 @@
"webpack-sources": "^1.1.0"
}
},
- "lcid": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
- "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
- "dev": true,
- "requires": {
- "invert-kv": "^2.0.0"
- }
- },
"leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
@@ -6563,9 +8542,9 @@
}
},
"lodash": {
- "version": "4.17.15",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
- "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+ "version": "4.17.20",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+ "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
"dev": true
},
"lodash._baseassign": {
@@ -6676,9 +8655,9 @@
}
},
"loglevel": {
- "version": "1.6.8",
- "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz",
- "integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.0.tgz",
+ "integrity": "sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ==",
"dev": true
},
"longest-streak": {
@@ -6737,15 +8716,6 @@
}
}
},
- "map-age-cleaner": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
- "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
- "dev": true,
- "requires": {
- "p-defer": "^1.0.0"
- }
- },
"map-cache": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
@@ -6789,14 +8759,14 @@
"dev": true
},
"md5": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz",
- "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
+ "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
"dev": true,
"requires": {
- "charenc": "~0.0.1",
- "crypt": "~0.0.1",
- "is-buffer": "~1.1.1"
+ "charenc": "0.0.2",
+ "crypt": "0.0.2",
+ "is-buffer": "~1.1.6"
},
"dependencies": {
"is-buffer": {
@@ -6839,17 +8809,6 @@
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
"dev": true
},
- "mem": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
- "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
- "dev": true,
- "requires": {
- "map-age-cleaner": "^0.1.1",
- "mimic-fn": "^2.0.0",
- "p-is-promise": "^2.0.0"
- }
- },
"memory-fs": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
@@ -6861,18 +8820,16 @@
}
},
"meow": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/meow/-/meow-7.0.1.tgz",
- "integrity": "sha512-tBKIQqVrAHqwit0vfuFPY3LlzJYkEOFyKa3bPgxzNl6q/RtN8KQ+ALYEASYuFayzSAsjlhXj/JZ10rH85Q6TUw==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-7.1.1.tgz",
+ "integrity": "sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA==",
"dev": true,
"requires": {
"@types/minimist": "^1.2.0",
- "arrify": "^2.0.1",
- "camelcase": "^6.0.0",
"camelcase-keys": "^6.2.2",
"decamelize-keys": "^1.1.0",
"hard-rejection": "^2.1.0",
- "minimist-options": "^4.0.2",
+ "minimist-options": "4.1.0",
"normalize-package-data": "^2.5.0",
"read-pkg-up": "^7.0.1",
"redent": "^3.0.0",
@@ -6881,18 +8838,6 @@
"yargs-parser": "^18.1.3"
},
"dependencies": {
- "arrify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
- "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
- "dev": true
- },
- "camelcase": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.0.0.tgz",
- "integrity": "sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==",
- "dev": true
- },
"type-fest": {
"version": "0.13.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
@@ -6907,14 +8852,6 @@
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
- },
- "dependencies": {
- "camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "dev": true
- }
}
}
}
@@ -7106,9 +9043,9 @@
}
},
"minipass-pipeline": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.3.tgz",
- "integrity": "sha512-cFOknTvng5vqnwOpDsZTWhNll6Jf8o2x+/diplafmxpuIymAjzoOolZG0VvQf3V2HgqzJNhnuKHYp2BqDgz8IQ==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
+ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
"dev": true,
"requires": {
"minipass": "^3.0.0"
@@ -7253,9 +9190,9 @@
}
},
"node-forge": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz",
- "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==",
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
+ "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==",
"dev": true
},
"node-libs-browser": {
@@ -7409,12 +9346,6 @@
"integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=",
"dev": true
},
- "number-is-nan": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
- "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
- "dev": true
- },
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -7465,13 +9396,13 @@
"dev": true
},
"object-is": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz",
- "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==",
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz",
+ "integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==",
"dev": true,
"requires": {
"define-properties": "^1.1.3",
- "es-abstract": "^1.17.5"
+ "es-abstract": "^1.18.0-next.1"
}
},
"object-keys": {
@@ -7496,15 +9427,15 @@
}
},
"object.assign": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
- "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz",
+ "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==",
"dev": true,
"requires": {
- "define-properties": "^1.1.2",
- "function-bind": "^1.1.1",
- "has-symbols": "^1.0.0",
- "object-keys": "^1.0.11"
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.18.0-next.0",
+ "has-symbols": "^1.0.1",
+ "object-keys": "^1.1.1"
}
},
"object.getownpropertydescriptors": {
@@ -7515,6 +9446,27 @@
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.0-next.1"
+ },
+ "dependencies": {
+ "es-abstract": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
+ "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1",
+ "is-callable": "^1.2.2",
+ "is-regex": "^1.1.1",
+ "object-inspect": "^1.8.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.1",
+ "string.prototype.trimend": "^1.0.1",
+ "string.prototype.trimstart": "^1.0.1"
+ }
+ }
}
},
"object.omit": {
@@ -7545,6 +9497,27 @@
"es-abstract": "^1.17.0-next.1",
"function-bind": "^1.1.1",
"has": "^1.0.3"
+ },
+ "dependencies": {
+ "es-abstract": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
+ "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1",
+ "is-callable": "^1.2.2",
+ "is-regex": "^1.1.1",
+ "object-inspect": "^1.8.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.1",
+ "string.prototype.trimend": "^1.0.1",
+ "string.prototype.trimstart": "^1.0.1"
+ }
+ }
}
},
"obuf": {
@@ -7596,9 +9569,9 @@
}
},
"optimize-css-assets-webpack-plugin": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz",
- "integrity": "sha512-q9fbvCRS6EYtUKKSwI87qm2IxlyJK5b4dygW1rKUBT6mMDhdG5e5bZT63v6tnJR9F9FB/H5a0HTmtw+laUBxKA==",
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.4.tgz",
+ "integrity": "sha512-wqd6FdI2a5/FdoiCNNkEvLeA//lHHfG24Ln2Xm2qqdIk4aOlsR18jwpyOihqQ8849W3qu2DX8fOYxpvTMj+93A==",
"dev": true,
"requires": {
"cssnano": "^4.1.10",
@@ -7634,41 +9607,18 @@
"integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
"dev": true
},
- "os-locale": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
- "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
- "dev": true,
- "requires": {
- "execa": "^1.0.0",
- "lcid": "^2.0.0",
- "mem": "^4.0.0"
- }
- },
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
- "p-defer": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
- "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
- "dev": true
- },
"p-finally": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
"dev": true
},
- "p-is-promise": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
- "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==",
- "dev": true
- },
"p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
@@ -7753,14 +9703,13 @@
}
},
"parse-asn1": {
- "version": "5.1.5",
- "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz",
- "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==",
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz",
+ "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==",
"dev": true,
"requires": {
- "asn1.js": "^4.0.0",
+ "asn1.js": "^5.2.0",
"browserify-aes": "^1.0.0",
- "create-hash": "^1.1.0",
"evp_bytestokey": "^1.0.0",
"pbkdf2": "^3.0.3",
"safe-buffer": "^5.1.1"
@@ -7929,14 +9878,14 @@
"dev": true
},
"portfinder": {
- "version": "1.0.26",
- "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.26.tgz",
- "integrity": "sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ==",
+ "version": "1.0.28",
+ "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
+ "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==",
"dev": true,
"requires": {
"async": "^2.6.2",
"debug": "^3.1.1",
- "mkdirp": "^0.5.1"
+ "mkdirp": "^0.5.5"
},
"dependencies": {
"debug": {
@@ -8013,9 +9962,9 @@
}
},
"postcss-calc": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.2.tgz",
- "integrity": "sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ==",
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.5.tgz",
+ "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==",
"dev": true,
"requires": {
"postcss": "^7.0.27",
@@ -8117,9 +10066,9 @@
}
},
"postcss-load-config": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz",
- "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==",
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.2.tgz",
+ "integrity": "sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==",
"dev": true,
"requires": {
"cosmiconfig": "^5.0.0",
@@ -8662,40 +10611,6 @@
}
}
},
- "postcss-reporter": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-6.0.1.tgz",
- "integrity": "sha512-LpmQjfRWyabc+fRygxZjpRxfhRf9u/fdlKf4VHG4TSPbV2XNsuISzYW1KL+1aQzx53CAppa1bKG4APIB/DOXXw==",
- "dev": true,
- "requires": {
- "chalk": "^2.4.1",
- "lodash": "^4.17.11",
- "log-symbols": "^2.2.0",
- "postcss": "^7.0.7"
- },
- "dependencies": {
- "chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- }
- },
- "log-symbols": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
- "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
- "dev": true,
- "requires": {
- "chalk": "^2.0.1"
- }
- }
- }
- },
"postcss-resolve-nested-selector": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz",
@@ -8935,9 +10850,9 @@
"dev": true
},
"querystringify": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
- "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
"dev": true
},
"quick-lru": {
@@ -9004,14 +10919,14 @@
},
"dependencies": {
"parse-json": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz",
- "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz",
+ "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1",
+ "json-parse-even-better-errors": "^2.3.0",
"lines-and-columns": "^1.1.6"
}
},
@@ -9142,19 +11057,18 @@
}
},
"regenerator-runtime": {
- "version": "0.13.5",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
- "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==",
+ "version": "0.13.7",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
+ "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==",
"dev": true
},
"regenerator-transform": {
- "version": "0.14.4",
- "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.4.tgz",
- "integrity": "sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw==",
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz",
+ "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==",
"dev": true,
"requires": {
- "@babel/runtime": "^7.8.4",
- "private": "^0.1.8"
+ "@babel/runtime": "^7.8.4"
}
},
"regex-not": {
@@ -9181,6 +11095,27 @@
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.0-next.1"
+ },
+ "dependencies": {
+ "es-abstract": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
+ "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1",
+ "is-callable": "^1.2.2",
+ "is-regex": "^1.1.1",
+ "object-inspect": "^1.8.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.1",
+ "string.prototype.trimend": "^1.0.1",
+ "string.prototype.trimstart": "^1.0.1"
+ }
+ }
}
},
"regexpp": {
@@ -9190,9 +11125,9 @@
"dev": true
},
"regexpu-core": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz",
- "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==",
+ "version": "4.7.1",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz",
+ "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==",
"dev": true,
"requires": {
"regenerate": "^1.4.0",
@@ -9233,9 +11168,9 @@
"dev": true
},
"remark": {
- "version": "12.0.0",
- "resolved": "https://registry.npmjs.org/remark/-/remark-12.0.0.tgz",
- "integrity": "sha512-oX4lMIS0csgk8AEbzY0h2jdR0ngiCHOpwwpxjmRa5TqAkeknY+tkhjRJGZqnCmvyuWh55/0SW5WY3R3nn3PH9A==",
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/remark/-/remark-12.0.1.tgz",
+ "integrity": "sha512-gS7HDonkdIaHmmP/+shCPejCEEW+liMp/t/QwmF0Xt47Rpuhl32lLtDV1uKWvGoq+kxr5jSgg5oAIpGuyULjUw==",
"dev": true,
"requires": {
"remark-parse": "^8.0.0",
@@ -9244,9 +11179,9 @@
}
},
"remark-parse": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.2.tgz",
- "integrity": "sha512-eMI6kMRjsAGpMXXBAywJwiwAse+KNpmt+BK55Oofy4KvBZEqUDj6mWbGLJZrujoPIPPxDXzn3T9baRlpsm2jnQ==",
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz",
+ "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==",
"dev": true,
"requires": {
"ccount": "^1.0.0",
@@ -9268,9 +11203,9 @@
}
},
"remark-stringify": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-8.1.0.tgz",
- "integrity": "sha512-FSPZv1ds76oAZjurhhuV5qXSUSoz6QRPuwYK38S41sLHwg4oB7ejnmZshj7qwjgYLf93kdz6BOX9j5aidNE7rA==",
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-8.1.1.tgz",
+ "integrity": "sha512-q4EyPZT3PcA3Eq7vPpT6bIdokXzFGp9i85igjmhRyXWmPs0Y6/d2FYwUNotKAWyLch7g0ASZJn/KHHcHZQ163A==",
"dev": true,
"requires": {
"ccount": "^1.0.0",
@@ -9552,9 +11487,9 @@
"dev": true
},
"sass": {
- "version": "1.26.9",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.26.9.tgz",
- "integrity": "sha512-t8AkRVi+xvba4yZiLWkJdgJHBFCB3Dh4johniQkPy9ywkgFHNasXFEFP+RG/F6LhQ+aoE4aX+IorIWQjS0esVw==",
+ "version": "1.27.0",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.27.0.tgz",
+ "integrity": "sha512-0gcrER56OkzotK/GGwgg4fPrKuiFlPNitO7eUJ18Bs+/NBlofJfMxmxqpqJxjae9vu0Wq8TZzrSyxZal00WDig==",
"dev": true,
"requires": {
"chokidar": ">=2.0.0 <4.0.0"
@@ -9605,12 +11540,12 @@
"dev": true
},
"selfsigned": {
- "version": "1.10.7",
- "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz",
- "integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==",
+ "version": "1.10.8",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz",
+ "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==",
"dev": true,
"requires": {
- "node-forge": "0.9.0"
+ "node-forge": "^0.10.0"
}
},
"semver": {
@@ -9666,9 +11601,9 @@
}
},
"serialize-javascript": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz",
- "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
+ "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
"dev": true,
"requires": {
"randombytes": "^2.1.0"
@@ -10118,9 +12053,9 @@
}
},
"spdx-license-ids": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
- "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz",
+ "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==",
"dev": true
},
"spdy": {
@@ -10137,12 +12072,12 @@
},
"dependencies": {
"debug": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
- "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+ "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
"dev": true,
"requires": {
- "ms": "^2.1.1"
+ "ms": "2.1.2"
}
},
"ms": {
@@ -10168,12 +12103,12 @@
},
"dependencies": {
"debug": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
- "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+ "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
"dev": true,
"requires": {
- "ms": "^2.1.1"
+ "ms": "2.1.2"
}
},
"ms": {
@@ -10346,6 +12281,27 @@
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"
+ },
+ "dependencies": {
+ "es-abstract": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
+ "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1",
+ "is-callable": "^1.2.2",
+ "is-regex": "^1.1.1",
+ "object-inspect": "^1.8.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.1",
+ "string.prototype.trimend": "^1.0.1",
+ "string.prototype.trimstart": "^1.0.1"
+ }
+ }
}
},
"string.prototype.trimstart": {
@@ -10356,6 +12312,27 @@
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"
+ },
+ "dependencies": {
+ "es-abstract": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
+ "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1",
+ "is-callable": "^1.2.2",
+ "is-regex": "^1.1.1",
+ "object-inspect": "^1.8.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.1",
+ "string.prototype.trimend": "^1.0.1",
+ "string.prototype.trimstart": "^1.0.1"
+ }
+ }
}
},
"string_decoder": {
@@ -10464,19 +12441,21 @@
}
},
"stylelint": {
- "version": "13.6.1",
- "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.6.1.tgz",
- "integrity": "sha512-XyvKyNE7eyrqkuZ85Citd/Uv3ljGiuYHC6UiztTR6sWS9rza8j3UeQv/eGcQS9NZz/imiC4GKdk1EVL3wst5vw==",
+ "version": "13.7.2",
+ "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.7.2.tgz",
+ "integrity": "sha512-mmieorkfmO+ZA6CNDu1ic9qpt4tFvH2QUB7vqXgrMVHe5ENU69q7YDq0YUg/UHLuCsZOWhUAvcMcLzLDIERzSg==",
"dev": true,
"requires": {
- "@stylelint/postcss-css-in-js": "^0.37.1",
+ "@stylelint/postcss-css-in-js": "^0.37.2",
"@stylelint/postcss-markdown": "^0.36.1",
- "autoprefixer": "^9.8.0",
+ "autoprefixer": "^9.8.6",
"balanced-match": "^1.0.0",
"chalk": "^4.1.0",
- "cosmiconfig": "^6.0.0",
+ "cosmiconfig": "^7.0.0",
"debug": "^4.1.1",
"execall": "^2.0.0",
+ "fast-glob": "^3.2.4",
+ "fastest-levenshtein": "^1.0.12",
"file-entry-cache": "^5.0.1",
"get-stdin": "^8.0.0",
"global-modules": "^2.0.0",
@@ -10487,18 +12466,16 @@
"import-lazy": "^4.0.0",
"imurmurhash": "^0.1.4",
"known-css-properties": "^0.19.0",
- "leven": "^3.1.0",
- "lodash": "^4.17.15",
+ "lodash": "^4.17.20",
"log-symbols": "^4.0.0",
"mathml-tag-names": "^2.1.3",
- "meow": "^7.0.1",
+ "meow": "^7.1.1",
"micromatch": "^4.0.2",
"normalize-selector": "^0.2.0",
"postcss": "^7.0.32",
"postcss-html": "^0.36.0",
"postcss-less": "^3.1.4",
"postcss-media-query-parser": "^0.2.3",
- "postcss-reporter": "^6.0.1",
"postcss-resolve-nested-selector": "^0.1.1",
"postcss-safe-parser": "^4.0.2",
"postcss-sass": "^0.4.4",
@@ -10514,7 +12491,7 @@
"style-search": "^0.1.0",
"sugarss": "^2.0.0",
"svg-tags": "^1.0.0",
- "table": "^5.4.6",
+ "table": "^6.0.1",
"v8-compile-cache": "^2.1.1",
"write-file-atomic": "^3.0.3"
},
@@ -10525,12 +12502,54 @@
"integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==",
"dev": true
},
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
"array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
"dev": true
},
+ "astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true
+ },
+ "autoprefixer": {
+ "version": "9.8.6",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz",
+ "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.12.0",
+ "caniuse-lite": "^1.0.30001109",
+ "colorette": "^1.2.1",
+ "normalize-range": "^0.1.2",
+ "num2fraction": "^1.2.2",
+ "postcss": "^7.0.32",
+ "postcss-value-parser": "^4.1.0"
+ }
+ },
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
@@ -10540,26 +12559,53 @@
"fill-range": "^7.0.1"
}
},
+ "caniuse-lite": {
+ "version": "1.0.30001148",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001148.tgz",
+ "integrity": "sha512-E66qcd0KMKZHNJQt9hiLZGE3J4zuTqE1OnU53miEVtylFbwOEmeA5OsRu90noZful+XGSQOni1aT2tiqu/9yYw==",
+ "dev": true
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "colorette": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz",
+ "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==",
+ "dev": true
+ },
"cosmiconfig": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
- "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz",
+ "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==",
"dev": true,
"requires": {
"@types/parse-json": "^4.0.0",
- "import-fresh": "^3.1.0",
+ "import-fresh": "^3.2.1",
"parse-json": "^5.0.0",
"path-type": "^4.0.0",
- "yaml": "^1.7.2"
+ "yaml": "^1.10.0"
}
},
"debug": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
- "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+ "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
"dev": true,
"requires": {
- "ms": "^2.1.1"
+ "ms": "2.1.2"
}
},
"dir-glob": {
@@ -10649,14 +12695,14 @@
"dev": true
},
"parse-json": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz",
- "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz",
+ "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1",
+ "json-parse-even-better-errors": "^2.3.0",
"lines-and-columns": "^1.1.6"
}
},
@@ -10678,6 +12724,17 @@
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
"dev": true
},
+ "slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ }
+ },
"string-width": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
@@ -10689,6 +12746,18 @@
"strip-ansi": "^6.0.0"
}
},
+ "table": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/table/-/table-6.0.3.tgz",
+ "integrity": "sha512-8321ZMcf1B9HvVX/btKv8mMZahCjn2aYrDlpqHaBFCfnox64edeH9kEid0vTLTRR8gWR2A20aDgeuTTea4sVtw==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.4",
+ "lodash": "^4.17.20",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.0"
+ }
+ },
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -10802,12 +12871,6 @@
"source-map-support": "~0.5.10"
},
"dependencies": {
- "commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true
- },
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -10817,9 +12880,9 @@
}
},
"terser-webpack-plugin": {
- "version": "2.3.7",
- "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.7.tgz",
- "integrity": "sha512-xzYyaHUNhzgaAdBsXxk2Yvo/x1NJdslUaussK3fdpBbvttm1iIwU+c26dj9UxJcwk2c5UWt5F55MUTIA8BE7Dg==",
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz",
+ "integrity": "sha512-/fKw3R+hWyHfYx7Bv6oPqmk4HGQcrWLtV3X6ggvPuwPNHSnzvVV51z6OaaCOus4YLjutYGOz3pEpbhe6Up2s1w==",
"dev": true,
"requires": {
"cacache": "^13.0.1",
@@ -10827,18 +12890,12 @@
"jest-worker": "^25.4.0",
"p-limit": "^2.3.0",
"schema-utils": "^2.6.6",
- "serialize-javascript": "^3.1.0",
+ "serialize-javascript": "^4.0.0",
"source-map": "^0.6.1",
"terser": "^4.6.12",
"webpack-sources": "^1.4.3"
},
"dependencies": {
- "commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true
- },
"find-cache-dir": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz",
@@ -10902,12 +12959,6 @@
"find-up": "^4.0.0"
}
},
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "dev": true
- },
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -11184,9 +13235,9 @@
"dev": true
},
"unified": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/unified/-/unified-9.0.0.tgz",
- "integrity": "sha512-ssFo33gljU3PdlWLjNp15Inqb77d6JnJSfyplGJPT/a+fNRNyCBeveBAYJdO5khKdF6WVHa/yYCC7Xl6BDwZUQ==",
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz",
+ "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==",
"dev": true,
"requires": {
"bail": "^1.0.0",
@@ -11281,9 +13332,9 @@
}
},
"unist-util-visit": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz",
- "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
+ "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
"dev": true,
"requires": {
"@types/unist": "^2.0.0",
@@ -11292,9 +13343,9 @@
}
},
"unist-util-visit-parents": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz",
- "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.0.tgz",
+ "integrity": "sha512-0g4wbluTF93npyPrp/ymd3tCDTMnP0yo2akFD2FIBAYXq/Sga3lwaU1D8OYKbtpioaI6CkDcQ6fsMnmtzt7htw==",
"dev": true,
"requires": {
"@types/unist": "^2.0.0",
@@ -11453,6 +13504,27 @@
"es-abstract": "^1.17.2",
"has-symbols": "^1.0.1",
"object.getownpropertydescriptors": "^2.1.0"
+ },
+ "dependencies": {
+ "es-abstract": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
+ "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1",
+ "is-callable": "^1.2.2",
+ "is-regex": "^1.1.1",
+ "object-inspect": "^1.8.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.1",
+ "string.prototype.trimend": "^1.0.1",
+ "string.prototype.trimstart": "^1.0.1"
+ }
+ }
}
},
"utils-merge": {
@@ -11496,9 +13568,9 @@
"dev": true
},
"vfile": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.1.1.tgz",
- "integrity": "sha512-lRjkpyDGjVlBA7cDQhQ+gNcvB1BGaTHYuSOcY3S7OhDmBtnzX95FhtZZDecSTDm6aajFymyve6S5DN4ZHGezdQ==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.0.tgz",
+ "integrity": "sha512-a/alcwCvtuc8OX92rqqo7PflxiCgXRFjdyoGVuYV+qbgCb0GgZJRvIgCD4+U/Kl1yhaRsaTwksF88xbPyGsgpw==",
"dev": true,
"requires": {
"@types/unist": "^2.0.0",
@@ -11517,9 +13589,9 @@
}
},
"vfile-location": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.0.1.tgz",
- "integrity": "sha512-yYBO06eeN/Ki6Kh1QAkgzYpWT1d3Qln+ZCtSbJqFExPl1S3y2qqotJQXoh6qEvl/jDlgpUJolBn3PItVnnZRqQ==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.1.0.tgz",
+ "integrity": "sha512-FCZ4AN9xMcjFIG1oGmZKo61PjwJHRVA+0/tPUP2ul4uIwjGGndIxavEMRpWn5p4xwm/ZsdXp9YNygf1ZyE4x8g==",
"dev": true
},
"vfile-message": {
@@ -11539,9 +13611,9 @@
"dev": true
},
"vue": {
- "version": "2.6.11",
- "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.11.tgz",
- "integrity": "sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ==",
+ "version": "2.6.12",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.12.tgz",
+ "integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==",
"dev": true
},
"vue-eslint-parser": {
@@ -11606,9 +13678,9 @@
}
},
"vue-router": {
- "version": "3.3.4",
- "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.3.4.tgz",
- "integrity": "sha512-SdKRBeoXUjaZ9R/8AyxsdTqkOfMcI5tWxPZOUX5Ie1BTL5rPSZ0O++pbiZCeYeythiZIdLEfkDiQPKIaWk5hDg==",
+ "version": "3.4.6",
+ "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.6.tgz",
+ "integrity": "sha512-kaXnB3pfFxhAJl/Mp+XG1HJMyFqrL/xPqV7oXlpXn4AwMmm6VNgf0nllW8ksflmZANfI4kdo0bVn/FYSsAolPQ==",
"dev": true
},
"vue-style-loader": {
@@ -11622,9 +13694,9 @@
}
},
"vue-template-compiler": {
- "version": "2.6.11",
- "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz",
- "integrity": "sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA==",
+ "version": "2.6.12",
+ "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.12.tgz",
+ "integrity": "sha512-OzzZ52zS41YUbkCBfdXShQTe69j1gQDZ9HIX8miuC9C3rBCk9wIRjLiZZLrmX9V+Ftq/YEyv1JaVr5Y/hNtByg==",
"dev": true,
"requires": {
"de-indent": "^1.0.2",
@@ -11644,15 +13716,116 @@
"dev": true
},
"watchpack": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.2.tgz",
- "integrity": "sha512-ymVbbQP40MFTp+cNMvpyBpBtygHnPzPkHqoIwRRj/0B8KhqQwV8LaKjtbaxF2lK4vl8zN9wCxS46IFCU5K4W0g==",
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz",
+ "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==",
"dev": true,
"requires": {
- "chokidar": "^3.4.0",
+ "chokidar": "^3.4.1",
"graceful-fs": "^4.1.2",
"neo-async": "^2.5.0",
"watchpack-chokidar2": "^2.0.0"
+ },
+ "dependencies": {
+ "anymatch": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
+ "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "binary-extensions": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
+ "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
+ "dev": true,
+ "optional": true
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "chokidar": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz",
+ "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "anymatch": "~3.1.1",
+ "braces": "~3.0.2",
+ "fsevents": "~2.1.2",
+ "glob-parent": "~5.1.0",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.4.0"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "fsevents": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
+ "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+ "dev": true,
+ "optional": true
+ },
+ "is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "optional": true
+ },
+ "readdirp": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
+ "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ }
}
},
"watchpack-chokidar2": {
@@ -11721,9 +13894,9 @@
}
},
"webpack": {
- "version": "4.43.0",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.43.0.tgz",
- "integrity": "sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g==",
+ "version": "4.44.2",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz",
+ "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==",
"dev": true,
"requires": {
"@webassemblyjs/ast": "1.9.0",
@@ -11734,7 +13907,7 @@
"ajv": "^6.10.2",
"ajv-keywords": "^3.4.1",
"chrome-trace-event": "^1.0.2",
- "enhanced-resolve": "^4.1.0",
+ "enhanced-resolve": "^4.3.0",
"eslint-scope": "^4.0.3",
"json-parse-better-errors": "^1.0.2",
"loader-runner": "^2.4.0",
@@ -11747,14 +13920,14 @@
"schema-utils": "^1.0.0",
"tapable": "^1.1.3",
"terser-webpack-plugin": "^1.4.3",
- "watchpack": "^1.6.1",
+ "watchpack": "^1.7.4",
"webpack-sources": "^1.4.1"
},
"dependencies": {
"acorn": {
- "version": "6.4.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
- "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
+ "version": "6.4.2",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
+ "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==",
"dev": true
},
"cacache": {
@@ -11780,12 +13953,6 @@
"y18n": "^4.0.0"
}
},
- "commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true
- },
"eslint-scope": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
@@ -11834,16 +14001,16 @@
}
},
"terser-webpack-plugin": {
- "version": "1.4.4",
- "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz",
- "integrity": "sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA==",
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz",
+ "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==",
"dev": true,
"requires": {
"cacache": "^12.0.2",
"find-cache-dir": "^2.1.0",
"is-wsl": "^1.1.0",
"schema-utils": "^1.0.0",
- "serialize-javascript": "^3.1.0",
+ "serialize-javascript": "^4.0.0",
"source-map": "^0.6.1",
"terser": "^4.1.2",
"webpack-sources": "^1.4.0",
@@ -12086,12 +14253,12 @@
}
},
"debug": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
- "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+ "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
"dev": true,
"requires": {
- "ms": "^2.1.1"
+ "ms": "2.1.2"
}
},
"glob-parent": {
@@ -12138,12 +14305,6 @@
"ajv-keywords": "^3.1.0"
}
},
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "dev": true
- },
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
@@ -12381,124 +14542,131 @@
"dev": true
},
"yargs": {
- "version": "12.0.5",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
- "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
"dev": true,
"requires": {
- "cliui": "^4.0.0",
+ "cliui": "^6.0.0",
"decamelize": "^1.2.0",
- "find-up": "^3.0.0",
- "get-caller-file": "^1.0.1",
- "os-locale": "^3.0.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
- "require-main-filename": "^1.0.1",
+ "require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
- "string-width": "^2.0.0",
+ "string-width": "^4.2.0",
"which-module": "^2.0.0",
- "y18n": "^3.2.1 || ^4.0.0",
- "yargs-parser": "^11.1.1"
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
},
"dependencies": {
- "ansi-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
- "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
- "dev": true
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
},
"cliui": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
- "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
- "string-width": "^2.1.1",
- "strip-ansi": "^4.0.0",
- "wrap-ansi": "^2.0.0"
+ "color-name": "~1.1.4"
}
},
- "get-caller-file": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
- "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
- "require-main-filename": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
- "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
- "string-width": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
- "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"requires": {
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^4.0.0"
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
}
},
- "strip-ansi": {
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ },
+ "path-exists": {
"version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
- "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
+ "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
"dev": true,
"requires": {
- "ansi-regex": "^3.0.0"
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.0"
}
},
"wrap-ansi": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
- "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
"dev": true,
"requires": {
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
- "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
- "dev": true,
- "requires": {
- "number-is-nan": "^1.0.0"
- }
- },
- "string-width": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
- "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
- "dev": true,
- "requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "dev": true,
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- }
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
}
},
"yargs-parser": {
- "version": "11.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
- "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
"dev": true,
"requires": {
"camelcase": "^5.0.0",
diff --git a/src/package.json b/src/package.json
--- a/src/package.json
+++ b/src/package.json
@@ -11,27 +11,27 @@
"lint": "eslint --ext .js,.vue resources && stylelint \"resources/sass/*.scss\" \"resources/vue/*.vue\""
},
"devDependencies": {
- "@fortawesome/fontawesome-svg-core": "^1.2.29",
- "@fortawesome/free-brands-svg-icons": "^5.13.1",
- "@fortawesome/free-regular-svg-icons": "^5.13.1",
- "@fortawesome/free-solid-svg-icons": "^5.13.1",
+ "@fortawesome/fontawesome-svg-core": "^1.2.32",
+ "@fortawesome/free-brands-svg-icons": "^5.15.1",
+ "@fortawesome/free-regular-svg-icons": "^5.15.1",
+ "@fortawesome/free-solid-svg-icons": "^5.15.1",
"@fortawesome/vue-fontawesome": "^0.1.10",
"axios": "^0.19",
- "bootstrap": "^4.5.0",
+ "bootstrap": "^4.5.3",
"cross-env": "^7.0",
"eslint": "^6.8.0",
"eslint-plugin-vue": "^6.2.2",
"jquery": "^3.5.1",
- "laravel-mix": "^5.0.4",
+ "laravel-mix": "^5.0.6",
"popper.js": "^1.16.0",
"resolve-url-loader": "^2.3.1",
- "sass": "^1.26.9",
+ "sass": "^1.27.0",
"sass-loader": "^8.0.0",
- "stylelint": "^13.6.1",
+ "stylelint": "^13.7.2",
"stylelint-config-standard": "^20.0.0",
- "vue": "^2.6.11",
- "vue-router": "^3.3.4",
- "vue-template-compiler": "^2.6.11",
+ "vue": "^2.6.12",
+ "vue-router": "^3.4.6",
+ "vue-template-compiler": "^2.6.12",
"vuex": "^3.4.0"
}
}
diff --git a/src/phpunit.xml b/src/phpunit.xml
--- a/src/phpunit.xml
+++ b/src/phpunit.xml
@@ -13,6 +13,10 @@
<directory suffix="Test.php">tests/Unit</directory>
</testsuite>
+ <testsuite name="Functional">
+ <directory suffix="Test.php">tests/Functional</directory>
+ </testsuite>
+
<testsuite name="Feature">
<directory suffix="Test.php">tests/Feature</directory>
</testsuite>
diff --git a/src/resources/countries.php b/src/resources/countries.php
--- a/src/resources/countries.php
+++ b/src/resources/countries.php
@@ -1,6 +1,6 @@
<?php return [
'AF' => ['AFN','Afghanistan'],
- 'AX' => ['EUR','Åland Islands'],
+ 'AX' => ['EUR','Aland Islands'],
'AL' => ['ALL','Albania'],
'DZ' => ['DZD','Algeria'],
'AS' => ['USD','American Samoa'],
@@ -14,60 +14,62 @@
'AU' => ['AUD','Australia'],
'AT' => ['EUR','Austria'],
'AZ' => ['AZN','Azerbaijan'],
+ 'BS' => ['BSD','Bahamas'],
'BH' => ['BHD','Bahrain'],
'BD' => ['BDT','Bangladesh'],
- 'BB' => ['USD','Barbados'],
- 'BY' => ['BYN','Belarus'],
+ 'BB' => ['BBD','Barbados'],
+ 'BY' => ['BYR','Belarus'],
'BE' => ['EUR','Belgium'],
'BZ' => ['BZD','Belize'],
'BJ' => ['XOF','Benin'],
- 'BM' => ['USD','Bermuda'],
- 'BT' => ['INR','Bhutan'],
- 'BO' => ['BOV','Bolivia (Plurinational State of)'],
- 'BQ' => ['USD','Bonaire, Sint Eustatius and Saba'],
+ 'BM' => ['BMD','Bermuda'],
+ 'BT' => ['BTN','Bhutan'],
+ 'BO' => ['BOB','Bolivia'],
+ 'BQ' => ['USD','Bonaire, Saint Eustatius and Saba '],
'BA' => ['BAM','Bosnia and Herzegovina'],
'BW' => ['BWP','Botswana'],
'BV' => ['NOK','Bouvet Island'],
'BR' => ['BRL','Brazil'],
'IO' => ['USD','British Indian Ocean Territory'],
+ 'VG' => ['USD','British Virgin Islands'],
+ 'BN' => ['BND','Brunei'],
'BG' => ['BGN','Bulgaria'],
'BF' => ['XOF','Burkina Faso'],
'BI' => ['BIF','Burundi'],
- 'KH' => ['USD','Cambodia'],
+ 'KH' => ['KHR','Cambodia'],
'CM' => ['XAF','Cameroon'],
'CA' => ['CAD','Canada'],
+ 'CV' => ['CVE','Cape Verde'],
'KY' => ['KYD','Cayman Islands'],
'CF' => ['XAF','Central African Republic'],
'TD' => ['XAF','Chad'],
'CL' => ['CLP','Chile'],
'CN' => ['CNY','China'],
'CX' => ['AUD','Christmas Island'],
- 'CC' => ['AUD','Cocos (Keeling) Islands'],
- 'CO' => ['COU','Colombia'],
+ 'CC' => ['AUD','Cocos Islands'],
+ 'CO' => ['COP','Colombia'],
'KM' => ['KMF','Comoros'],
- 'CG' => ['XAF','Congo'],
- 'CD' => ['CDF','Congo, Democratic Republic of the'],
'CK' => ['NZD','Cook Islands'],
'CR' => ['CRC','Costa Rica'],
- 'CI' => ['XOF','Côte d\'Ivoire'],
'HR' => ['HRK','Croatia'],
'CU' => ['CUP','Cuba'],
- 'CW' => ['ANG','Curaçao'],
+ 'CW' => ['ANG','Curacao'],
'CY' => ['EUR','Cyprus'],
- 'CZ' => ['CZK','Czechia'],
+ 'CZ' => ['CZK','Czech Republic'],
+ 'CD' => ['CDF','Democratic Republic of the Congo'],
'DK' => ['DKK','Denmark'],
'DJ' => ['DJF','Djibouti'],
'DM' => ['XCD','Dominica'],
'DO' => ['DOP','Dominican Republic'],
+ 'TL' => ['USD','East Timor'],
'EC' => ['USD','Ecuador'],
'EG' => ['EGP','Egypt'],
'SV' => ['USD','El Salvador'],
'GQ' => ['XAF','Equatorial Guinea'],
'ER' => ['ERN','Eritrea'],
'EE' => ['EUR','Estonia'],
- 'SZ' => ['SZL','Eswatini'],
'ET' => ['ETB','Ethiopia'],
- 'FK' => ['FKP','Falkland Islands (Malvinas)'],
+ 'FK' => ['FKP','Falkland Islands'],
'FO' => ['DKK','Faroe Islands'],
'FJ' => ['FJD','Fiji'],
'FI' => ['EUR','Finland'],
@@ -76,6 +78,7 @@
'PF' => ['XPF','French Polynesia'],
'TF' => ['EUR','French Southern Territories'],
'GA' => ['XAF','Gabon'],
+ 'GM' => ['GMD','Gambia'],
'GE' => ['GEL','Georgia'],
'DE' => ['EUR','Germany'],
'GH' => ['GHS','Ghana'],
@@ -86,10 +89,11 @@
'GP' => ['EUR','Guadeloupe'],
'GU' => ['USD','Guam'],
'GT' => ['GTQ','Guatemala'],
+ 'GG' => ['GBP','Guernsey'],
'GN' => ['GNF','Guinea'],
'GW' => ['XOF','Guinea-Bissau'],
'GY' => ['GYD','Guyana'],
- 'HT' => ['USD','Haiti'],
+ 'HT' => ['HTG','Haiti'],
'HM' => ['AUD','Heard Island and McDonald Islands'],
'HN' => ['HNL','Honduras'],
'HK' => ['HKD','Hong Kong'],
@@ -97,12 +101,13 @@
'IS' => ['ISK','Iceland'],
'IN' => ['INR','India'],
'ID' => ['IDR','Indonesia'],
- 'IR' => ['IRR','Iran (Islamic Republic of)'],
+ 'IR' => ['IRR','Iran'],
'IQ' => ['IQD','Iraq'],
'IE' => ['EUR','Ireland'],
'IM' => ['GBP','Isle of Man'],
'IL' => ['ILS','Israel'],
'IT' => ['EUR','Italy'],
+ 'CI' => ['XOF','Ivory Coast'],
'JM' => ['JMD','Jamaica'],
'JP' => ['JPY','Japan'],
'JE' => ['GBP','Jersey'],
@@ -110,20 +115,20 @@
'KZ' => ['KZT','Kazakhstan'],
'KE' => ['KES','Kenya'],
'KI' => ['AUD','Kiribati'],
- 'KP' => ['KPW','Korea (Democratic People\'s Republic of)'],
- 'KR' => ['KRW','Korea, Republic of'],
+ 'XK' => ['EUR','Kosovo'],
'KW' => ['KWD','Kuwait'],
'KG' => ['KGS','Kyrgyzstan'],
- 'LA' => ['LAK','Lao People\'s Democratic Republic'],
+ 'LA' => ['LAK','Laos'],
'LV' => ['EUR','Latvia'],
'LB' => ['LBP','Lebanon'],
- 'LS' => ['ZAR','Lesotho'],
+ 'LS' => ['LSL','Lesotho'],
'LR' => ['LRD','Liberia'],
'LY' => ['LYD','Libya'],
'LI' => ['CHF','Liechtenstein'],
'LT' => ['EUR','Lithuania'],
'LU' => ['EUR','Luxembourg'],
'MO' => ['MOP','Macao'],
+ 'MK' => ['MKD','Macedonia'],
'MG' => ['MGA','Madagascar'],
'MW' => ['MWK','Malawi'],
'MY' => ['MYR','Malaysia'],
@@ -132,12 +137,12 @@
'MT' => ['EUR','Malta'],
'MH' => ['USD','Marshall Islands'],
'MQ' => ['EUR','Martinique'],
- 'MR' => ['MRU','Mauritania'],
+ 'MR' => ['MRO','Mauritania'],
'MU' => ['MUR','Mauritius'],
'YT' => ['EUR','Mayotte'],
- 'MX' => ['MXV','Mexico'],
- 'FM' => ['USD','Micronesia (Federated States of)'],
- 'MD' => ['MDL','Moldova, Republic of'],
+ 'MX' => ['MXN','Mexico'],
+ 'FM' => ['USD','Micronesia'],
+ 'MD' => ['MDL','Moldova'],
'MC' => ['EUR','Monaco'],
'MN' => ['MNT','Mongolia'],
'ME' => ['EUR','Montenegro'],
@@ -145,9 +150,10 @@
'MA' => ['MAD','Morocco'],
'MZ' => ['MZN','Mozambique'],
'MM' => ['MMK','Myanmar'],
- 'NA' => ['ZAR','Namibia'],
+ 'NA' => ['NAD','Namibia'],
'NR' => ['AUD','Nauru'],
'NP' => ['NPR','Nepal'],
+ 'NL' => ['EUR','Netherlands'],
'NC' => ['XPF','New Caledonia'],
'NZ' => ['NZD','New Zealand'],
'NI' => ['NIO','Nicaragua'],
@@ -155,14 +161,14 @@
'NG' => ['NGN','Nigeria'],
'NU' => ['NZD','Niue'],
'NF' => ['AUD','Norfolk Island'],
- 'MK' => ['MKD','North Macedonia'],
+ 'KP' => ['KPW','North Korea'],
'MP' => ['USD','Northern Mariana Islands'],
- 'NL' => ['EUR','The Netherlands'],
'NO' => ['NOK','Norway'],
'OM' => ['OMR','Oman'],
'PK' => ['PKR','Pakistan'],
'PW' => ['USD','Palau'],
- 'PA' => ['USD','Panama'],
+ 'PS' => ['ILS','Palestinian Territory'],
+ 'PA' => ['PAB','Panama'],
'PG' => ['PGK','Papua New Guinea'],
'PY' => ['PYG','Paraguay'],
'PE' => ['PEN','Peru'],
@@ -172,42 +178,49 @@
'PT' => ['EUR','Portugal'],
'PR' => ['USD','Puerto Rico'],
'QA' => ['QAR','Qatar'],
- 'RE' => ['EUR','Réunion'],
+ 'CG' => ['XAF','Republic of the Congo'],
+ 'RE' => ['EUR','Reunion'],
'RO' => ['RON','Romania'],
- 'RU' => ['RUB','Russian Federation'],
+ 'RU' => ['RUB','Russia'],
'RW' => ['RWF','Rwanda'],
- 'BL' => ['EUR','Saint Barthélemy'],
+ 'BL' => ['EUR','Saint Barthelemy'],
+ 'SH' => ['SHP','Saint Helena'],
'KN' => ['XCD','Saint Kitts and Nevis'],
'LC' => ['XCD','Saint Lucia'],
- 'MF' => ['EUR','Saint Martin (French part)'],
+ 'MF' => ['EUR','Saint Martin'],
'PM' => ['EUR','Saint Pierre and Miquelon'],
'VC' => ['XCD','Saint Vincent and the Grenadines'],
'WS' => ['WST','Samoa'],
'SM' => ['EUR','San Marino'],
+ 'ST' => ['STD','Sao Tome and Principe'],
'SA' => ['SAR','Saudi Arabia'],
'SN' => ['XOF','Senegal'],
'RS' => ['RSD','Serbia'],
'SC' => ['SCR','Seychelles'],
'SL' => ['SLL','Sierra Leone'],
'SG' => ['SGD','Singapore'],
- 'SX' => ['ANG','Sint Maarten (Dutch part)'],
+ 'SX' => ['ANG','Sint Maarten'],
'SK' => ['EUR','Slovakia'],
'SI' => ['EUR','Slovenia'],
'SB' => ['SBD','Solomon Islands'],
'SO' => ['SOS','Somalia'],
'ZA' => ['ZAR','South Africa'],
+ 'GS' => ['GBP','South Georgia and the South Sandwich Islands'],
+ 'KR' => ['KRW','South Korea'],
'SS' => ['SSP','South Sudan'],
'ES' => ['EUR','Spain'],
'LK' => ['LKR','Sri Lanka'],
'SD' => ['SDG','Sudan'],
'SR' => ['SRD','Suriname'],
+ 'SJ' => ['NOK','Svalbard and Jan Mayen'],
+ 'SZ' => ['SZL','Swaziland'],
'SE' => ['SEK','Sweden'],
- 'CH' => ['CHW','Switzerland'],
- 'SY' => ['SYP','Syrian Arab Republic'],
+ 'CH' => ['CHF','Switzerland'],
+ 'SY' => ['SYP','Syria'],
+ 'TW' => ['TWD','Taiwan'],
'TJ' => ['TJS','Tajikistan'],
- 'TZ' => ['TZS','Tanzania, United Republic of'],
+ 'TZ' => ['TZS','Tanzania'],
'TH' => ['THB','Thailand'],
- 'TL' => ['USD','Timor-Leste'],
'TG' => ['XOF','Togo'],
'TK' => ['NZD','Tokelau'],
'TO' => ['TOP','Tonga'],
@@ -217,22 +230,22 @@
'TM' => ['TMT','Turkmenistan'],
'TC' => ['USD','Turks and Caicos Islands'],
'TV' => ['AUD','Tuvalu'],
+ 'VI' => ['USD','U.S. Virgin Islands'],
'UG' => ['UGX','Uganda'],
'UA' => ['UAH','Ukraine'],
'AE' => ['AED','United Arab Emirates'],
- 'GB' => ['GBP','United Kingdom of Great Britain and Northern Ireland'],
- 'US' => ['USN','United States of America'],
+ 'GB' => ['GBP','United Kingdom'],
+ 'US' => ['USD','United States'],
'UM' => ['USD','United States Minor Outlying Islands'],
- 'UY' => ['UYW','Uruguay'],
+ 'UY' => ['UYU','Uruguay'],
'UZ' => ['UZS','Uzbekistan'],
'VU' => ['VUV','Vanuatu'],
- 'VE' => ['VES','Venezuela (Bolivarian Republic of)'],
- 'VN' => ['VND','Viet Nam'],
- 'VG' => ['USD','Virgin Islands (British)'],
- 'VI' => ['USD','Virgin Islands (U.S.)'],
+ 'VA' => ['EUR','Vatican'],
+ 'VE' => ['VEF','Venezuela'],
+ 'VN' => ['VND','Vietnam'],
'WF' => ['XPF','Wallis and Futuna'],
'EH' => ['MAD','Western Sahara'],
'YE' => ['YER','Yemen'],
- 'ZM' => ['ZMW','Zambia'],
+ 'ZM' => ['ZMK','Zambia'],
'ZW' => ['ZWL','Zimbabwe'],
];
diff --git a/src/resources/js/app.js b/src/resources/js/app.js
--- a/src/resources/js/app.js
+++ b/src/resources/js/app.js
@@ -59,6 +59,10 @@
localStorage.setItem('token', response.access_token)
axios.defaults.headers.common.Authorization = 'Bearer ' + response.access_token
+ if (response.email) {
+ store.state.authInfo = response
+ }
+
if (dashboard !== false) {
this.$router.push(store.state.afterLogin || { name: 'dashboard' })
}
@@ -186,7 +190,10 @@
},
clickRecord(event) {
if (!/^(a|button|svg|path)$/i.test(event.target.nodeName)) {
- $(event.target).closest('tr').find('a')[0].click()
+ let link = $(event.target).closest('tr').find('a')[0]
+ if (link) {
+ link.click()
+ }
}
},
domainStatusClass(domain) {
diff --git a/src/resources/lang/en/documents.php b/src/resources/lang/en/documents.php
--- a/src/resources/lang/en/documents.php
+++ b/src/resources/lang/en/documents.php
@@ -32,6 +32,8 @@
'receipt-filename' => ":site Receipt for :id",
'receipt-title' => "Receipt for :month :year",
'receipt-item-desc' => ":site Services",
+ 'receipt-refund' => "Refund",
+ 'receipt-chargeback' => "Chargeback",
'subtotal' => "Subtotal",
'vat' => "VAT (:rate%)",
diff --git a/src/resources/lang/en/transactions.php b/src/resources/lang/en/transactions.php
--- a/src/resources/lang/en/transactions.php
+++ b/src/resources/lang/en/transactions.php
@@ -5,17 +5,22 @@
'entitlement-billed' => ':sku_title for :object is billed at :amount',
'entitlement-deleted' => ':user_email deleted :sku_title for :object',
+ 'entitlement-created-short' => 'Added :sku_title for :object',
+ 'entitlement-billed-short' => 'Billed :sku_title for :object',
+ 'entitlement-deleted-short' => 'Deleted :sku_title for :object',
+
'wallet-award' => 'Bonus of :amount awarded to :wallet; :description',
+ 'wallet-chargeback' => ':amount was charged back from :wallet',
'wallet-credit' => ':amount was added to the balance of :wallet',
'wallet-debit' => ':amount was deducted from the balance of :wallet',
'wallet-penalty' => 'The balance of :wallet was reduced by :amount; :description',
-
- 'entitlement-created-short' => 'Added :sku_title for :object',
- 'entitlement-billed-short' => 'Billed :sku_title for :object',
- 'entitlement-deleted-short' => 'Deleted :sku_title for :object',
+ 'wallet-refund' => ':amount was refunded from the balance of :wallet',
+ 'wallet-refund' => ':amount was refunded from :wallet',
'wallet-award-short' => 'Bonus: :description',
+ 'wallet-chargeback-short' => 'Chargeback',
'wallet-credit-short' => 'Payment',
'wallet-debit-short' => 'Deduction',
'wallet-penalty-short' => 'Charge: :description',
+ 'wallet-refund-short' => 'Refund: :description',
];
diff --git a/src/resources/sass/app.scss b/src/resources/sass/app.scss
--- a/src/resources/sass/app.scss
+++ b/src/resources/sass/app.scss
@@ -88,7 +88,7 @@
&.fadeOut {
visibility: hidden;
opacity: 0;
- transition: visibility 400ms linear, opacity 400ms linear;
+ transition: visibility 300ms linear, opacity 300ms linear;
}
}
diff --git a/src/resources/vue/Admin/Dashboard.vue b/src/resources/vue/Admin/Dashboard.vue
--- a/src/resources/vue/Admin/Dashboard.vue
+++ b/src/resources/vue/Admin/Dashboard.vue
@@ -15,17 +15,23 @@
<tr>
<th scope="col">Primary Email</th>
<th scope="col">ID</th>
+ <th scope="col" class="d-none d-md-table-cell">Created</th>
+ <th scope="col" class="d-none d-md-table-cell">Deleted</th>
</tr>
</thead>
<tbody>
- <tr v-for="user in users" :id="'user' + user.id" :key="user.id">
- <td>
+ <tr v-for="user in users" :id="'user' + user.id" :key="user.id" :class="user.isDeleted ? 'text-secondary' : ''">
+ <td class="text-nowrap">
<svg-icon icon="user" :class="$root.userStatusClass(user)" :title="$root.userStatusText(user)"></svg-icon>
- <router-link :to="{ path: 'user/' + user.id }">{{ user.email }}</router-link>
+ <router-link v-if="!user.isDeleted" :to="{ path: 'user/' + user.id }">{{ user.email }}</router-link>
+ <span v-if="user.isDeleted">{{ user.email }}</span>
</td>
<td>
- <router-link :to="{ path: 'user/' + user.id }">{{ user.id }}</router-link>
+ <router-link v-if="!user.isDeleted" :to="{ path: 'user/' + user.id }">{{ user.id }}</router-link>
+ <span v-if="user.isDeleted">{{ user.id }}</span>
</td>
+ <td class="d-none d-md-table-cell">{{ toDate(user.created_at) }}</td>
+ <td class="d-none d-md-table-cell">{{ toDate(user.deleted_at) }}</td>
</tr>
</tbody>
</table>
@@ -65,7 +71,7 @@
axios.get('/api/v4/users', { params: { search: this.search } })
.then(response => {
- if (response.data.count == 1) {
+ if (response.data.count == 1 && !response.data.list[0].isDeleted) {
this.$router.push({ name: 'user', params: { user: response.data.list[0].id } })
return
}
@@ -77,6 +83,11 @@
this.users = response.data.list
})
.catch(this.$root.errorHandler)
+ },
+ toDate(datetime) {
+ if (datetime) {
+ return datetime.split(' ')[0]
+ }
}
}
}
diff --git a/src/resources/vue/Admin/User.vue b/src/resources/vue/Admin/User.vue
--- a/src/resources/vue/Admin/User.vue
+++ b/src/resources/vue/Admin/User.vue
@@ -244,7 +244,8 @@
<tr v-for="item in users" :id="'user' + item.id" :key="item.id" @click="$root.clickRecord">
<td>
<svg-icon icon="user" :class="$root.userStatusClass(item)" :title="$root.userStatusText(item)"></svg-icon>
- <router-link :to="{ path: '/user/' + item.id }">{{ item.email }}</router-link>
+ <router-link v-if="item.id != user.id" :to="{ path: '/user/' + item.id }">{{ item.email }}</router-link>
+ <span v-else>{{ item.email }}</span>
</td>
</tr>
</tbody>
@@ -479,9 +480,7 @@
// TODO: Multiple wallets
axios.get('/api/v4/users?owner=' + user_id)
.then(response => {
- this.users = response.data.list.filter(user => {
- return user.id != user_id;
- })
+ this.users = response.data.list;
})
// Fetch domains
diff --git a/src/resources/vue/App.vue b/src/resources/vue/App.vue
--- a/src/resources/vue/App.vue
+++ b/src/resources/vue/App.vue
@@ -19,10 +19,9 @@
axios.get('/api/auth/info?refresh_token=1')
.then(response => {
- this.isLoading = false
- this.$root.stopLoading()
this.$root.loginUser(response.data, false)
- this.$store.state.authInfo = response.data
+ this.$root.stopLoading()
+ this.isLoading = false
})
.catch(error => {
// Release lock on the router-view, otherwise links (e.g. Logout) will not work
diff --git a/src/resources/vue/Dashboard.vue b/src/resources/vue/Dashboard.vue
--- a/src/resources/vue/Dashboard.vue
+++ b/src/resources/vue/Dashboard.vue
@@ -34,22 +34,9 @@
}
},
mounted() {
- const authInfo = this.$store.state.isLoggedIn ? this.$store.state.authInfo : null
-
- if (authInfo) {
- this.status = authInfo.statusInfo
- this.getBalance(authInfo)
- } else {
- this.$root.startLoading()
- axios.get('/api/auth/info')
- .then(response => {
- this.$store.state.authInfo = response.data
- this.status = response.data.statusInfo
- this.getBalance(response.data)
- this.$root.stopLoading()
- })
- .catch(this.$root.errorHandler)
- }
+ const authInfo = this.$store.state.authInfo
+ this.status = authInfo.statusInfo
+ this.getBalance(authInfo)
},
methods: {
getBalance(authInfo) {
diff --git a/src/resources/vue/Widgets/ListInput.vue b/src/resources/vue/Widgets/ListInput.vue
--- a/src/resources/vue/Widgets/ListInput.vue
+++ b/src/resources/vue/Widgets/ListInput.vue
@@ -27,14 +27,28 @@
list: { type: Array, default: () => [] },
id: { type: String, default: '' }
},
+ mounted() {
+ this.input = $(this.$el).find('.main-input')[0]
+
+ // On form submit add the text from main input to the list
+ // Users tend to forget about pressing the "plus" button
+ // Note: We can't use form.onsubmit (too late)
+ // Note: Use of input.onblur has been proven to be problematic
+ // TODO: What with forms that have no submit button?
+ $(this.$el).closest('form').find('button[type=submit]').on('click', () => {
+ this.addItem(false)
+ })
+ },
methods: {
- addItem() {
- let input = $(this.$el).find('.main-input')
- let value = input.val()
+ addItem(focus) {
+ let value = this.input.value
if (value) {
this.list.push(value)
- input.val('').focus()
+ this.input.value = ''
+ if (focus !== false) {
+ this.input.focus()
+ }
}
},
deleteItem(index) {
diff --git a/src/tests/Browser.php b/src/tests/Browser.php
--- a/src/tests/Browser.php
+++ b/src/tests/Browser.php
@@ -119,7 +119,24 @@
{
$element = $this->resolver->findOrFail($selector);
- Assert::assertTrue(strpos($element->getText(), $text) !== false, "No expected text in [$selector]");
+ if ($text === '') {
+ Assert::assertTrue((string) $element->getText() === $text, "Element's text is not empty [$selector]");
+ } else {
+ Assert::assertTrue(strpos($element->getText(), $text) !== false, "No expected text in [$selector]");
+ }
+
+ return $this;
+ }
+
+ /**
+ * Assert that the given element contains specified text,
+ * no matter it's displayed or not - using a regular expression.
+ */
+ public function assertTextRegExp($selector, $regexp)
+ {
+ $element = $this->resolver->findOrFail($selector);
+
+ Assert::assertRegExp($regexp, $element->getText(), "No expected text in [$selector]");
return $this;
}
diff --git a/src/tests/Browser/Admin/DashboardTest.php b/src/tests/Browser/Admin/DashboardTest.php
--- a/src/tests/Browser/Admin/DashboardTest.php
+++ b/src/tests/Browser/Admin/DashboardTest.php
@@ -2,12 +2,12 @@
namespace Tests\Browser\Admin;
+use Illuminate\Support\Facades\Queue;
use Tests\Browser;
use Tests\Browser\Components\Toast;
use Tests\Browser\Pages\Dashboard;
use Tests\Browser\Pages\Home;
use Tests\TestCaseDusk;
-use Illuminate\Foundation\Testing\DatabaseMigrations;
class DashboardTest extends TestCaseDusk
{
@@ -21,6 +21,9 @@
$jack = $this->getTestUser('jack@kolab.org');
$jack->setSetting('external_email', null);
+
+ $this->deleteTestUser('test@testsearch.com');
+ $this->deleteTestDomain('testsearch.com');
}
/**
@@ -31,6 +34,9 @@
$jack = $this->getTestUser('jack@kolab.org');
$jack->setSetting('external_email', null);
+ $this->deleteTestUser('test@testsearch.com');
+ $this->deleteTestDomain('testsearch.com');
+
parent::tearDown();
}
@@ -60,9 +66,24 @@
$browser->type('@search input', 'john.doe.external@gmail.com')
->click('@search form button')
->assertToast(Toast::TYPE_INFO, '2 user accounts have been found.')
- ->whenAvailable('@search table', function (Browser $browser) {
- $browser->assertElementsCount('tbody tr', 2);
- // TODO: Assert table content
+ ->whenAvailable('@search table', function (Browser $browser) use ($john, $jack) {
+ $browser->assertElementsCount('tbody tr', 2)
+ ->with('tbody tr:first-child', function (Browser $browser) use ($jack) {
+ $browser->assertSeeIn('td:nth-child(1) a', $jack->email)
+ ->assertSeeIn('td:nth-child(2) a', $jack->id)
+ ->assertVisible('td:nth-child(3)')
+ ->assertTextRegExp('td:nth-child(3)', '/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/')
+ ->assertVisible('td:nth-child(4)')
+ ->assertText('td:nth-child(4)', '');
+ })
+ ->with('tbody tr:last-child', function (Browser $browser) use ($john) {
+ $browser->assertSeeIn('td:nth-child(1) a', $john->email)
+ ->assertSeeIn('td:nth-child(2) a', $john->id)
+ ->assertVisible('td:nth-child(3)')
+ ->assertTextRegExp('td:nth-child(3)', '/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/')
+ ->assertVisible('td:nth-child(4)')
+ ->assertText('td:nth-child(4)', '');
+ });
});
// Test search with single record result -> redirect to user page
@@ -76,4 +97,44 @@
});
});
}
+
+ /**
+ * Test user search deleted user/domain
+ */
+ public function testSearchDeleted(): void
+ {
+ $this->browse(function (Browser $browser) {
+ $browser->visit(new Home())
+ ->submitLogon('jeroen@jeroen.jeroen', 'jeroen', true)
+ ->on(new Dashboard())
+ ->assertFocused('@search input')
+ ->assertMissing('@search table');
+
+ // Deleted users/domains
+ $domain = $this->getTestDomain('testsearch.com', ['type' => \App\Domain::TYPE_EXTERNAL]);
+ $user = $this->getTestUser('test@testsearch.com');
+ $plan = \App\Plan::where('title', 'group')->first();
+ $user->assignPlan($plan, $domain);
+ $user->setAliases(['alias@testsearch.com']);
+ Queue::fake();
+ $user->delete();
+
+ // Test search with multiple results
+ $browser->type('@search input', 'testsearch.com')
+ ->click('@search form button')
+ ->assertToast(Toast::TYPE_INFO, '1 user accounts have been found.')
+ ->whenAvailable('@search table', function (Browser $browser) use ($user) {
+ $browser->assertElementsCount('tbody tr', 1)
+ ->assertVisible('tbody tr:first-child.text-secondary')
+ ->with('tbody tr:first-child', function (Browser $browser) use ($user) {
+ $browser->assertSeeIn('td:nth-child(1) span', $user->email)
+ ->assertSeeIn('td:nth-child(2) span', $user->id)
+ ->assertVisible('td:nth-child(3)')
+ ->assertTextRegExp('td:nth-child(3)', '/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/')
+ ->assertVisible('td:nth-child(4)')
+ ->assertTextRegExp('td:nth-child(4)', '/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/');
+ });
+ });
+ });
+ }
}
diff --git a/src/tests/Browser/Admin/UserFinancesTest.php b/src/tests/Browser/Admin/UserFinancesTest.php
--- a/src/tests/Browser/Admin/UserFinancesTest.php
+++ b/src/tests/Browser/Admin/UserFinancesTest.php
@@ -122,10 +122,13 @@
// Now we go to Ned's info page, he's a controller on John's wallet
$this->browse(function (Browser $browser) {
$ned = $this->getTestUser('ned@kolab.org');
+ $wallet = $ned->wallets()->first();
+ $wallet->balance = 0;
+ $wallet->save();
$page = new UserPage($ned->id);
$browser->click('@nav #tab-users')
- ->click('@user-users tbody tr:nth-child(3) td:first-child a')
+ ->click('@user-users tbody tr:nth-child(4) td:first-child a')
->on($page)
->with('@user-finances', function (Browser $browser) {
$browser->waitUntilMissing('.app-loader')
diff --git a/src/tests/Browser/Admin/UserTest.php b/src/tests/Browser/Admin/UserTest.php
--- a/src/tests/Browser/Admin/UserTest.php
+++ b/src/tests/Browser/Admin/UserTest.php
@@ -102,7 +102,7 @@
->assertSeeIn('.row:nth-child(6) label', 'External email')
->assertMissing('.row:nth-child(6) #external_email a')
->assertSeeIn('.row:nth-child(7) label', 'Country')
- ->assertSeeIn('.row:nth-child(7) #country', 'United States of America');
+ ->assertSeeIn('.row:nth-child(7) #country', 'United States');
});
// Some tabs are loaded in background, wait a second
@@ -198,7 +198,7 @@
->assertSeeIn('.row:nth-child(8) label', 'Address')
->assertSeeIn('.row:nth-child(8) #billing_address', $john->getSetting('billing_address'))
->assertSeeIn('.row:nth-child(9) label', 'Country')
- ->assertSeeIn('.row:nth-child(9) #country', 'United States of America');
+ ->assertSeeIn('.row:nth-child(9) #country', 'United States');
});
// Some tabs are loaded in background, wait a second
@@ -243,16 +243,18 @@
});
// Assert Users tab
- $browser->assertSeeIn('@nav #tab-users', 'Users (3)')
+ $browser->assertSeeIn('@nav #tab-users', 'Users (4)')
->click('@nav #tab-users')
->with('@user-users table', function (Browser $browser) {
- $browser->assertElementsCount('tbody tr', 3)
+ $browser->assertElementsCount('tbody tr', 4)
->assertSeeIn('tbody tr:nth-child(1) td:first-child a', 'jack@kolab.org')
->assertVisible('tbody tr:nth-child(1) td:first-child svg.text-success')
->assertSeeIn('tbody tr:nth-child(2) td:first-child a', 'joe@kolab.org')
->assertVisible('tbody tr:nth-child(2) td:first-child svg.text-success')
- ->assertSeeIn('tbody tr:nth-child(3) td:first-child a', 'ned@kolab.org')
+ ->assertSeeIn('tbody tr:nth-child(3) td:first-child span', 'john@kolab.org')
->assertVisible('tbody tr:nth-child(3) td:first-child svg.text-success')
+ ->assertSeeIn('tbody tr:nth-child(4) td:first-child a', 'ned@kolab.org')
+ ->assertVisible('tbody tr:nth-child(4) td:first-child svg.text-success')
->assertMissing('tfoot');
});
});
@@ -262,7 +264,7 @@
$ned = $this->getTestUser('ned@kolab.org');
$page = new UserPage($ned->id);
- $browser->click('@user-users tbody tr:nth-child(3) td:first-child a')
+ $browser->click('@user-users tbody tr:nth-child(4) td:first-child a')
->on($page);
// Assert main info box content
diff --git a/src/tests/Browser/DomainTest.php b/src/tests/Browser/DomainTest.php
--- a/src/tests/Browser/DomainTest.php
+++ b/src/tests/Browser/DomainTest.php
@@ -65,14 +65,9 @@
$browser->assertSeeIn('pre', $domain->namespace)
->assertSeeIn('pre', $domain->hash())
->click('button')
- ->assertToast(Toast::TYPE_ERROR, 'Domain ownership verification failed.');
-
- // Make sure the domain is confirmed now
- $domain->status |= Domain::STATUS_CONFIRMED;
- $domain->save();
-
- $browser->click('button')
->assertToast(Toast::TYPE_SUCCESS, 'Domain verified successfully.');
+
+ // TODO: Test scenario when a domain confirmation failed
})
->whenAvailable('@config', function ($browser) use ($domain) {
$browser->assertSeeIn('pre', $domain->namespace);
diff --git a/src/tests/Browser/StatusTest.php b/src/tests/Browser/StatusTest.php
--- a/src/tests/Browser/StatusTest.php
+++ b/src/tests/Browser/StatusTest.php
@@ -54,16 +54,20 @@
{
// Unconfirmed domain and user
$domain = Domain::where('namespace', 'kolab.org')->first();
+
if ($domain->isConfirmed()) {
$domain->status ^= Domain::STATUS_CONFIRMED;
$domain->save();
}
$john = $this->getTestUser('john@kolab.org');
+
$john->created_at = Carbon::now();
+
if ($john->isImapReady()) {
$john->status ^= User::STATUS_IMAP_READY;
}
+
$john->save();
$this->browse(function ($browser) use ($john, $domain) {
@@ -113,10 +117,13 @@
$domain->status ^= Domain::STATUS_CONFIRMED;
$domain->save();
}
+
$john->created_at = Carbon::now()->subSeconds(3600);
+
if ($john->isImapReady()) {
$john->status ^= User::STATUS_IMAP_READY;
}
+
$john->save();
$this->browse(function ($browser) use ($john, $domain) {
@@ -153,6 +160,18 @@
$domain->status = Domain::STATUS_NEW | Domain::STATUS_ACTIVE | Domain::STATUS_LDAP_READY;
$domain->save();
+ // side-step
+ $this->assertFalse($domain->isNew());
+ $this->assertTrue($domain->isActive());
+ $this->assertTrue($domain->isLdapReady());
+ $this->assertTrue($domain->isExternal());
+
+ $this->assertFalse($domain->isHosted());
+ $this->assertFalse($domain->isConfirmed());
+ $this->assertFalse($domain->isVerified());
+ $this->assertFalse($domain->isSuspended());
+ $this->assertFalse($domain->isDeleted());
+
$this->browse(function ($browser) use ($domain) {
// Test auto-refresh
$browser->on(new Dashboard())
diff --git a/src/tests/Feature/Backends/LDAPTest.php b/src/tests/Feature/Backends/LDAPTest.php
--- a/src/tests/Feature/Backends/LDAPTest.php
+++ b/src/tests/Feature/Backends/LDAPTest.php
@@ -221,6 +221,24 @@
$this->assertSame(null, LDAP::getUser($user->email));
}
+ /**
+ * Test handling errors on user creation
+ *
+ * @group ldap
+ */
+ public function testCreateUserException(): void
+ {
+ $this->expectException(\Exception::class);
+ $this->expectExceptionMessageMatches('/Failed to create user/');
+
+ $user = new User([
+ 'email' => 'test-non-existing-ldap@non-existing.org',
+ 'status' => User::STATUS_ACTIVE,
+ ]);
+
+ LDAP::createUser($user);
+ }
+
/**
* Test handling update of a non-existing domain
*
diff --git a/src/tests/Feature/BillingTest.php b/src/tests/Feature/BillingTest.php
--- a/src/tests/Feature/BillingTest.php
+++ b/src/tests/Feature/BillingTest.php
@@ -82,7 +82,10 @@
*/
public function testFullTrial(): void
{
- $this->backdateEntitlements($this->wallet->entitlements, Carbon::now()->subMonthsWithoutOverflow(1));
+ $this->backdateEntitlements(
+ $this->wallet->entitlements,
+ Carbon::now()->subMonthsWithoutOverflow(1)
+ );
$this->assertEquals(999, $this->wallet->expectedCharges());
}
diff --git a/src/tests/Feature/Console/UserForceDeleteTest.php b/src/tests/Feature/Console/UserForceDeleteTest.php
new file mode 100644
--- /dev/null
+++ b/src/tests/Feature/Console/UserForceDeleteTest.php
@@ -0,0 +1,98 @@
+<?php
+
+namespace Tests\Feature\Console;
+
+use Illuminate\Support\Facades\Queue;
+use Tests\TestCase;
+
+class UserForceDeleteTest extends TestCase
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function setUp(): void
+ {
+ parent::setUp();
+
+ $this->deleteTestUser('user@force-delete.com');
+ $this->deleteTestDomain('force-delete.com');
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function tearDown(): void
+ {
+ $this->deleteTestUser('user@force-delete.com');
+ $this->deleteTestDomain('force-delete.com');
+
+ parent::tearDown();
+ }
+
+ /**
+ * Test the command
+ */
+ public function testHandle(): void
+ {
+ // Non-existing user
+ $this->artisan('user:force-delete unknown@unknown.org')
+ ->assertExitCode(1);
+
+ Queue::fake();
+ $user = $this->getTestUser('user@force-delete.com');
+ $domain = $this->getTestDomain('force-delete.com', [
+ 'status' => \App\Domain::STATUS_NEW,
+ 'type' => \App\Domain::TYPE_HOSTED,
+ ]);
+ $package_kolab = \App\Package::where('title', 'kolab')->first();
+ $package_domain = \App\Package::where('title', 'domain-hosting')->first();
+ $user->assignPackage($package_kolab);
+ $domain->assignPackage($package_domain, $user);
+ $wallet = $user->wallets()->first();
+ $entitlements = $wallet->entitlements->pluck('id')->all();
+
+ $this->assertCount(5, $entitlements);
+
+ // Non-deleted user
+ $this->artisan('user:force-delete user@force-delete.com')
+ ->assertExitCode(1);
+
+ $user->delete();
+
+ $this->assertTrue($user->trashed());
+ $this->assertTrue($domain->fresh()->trashed());
+
+ // Deleted user
+ $this->artisan('user:force-delete user@force-delete.com')
+ ->assertExitCode(0);
+
+ $this->assertCount(
+ 0,
+ \App\User::withTrashed()->where('email', 'user@force-delete.com')->get()
+ );
+ $this->assertCount(
+ 0,
+ \App\Domain::withTrashed()->where('namespace', 'force-delete.com')->get()
+ );
+ $this->assertCount(
+ 0,
+ \App\Wallet::where('id', $wallet->id)->get()
+ );
+ $this->assertCount(
+ 0,
+ \App\Entitlement::withTrashed()->where('wallet_id', $wallet->id)->get()
+ );
+ $this->assertCount(
+ 0,
+ \App\Entitlement::withTrashed()->where('entitleable_id', $user->id)->get()
+ );
+ $this->assertCount(
+ 0,
+ \App\Transaction::whereIn('object_id', $entitlements)
+ ->where('object_type', \App\Entitlement::class)
+ ->get()
+ );
+
+ // TODO: Test that it also deletes users in a group account
+ }
+}
diff --git a/src/tests/Feature/Controller/Admin/UsersTest.php b/src/tests/Feature/Controller/Admin/UsersTest.php
--- a/src/tests/Feature/Controller/Admin/UsersTest.php
+++ b/src/tests/Feature/Controller/Admin/UsersTest.php
@@ -18,6 +18,8 @@
self::useAdminUrl();
$this->deleteTestUser('UsersControllerTest1@userscontroller.com');
+ $this->deleteTestUser('test@testsearch.com');
+ $this->deleteTestDomain('testsearch.com');
$jack = $this->getTestUser('jack@kolab.org');
$jack->setSetting('external_email', null);
@@ -29,6 +31,8 @@
public function tearDown(): void
{
$this->deleteTestUser('UsersControllerTest1@userscontroller.com');
+ $this->deleteTestUser('test@testsearch.com');
+ $this->deleteTestDomain('testsearch.com');
$jack = $this->getTestUser('jack@kolab.org');
$jack->setSetting('external_email', null);
@@ -146,6 +150,48 @@
$this->assertSame(0, $json['count']);
$this->assertCount(0, $json['list']);
+
+ // Deleted users/domains
+ $domain = $this->getTestDomain('testsearch.com', ['type' => \App\Domain::TYPE_EXTERNAL]);
+ $user = $this->getTestUser('test@testsearch.com');
+ $plan = \App\Plan::where('title', 'group')->first();
+ $user->assignPlan($plan, $domain);
+ $user->setAliases(['alias@testsearch.com']);
+ Queue::fake();
+ $user->delete();
+
+ $response = $this->actingAs($admin)->get("api/v4/users?search=test@testsearch.com");
+ $response->assertStatus(200);
+
+ $json = $response->json();
+
+ $this->assertSame(1, $json['count']);
+ $this->assertCount(1, $json['list']);
+ $this->assertSame($user->id, $json['list'][0]['id']);
+ $this->assertSame($user->email, $json['list'][0]['email']);
+ $this->assertTrue($json['list'][0]['isDeleted']);
+
+ $response = $this->actingAs($admin)->get("api/v4/users?search=alias@testsearch.com");
+ $response->assertStatus(200);
+
+ $json = $response->json();
+
+ $this->assertSame(1, $json['count']);
+ $this->assertCount(1, $json['list']);
+ $this->assertSame($user->id, $json['list'][0]['id']);
+ $this->assertSame($user->email, $json['list'][0]['email']);
+ $this->assertTrue($json['list'][0]['isDeleted']);
+
+ $response = $this->actingAs($admin)->get("api/v4/users?search=testsearch.com");
+ $response->assertStatus(200);
+
+ $json = $response->json();
+
+ $this->assertSame(1, $json['count']);
+ $this->assertCount(1, $json['list']);
+ $this->assertSame($user->id, $json['list'][0]['id']);
+ $this->assertSame($user->email, $json['list'][0]['email']);
+ $this->assertTrue($json['list'][0]['isDeleted']);
}
/**
diff --git a/src/tests/Feature/Controller/AuthTest.php b/src/tests/Feature/Controller/AuthTest.php
--- a/src/tests/Feature/Controller/AuthTest.php
+++ b/src/tests/Feature/Controller/AuthTest.php
@@ -101,10 +101,26 @@
$this->assertSame('Invalid username or password.', $json['message']);
// Valid user+password
+ $user = $this->getTestUser('john@kolab.org');
$post = ['email' => 'john@kolab.org', 'password' => 'simple123'];
$response = $this->post("api/auth/login", $post);
$json = $response->json();
+ $response->assertStatus(200);
+ $this->assertTrue(!empty($json['access_token']));
+ $this->assertEquals(\config('jwt.ttl') * 60, $json['expires_in']);
+ $this->assertEquals('bearer', $json['token_type']);
+ $this->assertEquals($user->id, $json['id']);
+ $this->assertEquals($user->email, $json['email']);
+ $this->assertTrue(is_array($json['statusInfo']));
+ $this->assertTrue(is_array($json['settings']));
+ $this->assertTrue(is_array($json['aliases']));
+
+ // Valid user+password (upper-case)
+ $post = ['email' => 'John@Kolab.org', 'password' => 'simple123'];
+ $response = $this->post("api/auth/login", $post);
+ $json = $response->json();
+
$response->assertStatus(200);
$this->assertTrue(!empty($json['access_token']));
$this->assertEquals(\config('jwt.ttl') * 60, $json['expires_in']);
diff --git a/src/tests/Feature/Controller/DomainsTest.php b/src/tests/Feature/Controller/DomainsTest.php
--- a/src/tests/Feature/Controller/DomainsTest.php
+++ b/src/tests/Feature/Controller/DomainsTest.php
@@ -229,14 +229,14 @@
$json = $response->json();
$this->assertTrue($json['isVerified']);
- $this->assertFalse($json['isReady']);
+ $this->assertTrue($json['isReady']);
$this->assertCount(4, $json['process']);
$this->assertSame('domain-verified', $json['process'][2]['label']);
$this->assertSame(true, $json['process'][2]['state']);
$this->assertSame('domain-confirmed', $json['process'][3]['label']);
- $this->assertSame(false, $json['process'][3]['state']);
- $this->assertSame('error', $json['status']);
- $this->assertSame('Failed to verify an ownership of a domain.', $json['message']);
+ $this->assertSame(true, $json['process'][3]['state']);
+ $this->assertSame('success', $json['status']);
+ $this->assertSame('Setup process finished successfully.', $json['message']);
// TODO: Test completing all process steps
}
diff --git a/src/tests/Feature/Controller/PasswordResetTest.php b/src/tests/Feature/Controller/PasswordResetTest.php
--- a/src/tests/Feature/Controller/PasswordResetTest.php
+++ b/src/tests/Feature/Controller/PasswordResetTest.php
@@ -304,20 +304,24 @@
$json = $response->json();
$response->assertStatus(200);
- $this->assertCount(4, $json);
$this->assertSame('success', $json['status']);
$this->assertSame('bearer', $json['token_type']);
$this->assertTrue(!empty($json['expires_in']) && is_int($json['expires_in']) && $json['expires_in'] > 0);
$this->assertNotEmpty($json['access_token']);
+ $this->assertSame($user->email, $json['email']);
+ $this->assertSame($user->id, $json['id']);
- Queue::assertPushed(\App\Jobs\UserUpdate::class, 1);
- Queue::assertPushed(\App\Jobs\UserUpdate::class, function ($job) use ($user) {
- $job_user = TestCase::getObjectProperty($job, 'user');
+ Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 1);
- return $job_user->id == $user->id
- && $job_user->email == $user->email
- && $job_user->password_ldap != $user->password_ldap;
- });
+ Queue::assertPushed(
+ \App\Jobs\User\UpdateJob::class,
+ function ($job) use ($user) {
+ $userEmail = TestCase::getObjectProperty($job, 'userEmail');
+ $userId = TestCase::getObjectProperty($job, 'userId');
+
+ return $userEmail == $user->email && $userId == $user->id;
+ }
+ );
// Check if the code has been removed
$this->assertNull(VerificationCode::find($code->code));
diff --git a/src/tests/Feature/Controller/PaymentsMollieTest.php b/src/tests/Feature/Controller/PaymentsMollieTest.php
--- a/src/tests/Feature/Controller/PaymentsMollieTest.php
+++ b/src/tests/Feature/Controller/PaymentsMollieTest.php
@@ -34,8 +34,12 @@
Payment::where('wallet_id', $wallet->id)->delete();
Wallet::where('id', $wallet->id)->update(['balance' => 0]);
WalletSetting::where('wallet_id', $wallet->id)->delete();
- Transaction::where('object_id', $wallet->id)
- ->where('type', Transaction::WALLET_CREDIT)->delete();
+ $types = [
+ Transaction::WALLET_CREDIT,
+ Transaction::WALLET_REFUND,
+ Transaction::WALLET_CHARGEBACK,
+ ];
+ Transaction::where('object_id', $wallet->id)->whereIn('type', $types)->delete();
}
/**
@@ -48,8 +52,12 @@
Payment::where('wallet_id', $wallet->id)->delete();
Wallet::where('id', $wallet->id)->update(['balance' => 0]);
WalletSetting::where('wallet_id', $wallet->id)->delete();
- Transaction::where('object_id', $wallet->id)
- ->where('type', Transaction::WALLET_CREDIT)->delete();
+ $types = [
+ Transaction::WALLET_CREDIT,
+ Transaction::WALLET_REFUND,
+ Transaction::WALLET_CHARGEBACK,
+ ];
+ Transaction::where('object_id', $wallet->id)->whereIn('type', $types)->delete();
parent::tearDown();
}
@@ -569,7 +577,162 @@
return $job_payment->id === $payment->id;
});
- $responseStack = $this->unmockMollie();
+ $this->unmockMollie();
+ }
+
+ /**
+ * Test refund/chargeback handling by the webhook
+ *
+ * @group mollie
+ */
+ public function testRefundAndChargeback(): void
+ {
+ Bus::fake();
+
+ $user = $this->getTestUser('john@kolab.org');
+ $wallet = $user->wallets()->first();
+ $wallet->transactions()->delete();
+
+ $mollie = PaymentProvider::factory('mollie');
+
+ // Create a paid payment
+ $payment = Payment::create([
+ 'id' => 'tr_123456',
+ 'status' => PaymentProvider::STATUS_PAID,
+ 'amount' => 123,
+ 'type' => PaymentProvider::TYPE_ONEOFF,
+ 'wallet_id' => $wallet->id,
+ 'provider' => 'mollie',
+ 'description' => 'test',
+ ]);
+
+ // Test handling a refund by the webhook
+
+ $mollie_response1 = [
+ "resource" => "payment",
+ "id" => $payment->id,
+ "status" => "paid",
+ // Status is not enough, paidAt is used to distinguish the state
+ "paidAt" => date('c'),
+ "mode" => "test",
+ "_links" => [
+ "refunds" => [
+ "href" => "https://api.mollie.com/v2/payments/{$payment->id}/refunds",
+ "type" => "application/hal+json"
+ ]
+ ]
+ ];
+
+ $mollie_response2 = [
+ "count" => 1,
+ "_links" => [],
+ "_embedded" => [
+ "refunds" => [
+ [
+ "resource" => "refund",
+ "id" => "re_123456",
+ "status" => \Mollie\Api\Types\RefundStatus::STATUS_REFUNDED,
+ "paymentId" => $payment->id,
+ "description" => "refund desc",
+ "amount" => [
+ "currency" => "CHF",
+ "value" => "1.01",
+ ],
+ ]
+ ]
+ ]
+ ];
+
+ // We'll trigger the webhook with payment id and use mocking for
+ // requests to the Mollie payments API.
+ $responseStack = $this->mockMollie();
+ $responseStack->append(new Response(200, [], json_encode($mollie_response1)));
+ $responseStack->append(new Response(200, [], json_encode($mollie_response2)));
+
+ $post = ['id' => $payment->id];
+ $response = $this->post("api/webhooks/payment/mollie", $post);
+ $response->assertStatus(200);
+
+ $wallet->refresh();
+
+ $this->assertEquals(-101, $wallet->balance);
+
+ $transactions = $wallet->transactions()->where('type', Transaction::WALLET_REFUND)->get();
+
+ $this->assertCount(1, $transactions);
+ $this->assertSame(101, $transactions[0]->amount);
+ $this->assertSame(Transaction::WALLET_REFUND, $transactions[0]->type);
+ $this->assertSame("refund desc", $transactions[0]->description);
+
+ $payments = $wallet->payments()->where('id', 're_123456')->get();
+
+ $this->assertCount(1, $payments);
+ $this->assertSame(-101, $payments[0]->amount);
+ $this->assertSame(PaymentProvider::STATUS_PAID, $payments[0]->status);
+ $this->assertSame(PaymentProvider::TYPE_REFUND, $payments[0]->type);
+ $this->assertSame("mollie", $payments[0]->provider);
+ $this->assertSame("refund desc", $payments[0]->description);
+
+ // Test handling a chargeback by the webhook
+
+ $mollie_response1["_links"] = [
+ "chargebacks" => [
+ "href" => "https://api.mollie.com/v2/payments/{$payment->id}/chargebacks",
+ "type" => "application/hal+json"
+ ]
+ ];
+
+ $mollie_response2 = [
+ "count" => 1,
+ "_links" => [],
+ "_embedded" => [
+ "chargebacks" => [
+ [
+ "resource" => "chargeback",
+ "id" => "chb_123456",
+ "paymentId" => $payment->id,
+ "amount" => [
+ "currency" => "CHF",
+ "value" => "0.15",
+ ],
+ ]
+ ]
+ ]
+ ];
+
+ // We'll trigger the webhook with payment id and use mocking for
+ // requests to the Mollie payments API.
+ $responseStack = $this->mockMollie();
+ $responseStack->append(new Response(200, [], json_encode($mollie_response1)));
+ $responseStack->append(new Response(200, [], json_encode($mollie_response2)));
+
+ $post = ['id' => $payment->id];
+ $response = $this->post("api/webhooks/payment/mollie", $post);
+ $response->assertStatus(200);
+
+ $wallet->refresh();
+
+ $this->assertEquals(-116, $wallet->balance);
+
+ $transactions = $wallet->transactions()->where('type', Transaction::WALLET_CHARGEBACK)->get();
+
+ $this->assertCount(1, $transactions);
+ $this->assertSame(15, $transactions[0]->amount);
+ $this->assertSame(Transaction::WALLET_CHARGEBACK, $transactions[0]->type);
+ $this->assertSame('', $transactions[0]->description);
+
+ $payments = $wallet->payments()->where('id', 'chb_123456')->get();
+
+ $this->assertCount(1, $payments);
+ $this->assertSame(-15, $payments[0]->amount);
+ $this->assertSame(PaymentProvider::STATUS_PAID, $payments[0]->status);
+ $this->assertSame(PaymentProvider::TYPE_CHARGEBACK, $payments[0]->type);
+ $this->assertSame("mollie", $payments[0]->provider);
+ $this->assertSame('', $payments[0]->description);
+
+ Bus::assertNotDispatched(\App\Jobs\PaymentEmail::class);
+
+ $this->unmockMollie();
}
/**
diff --git a/src/tests/Feature/Controller/PaymentsStripeTest.php b/src/tests/Feature/Controller/PaymentsStripeTest.php
--- a/src/tests/Feature/Controller/PaymentsStripeTest.php
+++ b/src/tests/Feature/Controller/PaymentsStripeTest.php
@@ -457,6 +457,8 @@
*/
public function testTopUpAndWebhook(): void
{
+ $this->markTestIncomplete();
+
Bus::fake();
$user = $this->getTestUser('john@kolab.org');
@@ -539,6 +541,7 @@
$wallet->setSetting('mandate_disabled', null);
$wallet->balance = -2050;
$wallet->save();
+
$result = PaymentsController::topUpWallet($wallet);
$this->assertFalse($result);
$this->assertCount(1, $wallet->payments()->get());
diff --git a/src/tests/Feature/Controller/SignupTest.php b/src/tests/Feature/Controller/SignupTest.php
--- a/src/tests/Feature/Controller/SignupTest.php
+++ b/src/tests/Feature/Controller/SignupTest.php
@@ -475,18 +475,21 @@
$json = $response->json();
$response->assertStatus(200);
- $this->assertCount(4, $json);
$this->assertSame('success', $json['status']);
$this->assertSame('bearer', $json['token_type']);
$this->assertTrue(!empty($json['expires_in']) && is_int($json['expires_in']) && $json['expires_in'] > 0);
$this->assertNotEmpty($json['access_token']);
+ $this->assertSame($identity, $json['email']);
- Queue::assertPushed(\App\Jobs\UserCreate::class, 1);
- Queue::assertPushed(\App\Jobs\UserCreate::class, function ($job) use ($data) {
- $job_user = TestCase::getObjectProperty($job, 'user');
+ Queue::assertPushed(\App\Jobs\User\CreateJob::class, 1);
- return $job_user->email === \strtolower($data['login'] . '@' . $data['domain']);
- });
+ Queue::assertPushed(
+ \App\Jobs\User\CreateJob::class,
+ function ($job) use ($data) {
+ $userEmail = TestCase::getObjectProperty($job, 'userEmail');
+ return $userEmail === \strtolower($data['login'] . '@' . $data['domain']);
+ }
+ );
// Check if the code has been removed
$this->assertNull(SignupCode::where('code', $result['code'])->first());
@@ -586,25 +589,33 @@
$result = $response->json();
$response->assertStatus(200);
- $this->assertCount(4, $result);
$this->assertSame('success', $result['status']);
$this->assertSame('bearer', $result['token_type']);
$this->assertTrue(!empty($result['expires_in']) && is_int($result['expires_in']) && $result['expires_in'] > 0);
$this->assertNotEmpty($result['access_token']);
+ $this->assertSame("$login@$domain", $result['email']);
- Queue::assertPushed(\App\Jobs\DomainCreate::class, 1);
- Queue::assertPushed(\App\Jobs\DomainCreate::class, function ($job) use ($domain) {
- $job_domain = TestCase::getObjectProperty($job, 'domain');
+ Queue::assertPushed(\App\Jobs\Domain\CreateJob::class, 1);
- return $job_domain->namespace === $domain;
- });
+ Queue::assertPushed(
+ \App\Jobs\Domain\CreateJob::class,
+ function ($job) use ($domain) {
+ $domainNamespace = TestCase::getObjectProperty($job, 'domainNamespace');
+
+ return $domainNamespace === $domain;
+ }
+ );
- Queue::assertPushed(\App\Jobs\UserCreate::class, 1);
- Queue::assertPushed(\App\Jobs\UserCreate::class, function ($job) use ($data) {
- $job_user = TestCase::getObjectProperty($job, 'user');
+ Queue::assertPushed(\App\Jobs\User\CreateJob::class, 1);
- return $job_user->email === $data['login'] . '@' . $data['domain'];
- });
+ Queue::assertPushed(
+ \App\Jobs\User\CreateJob::class,
+ function ($job) use ($data) {
+ $userEmail = TestCase::getObjectProperty($job, 'userEmail');
+
+ return $userEmail === $data['login'] . '@' . $data['domain'];
+ }
+ );
// Check if the code has been removed
$this->assertNull(SignupCode::find($code->id));
diff --git a/src/tests/Feature/Controller/WalletsTest.php b/src/tests/Feature/Controller/WalletsTest.php
--- a/src/tests/Feature/Controller/WalletsTest.php
+++ b/src/tests/Feature/Controller/WalletsTest.php
@@ -64,7 +64,10 @@
$this->assertSame('You are out of credit, top up your balance now.', $notice);
- // User/entitlements created today, balance=-9,99 CHF (monthly cost)
+ // User/entitlements created slightly more than a month ago, balance=9,99 CHF (monthly)
+ $wallet->owner->created_at = Carbon::now()->subMonthsWithoutOverflow(1)->subDays(1);
+ $wallet->owner->save();
+
$wallet->balance = 999;
$notice = $method->invoke($controller, $wallet);
@@ -86,7 +89,7 @@
public function testReceiptDownload(): void
{
$user = $this->getTestUser('wallets-controller@kolabnow.com');
- $john = $this->getTestUser('john@klab.org');
+ $john = $this->getTestUser('john@kolab.org');
$wallet = $user->wallets()->first();
// Unauth access not allowed
@@ -129,7 +132,7 @@
public function testReceipts(): void
{
$user = $this->getTestUser('wallets-controller@kolabnow.com');
- $john = $this->getTestUser('john@klab.org');
+ $john = $this->getTestUser('john@kolab.org');
$wallet = $user->wallets()->first();
$wallet->payments()->delete();
@@ -206,6 +209,7 @@
$this->assertSame('CHF', $json['currency']);
$this->assertSame($wallet->balance, $json['balance']);
$this->assertTrue(empty($json['description']));
+ // TODO: This assertion does not work after a longer while from seeding
$this->assertTrue(!empty($json['notice']));
}
@@ -217,7 +221,7 @@
$package_kolab = \App\Package::where('title', 'kolab')->first();
$user = $this->getTestUser('wallets-controller@kolabnow.com');
$user->assignPackage($package_kolab);
- $john = $this->getTestUser('john@klab.org');
+ $john = $this->getTestUser('john@kolab.org');
$wallet = $user->wallets()->first();
// Unauth access not allowed
diff --git a/src/tests/Feature/Documents/ReceiptTest.php b/src/tests/Feature/Documents/ReceiptTest.php
--- a/src/tests/Feature/Documents/ReceiptTest.php
+++ b/src/tests/Feature/Documents/ReceiptTest.php
@@ -13,6 +13,15 @@
class ReceiptTest extends TestCase
{
+ private $paymentIDs = ['AAA1', 'AAA2', 'AAA3', 'AAA4', 'AAA5', 'AAA6', 'AAA7'];
+
+ public function setUp(): void
+ {
+ parent::setUp();
+
+ Payment::whereIn('id', $this->paymentIDs)->delete();
+ }
+
/**
* {@inheritDoc}
*/
@@ -20,6 +29,8 @@
{
$this->deleteTestUser('receipt-test@kolabnow.com');
+ Payment::whereIn('id', $this->paymentIDs)->delete();
+
parent::tearDown();
}
@@ -51,7 +62,7 @@
// The main table content
$content = $dom->getElementById('content');
$records = $content->getElementsByTagName('tr');
- $this->assertCount(5, $records);
+ $this->assertCount(7, $records);
$headerCells = $records[0]->getElementsByTagName('th');
$this->assertCount(3, $headerCells);
@@ -70,13 +81,23 @@
$this->assertSame('0,01 CHF', $this->getNodeContent($cells[2]));
$cells = $records[3]->getElementsByTagName('td');
$this->assertCount(3, $cells);
- $this->assertSame('2020-05-31', $this->getNodeContent($cells[0]));
+ $this->assertSame('2020-05-21', $this->getNodeContent($cells[0]));
$this->assertSame("$appName Services", $this->getNodeContent($cells[1]));
$this->assertSame('1,00 CHF', $this->getNodeContent($cells[2]));
- $summaryCells = $records[4]->getElementsByTagName('td');
+ $cells = $records[4]->getElementsByTagName('td');
+ $this->assertCount(3, $cells);
+ $this->assertSame('2020-05-30', $this->getNodeContent($cells[0]));
+ $this->assertSame("Refund", $this->getNodeContent($cells[1]));
+ $this->assertSame('-1,00 CHF', $this->getNodeContent($cells[2]));
+ $cells = $records[5]->getElementsByTagName('td');
+ $this->assertCount(3, $cells);
+ $this->assertSame('2020-05-31', $this->getNodeContent($cells[0]));
+ $this->assertSame("Chargeback", $this->getNodeContent($cells[1]));
+ $this->assertSame('-0,10 CHF', $this->getNodeContent($cells[2]));
+ $summaryCells = $records[6]->getElementsByTagName('td');
$this->assertCount(2, $summaryCells);
$this->assertSame('Total', $this->getNodeContent($summaryCells[0]));
- $this->assertSame('13,35 CHF', $this->getNodeContent($summaryCells[1]));
+ $this->assertSame('12,25 CHF', $this->getNodeContent($summaryCells[1]));
// Customer data
$customer = $dom->getElementById('customer');
@@ -116,7 +137,7 @@
// The main table content
$content = $dom->getElementById('content');
$records = $content->getElementsByTagName('tr');
- $this->assertCount(7, $records);
+ $this->assertCount(9, $records);
$cells = $records[1]->getElementsByTagName('td');
$this->assertCount(3, $cells);
@@ -130,21 +151,31 @@
$this->assertSame('0,01 CHF', $this->getNodeContent($cells[2]));
$cells = $records[3]->getElementsByTagName('td');
$this->assertCount(3, $cells);
- $this->assertSame('2020-05-31', $this->getNodeContent($cells[0]));
+ $this->assertSame('2020-05-21', $this->getNodeContent($cells[0]));
$this->assertSame("$appName Services", $this->getNodeContent($cells[1]));
$this->assertSame('0,92 CHF', $this->getNodeContent($cells[2]));
- $subtotalCells = $records[4]->getElementsByTagName('td');
+ $cells = $records[4]->getElementsByTagName('td');
+ $this->assertCount(3, $cells);
+ $this->assertSame('2020-05-30', $this->getNodeContent($cells[0]));
+ $this->assertSame("Refund", $this->getNodeContent($cells[1]));
+ $this->assertSame('-0,92 CHF', $this->getNodeContent($cells[2]));
+ $cells = $records[5]->getElementsByTagName('td');
+ $this->assertCount(3, $cells);
+ $this->assertSame('2020-05-31', $this->getNodeContent($cells[0]));
+ $this->assertSame("Chargeback", $this->getNodeContent($cells[1]));
+ $this->assertSame('-0,09 CHF', $this->getNodeContent($cells[2]));
+ $subtotalCells = $records[6]->getElementsByTagName('td');
$this->assertCount(2, $subtotalCells);
$this->assertSame('Subtotal', $this->getNodeContent($subtotalCells[0]));
- $this->assertSame('12,32 CHF', $this->getNodeContent($subtotalCells[1]));
- $vatCells = $records[5]->getElementsByTagName('td');
+ $this->assertSame('11,31 CHF', $this->getNodeContent($subtotalCells[1]));
+ $vatCells = $records[7]->getElementsByTagName('td');
$this->assertCount(2, $vatCells);
$this->assertSame('VAT (7.7%)', $this->getNodeContent($vatCells[0]));
- $this->assertSame('1,03 CHF', $this->getNodeContent($vatCells[1]));
- $totalCells = $records[6]->getElementsByTagName('td');
+ $this->assertSame('0,94 CHF', $this->getNodeContent($vatCells[1]));
+ $totalCells = $records[8]->getElementsByTagName('td');
$this->assertCount(2, $totalCells);
$this->assertSame('Total', $this->getNodeContent($totalCells[0]));
- $this->assertSame('13,35 CHF', $this->getNodeContent($totalCells[1]));
+ $this->assertSame('12,25 CHF', $this->getNodeContent($totalCells[1]));
}
/**
@@ -185,7 +216,7 @@
// Create two payments out of the 2020-05 period
// and three in it, plus one in the period but unpaid,
- // and one with amount 0
+ // and one with amount 0, and an extra refund and chanrgeback
$payment = Payment::create([
'id' => 'AAA1',
@@ -235,7 +266,7 @@
$payment->updated_at = Carbon::create(2020, 5, 1, 0, 0, 0);
$payment->save();
- // ... so we expect the last three on the receipt
+ // ... so we expect the five three on the receipt
$payment = Payment::create([
'id' => 'AAA5',
'status' => PaymentProvider::STATUS_PAID,
@@ -269,6 +300,30 @@
'provider' => 'stripe',
'amount' => 100,
]);
+ $payment->updated_at = Carbon::create(2020, 5, 21, 23, 59, 0);
+ $payment->save();
+
+ $payment = Payment::create([
+ 'id' => 'ref1',
+ 'status' => PaymentProvider::STATUS_PAID,
+ 'type' => PaymentProvider::TYPE_REFUND,
+ 'description' => 'refund desc',
+ 'wallet_id' => $wallet->id,
+ 'provider' => 'stripe',
+ 'amount' => -100,
+ ]);
+ $payment->updated_at = Carbon::create(2020, 5, 30, 23, 59, 0);
+ $payment->save();
+
+ $payment = Payment::create([
+ 'id' => 'chback1',
+ 'status' => PaymentProvider::STATUS_PAID,
+ 'type' => PaymentProvider::TYPE_CHARGEBACK,
+ 'description' => '',
+ 'wallet_id' => $wallet->id,
+ 'provider' => 'stripe',
+ 'amount' => -10,
+ ]);
$payment->updated_at = Carbon::create(2020, 5, 31, 23, 59, 0);
$payment->save();
diff --git a/src/tests/Feature/DomainTest.php b/src/tests/Feature/DomainTest.php
--- a/src/tests/Feature/DomainTest.php
+++ b/src/tests/Feature/DomainTest.php
@@ -47,6 +47,27 @@
parent::tearDown();
}
+ /**
+ * Test domain create/creating observer
+ */
+ public function testCreate(): void
+ {
+ Queue::fake();
+
+ $domain = Domain::create([
+ 'namespace' => 'GMAIL.COM',
+ 'status' => Domain::STATUS_NEW,
+ 'type' => Domain::TYPE_EXTERNAL,
+ ]);
+
+ $result = Domain::where('namespace', 'gmail.com')->first();
+
+ $this->assertSame('gmail.com', $result->namespace);
+ $this->assertSame($domain->id, $result->id);
+ $this->assertSame($domain->type, $result->type);
+ $this->assertSame(Domain::STATUS_NEW, $result->status);
+ }
+
/**
* Test domain creating jobs
*/
@@ -62,19 +83,20 @@
'type' => Domain::TYPE_EXTERNAL,
]);
- Queue::assertPushed(\App\Jobs\DomainCreate::class, 1);
+ Queue::assertPushed(\App\Jobs\Domain\CreateJob::class, 1);
Queue::assertPushed(
- \App\Jobs\DomainCreate::class,
+ \App\Jobs\Domain\CreateJob::class,
function ($job) use ($domain) {
- $job_domain = TestCase::getObjectProperty($job, 'domain');
+ $domainId = TestCase::getObjectProperty($job, 'domainId');
+ $domainNamespace = TestCase::getObjectProperty($job, 'domainNamespace');
- return $job_domain->id === $domain->id &&
- $job_domain->namespace === $domain->namespace;
+ return $domainId === $domain->id &&
+ $domainNamespace === $domain->namespace;
}
);
- $job = new \App\Jobs\DomainCreate($domain);
+ $job = new \App\Jobs\Domain\CreateJob($domain->id);
$job->handle();
}
@@ -187,7 +209,7 @@
$this->assertFalse($domain->fresh()->isDeleted());
// Delete the domain for real
- $job = new \App\Jobs\DomainDelete($domain->id);
+ $job = new \App\Jobs\Domain\DeleteJob($domain->id);
$job->handle();
$this->assertTrue(Domain::withTrashed()->where('id', $domain->id)->first()->isDeleted());
diff --git a/src/tests/Feature/EntitlementTest.php b/src/tests/Feature/EntitlementTest.php
--- a/src/tests/Feature/EntitlementTest.php
+++ b/src/tests/Feature/EntitlementTest.php
@@ -150,18 +150,32 @@
$wallet = $user->wallets()->first();
- $this->backdateEntitlements($user->entitlements, Carbon::now()->subWeeks(7));
+ $backdate = Carbon::now()->subWeeks(7);
+ $this->backdateEntitlements($user->entitlements, $backdate);
$charge = $wallet->chargeEntitlements();
- $this->assertTrue($wallet->balance < 0);
+ $this->assertSame(-1099, $wallet->balance);
$balance = $wallet->balance;
+ $discount = \App\Discount::where('discount', 30)->first();
+ $wallet->discount()->associate($discount);
+ $wallet->save();
$user->removeSku($storage, 4);
- // we expect the wallet to have been charged.
- $this->assertTrue($wallet->fresh()->balance < $balance);
+ // we expect the wallet to have been charged for ~3 weeks of use of
+ // 4 deleted storage entitlements, it should also take discount into account
+ $backdate->addMonthsWithoutOverflow(1);
+ $diffInDays = $backdate->diffInDays(Carbon::now());
+
+ // entitlements-num * cost * discount * days-in-month
+ $max = intval(4 * 25 * 0.7 * $diffInDays / 28);
+ $min = intval(4 * 25 * 0.7 * $diffInDays / 31);
+
+ $wallet->refresh();
+ $this->assertTrue($wallet->balance >= $balance - $max);
+ $this->assertTrue($wallet->balance <= $balance - $min);
$transactions = \App\Transaction::where('object_id', $wallet->id)
->where('object_type', \App\Wallet::class)->get();
diff --git a/src/tests/Feature/Jobs/DomainCreateTest.php b/src/tests/Feature/Jobs/DomainCreateTest.php
--- a/src/tests/Feature/Jobs/DomainCreateTest.php
+++ b/src/tests/Feature/Jobs/DomainCreateTest.php
@@ -2,7 +2,6 @@
namespace Tests\Feature\Jobs;
-use App\Jobs\DomainCreate;
use App\Domain;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Queue;
@@ -48,20 +47,21 @@
Queue::fake();
Queue::assertNothingPushed();
- $job = new DomainCreate($domain);
+ $job = new \App\Jobs\Domain\CreateJob($domain->id);
$job->handle();
$this->assertTrue($domain->fresh()->isLdapReady());
- Queue::assertPushed(\App\Jobs\DomainVerify::class, 1);
+ Queue::assertPushed(\App\Jobs\Domain\VerifyJob::class, 1);
Queue::assertPushed(
- \App\Jobs\DomainVerify::class,
+ \App\Jobs\Domain\VerifyJob::class,
function ($job) use ($domain) {
- $job_domain = TestCase::getObjectProperty($job, 'domain');
+ $domainId = TestCase::getObjectProperty($job, 'domainId');
+ $domainNamespace = TestCase::getObjectProperty($job, 'domainNamespace');
- return $job_domain->id === $domain->id &&
- $job_domain->namespace === $domain->namespace;
+ return $domainId === $domain->id &&
+ $domainNamespace === $domain->namespace;
}
);
}
diff --git a/src/tests/Feature/Jobs/DomainVerifyTest.php b/src/tests/Feature/Jobs/DomainVerifyTest.php
--- a/src/tests/Feature/Jobs/DomainVerifyTest.php
+++ b/src/tests/Feature/Jobs/DomainVerifyTest.php
@@ -2,7 +2,6 @@
namespace Tests\Feature\Jobs;
-use App\Jobs\DomainVerify;
use App\Domain;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;
@@ -45,7 +44,7 @@
$this->assertFalse($domain->isVerified());
- $job = new DomainVerify($domain);
+ $job = new \App\Jobs\Domain\VerifyJob($domain->id);
$job->handle();
$this->assertTrue($domain->fresh()->isVerified());
@@ -68,7 +67,7 @@
$this->assertFalse($domain->isVerified());
- $job = new DomainVerify($domain);
+ $job = new \App\Jobs\Domain\VerifyJob($domain->id);
$job->handle();
$this->assertFalse($domain->fresh()->isVerified());
diff --git a/src/tests/Feature/Jobs/PaymentEmailTest.php b/src/tests/Feature/Jobs/PaymentEmailTest.php
--- a/src/tests/Feature/Jobs/PaymentEmailTest.php
+++ b/src/tests/Feature/Jobs/PaymentEmailTest.php
@@ -69,8 +69,8 @@
Mail::assertSent(PaymentSuccess::class, 1);
// Assert the mail was sent to the user's email
- Mail::assertSent(PaymentSuccess::class, function ($mail) use ($user) {
- return $mail->hasTo($user->email) && $mail->hasCc('ext@email.tld');
+ Mail::assertSent(PaymentSuccess::class, function ($mail) {
+ return $mail->hasTo('ext@email.tld') && !$mail->hasCc('ext@email.tld');
});
$payment->status = PaymentProvider::STATUS_FAILED;
@@ -83,8 +83,8 @@
Mail::assertSent(PaymentFailure::class, 1);
// Assert the mail was sent to the user's email
- Mail::assertSent(PaymentFailure::class, function ($mail) use ($user) {
- return $mail->hasTo($user->email) && $mail->hasCc('ext@email.tld');
+ Mail::assertSent(PaymentFailure::class, function ($mail) {
+ return $mail->hasTo('ext@email.tld') && !$mail->hasCc('ext@email.tld');
});
$payment->status = PaymentProvider::STATUS_EXPIRED;
diff --git a/src/tests/Feature/Jobs/PaymentMandateDisabledEmailTest.php b/src/tests/Feature/Jobs/PaymentMandateDisabledEmailTest.php
--- a/src/tests/Feature/Jobs/PaymentMandateDisabledEmailTest.php
+++ b/src/tests/Feature/Jobs/PaymentMandateDisabledEmailTest.php
@@ -56,8 +56,8 @@
Mail::assertSent(PaymentMandateDisabled::class, 1);
// Assert the mail was sent to the user's email
- Mail::assertSent(PaymentMandateDisabled::class, function ($mail) use ($user) {
- return $mail->hasTo($user->email) && $mail->hasCc('ext@email.tld');
+ Mail::assertSent(PaymentMandateDisabled::class, function ($mail) {
+ return $mail->hasTo('ext@email.tld') && !$mail->hasCc('ext@email.tld');
});
}
}
diff --git a/src/tests/Feature/Jobs/UserCreateTest.php b/src/tests/Feature/Jobs/UserCreateTest.php
--- a/src/tests/Feature/Jobs/UserCreateTest.php
+++ b/src/tests/Feature/Jobs/UserCreateTest.php
@@ -2,7 +2,7 @@
namespace Tests\Feature\Jobs;
-use App\Jobs\UserCreate;
+use App\User;
use Tests\TestCase;
class UserCreateTest extends TestCase
@@ -35,9 +35,44 @@
$this->assertFalse($user->isLdapReady());
- $job = new UserCreate($user);
+ $job = new \App\Jobs\User\CreateJob($user->id);
$job->handle();
$this->assertTrue($user->fresh()->isLdapReady());
+ $this->assertFalse($job->hasFailed());
+
+ // Test job failures
+ $job = new \App\Jobs\User\CreateJob($user->id);
+ $job->handle();
+
+ $this->assertTrue($job->hasFailed());
+ $this->assertSame("User {$user->id} is already marked as ldap-ready.", $job->failureMessage);
+
+ $user->status |= User::STATUS_DELETED;
+ $user->save();
+
+ $job = new \App\Jobs\User\CreateJob($user->id);
+ $job->handle();
+
+ $this->assertTrue($job->hasFailed());
+ $this->assertSame("User {$user->id} is marked as deleted.", $job->failureMessage);
+
+ $user->status ^= User::STATUS_DELETED;
+ $user->save();
+ $user->delete();
+
+ $job = new \App\Jobs\User\CreateJob($user->id);
+ $job->handle();
+
+ $this->assertTrue($job->hasFailed());
+ $this->assertSame("User {$user->id} is actually deleted.", $job->failureMessage);
+
+ // TODO: Test failures on domain sanity checks
+
+ $job = new \App\Jobs\User\CreateJob(123);
+ $job->handle();
+
+ $this->assertTrue($job->hasFailed());
+ $this->assertSame("User 123 could not be found in the database.", $job->failureMessage);
}
}
diff --git a/src/tests/Feature/Jobs/UserUpdateTest.php b/src/tests/Feature/Jobs/UserUpdateTest.php
--- a/src/tests/Feature/Jobs/UserUpdateTest.php
+++ b/src/tests/Feature/Jobs/UserUpdateTest.php
@@ -3,7 +3,6 @@
namespace Tests\Feature\Jobs;
use App\Backends\LDAP;
-use App\Jobs\UserUpdate;
use Illuminate\Support\Facades\Queue;
use Tests\TestCase;
@@ -42,7 +41,7 @@
$user = $this->getTestUser('new-job-user@' . \config('app.domain'));
// Create the user in LDAP
- $job = new \App\Jobs\UserCreate($user);
+ $job = new \App\Jobs\User\CreateJob($user->id);
$job->handle();
// Test setting two aliases
@@ -50,9 +49,10 @@
'new-job-user1@' . \config('app.domain'),
'new-job-user2@' . \config('app.domain'),
];
+
$user->setAliases($aliases);
- $job = new UserUpdate($user->fresh());
+ $job = new \App\Jobs\User\UpdateJob($user->id);
$job->handle();
$ldap_user = LDAP::getUser('new-job-user@' . \config('app.domain'));
@@ -63,9 +63,10 @@
$aliases = [
'new-job-user1@' . \config('app.domain'),
];
+
$user->setAliases($aliases);
- $job = new UserUpdate($user->fresh());
+ $job = new \App\Jobs\User\UpdateJob($user->id);
$job->handle();
$ldap_user = LDAP::getUser('new-job-user@' . \config('app.domain'));
@@ -76,7 +77,7 @@
$aliases = [];
$user->setAliases($aliases);
- $job = new UserUpdate($user->fresh());
+ $job = new \App\Jobs\User\UpdateJob($user->id);
$job->handle();
$ldap_user = LDAP::getUser('new-job-user@' . \config('app.domain'));
diff --git a/src/tests/Feature/Jobs/UserVerifyTest.php b/src/tests/Feature/Jobs/UserVerifyTest.php
--- a/src/tests/Feature/Jobs/UserVerifyTest.php
+++ b/src/tests/Feature/Jobs/UserVerifyTest.php
@@ -2,8 +2,6 @@
namespace Tests\Feature\Jobs;
-use App\Jobs\UserCreate;
-use App\Jobs\UserVerify;
use App\User;
use Illuminate\Support\Facades\Queue;
use Tests\TestCase;
@@ -44,6 +42,7 @@
Queue::fake();
$user = $this->getTestUser('ned@kolab.org');
+
if ($user->isImapReady()) {
$user->status ^= User::STATUS_IMAP_READY;
$user->save();
@@ -52,7 +51,7 @@
$this->assertFalse($user->isImapReady());
for ($i = 0; $i < 10; $i++) {
- $job = new UserVerify($user);
+ $job = new \App\Jobs\User\VerifyJob($user->id);
$job->handle();
if ($user->fresh()->isImapReady()) {
diff --git a/src/tests/Feature/Jobs/WalletCheckTest.php b/src/tests/Feature/Jobs/WalletCheckTest.php
--- a/src/tests/Feature/Jobs/WalletCheckTest.php
+++ b/src/tests/Feature/Jobs/WalletCheckTest.php
@@ -115,10 +115,36 @@
}
/**
- * Test job handle, reminder notification
+ * Test job handle, top-up before reminder notification
*
* @depends testHandleInitial
*/
+ public function testHandleBeforeReminder(): void
+ {
+ Mail::fake();
+
+ $user = $this->getTestUser('ned@kolab.org');
+ $wallet = $user->wallets()->first();
+ $now = Carbon::now();
+
+ // Balance turned negative 7-1 days ago
+ $wallet->setSetting('balance_negative_since', $now->subDays(7 - 1)->toDateTimeString());
+
+ $job = new WalletCheck($wallet);
+ $res = $job->handle();
+
+ Mail::assertNothingSent();
+
+ // TODO: Test that it actually executed the topUpWallet()
+ $this->assertSame(WalletCheck::THRESHOLD_BEFORE_REMINDER, $res);
+ $this->assertFalse($user->fresh()->isSuspended());
+ }
+
+ /**
+ * Test job handle, reminder notification
+ *
+ * @depends testHandleBeforeReminder
+ */
public function testHandleReminder(): void
{
Mail::fake();
@@ -149,10 +175,37 @@
}
/**
- * Test job handle, account suspending
+ * Test job handle, top-up wallet before account suspending
*
* @depends testHandleReminder
*/
+ public function testHandleBeforeSuspended(): void
+ {
+ Mail::fake();
+
+ $user = $this->getTestUser('ned@kolab.org');
+ $wallet = $user->wallets()->first();
+ $now = Carbon::now();
+
+ // Balance turned negative 7+14-1 days ago
+ $days = 7 + 14 - 1;
+ $wallet->setSetting('balance_negative_since', $now->subDays($days)->toDateTimeString());
+
+ $job = new WalletCheck($wallet);
+ $res = $job->handle();
+
+ Mail::assertNothingSent();
+
+ // TODO: Test that it actually executed the topUpWallet()
+ $this->assertSame(WalletCheck::THRESHOLD_BEFORE_SUSPEND, $res);
+ $this->assertFalse($user->fresh()->isSuspended());
+ }
+
+ /**
+ * Test job handle, account suspending
+ *
+ * @depends testHandleBeforeSuspended
+ */
public function testHandleSuspended(): void
{
Mail::fake();
diff --git a/src/tests/Feature/UserTest.php b/src/tests/Feature/UserTest.php
--- a/src/tests/Feature/UserTest.php
+++ b/src/tests/Feature/UserTest.php
@@ -55,50 +55,10 @@
$this->markTestIncomplete();
}
- /**
- * Verify user creation process
- */
- public function testUserCreateJob(): void
- {
- // Fake the queue, assert that no jobs were pushed...
- Queue::fake();
- Queue::assertNothingPushed();
-
- $user = User::create([
- 'email' => 'user-test@' . \config('app.domain')
- ]);
-
- Queue::assertPushed(\App\Jobs\UserCreate::class, 1);
- Queue::assertPushed(\App\Jobs\UserCreate::class, function ($job) use ($user) {
- $job_user = TestCase::getObjectProperty($job, 'user');
-
- return $job_user->id === $user->id
- && $job_user->email === $user->email;
- });
-
- Queue::assertPushedWithChain(\App\Jobs\UserCreate::class, [
- \App\Jobs\UserVerify::class,
- ]);
-/*
- FIXME: Looks like we can't really do detailed assertions on chained jobs
- Another thing to consider is if we maybe should run these jobs
- independently (not chained) and make sure there's no race-condition
- in status update
-
- Queue::assertPushed(\App\Jobs\UserVerify::class, 1);
- Queue::assertPushed(\App\Jobs\UserVerify::class, function ($job) use ($user) {
- $job_user = TestCase::getObjectProperty($job, 'user');
-
- return $job_user->id === $user->id
- && $job_user->email === $user->email;
- });
-*/
- }
-
/**
* Verify a wallet assigned a controller is among the accounts of the assignee.
*/
- public function testListUserAccounts(): void
+ public function testAccounts(): void
{
$userA = $this->getTestUser('UserAccountA@UserAccount.com');
$userB = $this->getTestUser('UserAccountB@UserAccount.com');
@@ -114,11 +74,6 @@
$this->assertTrue($userB->accounts()->get()[0]->id === $userA->wallets()->get()[0]->id);
}
- public function testAccounts(): void
- {
- $this->markTestIncomplete();
- }
-
public function testCanDelete(): void
{
$this->markTestIncomplete();
@@ -134,6 +89,73 @@
$this->markTestIncomplete();
}
+ /**
+ * Test user create/creating observer
+ */
+ public function testCreate(): void
+ {
+ Queue::fake();
+
+ $domain = \config('app.domain');
+
+ $user = User::create(['email' => 'USER-test@' . \strtoupper($domain)]);
+
+ $result = User::where('email', 'user-test@' . $domain)->first();
+
+ $this->assertSame('user-test@' . $domain, $result->email);
+ $this->assertSame($user->id, $result->id);
+ $this->assertSame(User::STATUS_NEW | User::STATUS_ACTIVE, $result->status);
+ }
+
+ /**
+ * Verify user creation process
+ */
+ public function testCreateJobs(): void
+ {
+ // Fake the queue, assert that no jobs were pushed...
+ Queue::fake();
+ Queue::assertNothingPushed();
+
+ $user = User::create([
+ 'email' => 'user-test@' . \config('app.domain')
+ ]);
+
+ Queue::assertPushed(\App\Jobs\User\CreateJob::class, 1);
+
+ Queue::assertPushed(
+ \App\Jobs\User\CreateJob::class,
+ function ($job) use ($user) {
+ $userEmail = TestCase::getObjectProperty($job, 'userEmail');
+ $userId = TestCase::getObjectProperty($job, 'userId');
+
+ return $userEmail === $user->email
+ && $userId === $user->id;
+ }
+ );
+
+ Queue::assertPushedWithChain(
+ \App\Jobs\User\CreateJob::class,
+ [
+ \App\Jobs\User\VerifyJob::class,
+ ]
+ );
+/*
+ FIXME: Looks like we can't really do detailed assertions on chained jobs
+ Another thing to consider is if we maybe should run these jobs
+ independently (not chained) and make sure there's no race-condition
+ in status update
+
+ Queue::assertPushed(\App\Jobs\User\VerifyJob::class, 1);
+ Queue::assertPushed(\App\Jobs\User\VerifyJob::class, function ($job) use ($user) {
+ $userEmail = TestCase::getObjectProperty($job, 'userEmail');
+ $userId = TestCase::getObjectProperty($job, 'userId');
+
+ return $userEmail === $user->email
+ && $userId === $user->id;
+ });
+*/
+ }
+
/**
* Tests for User::domains()
*/
@@ -204,7 +226,7 @@
$this->assertFalse($user->fresh()->isDeleted());
// Delete the user for real
- $job = new \App\Jobs\UserDelete($id);
+ $job = new \App\Jobs\User\DeleteJob($id);
$job->handle();
$this->assertTrue(User::withTrashed()->where('id', $id)->first()->isDeleted());
@@ -341,7 +363,7 @@
// Add an alias
$user->setAliases(['UserAlias1@UserAccount.com']);
- Queue::assertPushed(\App\Jobs\UserUpdate::class, 1);
+ Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 1);
$aliases = $user->aliases()->get();
$this->assertCount(1, $aliases);
@@ -350,7 +372,7 @@
// Add another alias
$user->setAliases(['UserAlias1@UserAccount.com', 'UserAlias2@UserAccount.com']);
- Queue::assertPushed(\App\Jobs\UserUpdate::class, 2);
+ Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 2);
$aliases = $user->aliases()->orderBy('alias')->get();
$this->assertCount(2, $aliases);
@@ -360,7 +382,7 @@
// Remove an alias
$user->setAliases(['UserAlias1@UserAccount.com']);
- Queue::assertPushed(\App\Jobs\UserUpdate::class, 3);
+ Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 3);
$aliases = $user->aliases()->get();
$this->assertCount(1, $aliases);
@@ -369,7 +391,7 @@
// Remove all aliases
$user->setAliases([]);
- Queue::assertPushed(\App\Jobs\UserUpdate::class, 4);
+ Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 4);
$this->assertCount(0, $user->aliases()->get());
@@ -418,7 +440,7 @@
$user = $this->getTestUser('UserAccountA@UserAccount.com');
- Queue::assertPushed(\App\Jobs\UserUpdate::class, 0);
+ Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 0);
// Test default settings
// Note: Technicly this tests UserObserver::created() behavior
@@ -432,7 +454,7 @@
// Add a setting
$user->setSetting('first_name', 'Firstname');
- Queue::assertPushed(\App\Jobs\UserUpdate::class, 1);
+ Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 1);
// Note: We test both current user as well as fresh user object
// to make sure cache works as expected
@@ -442,7 +464,7 @@
// Update a setting
$user->setSetting('first_name', 'Firstname1');
- Queue::assertPushed(\App\Jobs\UserUpdate::class, 2);
+ Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 2);
// Note: We test both current user as well as fresh user object
// to make sure cache works as expected
@@ -452,7 +474,7 @@
// Delete a setting (null)
$user->setSetting('first_name', null);
- Queue::assertPushed(\App\Jobs\UserUpdate::class, 3);
+ Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 3);
// Note: We test both current user as well as fresh user object
// to make sure cache works as expected
@@ -463,7 +485,7 @@
$user->setSetting('first_name', 'Firstname1');
$user->setSetting('first_name', '');
- Queue::assertPushed(\App\Jobs\UserUpdate::class, 5);
+ Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 5);
// Note: We test both current user as well as fresh user object
// to make sure cache works as expected
@@ -478,7 +500,7 @@
]);
// TODO: This really should create a single UserUpdate job, not 3
- Queue::assertPushed(\App\Jobs\UserUpdate::class, 7);
+ Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 7);
// Note: We test both current user as well as fresh user object
// to make sure cache works as expected
diff --git a/src/tests/Feature/WalletTest.php b/src/tests/Feature/WalletTest.php
--- a/src/tests/Feature/WalletTest.php
+++ b/src/tests/Feature/WalletTest.php
@@ -44,8 +44,6 @@
parent::tearDown();
}
-
-
/**
* Test that turning wallet balance from negative to positive
* unsuspends the account
@@ -88,7 +86,10 @@
// User/entitlements created today, balance=0
$until = $wallet->balanceLastsUntil();
- $this->assertSame(Carbon::now()->toDateString(), $until->toDateString());
+ $this->assertSame(
+ Carbon::now()->addMonthsWithoutOverflow(1)->toDateString(),
+ $until->toDateString()
+ );
// User/entitlements created today, balance=-10 CHF
$wallet->balance = -1000;
@@ -103,7 +104,7 @@
$daysInLastMonth = \App\Utils::daysInLastMonth();
$this->assertSame(
- Carbon::now()->addDays($daysInLastMonth)->toDateString(),
+ Carbon::now()->addMonthsWithoutOverflow(1)->addDays($daysInLastMonth)->toDateString(),
$until->toDateString()
);
diff --git a/src/tests/Functional/Methods/DomainTest.php b/src/tests/Functional/Methods/DomainTest.php
new file mode 100644
--- /dev/null
+++ b/src/tests/Functional/Methods/DomainTest.php
@@ -0,0 +1,115 @@
+<?php
+
+namespace Tests\Functional\Methods;
+
+use Illuminate\Support\Facades\Queue;
+use Tests\TestCase;
+
+class DomainTest extends TestCase
+{
+ protected $domain;
+
+ public function setUp(): void
+ {
+ parent::setUp();
+
+ $this->domain = $this->getTestDomain(
+ 'test.domain',
+ [
+ 'status' => \App\Domain::STATUS_CONFIRMED | \App\Domain::STATUS_VERIFIED,
+ 'type' => \App\Domain::TYPE_EXTERNAL
+ ]
+ );
+ }
+
+ public function tearDown(): void
+ {
+ $this->deleteTestDomain('test.domain');
+
+ parent::tearDown();
+ }
+
+ /**
+ * Verify we can suspend an active domain.
+ */
+ public function testSuspendForActiveDomain()
+ {
+ Queue::fake();
+
+ $this->domain->status |= \App\Domain::STATUS_ACTIVE;
+
+ $this->assertFalse($this->domain->isSuspended());
+ $this->assertTrue($this->domain->isActive());
+
+ $this->domain->suspend();
+
+ $this->assertTrue($this->domain->isSuspended());
+ $this->assertFalse($this->domain->isActive());
+ }
+
+ /**
+ * Verify we can unsuspend a suspended domain
+ */
+ public function testUnsuspendForSuspendedDomain()
+ {
+ Queue::fake();
+
+ $this->domain->status |= \App\Domain::STATUS_SUSPENDED;
+
+ $this->assertTrue($this->domain->isSuspended());
+ $this->assertFalse($this->domain->isActive());
+
+ $this->domain->unsuspend();
+
+ $this->assertFalse($this->domain->isSuspended());
+ $this->assertTrue($this->domain->isActive());
+ }
+
+ /**
+ * Verify we can unsuspend a suspended domain that wasn't confirmed
+ */
+ public function testUnsuspendForSuspendedUnconfirmedDomain()
+ {
+ Queue::fake();
+
+ $this->domain->status = \App\Domain::STATUS_NEW | \App\Domain::STATUS_SUSPENDED;
+
+ $this->assertTrue($this->domain->isNew());
+ $this->assertTrue($this->domain->isSuspended());
+ $this->assertFalse($this->domain->isActive());
+ $this->assertFalse($this->domain->isConfirmed());
+ $this->assertFalse($this->domain->isVerified());
+
+ $this->domain->unsuspend();
+
+ $this->assertTrue($this->domain->isNew());
+ $this->assertFalse($this->domain->isSuspended());
+ $this->assertFalse($this->domain->isActive());
+ $this->assertFalse($this->domain->isConfirmed());
+ $this->assertFalse($this->domain->isVerified());
+ }
+
+ /**
+ * Verify we can unsuspend a suspended domain that was verified but not confirmed
+ */
+ public function testUnsuspendForSuspendedVerifiedUnconfirmedDomain()
+ {
+ Queue::fake();
+
+ $this->domain->status = \App\Domain::STATUS_NEW | \App\Domain::STATUS_SUSPENDED | \App\Domain::STATUS_VERIFIED;
+
+ $this->assertTrue($this->domain->isNew());
+ $this->assertTrue($this->domain->isSuspended());
+ $this->assertFalse($this->domain->isActive());
+ $this->assertFalse($this->domain->isConfirmed());
+ $this->assertTrue($this->domain->isVerified());
+
+ $this->domain->unsuspend();
+
+ $this->assertTrue($this->domain->isNew());
+ $this->assertFalse($this->domain->isSuspended());
+ $this->assertFalse($this->domain->isActive());
+ $this->assertFalse($this->domain->isConfirmed());
+ $this->assertTrue($this->domain->isVerified());
+ }
+}
diff --git a/src/tests/TestCase.php b/src/tests/TestCase.php
--- a/src/tests/TestCase.php
+++ b/src/tests/TestCase.php
@@ -14,6 +14,10 @@
$entitlement->created_at = $targetDate;
$entitlement->updated_at = $targetDate;
$entitlement->save();
+
+ $owner = $entitlement->wallet->owner;
+ $owner->created_at = $targetDate;
+ $owner->save();
}
}
diff --git a/src/tests/TestCaseTrait.php b/src/tests/TestCaseTrait.php
--- a/src/tests/TestCaseTrait.php
+++ b/src/tests/TestCaseTrait.php
@@ -117,7 +117,7 @@
return;
}
- $job = new \App\Jobs\DomainDelete($domain->id);
+ $job = new \App\Jobs\Domain\DeleteJob($domain->id);
$job->handle();
$domain->forceDelete();
@@ -133,7 +133,7 @@
return;
}
- $job = new \App\Jobs\UserDelete($user->id);
+ $job = new \App\Jobs\User\DeleteJob($user->id);
$job->handle();
$user->forceDelete();
diff --git a/src/tests/Unit/DomainTest.php b/src/tests/Unit/DomainTest.php
--- a/src/tests/Unit/DomainTest.php
+++ b/src/tests/Unit/DomainTest.php
@@ -24,38 +24,59 @@
$domains = \App\Utils::powerSet($statuses);
- foreach ($domains as $domain_statuses) {
+ foreach ($domains as $domainStatuses) {
$domain = new Domain(
[
'namespace' => 'test.com',
- 'status' => \array_sum($domain_statuses),
+ 'status' => \array_sum($domainStatuses),
'type' => Domain::TYPE_EXTERNAL
]
);
- $this->assertTrue($domain->isNew() === in_array(Domain::STATUS_NEW, $domain_statuses));
- $this->assertTrue($domain->isActive() === in_array(Domain::STATUS_ACTIVE, $domain_statuses));
- $this->assertTrue($domain->isConfirmed() === in_array(Domain::STATUS_CONFIRMED, $domain_statuses));
- $this->assertTrue($domain->isSuspended() === in_array(Domain::STATUS_SUSPENDED, $domain_statuses));
- $this->assertTrue($domain->isDeleted() === in_array(Domain::STATUS_DELETED, $domain_statuses));
- $this->assertTrue($domain->isLdapReady() === in_array(Domain::STATUS_LDAP_READY, $domain_statuses));
- $this->assertTrue($domain->isVerified() === in_array(Domain::STATUS_VERIFIED, $domain_statuses));
- }
- }
+ $domainStatuses = [];
- /**
- * Test setStatusAttribute exception
- */
- public function testDomainStatusInvalid(): void
- {
- $this->expectException(\Exception::class);
-
- $domain = new Domain(
- [
- 'namespace' => 'test.com',
- 'status' => 1234567,
- ]
- );
+ foreach ($statuses as $status) {
+ if ($domain->status & $status) {
+ $domainStatuses[] = $status;
+ }
+ }
+
+ $this->assertSame($domain->status, \array_sum($domainStatuses));
+
+ // either one is true, but not both
+ $this->assertSame(
+ $domain->isNew() === in_array(Domain::STATUS_NEW, $domainStatuses),
+ $domain->isActive() === in_array(Domain::STATUS_ACTIVE, $domainStatuses)
+ );
+
+ $this->assertTrue(
+ $domain->isNew() === in_array(Domain::STATUS_NEW, $domainStatuses)
+ );
+
+ $this->assertTrue(
+ $domain->isActive() === in_array(Domain::STATUS_ACTIVE, $domainStatuses)
+ );
+
+ $this->assertTrue(
+ $domain->isConfirmed() === in_array(Domain::STATUS_CONFIRMED, $domainStatuses)
+ );
+
+ $this->assertTrue(
+ $domain->isSuspended() === in_array(Domain::STATUS_SUSPENDED, $domainStatuses)
+ );
+
+ $this->assertTrue(
+ $domain->isDeleted() === in_array(Domain::STATUS_DELETED, $domainStatuses)
+ );
+
+ $this->assertTrue(
+ $domain->isLdapReady() === in_array(Domain::STATUS_LDAP_READY, $domainStatuses)
+ );
+
+ $this->assertTrue(
+ $domain->isVerified() === in_array(Domain::STATUS_VERIFIED, $domainStatuses)
+ );
+ }
}
/**
diff --git a/src/tests/Unit/Methods/DomainTest.php b/src/tests/Unit/Methods/DomainTest.php
new file mode 100644
--- /dev/null
+++ b/src/tests/Unit/Methods/DomainTest.php
@@ -0,0 +1,161 @@
+<?php
+
+namespace Tests\Unit\Methods;
+
+use Tests\TestCase;
+
+class DomainTest extends TestCase
+{
+ protected $domain;
+
+ public function setUp(): void
+ {
+ parent::setUp();
+
+ $this->domain = new \App\Domain();
+ }
+
+ /**
+ * Test lower-casing namespace attribute.
+ */
+ public function testSetNamespaceAttributeLowercases()
+ {
+ $this->domain = new \App\Domain();
+
+ $this->domain->namespace = 'UPPERCASE';
+
+ $this->assertTrue($this->domain->namespace === 'uppercase'); // @phpstan-ignore-line
+ }
+
+ /**
+ * Test setting the status to something invalid
+ */
+ public function testSetStatusAttributeInvalid()
+ {
+ $this->expectException(\Exception::class);
+
+ $this->domain->status = 123456;
+ }
+
+ /**
+ * Test public domain.
+ */
+ public function testSetStatusAttributeOnPublicDomain()
+ {
+ $this->domain->{'type'} = \App\Domain::TYPE_PUBLIC;
+
+ $this->domain->status = 115;
+
+ $this->assertTrue($this->domain->status == 115);
+ }
+
+ /**
+ * Test status mutations
+ */
+ public function testSetStatusAttributeActiveMakesForNotNew()
+ {
+ $this->domain->status = \App\Domain::STATUS_NEW;
+
+ $this->assertTrue($this->domain->isNew());
+ $this->assertFalse($this->domain->isActive());
+
+ $this->domain->status |= \App\Domain::STATUS_ACTIVE;
+
+ $this->assertFalse($this->domain->isNew());
+ $this->assertTrue($this->domain->isActive());
+ }
+
+ /**
+ * Verify setting confirmed sets verified.
+ */
+ public function testSetStatusAttributeConfirmedMakesForVerfied()
+ {
+ $this->domain->status = \App\Domain::STATUS_CONFIRMED;
+
+ $this->assertTrue($this->domain->isConfirmed());
+ $this->assertTrue($this->domain->isVerified());
+ }
+
+ /**
+ * Verify setting confirmed sets active.
+ */
+ public function testSetStatusAttributeConfirmedMakesForActive()
+ {
+ $this->domain->status = \App\Domain::STATUS_CONFIRMED;
+
+ $this->assertTrue($this->domain->isConfirmed());
+ $this->assertTrue($this->domain->isActive());
+ }
+
+ /**
+ * Verify setting deleted drops active.
+ */
+ public function testSetStatusAttributeDeletedVoidsActive()
+ {
+ $this->domain->status = \App\Domain::STATUS_ACTIVE;
+
+ $this->assertTrue($this->domain->isActive());
+ $this->assertFalse($this->domain->isNew());
+ $this->assertFalse($this->domain->isDeleted());
+
+ $this->domain->status |= \App\Domain::STATUS_DELETED;
+
+ $this->assertFalse($this->domain->isActive());
+ $this->assertFalse($this->domain->isNew());
+ $this->assertTrue($this->domain->isDeleted());
+ }
+
+ /**
+ * Verify setting suspended drops active.
+ */
+ public function testSetStatusAttributeSuspendedVoidsActive()
+ {
+ $this->domain->status = \App\Domain::STATUS_ACTIVE;
+
+ $this->assertTrue($this->domain->isActive());
+ $this->assertFalse($this->domain->isSuspended());
+
+ $this->domain->status |= \App\Domain::STATUS_SUSPENDED;
+
+ $this->assertFalse($this->domain->isActive());
+ $this->assertTrue($this->domain->isSuspended());
+ }
+
+ /**
+ * Verify we can suspend a suspended domain without disaster.
+ *
+ * This doesn't change anything to trigger a save.
+ */
+ public function testSuspendForSuspendedDomain()
+ {
+ $this->domain->status = \App\Domain::STATUS_ACTIVE;
+
+ $this->domain->status |= \App\Domain::STATUS_SUSPENDED;
+
+ $this->assertTrue($this->domain->isSuspended());
+ $this->assertFalse($this->domain->isActive());
+
+ $this->domain->suspend();
+
+ $this->assertTrue($this->domain->isSuspended());
+ $this->assertFalse($this->domain->isActive());
+ }
+
+ /**
+ * Verify we can unsuspend an active (unsuspended) domain
+ *
+ * This doesn't change anything to trigger a save.
+ */
+ public function testUnsuspendForActiveDomain()
+ {
+ $this->domain->status = \App\Domain::STATUS_ACTIVE;
+
+ $this->assertFalse($this->domain->isSuspended());
+ $this->assertTrue($this->domain->isActive());
+
+ $this->domain->unsuspend();
+
+ $this->assertFalse($this->domain->isSuspended());
+ $this->assertTrue($this->domain->isActive());
+ }
+}
diff --git a/src/tests/Unit/UtilsTest.php b/src/tests/Unit/UtilsTest.php
--- a/src/tests/Unit/UtilsTest.php
+++ b/src/tests/Unit/UtilsTest.php
@@ -9,10 +9,8 @@
{
/**
* Test for Utils::powerSet()
- *
- * @return void
*/
- public function testPowerSet()
+ public function testPowerSet(): void
{
$set = [];
@@ -54,12 +52,37 @@
$this->assertTrue(in_array(["a1", "a2", "a3"], $result));
}
+ /**
+ * Test for Utils::serviceUrl()
+ */
+ public function testServiceUrl(): void
+ {
+ $public_href = 'https://public.url/cockpit';
+ $local_href = 'https://local.url/cockpit';
+
+ \config([
+ 'app.url' => $local_href,
+ 'app.public_url' => '',
+ ]);
+
+ $this->assertSame($local_href, Utils::serviceUrl(''));
+ $this->assertSame($local_href . '/unknown', Utils::serviceUrl('unknown'));
+ $this->assertSame($local_href . '/unknown', Utils::serviceUrl('/unknown'));
+
+ \config([
+ 'app.url' => $local_href,
+ 'app.public_url' => $public_href,
+ ]);
+
+ $this->assertSame($public_href, Utils::serviceUrl(''));
+ $this->assertSame($public_href . '/unknown', Utils::serviceUrl('unknown'));
+ $this->assertSame($public_href . '/unknown', Utils::serviceUrl('/unknown'));
+ }
+
/**
* Test for Utils::uuidInt()
- *
- * @return void
*/
- public function testUuidInt()
+ public function testUuidInt(): void
{
$result = Utils::uuidInt();
@@ -69,10 +92,8 @@
/**
* Test for Utils::uuidStr()
- *
- * @return void
*/
- public function testUuidStr()
+ public function testUuidStr(): void
{
$result = Utils::uuidStr();

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 4, 11:38 AM (12 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18828954
Default Alt Text
D1636.1775302694.diff (527 KB)

Event Timeline